Puncte:3

Tcpdump afișează un port de redirecționare diferit după adăugarea regulii REDIRECT în iptables

drapel us

Încerc să direcționez traficul clientului către un cluster Kubernetes NodePort care ascultă 192.168.1.100.30000.

Nevoile clientului să facă o cerere către 192.168.1.100.8000 așa că am adăugat următoarea regulă REDIRECT în iptables:

iptables -t nat -I PREROUTING -p tcp --dst 192.168.1.100 --dport 8000 -j REDIRECT --la-port 30000

Eliberez apoi o buclă către 192.168.1.100:8000 cu toate acestea, în tcpdump văd un alt port:

# tcpdump -i lo -nnvvv gazdă 192.168.1.100 și portul 8000
tcpdump: ascultare pe lo, tip link EN10MB (Ethernet), dimensiunea capturii 262144 octeți
[Interfață: lo] 20:39:22.685968 IP (to 0x0, ttl 64, id 20590, offset 0, flags [DF], proto TCP (6), lungime 40)
[Interfață: lo] 192.168.1.100.8000 > 192.168.1.100.49816: Flags [R.], cksum 0xacda (corect), seq 0, ack 3840205844, win 0, length 0
[Interfață: lo] 20:39:37.519256 IP (to 0x0, ttl 64, id 34221, offset 0, flags [DF], proto TCP (6), lungime 40)

M-aș aștepta ca tcpdump să arate ceva de genul

192.168.1.100.8000 > 192.168.1.100.30000

Cu toate acestea, afișează și provoacă o eroare de conexiune refuzată, deoarece niciun proces nu este listat 192.168.1.100.49816.

192.168.1.100.8000 > 192.168.1.100.49816

Folosesc un mediu de testare, așa că nu am acces la dispozitive de la distanță, de aceea folosesc răsuci pentru a testa calea iptables REDIRECT.

Există un motiv pentru care adăugarea unei reguli REDIRECT face ca tcpdump să redirecționeze traficul către un alt port decât cel specificat?

Editați | ×:

După @A.B. sugestia a adăugat următoarea regulă OUTPUT:

iptables -t nat -I IEȘIRE -d 192.168.1.100 -p tcp --dport 8000 -j REDIRECT --la-port 30000

iar curl continuă mai departe, numărul de pachete pentru lanțul OUTPUT crește (pachetul lanțului PREROUTING REDIRECT nu a crescut totuși):

2 10 600 REDIRECT tcp -- * * 0.0.0.0/0 192.168.1.100 tcp dpt:8000 porturi redir 30000

Totuși, obținem următoarea eroare:

