VPS-brandvägg: öppna bara VPN-porten och bevisa det sedan
En port måste förbli offentlig, annars ansluter ingen klient. Neka resten, håll vidarebefordran åtskild från inkommande trafik och lämna en återställningsväg som du har testat i förväg.
En brandvägg som bara släpper in VPN-porten är inte en regel. Det är tre separata beslut som råkar gälla samma portnummer: inkedjan avgör vad som kan nå en lokal process, vidarebefordringskedjan avgör vad som kan passera genom värden för tunnelklienternas räkning, och NAT-tabellen skriver om källadressen på väg ut. Får du en av dem fel blir resultatet sällan ett rent avbrott. Du får en värd som tar emot klienter men inte laddar något, eller en värd som ser stängd ut tills någon läser ordningen i kedjorna.
Den enda porten som inte kan stängas
VPN-lyssnaren måste ta emot anslutningar från adresser du inte kan förutse och är därför en offentlig tjänst per definition. Det är det enda undantaget som designen är byggd kring: en UDP-port för OpenVPN, en UDP-port för WireGuard, en TCP-port för en SSL VPN. Allt annat hör hemma bakom tunneln, vilket innebär att applikationstjänster bör binda till tunneladressen eller till loopback i stället för till alla gränssnitt.
Bindning är dock inte verkställighet. En process bunden till 0.0.0.0 är bara nåbar om en regel släpper in den, och standardprincipen är reservvägen för trafik som ingen regel matchade, inte regeln som styr porten. En accept ovanför din drop är fortfarande en accept, och att flytta en tjänst från den offentliga adressen är en självständig förbättring, inte en ersättning för kedjan.
Inkommande, vidarebefordran och NAT svarar på olika frågor
Inkommande trafik är adresserad till värden själv, så det är där VPN-lyssnaren och den administrativa vägen bor. Vidarebefordringstrafik passerar genom värden, och tunnelklienter behöver det plus net.ipv4.ip_forward=1. Den klassiska halvtrasiga konfigurationen tillåter det utgående flödet och glömmer returriktningen, så klienten slutför handskakningen och sedan laddas ingenting; en conntrack-regel för etablerad och relaterad trafik täcker den riktningen.
NAT är den tredje frågan. Utan omskrivning i postrouting lämnar vidarebefordrade paket värden med tunnelns privata källa och släpps högre upp, eftersom inget nätverk bortom värden vet hur poolen ska dirigeras tillbaka. Källprefixet i den regeln måste matcha VPN-poolen, inte värdens egen adress, och samma sak gäller vidarebefordringsregeln som namnger klientnätet.
IPv6 är en andra princip, inte en eftertanke. En värd med strikt IPv4-kedja och öppen princip på ip6tables har inte stängt något; tjänsterna är fortfarande nåbara över den andra familjen. Antingen speglar du regeluppsättningen med ip6tables, eller så inaktiverar du IPv6 medvetet på det offentliga gränssnittet, och skriver ned vilket du valde.
En baslinje du läser i en enda genomgång
Börja med drop och lägg sedan bara till det värden behöver. Först loopback och svar, sedan den administrativa vägen, sedan tunnel-lyssnaren, sedan vidarebefordringsprincipen för klienter:
iptables -P INPUT DROP
iptables -P FORWARD DROP
iptables -A INPUT -i lo -j ACCEPT
iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
iptables -A INPUT -p tcp --dport 22 -m conntrack --ctstate NEW -j ACCEPT
iptables -A INPUT -p udp --dport 1194 -m conntrack --ctstate NEW -j ACCEPT
sysctl -w net.ipv4.ip_forward=1
iptables -A FORWARD -i tun0 -o eth0 -s 10.8.0.0/24 -j ACCEPT
iptables -A FORWARD -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
iptables -t nat -A POSTROUTING -s 10.8.0.0/24 -o eth0 -j MASQUERADEGränssnittsnamnen, porten och poolen är platshållare; läs dem från servern i stället för att kopiera dem. Att spara resultatet är lika viktigt som att skriva det, för en regeluppsättning som bara lever i minnet försvinner vid nästa omstart och öppnar värden tyst igen. Gör den beständig med distributionens mekanism och håll en kopia utanför maskinen för den dag maskinen inte startar.
Stäng den sista porten utan att förlora värden
Det finns en hake i designen. Om SSH bara finns genom tunneln tar en misslyckad VPN-tjänst SSH med sig, och den enda vägen tillbaka kan vara en konsol du aldrig har öppnat. Innan du stänger den sista offentliga porten, bekräfta att konsolen finns och att du verkligen kan använda den, eller behåll en smal administrativ väg som inte beror på tunneln: SSH från en fast adress, bara nycklar, lösenordsautentisering av.
Tillämpa ändringen från en session som redan är etablerad, inte genom anslutningen du är på väg att filtrera. Schemalägg en återrullning så att ett misstag löper ut i stället för att bli permanent, till exempel ett systemd-run --on-active=10min-jobb som återställer föregående regeluppsättning, och håll en andra SSH-session öppen medan du testar den första. Kontrollera sedan att återrullningsjobbet faktiskt utlöses, för otestad återställning är detsamma som ingen återställning.
Verifiera vägen, inte skriptet
Läs de laddade reglerna, inte filen som skulle ladda dem. Från en auktoriserad extern värd, bekräfta att bara de avsedda portarna svarar; inifrån tunneln, bekräfta att tjänsterna du ville publicera är nåbara. En standard-neka-princip som också blockerar tunneltrafik ser identisk ut med en fungerande nedstängning tills någon försöker använda den.
iptables -S
iptables -t nat -S
ss -lntup
ip -4 addr showAnteckna den tillåtna porten, klientpoolen, tunnelgränssnittet, den administrativa källan och konsolproceduren bredvid konfigurationen. Nästa ändring av poolen eller gränssnittsnamnet måste följas upp både i filtret och i NAT-regeln, annars återgår värden till ett halvöppet tillstånd utan att någon märker det.
En vana är värd mer än regeluppsättningen: efter varje ändring, bevisa vidarebefordringsvägen med en klientbegäran och återställningsvägen med en andra session. En nedstängning du inte har använt är en hypotes.