Waarom je openbare Linux-dienst juist via de VPN antwoordt
Een lokale dienst kan aannemen op eth0 en antwoorden via een full-tunnel-VPN. Een bronregel met een volledige WAN-tabel houdt die antwoorden op het oorspronkelijke pad.
Niets in de socket onthoudt welke interface het verzoek heeft gedragen, dus een standaardroute van een full-tunnel-VPN kan een antwoord onderscheppen dat op de WAN thuishoort. De dienst negeert de inkomende interface niet; Linux routeert een lokaal gegenereerd antwoord op basis van bestemming en bronbeleid. Een bronregel kan in plaats daarvan alleen de antwoorden van de dienst via een volledige WAN-tabel sturen en de gewone uitgaande weg op de tunnel laten. De poort blijft open terwijl het antwoord via het verkeerde pad vertrekt, en daarom lijkt het symptoom eenzijdig.
De misvatting: antwoorden volgen de interface waarop ze aankwamen
Het lijkt logisch dat een pakket dat op eth0 aankomt ook op eth0 vertrekt. Stateless pakketfilters kunnen zo geschreven worden, en tcpdump aan de inkomende kant toont het verzoek precies waar het verwacht wordt. Routering werkt niet zo voor verkeer dat de host zelf maakt.
Zodra de dienst de verbinding accepteert, is het antwoord een nieuw lokaal gegenereerd pakket. De kernel raadpleegt de routeringsregels voor de bestemming en bron van het antwoord, en de standaardroute van de VPN is een volstrekt geldig antwoord. Niets in de socket onthoudt welke interface het verzoek heeft gedragen.
Daarom lijkt het symptoom eenzijdig: verzoeken komen aan, antwoorden verdwijnen. Daarom verandert een firewallregel voor de inkomende poort ook niets. Het pakket wordt niet tegengehouden op de weg naar binnen; het wordt op de weg naar buiten elders gerouteerd. Volg het antwoord met een brongekwalificeerde opzoeking en de omweg wordt zichtbaar.
Wat de kernel werkelijk routeert: het bronadres
Het handvat dat je nodig hebt is het lokale adres dat de dienst voor antwoorden gebruikt. Op een host met het illustratieve eth0-adres 192.0.2.10/24 en de gateway 192.0.2.1 staat dat adres op de interface. Op een cloud-VM kan het openbare adres stroomopwaarts vertaald zijn en op de gast ontbreken, dus gebruik het adres dat de host werkelijk heeft.
Inspecteer de huidige toestand voordat je een tabelnummer of regelprioriteit reserveert. Bestaande beleidsregels kunnen een nieuwe overschaduwen, en een oude tabel met hetzelfde nummer kan al ongerelateerde routes bevatten:
ip -4 addr show dev eth0
ip -4 rule show
ip -4 route show table all
Kies daarna een tabel op basis van de bron. De regel komt overeen met antwoorden die al 192.0.2.10 dragen, precies het lokaal beëindigde verkeer dat je wilt uitzonderen. Doorgestuurd verkeer en pakketten van andere lokale adressen komen niet overeen.
Bouw een volledige retourtabel, geen halve standaardroute
Een tabel met alleen een standaardroute is niet genoeg. De kernel moet de gateway nog steeds oplossen, en die oplossing vereist het verbonden prefix in dezelfde tabel. Een tabel zonder dat prefix faalt bij het oplossen van de gateway, zelfs wanneer de standaardroute correct lijkt. Voeg beide toe en wijs daarna de bronregel naar de tabel:
ip -4 route add table 100 192.0.2.0/24 dev eth0 src 192.0.2.10
ip -4 route add table 100 default via 192.0.2.1 dev eth0
ip -4 rule add priority 1000 from 192.0.2.10/32 lookup 100
Gebruik het echte prefix en de echte gateway in plaats van het voorbeeld te kopiëren. Een cloud-interface die als /32 is geconfigureerd met een on-link-gateway heeft een andere verbonden route nodig, en een tabel die uit het verkeerde prefix is gebouwd, faalt bij de eerste hop. Het attribuut src vermeldt de voorkeursbron voor die route; het vervangt de bronregel niet.
De volgorde is ook belangrijk. Een brede regel met een lager prioriteitsnummer wordt eerst geëvalueerd, dus de bronregel moet worden bereikt vóór elke regel die dit verkeer terug naar de hoofdtabel zou sturen. Controleer de prioriteiten met ip rule show nadat je hem hebt toegevoegd, niet alleen bij het opstarten.
Verifieer met een brongekwalificeerde opzoeking
Vraag de kernel om een testbestemming vanaf het dienstadres te routeren. Het antwoord hoort eth0 en de WAN-gateway te noemen, niet de tunnel:
ip -4 route get 198.51.100.25 from 192.0.2.10
Breng daarna een nieuwe geautoriseerde verbinding tot stand en observeer beide richtingen. Een opzoeking die de juiste tabel kiest terwijl de live verbinding nog steeds faalt, wijst op reverse-path-filtering of een firewallregel, niet op de tabel. Controleer die maatregelen voordat je iets wereldwijd uitschakelt.
Plaats de definitieve routes en de regel onder de netwerkbeheerder die de interface bezit. Adreswijzigingen, DHCP-vernieuwing en VPN-herverbindingen herschrijven allemaal de kerneltoestand, en een met de hand toegevoegde regel verdwijnt of wijst na de volgende gebeurtenis naar een verouderde gateway.
Waar deze uitzondering stopt
De regel zondert lokaal beëindigd verkeer van één bronadres uit. Ze dekt geen door Docker gepubliceerde poorten, DNAT of diensten die via de host worden doorgestuurd, omdat die pakketten als doorgestuurd verkeer worden gerouteerd en nooit op dezelfde manier de lokale bron van de host dragen. Zulke ontwerpen vereisen meestal een markering die bij de ingress wordt gezet en een regel die bij de markering past.
Ze zorgt er ook niet voor dat het openbare adres van de host op de interface verschijnt. Wanneer een upstream-NAT dat adres bezit, moet het antwoord nog steeds vertrekken via het pad dat die NAT verwacht, en daarom moet de WAN-tabel de oorspronkelijke gateway en het prefix weerspiegelen in plaats van een geraden openbaar bereik.
Houd de uitzondering gedocumenteerd met het tabelnummer, de regelprioriteit en het exacte bronadres. De volgende wijziging aan de VPN of de interface kan hem stilzwijgend breken, en een notitie die de drie waarden noemt, is sneller te controleren dan het symptoom opnieuw te ontdekken uit een klantrapport.
Als de dienst na een geslaagde brongekwalificeerde opzoeking nog steeds via het verkeerde pad antwoordt, vergelijk dan het bronadres van de live socket met dat in de regel. Een dienst die aan een jokertekenadres is gebonden, kan een andere bron kiezen dan het adres dat je hebt getest, en dat verschil is de resterende kloof.