# curl -vk https://192.168.1.100:8000/v1/api
* Urmează să se conecteze() la portul 192.168.1.100 8000 (#0)
* Se încearcă 192.168.1.100...
* Conectat la 192.168.1.100 (192.168.1.100) portul 8000 (#0)
* Inițializarea NSS cu certpath: sql:/etc/pki/nssdb
* Eroare NSS -12263 (SSL_ERROR_RX_RECORD_TOO_LONG)
* SSL a primit o înregistrare care a depășit lungimea maximă permisă.
* Închiderea conexiunii 0
curl: (35) SSL a primit o înregistrare care a depășit lungimea maximă permisă.

De asemenea, am încercat să adaug o rețea de sistem la distanță, de data aceasta numărul de pachete PREROUTING REDIRECT CHAIN ​​crește după executare curl sistem la distanță... (dar lanțul de ieșire nu crește):

2 34 2040 REDIRECT tcp -- * * 0.0.0.0/0 172.16.128.1 tcp dpt:8000 porturi redir 30000

Eroare:

# ip netns exec remotesystem curl -vk https://192.168.1.100:8000/v1/api
* Urmează să se conecteze() la portul 192.168.1.100 8000 (#0)
* Se încearcă 192.168.1.100...
* Conexiunea a expirat
* Conectarea eșuată la 192.168.1.100:8000; Conexiunea a expirat
* Închiderea conexiunii 0
curl: (7) Conectarea eșuată la 192.168.1.100:8000; Conexiunea a expirat
A.B avatar
drapel cl
A.B
Regula ta nu va funcționa cu un test de la gazdă. Testați din nou de la un sistem la distanță, nu de la sistem către el însuși.
tiger_groove avatar
drapel us
De ce nu ar funcționa, ai putea explica? Există o modalitate de a o face să funcționeze de la gazdă cu o interfață loopback?
A.B avatar
drapel cl
A.B
Vă rugăm să adăugați mai întâi context la întrebare: spuneți ce faceți, dar aș vrea să știu de ce o faceți mai întâi (pentru a rezolva ce problemă practică care v-a făcut să utilizați asta?)
tiger_groove avatar
drapel us
Adăugat în postare
A.B avatar
drapel cl
A.B
Nu se poate spune motivul pentru utilizarea sistemului local (mai degrabă decât la distanță) este explicat, dar răspunsul nu va avea nevoie de el în cele din urmă.
tiger_groove avatar
drapel us
Folosesc un mediu de testare, așa că nu am acces la dispozitive la distanță, de aceea folosesc `curl` pentru a testa calea iptables REDIRECT. Ce vrei să spui că răspunsul oricum nu va avea nevoie de el?
jcaron avatar
drapel co
Rețineți că „192.168.1.100.8000 > 192.168.1.100.49816” nu înseamnă „redirecționare de la portul 8000 la portul 49816”, înseamnă „un pachet a fost trimis de la portul 8000 la portul 49816”, care este pur și simplu portul folosit. de clientul dvs. (local), iar pachetul este TCP RST ("conexiune refuzată"). Ar trebui să aveți un pachet anterior de la 49816 la 8000 înainte de aceasta (cererea de conectare, TCP SYN). Iar conexiunea refuzată nu este pentru că nu se ascultă nimic pe 49816, ci mai degrabă nu se ascultă nimic pe 8000.
Puncte:4
drapel cl
A.B

Pentru a fi clar: testul OP se face de la sistemul 192.168.1.100 la el însuși, nu de la un sistem de la distanță și asta este cauza problemei. Portul nu a fost schimbat în acest caz, deoarece nicio regulă NAT nu s-a potrivit, în timp ce s-ar fi potrivit dacă ar fi făcut dintr-un sistem la distanță.

Schema de mai jos arată cum este efectuată ordinea operațiunilor pe un pachet:

Fluxul de pachete în Netfilter și General Networking

Motivul este modul în care funcționează NAT pe Linux: iptables vede un pachet în nat tabel numai pentru primul pachet dintr-un nou flux conntrack (care este astfel în stare NEW).

Această regulă funcționează bine atunci când este de la un sistem de la distanță. În acest caz, primul pachet văzut va fi un pachet de intrare:

la portul 8000 --> AF_PACKET (tcpdump) --> conntrack --> nat/PREROUTING (iptables REDIRECT): la portul 30000
--> decizie de rutare --> ... --> proces local de primire pe portul 30000

Toate pachetele următoare din același flux vor avea conntrack să gestioneze direct schimbarea portului (sau inversarea portului pentru răspunsuri) și vor omite orice regulă iptables din nat tabel (așa cum este scris în schema: nat tabel consultat doar pentru NOU conexiuni). Deci, (sărind partea pachetului de răspuns), următorul pachet de intrare va fi supus în schimb:

la portul 8000 --> AF_PACKET (tcpdump) --> conntrack: la portul 30000
--> decizie de rutare --> ... --> proces local de primire pe portul 30000

Pentru un test pe sistem în sine, primul pachet nu este un pachet de intrare, ci un pachet de ieșire. Acest lucru se întâmplă, în schimb, folosind outgoing uite interfata:

proces local client curl --> decizie de rutare --> conntrack --> nat/OUTPUT (nicio regula aici)
--> verificare redirecționare --> AF_PACKET (tcpdump) --> la portul 8000

Și acum acest pachet este reîntors pe uite interfață, reapare ca un pachet care nu mai este primul pachet dintr-o conexiune, așa că urmează al doilea caz ca mai sus: conntrack singur are grijă de NAT și nu apelează nat/PREROUTING. Cu excepția faptului că nu a fost instruit în pasul de dinainte să facă orice NAT:

la portul 8000 --> AF_PACKET (tcpdump) --> conntrack
--> decizie de rutare --> ... -->Nuproces local de primire pe port8000

deoarece nu se ascultă nimic pe portul 8000, sistemul de operare trimite înapoi un TCP RST.

Pentru ca aceasta să funcționeze în sistemul local, a REDIRECŢIONA regula trebuie pusa si in nat/OUTPUT lanţ:

iptables -t nat -I IEȘIRE -d 192.168.1.100 -p tcp --dport 8000 -j REDIRECT --la-port 30000

Note Aditionale

  • dacă carcasa este destinată utilizării de la distanță, nu testați din sistemul local: regulile parcurse de test nu sunt aceleași. Acest lucru face ca testul să nu reflecte realitatea.

    Utilizați doar un spațiu de nume de rețea pentru a crea un sistem de buzunar la distanță în cazul în care nu este disponibil niciun alt sistem. Exemplu care ar trebui să funcționeze cu un sistem care are doar OP-uri nat/PREROUTING guverna si face curl http://192.168.1.100/ (care nu necesită DNS):

    ip netns adaugă sistem la distanță
    link ip adăugați nume vethremote up tip veth peer netns remotesystem nume eth0
    adresa ip adăugați 192.0.2.1/24 dev vethremote
    ip -n adresa sistemului la distanță adăugați 192.0.2.2/24 dev eth0
    ip -n link-ul la distanta seteaza eth0
    ip -n ruta sistemului la distanță adăugați 192.168.1.100 prin 192.0.2.1
    ip netns exec remotesystem curl http://192.168.1.100:8000/
    
  • tcpdump și NAT

    tcpdump se întâmplă la AF_PACKET pași din schema de mai sus: foarte devreme pentru intrare și foarte târziu pentru ieșire. Asta înseamnă că pentru un caz de sistem la distanță, nu va captura niciodată portul 30000, chiar și atunci când funcționează. Pentru cazul sistemului local, odată ce nat/OUTPUT este adăugată regula, va captura portul 30000.

    Doar nu aveți încredere orbește în adresa/portul afișat de tcpdump când faci NAT: depinde de caz și de unde are loc captura.

tiger_groove avatar
drapel us
Vă mulțumesc foarte mult pentru explicația detaliată, mai am câteva probleme și am pus mai multe informații în postarea mea. Se pare că devine mai departe decât înainte, dar pare că ceva încă se blochează.
A.B avatar
drapel cl
A.B
Bănuiesc că 1/ procesul local nu este un proces local, ci un container/pod (din moment ce este vorba despre Kubernetes), deci este, de asemenea, rutat sau filtrat în continuare (=> fără conexiune cu noul spațiu de nume net). Mi-am bazat răspunsul pe regula iptables unică prezentă în întrebare și nimic nu este disponibil. Mai mult, am încercat cu succes ceea ce am prezentat înainte de a da răspunsul 2/ așa cum este explicat contorul din tabelul nat crește doar pentru primul pachet (în stare NEW): fie va crește în nat/OUTPUT, fie nat/PREROUTING nu ambele. tabelul de filtrare va vedea toate pachetele. 3/ întrebarea inițială nu era despre https
A.B avatar
drapel cl
A.B
Nu voi mai schimba acest răspuns. Ar trebui să creați o nouă întrebare, cu TOT contextul dat în avans.Și, de preferință, reproduceți o problemă care nu va depinde de acest Q/A curent (păstrați utilizarea cu regula OUTPUT sau cu un sistem la distanță despre care se știe că se conectează)
tiger_groove avatar
drapel us
În regulă, voi crea o nouă întrebare. Apreciez cu adevărat ajutorul tău!
tiger_groove avatar
drapel us
Am creat o nouă întrebare, vă rog să-mi spuneți dacă acest lucru are sens pentru dvs. https://serverfault.com/questions/1097511/iptables-redirect-to-kubernetes-nodeport-causes-request-to-hang
A.B avatar
drapel cl
A.B
Noua dvs. problemă este despre efectuarea unei cereri de curl către API-ul dvs., nu despre un timeout, deoarece v-am sugerat o metodă de a înlocui un sistem de la distanță care nu a funcționat în configurația dvs. specifică. iptables nu ar trebui să fie implicat deloc în noua întrebare. Îmi pare rău că nu am explicat corect cum ar fi trebuit să fie noua întrebare
tiger_groove avatar
drapel us
Este ciudat pentru că atunci când efectuez curl-ul așa `ip netns exec remotesystem curl -vk https://192.168.1.100:30000/v1/flight` funcționează bine și primesc un răspuns înapoi, doar când îl schimb în `192.168 .1.100:8000` se blochează, nu sunt complet sigur de ce, dar se pare că ceva nu-i place regula iptables REDIRECT.
A.B avatar
drapel cl
A.B
Vorbeam despre cazul cu SSL_ERROR_RX_RECORD_TOO_LONG care nu s-a blocat.

Postează un răspuns

Majoritatea oamenilor nu înțeleg că a pune multe întrebări deblochează învățarea și îmbunătățește legătura interpersonală. În studiile lui Alison, de exemplu, deși oamenii își puteau aminti cu exactitate câte întrebări au fost puse în conversațiile lor, ei nu au intuit legătura dintre întrebări și apreciere. În patru studii, în care participanții au fost implicați în conversații ei înșiși sau au citit transcrieri ale conversațiilor altora, oamenii au avut tendința să nu realizeze că întrebarea ar influența – sau ar fi influențat – nivelul de prietenie dintre conversatori.