Twee verkeerstrichtingen, één box
Welkom
De meeste architectuurschema's tonen verkeer in één richting: client bovenaan, server onderaan, pijl naar beneden. In de realiteit gaat verkeer in beide richtingen.
Ingress: externe clients bereiken uw services via deze route. Een reverse proxy aan de rand van uw netwerk beëindigt TLS, routeert verzoeken en handhaaft het toegangsbeleid.
Egress: uw services bereiken externe services via deze route. Een API van een betaalverwerker aanroepen, een webhook-doel ophalen, een verzoek naar een partner sturen. Vaak via een forward proxy of NAT-gateway met een toelijst.
Veel architecturen beginnen met één box die beide verwerkt. Het werkt, tot de dag dat het niet meer werkt. Het falingspatroon is subtiel, wordt pas zichtbaar zodra er voldoende interne services bestaan, & leert een belangrijk lesje over scheiding van zorgen.
Aan het einde van deze les zult u begrijpen:
- Waarom ingress & egress fundamenteel verschillende verkeerpatronen vertegenwoordigen met verschillende schaalingsassen & verschillende falingspatronen
- Hairpin NAT & waarom een proxy die probeert met zichzelf te verbinden faalt
- De architecturale tak: één box wordt twee, & wat elk van hen dan exclusief bezit
- Winsten in beveiligingsisolatie: elke kant kan zich afsluiten voor zijn echte toegestane peers
- Hoe te identificeren wanneer uw single-box ontwerp de drempel heeft overschreden waar de splitsing noodzakelijk is
Waarom de Richtingen Verschillende Gereedschappen Vereisen
Twee verschillende werkbelastingen aan één netwerkgrens
Kenmerken van inkomend verkeer:
- Ingeleid door externe partijen (het brede internet)
- Volume schaalt met uw gebruikersbasis
- TLS-terminatie, verzoekroutings, rate limiting per bron
- Diepte-in-verdediging: DDoS, misbruik, scraping
- Publiek IP-adres moet verbindingen van iedereen accepteren
Kenmerken van uitgaand verkeer:
- Geïnitieerd door uw eigen services (een bekende, kleine set clients)
- Het volume schaalt met uw service-naar-service- & externe-API-aanroeppatronen
- Source-IP-allowlisting op afgelegen eindpunten (u heeft één vaste uitgaande IP-adres dat partners vertrouwen)
- Diepte-in-verdediging (defense-in-depth)-overwegingen: datadiefstal, gecompromitteerde interne services die naar buiten bellen
- Moet verbindingen van iedereen anders dan uw eigen services weigeren
De belangrijkste asymmetrie: ingress accepteert verkeer van de wereld; egress accepteert verkeer alleen van uw eigen services. Als u ze op dezelfde machine plaatst, moet die machine tegelijkertijd bereikbaar zijn vanuit de wereld (voor ingress) & alleen bereikbaar zijn vanuit uw services (voor egress). De firewallregels die aan de ene eis voldoen, werken tegen de andere.
De groeipad: een klein project kan beide achter één IP & één tool verbergen, omdat het volume klein is & de partner-IP-allowlist kort is. Naarmate het project groeit, neemt de wrijving tussen de twee rollen toe, & op een dag dwingt een specifiek falingspatroon (hairpin NAT) de splitsing af.
De bug die de splitsing dwingt
Een gesaniteerd verhaal over een storing
Stel je een echte architecturale takking voor die zich voordoet in productie-flotten. De namen hieronder zijn gewijzigd; de vorm is identiek aan wat teams in de praktijk tegenkomen.
Een organisatie draait een enkele proxy-server op 203.0.113.5. Deze verwerkt inkomend verkeer (poort 443 voor gebruikers) & uitgaand verkeer (poort 1080 SOCKS5 voor interne services die naar buiten toe bellen). Interne services bevinden zich in private subnets & routeren al hun uitgaand verkeer via die SOCKS5-proxy op 203.0.113.5:1080.
Eén van de services die achter hetzelfde 203.0.113.5 wordt gehost, is api.example.com. Openbare DNS lost api.example.com op naar 203.0.113.5.
Nu heeft een andere interne service de noodzaak om api.example.com aan te roepen. Het uitgaande pad:
1. Interne service lost api.example.com op → 203.0.113.5
2. Interne service stuurt de aanvraag via de SOCKS5-egress-proxy op 203.0.113.5:1080
3. De proxy probeert een verbinding van zichzelf naar 203.0.113.5:443 te openen
4. Verbinding geweigerd. Het pakket zou de zelfde NAT moeten verlaten en opnieuw moeten binnengaan, wat de meeste netwerkstacks afwijzen. De proxy kan niet met zichzelf verbinden via zijn eigen publieke IP.
Dit is hairpin NAT: een pakket dat een NAT verlaat en dezelfde NAT opnieuw moet binnengaan om zijn bestemming te bereiken. Zonder speciale hairpin-ondersteuning in de routinglaag wordt het pakket verstrengeld.
Waarom het laat opduikt
In de vroege fase van het project communiceerde elke interne service met andere interne services via een privé-hostnaam (internal-api.local) of riep geen publieke services van de eigen organisatie aan. Het hairpin-pad bestond simpelweg niet.
Toen vereiste een nieuwe functie dat service A api.example.com (een publieke hostnaam) aanroept. Het hairpin-pad werd geactiveerd. Verbinding geweigerd. Storing.
De oplossing verholp het symptoom (de resolver dwingen om het privé-IP van api.example.com te geven in plaats van het publieke). De oorzaak: één machine deed te veel taken.
De architecturale vork
Een box wordt twee
De nette oplossing: scheid de proxy in twee machines.
Ingress-server (openbaar IP-adres 203.0.113.5):
- Caddy / reverse proxy op poorten 80, 443
- Openbare DNS-records wijzen hierheen
- Hosts api.example.com, app.example.com, enz.
Egress-server (ander openbaar IP-adres 203.0.113.99):
- SOCKS5 / forward proxy op poort 1080
- De firewall beperkt inkomende verbindingen tot alleen IP-adressen van het interne subnet
- Interne services routeren alle uitgaand verkeer via dit adres
Wat dit oplevert:
1. Hairpin opgelost. Een interne service die api.example.com aanroept, routeert het uitgaande verkeer via 203.0.113.99 (egress), die vervolgens normaal verbinding maakt met 203.0.113.5 (ingress, een ander IP-adres). De NAT-loop verdwijnt omdat de twee IP-adressen op verschillende machines staan.
2. Beveiligingsisolatie. De firewall van de egress-server kan worden beperkt tot een klein aantal interne IP-adressen. De firewall van de ingress-server blijft open voor de wereld. Twee aparte regelsets, die elk één rol helder uitdrukken.
3. Onafhankelijke schaalbaarheid. Ingress-bandbreedte schaalt mee met het aantal gebruikers; egress-bandbreedte schaalt mee met de activiteit van interne services. U kunt de ene upgraden zonder de andere aan te raken.
4. Foutisolatie. Een verkeerd geconfigureerde egress breekt de openbare site niet langer. Een DDoS-aanval op de openbare site verstikt de egress-bandbreedte niet langer.
5. Helderder mentaal model. Elke machine heeft één taak. Ingenieurs redeneren over ingress-gerelateerde zaken zonder aan egress te hoeven denken, en omgekeerd.
Twee assen, twee afmetingsbeslissingen
Onafhankelijke schaling
Vóór de splitsing stelde groei in beide richtingen dezelfde machine onder druk. Na de splitsing heeft elke richting zijn eigen provisioning.
Ingress-grootte: schaalt met het aantal gebruikers. Capaciteitsbeslissingen zitten in de openbare laag (meer reverse proxy-replica's, grotere VM's, CDN ervoor). Bandbreedtebudget berekend op basis van gebruikersverkeer op piekmomenten.
Egress-grootte: schaalt met het volume van interne service-naar-externe API-aanroepen. Vaak gedomineerd door webhook-levering, aanroepen van betaalverwerkers of data-opvragingen van derden. Bandbreedtebudget berekend op basis van interne aanroeppatronen.
Foutisolatie: een DDoS-aanval op de openbare ingress verbruikt niet langer de egress-bandbreedte (die betaalverwerker-aanroepen gaan immers gewoon door). Een crash van een egress-proxy neemt de openbare site niet meer mee (gebruikers bereiken de site nog steeds; alleen interne uitgaande aanroepen falen).
Verschillende SLO's: ingress-beschikbaarheid is belangrijk voor gebruikers (zichtbare site-uitval); egress-beschikbaarheid is belangrijk voor operators (achtergrondstoringen die langer duren om te detecteren). Elke kant kan zijn eigen SLO dragen.
Meerdere egress-servers
Zodra de egress-rol een eigen machine is, is de volgende voor de hand liggende stap om meerdere egress-machines achter een load balancer te draaien voor HA. Elke nieuwe interne service wijst naar de egress-hostnaam (die oplost naar de load-balanced pool) in plaats van naar een enkel IP-adres.
Zelfde les als de rest van distributed systems: zodra een tier stateless is & een eigen rol heeft, kan deze goedkoop worden vermenigvuldigd.
Een nieuwe partnerintegratie
Je organisatie draait de ingress/egress-splitsing zoals ontworpen. De egress-server heeft een vast publiek IP-adres (203.0.113.99) dat je hebt allowlisted voor drie bestaande partner-API's (een betaalverwerker, een SMS-gateway en een e-mailprovider).
Een productteam wil een vierde integratie toevoegen: een webhook-leveringssysteem dat terugbelt naar klantendpoints over de hele wereld. Volumevoorspelling: 10.000 oproepen per minuut, met pieken tot 30.000.
Ontwerp een netwerkgrens voor een groeiende service
Synthese
Je hebt geleerd waarom inkomend en uitgaand verkeer verschillende tools vereisen, de hairpin-NAT-fout die de splitsing in echte vloten afdwingt, en hoe onafhankelijke schaalbaarheid, beveiligingsisolatie en foutisolatie zich opbouwen zodra de splitsing is gerealiseerd.
Pas alle vier toe.
Een middelgrote SaaS-bedrijf exploiteert drie product-subdomeinen (app, api, admin) voor hun gebruikers, plus vier uitgaande integraties (Stripe, Twilio, SendGrid, een klant-webhooksysteem). Momenteel zit alles achter één proxy-machine met één openbaar IP-adres. Er zijn meldingen binnengekomen van intermitterende hairpin-fouten wanneer interne services proberen api.example.com aan te roepen. Ze willen een permanente oplossing ontwerpen.
Waar deze cursus naartoe gaat
Waar deze cursus naartoe gaat
Je hebt nu een van de schoonste scheiding-van-betrokkenheden-refactors in gedistribueerde systemen gezien: één box wordt twee, elk met een duidelijke rol, & het systeem erft op weg schaalbaarheid, beveiliging & foutisolatie.
De volgende les (cs_distsys_failure_modes_and_blast_radius) breidt de redenering over isolatie van storingen uit. Je leest een gesaniteerd postmortem over DNS-SERVFAIL, identificeert het patroon van kaskadelende storingen & schrijft schuldloze actiepunten die zich richten op systemen in plaats van personen.
Begeleidelijke les: geometry_of_ingress_egress_separation presenteert de scheiding als een tweetijdige graaf & verkent knutpunten, netwerkpartities & wat grafentheorie je vertelt over een netwerkgrens.
Goed gedaan. Verder.