Partener de socket sau antet redirecționat: cărei adrese să ai încredere?
Partenerul de socket și un antet redirecționat sunt dovezi diferite. Compară ce demonstrează fiecare și ai încredere în antet doar printr-un lanț de proxy pe care îl controlezi.
O cerere care ajunge în aplicația ta poartă două tipuri de dovezi despre adresă: partenerul care a deschis conexiunea de rețea și un câmp HTTP care pretinde adresa unui client anterior. Ele răspund la întrebări diferite. Partenerul de socket este observat, în timp ce antetul este pretins de cine l-a scris, și niciunul nu ar trebui să îl înlocuiască în tăcere pe celălalt într-un jurnal sau într-o regulă de acces. Comparația de mai jos le ține separate și apoi arată singura aranjare în care antetul devine utilizabil.
Descrie traseul înainte de a compara ceva:
Client -> approved reverse proxy -> application originÎn această aranjare, partenerul de socket al originii este de obicei proxy-ul, iar un antet de redirecționare poate purta afirmația proxy-ului despre client. Valoarea lui vine din relația controlată cu acel proxy, nu din numele antetului.
Două tipuri de dovezi despre adresă
Partenerul de socket este un fapt despre o singură conexiune TCP: ceva a finalizat o strângere de mână de la acea adresă. Nu este neapărat persoana, dispozitivul sau contul care te interesează, pentru că un VPN sau o ieșire Tor pot fi în mod legitim sursa pe care o observă un serviciu. Totuși, rămâne singura adresă pe care gazda însăși a verificat-o, și în asta stă toată valoarea ei.
Un câmp de redirecționare este metadată despre un lanț. X-Forwarded-For, X-Real-IP și câmpul standardizat Forwarded pot fi scrise de orice client care ajunge la un punct final care le reflectă, așa că fiabilitatea lor depinde în întregime de cine a fost autorizat să le stabilească.
Păstrează ambele în contextul cererii sub nume distincte. O aplicație care suprascrie partenerul cu antetul pierde capacitatea de a reconstrui mai târziu o eroare de încredere, și exact atunci ai nevoie de ea.
Un antet nu redirecționează niciodată conexiunea
Scrierea unei adrese într-un câmp de redirecționare nu schimbă sursa conexiunii TCP care ajunge la server și nu modifică rutarea nicăieri pe traseu. Rutarea VPN obișnuită sau NAT de sursă livrează traficul fără niciun antet HTTP. La fel, o poartă de tranzit nu rescrie un schimb HTTPS protejat corespunzător fără a schimba aranjarea punctului final TLS.
Greșeala inversă este la fel de obișnuită: HTTPS nu face adevărat un antet de redirecționare furnizat de client. Protejează transportul unei afirmații false exact la fel ca pe cel al uneia adevărate.
Dacă un coleg propune o schimbare de antet pentru a remedia o problemă de rutare, diagnosticul a mers deja greșit. Remediază traseul sau remediază configurația proxy-ului care scrie antetul.
Numește proxy-ul autorizat să afirme
Două reguli fac un câmp de redirecționare utilizabil, și ambele sunt configurație, nu cod. Marginea normalizează sau aruncă tot ce vine din exterior, conform comportamentului său documentat pentru acele câmpuri. Apoi originea ia o adresă de substituție din traseul de proxy pe care l-ai numit și de nicăieri altundeva. A doua regulă este valabilă doar cât timp clienții nu pot ajunge la origine pe altă cale, deoarece o origine care răspunde atât la cereri directe, cât și la cereri prin proxy nu știe pe care dintre ele o deservește.
Modulul de IP real al NGINX arată separarea clar. set_real_ip_from numește expeditorii a căror afirmație contează, iar real_ip_header spune care câmp o poartă; primul face încrederea, al doilea spune doar unde să te uiți.
set_real_ip_from 10.20.0.0/24;
real_ip_header X-Forwarded-For;
# real_ip_recursive off - take the rightmost value in the field
# real_ip_recursive on - walk the list back past every trusted address
O directivă de selectare a antetului, singură, încă nu stabilește nimic despre cine a trimis valoarea.
Securitatea transportului trebuie să ruleze pe tot parcursul între componentele în care ai încredere. O margine care normalizează corect pierde acea valoare în momentul în care un salt neprotejat mai jos permite altcuiva să editeze afirmația în timp ce călătorește.
Gestionează deliberat lanțurile cu mai multe salturi
Mai multe proxy-uri necesită un model de lanț explicit. Nu lua valoarea cea mai din stânga sau din dreapta separată prin virgule doar pentru că un articol de blog a făcut asta; află care dintre proxy-urile tale adaugă, care înlocuiește și care păstrează câmpul de intrare. NGINX, de exemplu, poate parcurge lista înapoi față de setul său de încredere și se poate opri la prima adresă pe care nu o deține, iar aceasta este regula acelui produs, nu o lege pe care o urmează fiecare cadru. Citește documentația propriului tău proxy cu aceleași două întrebări: ce valoare selectează și în ce expeditori crede?
Notează lanțul: ordinea salturilor, care salt stabilește câmpul și care salt elimină copiile de intrare. Apoi ține acea notă lângă configurația proxy-ului, nu doar în tichet. Apoi testează-o trimițând o cerere cu un antet falsificat prin procesul de validare aprobat și confirmând că originea o ignoră.
Când adaugi un salt, revizuiește acel document. Un nou echilibrator de încărcare inserat în fața proxy-ului de încredere poate schimba care adresă câștigă fără ca cineva să editeze aplicația.
Păstrează ambele observații în jurnal
Acolo unde diagnosticarea este autorizată, înregistrează partenerul conexiunii și adresa de client normalizată ca două câmpuri separate și adaugă doar metadatele de redirecționare de care scopul chiar are nevoie. Apoi dovedește implementarea cu două cereri: una prin proxy, care ar trebui să înregistreze ambele valori în mod rezonabil, și o încercare directă la origine care trebuie refuzată.
Amintește-ți ce înseamnă perechea. Antetul adaugă context furnizat de o componentă în care ai ales să ai încredere; partenerul rămâne singura adresă pe care gazda ta a văzut-o efectiv. Niciunul nu este dovadă de identitate individuală, iar un design care tratează oricare dintre ele ca dovadă va greși cu privire la cineva.