Zahtjev koji stiže u vašu aplikaciju nosi dvije vrste dokaza o adresi: partnera koji je otvorio mrežnu vezu i HTTP polje koje tvrdi adresu ranijeg klijenta. Oni odgovaraju na različita pitanja. Soketni partner se posmatra, a zaglavlje tvrdi onaj ko ga je napisao, i nijedno ne treba tiho zamijeniti drugo u zapisu ili pravilu pristupa. Poređenje ispod drži ih odvojeno, a zatim pokazuje jedini raspored u kojem zaglavlje postaje upotrebljivo.

Opišite putanju prije nego što bilo šta uporedite:

Client -> approved reverse proxy -> application origin

U tom rasporedu soketni partner na izvorištu obično je proxy, a zaglavlje prosljeđivanja može nositi proxyjevu tvrdnju o klijentu. Njegova vrijednost dolazi iz kontrolisanog odnosa s tim proxyjem, a ne iz naziva zaglavlja.

Dvije vrste dokaza o adresi

Soketni partner je činjenica o jednoj TCP vezi: nešto je završilo rukovanje s te adrese. To nije nužno čovjek, uređaj ili račun do kojeg vam je stalo, jer VPN ili Tor izlaz mogu legitimno biti izvor koji usluga posmatra. Ipak, to je jedina adresa koju je sam host provjerio, i u tome je sva njegova vrijednost.

Polje prosljeđivanja su metapodaci o lancu. X-Forwarded-For, X-Real-IP i standardizovano polje Forwarded može napisati svaki klijent koji dosegne krajnju tačku koja ih vraća, pa njihova pouzdanost u potpunosti zavisi od toga kome je bilo dozvoljeno da ih postavi.

Zadržite oboje u kontekstu zahtjeva pod različitim imenima. Aplikacija koja prepiše partnera zaglavljem gubi sposobnost da kasnije rekonstruiše grešku povjerenja, a to je upravo trenutak kada vam je potrebna.

Zaglavlje nikada ne preusmjerava vezu

Upisivanje adrese u polje prosljeđivanja ne mijenja izvor TCP veze koja stiže na server i ne mijenja rutiranje nigdje na putanji. Uobičajeno VPN rutiranje ili izvorni NAT isporučuje saobraćaj bez ikakvog HTTP zaglavlja. Isto tako, tranzitni prolaz ne prepisuje ispravno zaštićenu HTTPS razmjenu bez promjene rasporeda TLS krajnje tačke.

Obrnuta greška je jednako česta: HTTPS ne čini zaglavlje prosljeđivanja koje je dao klijent istinitim. Ono štiti prijenos lažne tvrdnje isto tako dobro kao i istinite.

Ako kolega predloži promjenu zaglavlja da popravi problem s rutiranjem, dijagnoza je već pošla naopako. Popravite putanju ili popravite konfiguraciju proxyja koja piše zaglavlje.

Imenujte proxy kojem je dozvoljeno tvrditi

Dva pravila čine polje prosljeđivanja upotrebljivim, i oba su konfiguracija, a ne kod. Rub normalizuje ili odbacuje sve što dolazi spolja, slijedeći vlastito dokumentovano ponašanje za ta polja. Zatim izvorište uzima zamjensku adresu iz putanje proxyja koju ste imenovali i ni iz čega drugog. Drugo pravilo vrijedi samo dok klijenti ne mogu doći do izvorišta na drugi način, jer izvorište koje odgovara i na direktne i na proxy zahtjeve nema pojma kojem od njih služi.

NGINX modul za stvarnu IP adresu jasno pokazuje podjelu. set_real_ip_from imenuje pošiljaoce čija se tvrdnja računa, i real_ip_header kaže koje polje je nosi; prvo obavlja povjerenje, drugo samo kaže gdje gledati.

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

Sama direktiva za odabir zaglavlja još uvijek ništa ne utvrđuje o tome ko je poslao vrijednost.

Sigurnost transporta mora djelovati cijelim putem između komponenti kojima vjerujete. Rub koji ispravno normalizuje gubi tu vrijednost u trenutku kada nezaštićeni skok nizvodno dopusti nekome drugom da uredi tvrdnju dok putuje.

Svjesno rukujte lancima s više skokova

Više proxyja zahtijeva jasan model lanca. Ne uzimajte krajnju lijevu ili desnu vrijednost odvojenu zarezima samo zato što je tako uradio neki blog post; otkrijte koji od vaših proxyja dodaje, koji zamjenjuje, a koji čuva dolazno polje. NGINX, na primjer, može hodati listom unazad prema svom skupu pouzdanih i zaustaviti se na prvoj adresi koju ne posjeduje, i to je pravilo tog proizvoda, a ne zakon koji slijedi svaki radni okvir. Čitajte dokumentaciju vlastitog proxyja s ista dva pitanja: koju vrijednost bira i kojim pošiljaocima vjeruje?

Zapišite lanac: redoslijed skokova, koji skok postavlja polje i koji skok uklanja dolazne kopije. Zatim držite tu bilješku uz konfiguraciju proxyja, a ne samo u tiketu. Zatim to testirajte slanjem zahtjeva s krivotvorenim zaglavljem kroz odobreni proces validacije i potvrđivanjem da ga izvorište zanemaruje.

Kada dodate skok, ponovo pregledajte taj dokument. Novi balanser opterećenja umetnut ispred pouzdanog proxyja može promijeniti koja adresa pobjeđuje bez toga da iko uređuje aplikaciju.

Zadržite oba zapažanja u zapisu

Gdje je dijagnostika odobrena, bilježite partnera veze i normalizovanu adresu klijenta kao dva odvojena polja i dodajte samo metapodatke prosljeđivanja koje svrha zaista treba. Zatim dokažite implementaciju s dva zahtjeva: jedan kroz proxy koji treba razumno zabilježiti obje vrijednosti i jedan pokušaj direktno na izvorište koji mora biti odbijen.

Zapamtite šta par znači. Zaglavlje dodaje kontekst koji pruža komponenta koju ste odabrali da joj vjerujete; partner ostaje jedina adresa koju je vaš host zaista vidio. Nijedno nije dokaz individualnog identiteta, a dizajn koji bilo koje od njih tretira kao dokaz pogriješit će u vezi s nekim.

Povezani članci