Full tunnel i OpenVPN klipper din SSH-session: laga returvägen
Standardrutten skickar SSH-svar in i tunneln. Fäst peeren, filtrera redirect-gateway eller routa efter källa innan du förlorar maskinen.
Att slå på en OpenVPN-klient med full tunnel på en maskin du når över SSH kan klippa sessionen inom en sekund, och maskinen gör inget fel. Tunneln ändrar inte hur paket når servern; den ändrar hur svaren lämnar den. Så snart standardrutten pekar på tun0 går ett svar till din SSH-klient in i leverantörens nät, som inte har någon rutt tillbaka till din adress. Anslutningen hänger, nästa försök får timeout, och daemonen lyssnar fortfarande på port 22 hela tiden.
Läs routingtabellen innan du läser VPN-loggen. Loggen kommer att säga att tunneln kom upp, och den har rätt. Frågan är vilket gränssnitt varje svar lämnas till, och det är ett uppslag per paket i en tabell som tunneln just skrev om.
Varför svaret går ut genom fel dörr
Inkommande paket anländer fortfarande på det fysiska gränssnittet, eftersom en VPN-klient inte kan ändra hur internet når serverns publika adress. Svaren är ett eget beslut: för varje paket slår kärnan upp målet, och efter --redirect-gateway säger standardposten tunnel. Leverantörens utgång ser ett mål den inte betjänar och kastar paketet.
Det egna skyddet i OpenVPN täcker exakt ett mål. Handboken för 2.6 beskriver --redirect-gateway som en sekvens: den lägger till en värdrutt för VPN-peeren via den gateway som användes före tunneln, så att den krypterade trafiken inte kan loopa tillbaka i sig själv, och ersätter sedan standardrutten. Den värdrutten är bara för peeren. Din SSH-klient är bara ännu en internetadress och får inget undantag.
Ett prefixfel är värt att utesluta tidigt. ip route add -net 0.0.0.0 gw 10.8.0.1 dev tun0 utan längd matchar den enda adressen 0.0.0.0, inte internet; den måste vara 0.0.0.0/0. Och om det att ta standardrutten bryter tunnelns egen transport, lägg till slutpunkten som en värdrutt via det fysiska gränssnittet, med leverantörens riktiga adress.
Fäst din SSH-klientadress för en omedelbar reparation
Den snabbaste reparationen är en värdrutt för din klientadress via den gateway som servern använde innan tunneln fanns. Från din sida, hitta adressen som servern kommer att se, och läs sedan serverns tabell så att du känner till den gamla gatewayen:
curl -s https://ifconfig.co
ip route
På servern lägger du till undantaget innan klienten startar. Adresserna här är platshållare; formen är det som spelar roll:
sudo ip route add 80.128.240.55 via 192.168.178.1
Detta är reparationen som användes i det rapporterade fallet, och den fungerar omedelbart. Den är också ömtålig på två förutsägbara sätt: rutten försvinner vid omstart, och den blir fel i samma stund som din ISP ger dig en annan adress. Behandla den som en nödåtgärd och gör den avsiktligt beständig, via en nätverksenhet eller en dispatcher-krok, eller acceptera att den är tillfällig och skriv ner återställningsvägen.
Hindra klienten från att ta standardrutten
Det renare alternativet är att hindra tunneln från att ersätta standardrutten överhuvudtaget. route-nopull, använd med --client eller --pull, accepterar de pushade alternativen utom rutter, block-outside-dns och DHCP-liknande alternativ som DNS-servrar, så du lägger bara till de prefix du behöver. Ett smalare verktyg är ett pull-filter, som kastar en problematisk direktiv och behåller resten:
route-nopull
pull-filter ignore "redirect-gateway"
Använd det ena eller det andra, inte båda, och var tydlig med vad som ändras. Utan standardrutt genom tunneln surfar servern inte längre på internet via leverantören; den når bara det du uttryckligen routat. Om den fulla tunneln var hela poängen med uppsättningen är detta fel ratt, och värdrutten ovan är den rätta.
Dela upp returvägen efter källa eller anslutning
När den inkommande adressen är stabil håller en källregel svaren lokala utan att röra tunnelns egna rutter. Ge adressen för det fysiska gränssnittet en egen tabell med LAN-prefixet och den fysiska standarden, och välj sedan den tabellen för trafik som kommer därifrån:
ip rule add from 192.168.1.11 table 128
ip route add table 128 to 192.168.1.0/24 dev eth0
ip route add table 128 default via 192.168.1.1
Detta fungerar eftersom svar på en inkommande SSH-anslutning kommer från den adress som klienten anslöt till. Ett rapporterat fall där varje inkommande tjänst måste fortsätta fungera använde exakt denna form. När den inkommande adressen flyter eller vägen är dynamisk, markera anslutningen i stället: sätt en conntrack-markering på det första paketet från det fysiska gränssnittet, kopiera den till svarspaket i OUTPUT, och routa markerade paket genom en tabell som pekar på den fysiska gatewayen.
iptables -t mangle -A PREROUTING -i eth0 -m conntrack --ctstate NEW -j CONNMARK --set-mark 1234
iptables -t mangle -A OUTPUT -m connmark --mark 1234 -j MARK --set-mark 4321
ip route add default via 192.168.1.1 dev eth0 table 3412
ip rule add fwmark 4321 table 3412
Håll anslutningsmarkeringen, brandväggsmarkeringen och tabellnumret åtskilda under testet. Att återanvända ett nummer för två roller ger en regel som ser korrekt ut och träffar fel paket. Tabellens standardpost behöver också via med LAN-gatewayen på en vanlig Ethernet-länk; en naken dev eth0 fungerar bara när gränssnittet är punkt-till-punkt eller nästa hopp löses på annat sätt. Den rapporterade Jessie-värden satt på en länk där den nakna formen fungerade, vilket inte är en distributionsregel att kopiera.
Verifiera utan att låsa ute dig själv
Testa inte genom att koppla från. Håll den första sessionen öppen, ta upp tunneln och fråga kärnan vilken väg din egen adress skulle ta:
ip route get 80.128.240.55
Svaret bör namnge det fysiska gränssnittet och den gamla gatewayen, inte tunneln. Öppna sedan en andra SSH-anslutning; det är det riktiga testet, eftersom den gamla sessionen kan överleva på ett tillstånd som en ny anslutning inte kan återskapa. Om den andra hänger medan den första fortfarande svarar, har regeln aldrig träffat trafiken som betyder något, och markeringarna eller källadressen är där man ska titta.
Håll en konsol utanför bandet tillgänglig under hela övningen. En server vars enda åtkomstväg är tunneln du just har brutit kan inte repareras över den tunneln, och återrullningen är lättare när du har skrivit ner tabellnumren och prefixen du lade till.