Sokel-eweknie teenoor deurgeefkop: watter adres vertrou jy?
Die sokel-eweknie en ’n deurgeefkop is verskillende bewyse. Vergelyk wat elkeen bewys, en vertrou die kop net deur ’n instaanbedienerketting wat jy beheer.
’n Versoek wat by jou toepassing aankom, dra twee soorte adresbewyse: die eweknie wat die netwerkverbinding oopgemaak het, en ’n HTTP-veld wat die adres van ’n vroeëre kliënt beweer. Hulle antwoord verskillende vrae. Die sokel-eweknie word waargeneem, terwyl die kop deur elkeen wat dit geskryf het, beweer word, en nie een behoort die ander stilweg in ’n logboek of ’n toegangsreël te vervang nie. Die vergelyking hieronder hou hulle apart en wys dan die een reëling waarin die kop bruikbaar word.
Beskryf die pad voordat jy enigiets vergelyk:
Client -> approved reverse proxy -> application originIn daardie reëling is die oorsprong se sokel-eweknie gewoonlik die instaanbediener, en ’n deurgeefkop kan die instaanbediener se bewering oor die kliënt dra. Die waarde daarvan kom uit die beheerde verhouding met daardie instaanbediener, nie uit die kop se naam nie.
Twee soorte adresbewyse
Die sokel-eweknie is ’n feit oor een TCP-verbinding: iets het ’n handdruk vanaf daardie adres voltooi. Dit is nie noodwendig die mens, die toestel of die rekening waaroor jy sorg nie, want ’n VPN of ’n Tor-uitgang kan wettig die bron wees wat ’n diens waarneem. Dit bly steeds die enigste adres wat die gasheer self geverifieer het, en dit is die hele waarde daarvan.
’n Deurgeefveld is metadata oor ’n ketting. X-Forwarded-For, X-Real-IP en die gestandaardiseerde veld Forwarded kan deur enige kliënt geskryf word wat ’n eindpunt bereik wat hulle terugstuur, so hulle betroubaarheid hang heeltemal daarvan af wie toegelaat is om hulle te stel.
Hou albei in die versoekkonteks onder aparte name. ’n Toepassing wat die eweknie met die kop oorskryf, verloor die vermoë om later ’n vertrouensfout te rekonstrueer, en dit is juis wanneer jy dit nodig het.
’n Kop herlei nooit die verbinding nie
Om ’n adres in ’n deurgeefveld te skryf, verander nie die bron van die TCP-verbinding wat by die bediener aankom nie, en dit verander ook nie die roetering enige plek langs die pad nie. Gewone VPN-roetering of bron-NAT lewer verkeer sonder enige HTTP-kop hoegenaamd. Net so herskryf ’n deurgangsgateway nie ’n behoorlik beskermde HTTPS-uitruiling sonder om die TLS-eindpuntreëling te verander nie.
Die omgekeerde fout is net so algemeen: HTTPS maak nie ’n kliëntverskafde deurgeefkop waar nie. Dit beskerm die vervoer van ’n valse bewering net so goed soos dié van ’n ware een.
As ’n kollega ’n kopverandering voorstel om ’n roeteringsprobleem op te los, het die diagnose al verkeerd geloop. Maak die pad reg, of maak die instaanbediener-konfigurasie reg wat die kop skryf.
Noem die instaanbediener wat mag beweer
Twee reëls maak ’n deurgeefveld bruikbaar, en albei is konfigurasie eerder as kode. Die rand normaliseer of gooi weg wat van buite aankom, volgens sy eie gedokumenteerde gedrag vir daardie velde. Die oorsprong neem dan ’n vervangingsadres uit die instaanbedienerpad wat jy genoem het en uit niks anders nie. Daardie tweede reël geld net terwyl kliënte die oorsprong nie op ’n ander manier kan bereik nie, want ’n oorsprong wat beide direkte en deurgegewe versoeke beantwoord, het geen idee watter een hy bedien nie.
Die real-IP-module van NGINX wys die splitsing duidelik. set_real_ip_from noem die senders wie se bewering tel, en real_ip_header sê watter veld dit dra; die eerste doen die vertroue, die tweede sê net waar om te kyk.
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
’n Direktief wat net ’n kop kies, vestig op sigself nog niks oor wie die waarde gestuur het nie.
Vervoersekuriteit moet die hele pad tussen die komponente wat jy vertrou, loop. ’n Rand wat korrek normaliseer, verloor daardie waarde op die oomblik wanneer ’n onbeskermde sprong stroomaf iemand anders die bewering laat wysig terwyl dit reis.
Hanteer kettings met meer as een sprong doelbewus
Verskeie instaanbedieners het ’n eksplisiete kettingmodel nodig. Moenie die linker- of regterkantste kommagebaseerde waarde neem omdat ’n blogberig dit gedoen het nie; vind uit watter van jou instaanbedieners byvoeg, watter vervang en watter die inkomende veld bewaar. NGINX kan byvoorbeeld die lys agteruit deur sy vertroude stel loop en stop by die eerste adres wat hy nie besit nie, en dit is daardie produk se reël eerder as ’n wet wat elke raamwerk volg. Lees jou eie instaanbediener se dokumentasie met dieselfde twee vrae: watter waarde kies hy, en watter senders glo hy?
Skryf die ketting neer: sprongorde, watter sprong die veld stel, en watter sprong inkomende afskrifte verwyder. Hou dan daardie nota langs die instaanbediener-konfigurasie, nie net in die kaartjie nie. Toets dit dan deur ’n versoek met ’n vervalste kop deur die goedgekeurde valideringsproses te stuur en te bevestig dat die oorsprong dit ignoreer.
Wanneer jy ’n sprong byvoeg, hersien daardie dokument. ’n Nuwe lasbalanseerder wat voor die vertroude instaanbediener ingevoeg word, kan verander watter adres wen sonder dat iemand die toepassing wysig.
Hou albei waarnemings in die logboek
Waar diagnosering gemagtig is, teken die verbinding se eweknie en die genormaliseerde kliëntadres as twee aparte velde aan, en voeg net die deurgeefmetadata by wat die doel werklik nodig het. Bewys dan die ontplooiing met twee versoeke: een deurgegee wat albei waardes sinvol moet aanteken, en een direkte poging na die oorsprong wat geweier moet word.
Onthou wat die paar beteken. Die kop voeg konteks by wat deur ’n komponent verskaf word wat jy gekies het om te vertrou; die eweknie bly die enigste adres wat jou gasheer werklik gesien het. Nie een van die twee is bewys van individuele identiteit nie, en ’n ontwerp wat enigeen as bewys beskou, sal oor iemand verkeerd wees.