Un tallafoc que només admet el port de la VPN no és una sola regla. Són tres decisions separades que casualment afecten el mateix número de port: la cadena d’entrada decideix què pot arribar a un procés local, la cadena de reenviament decideix què pot travessar l’amfitrió en nom dels clients del túnel, i la taula NAT reescriu l’adreça d’origen a la sortida. Si n’encertes una malament, el resultat poques vegades és una caiguda neta. Tens un amfitrió que accepta clients però no carrega res, o un amfitrió que sembla tancat fins que algú llegeix l’ordre de les cadenes.

L’únic port que no es pot tancar

L’oient de la VPN ha d’acceptar connexions des d’adreces que no pots predir, per tant és un servei públic per definició. Aquesta és l’única excepció sobre la qual es construeix el disseny: un port UDP per a OpenVPN, un port UDP per a WireGuard, un port TCP per a una VPN SSL. Tota la resta pertany darrere del túnel, cosa que vol dir que els serveis d’aplicació s’han d’enllaçar a l’adreça del túnel o a loopback, no a totes les interfícies.

Enllaçar, però, no és aplicar. Un procés enllaçat a 0.0.0.0 només és abastable si una regla l’admet, i la política per defecte és el recurs per al trànsit que no ha encaixat amb cap regla, no la regla que governa el port. Una admissió col·locada per sobre de la teva denegació continua sent una admissió, i moure un servei fora de l’adreça pública és una millora independent, no un substitut de la cadena.

Entrada, reenviament i NAT responen preguntes diferents

El trànsit d’entrada va destinat al mateix amfitrió, així que és on viuen l’oient de la VPN i el camí administratiu. El trànsit de reenviament travessa l’amfitrió, i els clients del túnel el necessiten, a més de net.ipv4.ip_forward=1. La configuració clàssica mig trencada permet el flux de sortida i oblida la direcció de tornada, de manera que el client completa l’encaixada de mans i després no es carrega res; una regla de conntrack per al trànsit establert i relacionat cobreix aquella direcció.

NAT és la tercera pregunta. Sense una reescriptura a postrouting, els paquets reenviats surten amb l’origen privat del túnel i es descarten més amunt, perquè cap xarxa més enllà de l’amfitrió sap encaminar el pool de tornada. El prefix d’origen d’aquella regla ha de coincidir amb el pool de la VPN, no amb l’adreça pròpia de l’amfitrió, i el mateix val per a la regla de reenviament que anomena la subxarxa dels clients.

IPv6 és una segona política, no un pensament posterior. Un amfitrió amb una cadena IPv4 estricta i una política oberta a ip6tables no ha tancat res; els serveis encara són abastables per l’altra família. O bé reflecteixes el conjunt de regles amb ip6tables, o bé desactives IPv6 deliberadament a la interfície pública, i escrius quina de les dues opcions has triat.

Una base que es llegeix d’una passada

Comença amb la denegació i després afegeix només el que l’amfitrió necessita. Primer loopback i les respostes, després el camí administratiu, després l’oient del túnel, després la política de reenviament per als clients:

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 MASQUERADE

Els noms d’interfície, el port i el pool són marcadors de posició; llegeix-los del servidor en lloc de copiar-los. Desar el resultat importa tant com escriure’l, perquè un conjunt de regles que viu només a la memòria desapareix al proper reinici i reobre l’amfitrió sense fer soroll. Fes-lo persistent amb el mecanisme de la distribució i guarda’n una còpia fora de la màquina per al dia que la màquina no arrenqui.

Tancar l’últim port sense perdre l’amfitrió

Hi ha un parany al disseny. Si SSH només existeix a través del túnel, un servei de VPN fallit s’emporta SSH amb ell, i l’única manera de tornar pot ser una consola que no has obert mai. Abans de tancar l’últim port públic, confirma que aquella consola existeix i que realment la pots fer servir, o mantén un camí administratiu estret que no depengui del túnel: SSH des d’una adreça fixa, només claus, autenticació per contrasenya desactivada.

Aplica el canvi des d’una sessió ja establerta, no a través de la connexió que estàs a punt de filtrar. Programa un retorn enrere perquè un error caduqui en lloc de fer-se permanent, per exemple una tasca systemd-run --on-active=10min que restaura el conjunt de regles anterior, i mantén una segona sessió SSH oberta mentre proves la primera. Després verifica que la tasca de retorn s’executa de veritat, perquè una recuperació no provada és el mateix que cap recuperació.

Verifica el camí, no l’script

Llegeix les regles carregades, no el fitxer que se suposava que les havia de carregar. Des d’un amfitrió extern autoritzat, confirma que només responen els ports previstos; des de dins del túnel, confirma que els serveis que volies publicar són abastables. Una política de denegació per defecte que també bloqueja el trànsit del túnel sembla idèntica a un tancament que funciona fins que algú intenta fer-lo servir.

iptables -S
iptables -t nat -S
ss -lntup
ip -4 addr show

Anota el port permès, el pool de clients, la interfície del túnel, l’origen administratiu i el procediment de consola al costat de la configuració. El proper canvi al pool o al nom de la interfície s’ha de correspondre tant al filtre com a la regla NAT, o l’amfitrió torna a un estat mig obert sense que ningú se n’adoni.

Un hàbit val més que el conjunt de regles: després de cada canvi, demostra el camí de reenviament amb una petició d’un client i el camí de recuperació amb una segona sessió. Un tancament que no has fet servir és una hipòtesi.

Articles relacionats