Openbare SaaS-pagina’s kunnen voor iedereen open blijven terwijl de beheersbewerkingen erachter iedereen buiten de VPN weigeren. Het mechanisme dat dat mogelijk maakt is geen verborgen menu en geen aparte inlogpagina; het is een controle van het netwerkpad dat het verzoek heeft afgeleverd. Is het adresbewijs fout, dan sluit de controle echte beheerders buiten of laat iedereen door die een header kan typen. Begin met wat de origin werkelijk ontvangt.

Wat de origin na de tunnel werkelijk ontvangt

Wanneer een browser de openbare site bereikt via een VPN die ook internetverkeer vervoert, vertaalt de gateway de verbinding voordat die naar buiten gaat. De SaaS ziet het openbare uitgaande adres van de gateway, meestal één adres of een klein bereik, en ziet nooit het tunneladres van de laptop. Daarom mislukt het opnemen van 10.90.0.42 in de allowlist, en daarom mislukt het opnemen van het hele RFC 1918 nog luider: het tweede laat elk particulier netwerk door dat jou kan bereiken. Het enige adres dat een voorwaarde waard is, is het adres dat jouw organisatie bij de uitgang werkelijk bezit.

curl -s https://ifconfig.me
dig +short admin.example.com

Split-tunneling breekt die aanname stil. Als de VPN alleen particuliere kantoerroutes vervoert, verlaat het verzoek naar de openbare beheerhostnaam het lokale netwerk via de provider en ziet de origin een woonadres. Een verbonden VPN-pictogram bewijst niets over deze specifieke bestemming, dus test de bestemming en niet de tunnel.

Stop en repareer de routering voordat je enig beleid schrijft als het uitgaande adres per gebruiker verschilt. Een voorwaarde die alleen bij sommige beheerders past, is erger dan geen voorwaarde, omdat ze het probleem tot een incident verbergt.

Vertrouw alleen de proxy die het adres herschrijft

De meeste openbare sites staan achter een CDN of omgekeerde proxy, dus het socketadres van de origin hoort bij die frontend en niet bij de bezoeker. De frontend stuurt het oorspronkelijke adres meestal door in een header, en die header wordt door een aanvaller beheerd, tenzij de origin hem alleen van bekende proxies accepteert. Configureer de lijst met vertrouwde bronnen expliciet en maak de origin vanaf elke andere plek onbereikbaar. Zonder die tweede helft slaat een aanvaller de proxy over en stuurt de header rechtstreeks.

set_real_ip_from 192.0.2.0/24;
real_ip_header X-Forwarded-For;
real_ip_recursive on;
curl -H 'X-Forwarded-For: 198.51.100.27' https://origin.example.com/admin

Dezelfde redenering geldt voor het PROXY-protocol: het is alleen betrouwbaar als de listener is gebonden aan een interface die de proxy kan bereiken en niets anders. Ontbrekende adrescontext moet de beschermde controle laten mislukken in plaats van terug te vallen op een standaardtoestemming. Een ontbrekende header is geen bewijs van een vertrouwd pad.

Hang de voorwaarde aan elke beschermde bewerking

Zet de controle op de autorisatiegrens die elke beschermde bewerking passeert, niet in de pagina die het menu rendert. Routegroepen, middleware of een beleidslaag werken allemaal; een kopie per handler niet, omdat de handler die iemand volgend kwartaal toevoegt hem niet zal hebben.

user = requireAuthenticatedSession()
requirePermission(user, "admin")
requireVpnEgress(verifiedClientAddress(request))
performProtectedOperation(user, request)

Dezelfde grens moet de JSON-API, exports, ondertekende download-URL’s en de WebSocket-handshake dekken, omdat geen ervan vereist dat de HTML-pagina eerst wordt opgevraagd. Een downloadlink die is gemaakt terwijl de VPN actief was, blijft daarna geldig tenzij het download-eindpunt opnieuw controleert. Langdurige sessies hebben ook een herbeoordelingsregel nodig, anders wordt één geauthenticeerd verzoek een permanente uitzondering. Standaardweigering is de enige instelling die personeelsverloop overleeft.

Gedeelde caches zijn de andere manier om de controle heen. Een cache die al een beschermd antwoord bevat, kan het leveren zonder de origin te contacteren, dus markeer beheerantwoorden als privé en houd ze buiten gedeelde opslag. Als een cache ze moet leveren, moet de toegangscontrole vóór het leveren draaien, wat meestal betekent dat het helemaal geen gedeelde cache kan zijn.

Test de omwegen die je zojuist hebt gesloten

Oefen de matrix in plaats van het gelukkige pad: een beheerder via de VPN, dezelfde beheerder zonder, een niet-beheerder erdoor, en een vervalste adresheader. Voeg een verzoek rechtstreeks naar de origin toe en een verzoek met een gecachet antwoord, want die twee slaan de frontend volledig over.

curl -sI https://admin.example.com/export.csv
curl -s -H 'X-Forwarded-For: 198.51.100.27' https://origin.example.com/admin
curl -s https://admin.example.com/api/me -o /dev/null -w '%{http_code}\n'

Elk verzoek hoort de status terug te geven die het beleid belooft, en de log hoort vast te leggen welk adresbewijs is gebruikt. Dek IPv6 apart af, omdat een dual-stack-origin een andere bronfamilie kan zien dan degene die je hebt getest. Houd gewone klantbewerkingen buiten de VPN werkend, anders wordt de wijziging teruggedraaid zodra een klant voor het eerst klaagt. Schrijf het verwachte resultaat voor elke rij voordat je hem uitvoert, zodat een verrassende doorgang zichtbaar is.

Het uitgaande adres bewijst een toegestaan netwerkpad, niet een persoon en niet een beheerd apparaat. Houd het als één voorwaarde naast authenticatie en toestemming, en het beheergebied blijft smal zonder het hele product tot een alleen-VPN-dienst te maken. Die scheiding is het ontwerp, niet een beperking ervan.

Gerelateerde artikelen