Elke regel in het toegangslog toont hetzelfde loopbackadres, terwijl de pagina zelf laadt en het certificaat correct wordt gevalideerd. Niets is stuk in de zin van onbereikbaar, en daarom overleeft dit maandenlang. Wat stuk is, is de toerekening: de web-backend registreert het adres van de sprong die de verbinding doorstuurde, en elke latere beslissing die het log vertrouwde, erfde hetzelfde verkeerde antwoord.

De onderstaande controles gaan van de kabel naar binnen. Stop bij de eerste die de waarde verklaart die u ziet, want elke latere stap veronderstelt dat de eerdere al waar zijn. Geen ervan vereist dat u de front-endconfiguratie raadt.

Volg de twee verbindingen, niet de logregel

Port-Share multiplext twee protocollen op één TCP-listener. OpenVPN inspecteert de eerste bytes van een inkomende verbinding, houdt die wanneer ze op zijn eigen protocol lijkt, en geeft al het overige door aan een tweede bestemming. Die bestemming is meestal een webserver op dezelfde host, dus de geaccepteerde socket van de webserver heeft het OpenVPN-proces als peer.

ss -ltnp 'sport = :443'
ss -tnp 'dport = :8080'

De eerste opdracht laat zien wie de openbare listener bezit. De tweede laat de verbindingen zien die bij de backend-poort aankomen, en hun peeradres is het adres dat het toegangslog zal afdrukken. Is die peer loopback, dan is het log juist en ging de informatie een laag eerder verloren. Het logveld hernoemen of een client-IP-module inschakelen haalt geen adres terug dat de verbinding nooit heeft gedragen.

Dit is de controle die al het andere beslist. Is de peer van de backend het adres van de browser, dan is poortdeling niet uw probleem en is het logformaat dat wel.

Transportdoorsturing is geen header-injectie

De doorstuurder verplaatst bytes. Hij parseert geen HTTP, dus hij kan geen header invoegen in een verzoek dat hij nooit als verzoek leest, en hij kan niets toevoegen aan een TLS-stream die hij onaangeroerd doorlaat. Een module die een proxyheader verwacht, blijft wachten op een header die geen enkele component produceert.

Twee mechanismen kunnen het oorspronkelijke adres dragen, en beide vereisen overeenstemming aan beide kanten. Het PROXY-protocol zet een kleine header voor de verbinding, en de backend moet erop zijn ingesteld die te verwachten; een backend die dat niet doet, behandelt die bytes als het begin van het verzoek en faalt op een verwarrende manier. Vertrouwde proxyheaders zoals X-Forwarded-For werken wanneer een HTTP-bewuste proxy ze zet en de backend wordt verteld welke peers ze mogen beweren.

Geen van beide is automatisch, en geen van beide is standaard veilig. Een backend die elke binnenkomende doorgestuurde header gelooft, laat een client zijn eigen adres kiezen, wat een onnauwkeurigheid in het log omzet in een omzeiling van toegangscontrole. Voer de demonstratie één keer uit op een testhost voordat u een header op een productiepad vertrouwt.

curl -sS -H 'X-Forwarded-For: 127.0.0.1' https://site.example.com/health
grep -F '127.0.0.1' /var/log/nginx/access.log | tail -n 3

De optionele map voor brontoewijzing

Poortdeling heeft een optioneel mapargument dat een toewijzing vastlegt tussen het oorspronkelijke bronadres en de doorstuurverbinding, op platforms waar de functie is geïmplementeerd. Van de webkant wordt verwacht dat hij die toewijzing raadpleegt; het is geen header, en hij wordt niet in het verzoek geïnjecteerd.

Dat ontwerp is de moeite waard om te kennen, omdat het verklaart waarom sommige installaties echte adressen melden en andere niet, bij een ogenschijnlijk identieke front-endconfiguratie. Het verschil zit aan de ontvangende kant, en het woont meestal in een module of patch die de meeste verpakte webservers niet standaard inschakelen. Lees de documentatie van uw webserver voor de exacte hook die hij biedt, en bevestig dat de module is geladen in plaats van dat aan te nemen.

Als u deze weg volgt, behandel het dan als een integratie van twee helften: de toewijzing die de doorstuurder schrijft en de opzoeking die de backend doet. Verifieer beide, en bevestig dat de map een herstart overleeft en op een drukke listener niet onbeperkt groeit.

Bepaal welke component voor het adres instaat

Voordat u de configuratie wijzigt, benoem de component die een clientadres mag beweren en de componenten die dat mogen geloven. Eén opgeschreven antwoord voorkomt de gebruikelijke drift, waarbij drie verschillende lagen elk een andere bron vertrouwen.

Drie ontwerpen dekken de meeste behoeften. Houd de openbare listener en de weblistener gescheiden, zodat de webserver echte peers ziet en er geen toerekeningsprobleem bestaat. Zet een HTTP-bewuste reverse proxy ervoor, beëindig of parse het verzoek daar, en laat die een doorgestuurde header zetten voor een backend die alleen die proxy vertrouwt. Of behoud poortdeling en accepteer dat logs de sprong tonen, met toegangsregels geschreven tegen de applicatie-identiteit in plaats van een adres.

Wat niet werkt, is een doorgestuurd loopbackadres behandelen als bewijs dat het verzoek op deze machine is ontstaan. Die gevolgtrekking is precies omgekeerd: het adres is juist aanwezig omdat een lokale component de verbinding heeft gemaakt. Een regel die zo is geschreven, laat iedereen binnen die de listener kan bereiken.

Test de regel, niet de pagina

Een pagina die laadt, bewijst dat het doorstuurpad werkt en zegt niets over toerekening. Test de gebruiker van het adres: de toegangsregel, de snelheidslimiet, de auditregel, de geo-opzoeking.

curl -sS -o /dev/null -w '%{http_code}\n' https://site.example.com/
tail -n 5 /var/log/nginx/access.log
grep -c '' /var/log/nginx/access.log

Vergelijk een geautoriseerd extern verzoek met de registraties van zowel de front-end als de backend, en bevestig dat een regel die zou moeten weigeren nog steeds weigert en een die zou moeten toelaten nog steeds toelaat. Als de logregel correct is maar de regel zich nog steeds gedraagt alsof iedereen lokaal is, leest de regel een ander veld dan het veld dat u hebt gecorrigeerd.

Sluit af door de toerekeningsketen in de uitrolnotities te schrijven: welke listener, welke doorstuurder, welke header of toewijzing en welke backend is geconfigureerd om die te vertrouwen. De volgende persoon die een logregel leest, heeft alle vier nodig, en het ontbreken van die notitie is de reden dat hetzelfde ticket een jaar later opnieuw opengaat. Houd hem naast de configuratie in plaats van in een chatthread.

Gerelateerde artikelen