Non esiste un interruttore per singolo dispositivo in una VPN su router; l'interruttore che cerchi è una scorciatoia che scrive regole di policy routing al posto tuo. Nel momento in cui un portatile, un intervallo di porte, un elenco di indirizzi o un segmento LAN deve usare il tunnel mentre tutto il resto resta sul WAN, stai costruendo una policy route e non abilitando una funzione. Il lavoro ha tre parti mobili, e ciascuna fallisce in modo diverso: una tabella marcata senza rotta sembra silenzio, un mark applicato nella chain sbagliata sembra che non sia successo nulla, e una regola NAT mancante sembra un tunnel che si connette e non trasporta niente. Altri due pezzi mancano perché non compaiono mai nella regola mangle, e sono DNS e IPv6.

Il mito: il tunnel è un'impostazione del client

Un client VPN lato router fa bene una cosa brutale: mette 0.0.0.0/0 nella tabella di routing principale e la punta sul tunnel. WireGuard lo ricava da AllowedIPs, OpenVPN da un redirect-gateway inviato dal server, ed entrambi cambiano il percorso di ogni host dietro il router. Restringere AllowedIPs o aggiungere route-nopull cambia ciò che il client installa. Non cambia a chi si applica l'installazione, perché il client non vede mai i dispositivi. Vede solo pacchetti.

La selezione per sorgente o destinazione è una decisione di routing, quindi appartiene al livello di policy del router: una regola mangle più una seconda tabella su RouterOS, un MARK più una ip rule su OpenWrt o DD-WRT, oppure una regola firewall il cui gateway è il tunnel su pfSense. La ricetta del client WireGuard di Netgate è quella da leggere prima di tirare a indovinare, perché su quella piattaforma il gateway della regola, l'assegnazione dell'interfaccia e la voce NAT in uscita devono concordare prima che un solo client usi il tunnel.

La seconda metà del mito è il secondo router. Comprare un'altra scatola, o spostare il dispositivo su un SSID ospite, spesso funziona, e la ragione non è l'hardware: mette il dispositivo su una sottorete propria, che ti dà il selettore di sorgente che il firmware già capisce. Se puoi definire quel segmento sul router che possiedi, la scatola in più risolve un problema che non avevi.

Primo pezzo: un tunnel che non è la rotta predefinita

Su RouterOS, aggiungi il client senza rotta predefinita e dai al tunnel una tabella propria. La prima rotta è il default marcato; la seconda è la metà del guasto.

/ip route add dst-address=0.0.0.0/0 gateway=VPN_GATEWAY_IP routing-mark=vpn distance=1
/ip route add dst-address=0.0.0.0/0 type=unreachable routing-mark=vpn distance=2

La rotta unreachable è il motivo per cui una tabella marcata batte un elenco di eccezioni nella tabella principale. Quando il tunnel cade, i pacchetti marcati ricevono subito un unreachable invece di ricadere in silenzio sul WAN, così il guasto appare nel messaggio di errore dell'applicazione e non in una pagina di geolocalizzazione che controlli un'ora dopo.

RouterOS 7 separa ciò che la 6.x teneva insieme: dichiari la tabella con /routing table add name=vpn fib, poi la referenzi per nome sulla rotta e nella regola mangle. Uno snippet 6.x che scrive routing-mark senza definire la tabella si carica senza errori e non corrisponde a nulla. L'altro classico sono due metà 0.0.0.0/1, o due default alla stessa distanza in una tabella: il kernel ne sceglie uno, e il comportamento può cambiare dopo un riavvio.

Secondo pezzo: marca prima della ricerca della rotta

Il selettore decide quali pacchetti entrano in quella tabella. RouterOS di solito parte da un elenco di indirizzi per la policy di destinazione, o da un indirizzo sorgente per la policy per dispositivo:

/ip firewall mangle add chain=prerouting src-address=192.168.88.50 action=mark-routing new-routing-mark=vpn
/ip firewall mangle add chain=prerouting dst-address-list=via-vpn action=mark-routing new-routing-mark=vpn
/ip firewall address-list add list=via-vpn address=203.0.113.10

Il firmware Linux fa lo stesso con un mark netfilter e una regola che instrada i pacchetti marcati in una tabella che hai popolato:

iptables -t mangle -A PREROUTING -p tcp --dport 27000:27050 -j MARK --set-mark 0x200
ip route add default dev tun0 table 100
ip rule add fwmark 0x200 table 100

La chain non è una scelta di stile. Quando un pacchetto raggiunge FORWARD la ricerca della rotta è già avvenuta, quindi un MARK o un DROP lì può solo riscrivere o scartare. Il mark deve finire in PREROUTING per il traffico inoltrato e in OUTPUT per il traffico che il router origina, dove vivono DNS, NTP e i controlli degli aggiornamenti del router. Quel percorso di output è la ragione abituale per cui un'installazione completamente in tunnel risponde ancora dal resolver dell'ISP in un test di leak.

La policy per dispositivo richiede una corrispondenza che non scivoli. Prenota l'indirizzo in DHCP, oppure abbina un'interfaccia per un segmento dedicato; un indirizzo che poi passa a un altro dispositivo applica silenziosamente il tunnel al client sbagliato. Un bridge per SSID con sottorete propria è la versione più duratura della stessa idea, e dà anche alle regole IPv6 un posto dove stare.

Terzo pezzo: NAT, DNS e l'eccezione LAN

Il traffico che esce dal tunnel ha bisogno di un indirizzo sorgente a cui il lato remoto risponderà. Limita la traduzione all'interfaccia del tunnel: out-interface=VPN_NAME su RouterOS, -o tun0 su Linux, una voce NAT in uscita corrispondente su pfSense. Una regola masquerade senza quello scoping riscrive traffico che volevi lasciare com'era, e il sintomo è il dispositivo non in tunnel che perde il suo indirizzo pubblico.

L'eccezione LAN genera più thread di supporto del tunnel stesso. Se la tabella marcata contiene solo una rotta predefinita, una destinazione stampante o NAS dal dispositivo selezionato corrisponde a quel default e sparisce nel tunnel. Aggiungi la rotta LAN alla stessa tabella, oppure escludi la sottorete locale nel selettore; funzionano entrambe, e l'esclusione è più facile da tenere corretta quando aggiungi VLAN in seguito.

Il DNS prende un percorso separato. Le query che il router inoltra sono originate dal router e seguono OUTPUT, non il mark inoltrato, quindi un portatile completamente in tunnel può ancora risolvere tramite l'ISP. Punta i client su un resolver raggiungibile attraverso il tunnel, oppure marca il traffico porta 53 del router stesso, poi controlla l'indirizzo risolto invece di dare per scontato che la risposta abbia viaggiato con la richiesta web.

Quando la regola corrisponde ma l'app usa ancora il WAN

Gli elenchi di destinazioni invecchiano male. Un nome si risolve in un indirizzo che non è nell'elenco, quindi la richiesta prende il WAN mentre ogni test che hai fatto sull'indirizzo elencato funzionava. Aggiorna l'elenco dallo stesso resolver che usa il client, e preferisci un selettore basato sulla sorgente quando vuoi davvero tutto il traffico da un dispositivo.

IPv6 è il bypass silenzioso. Il dispositivo ha una seconda famiglia di indirizzi con la propria rotta predefinita e il proprio set di regole, e abbinare solo l'indirizzo IPv4 è metà di una policy. Applica lo stesso selettore a ip6tables o all'equivalente nftables, oppure disabilita IPv6 su quel segmento di proposito invece che per caso.

Anche le connessioni stabilite contano. Una voce conntrack creata prima della modifica continua a seguire il vecchio percorso finché non scade, quindi un browser rimasto aperto durante la modifica sembra esattamente una regola che non è mai stata applicata. Apri una connessione nuova, o svuota lo stato, prima di giudicare la policy.

Verifica con due dispositivi e un riavvio

Prova il dispositivo che dovrebbe stare in tunnel e quello che non dovrebbe, e confronta il secondo hop invece di un numero di velocità. Un traceroute da ciascuno mostra il gateway del tunnel o quello dell'ISP al secondo hop; se entrambi sembrano uguali, il mark o la tabella non stanno facendo ciò che dice la regola. Usa connessioni nuove per il test.

Poi riavvia. L'ordine di avvio è dove una policy funzionante diventa rotta, perché il client deve essere attivo prima che la rotta unreachable venga installata, e uno snapshot salvato che ripristina il vecchio set di regole sovrascriverà la tua tabella. Controlla che ogni regola sia nella configurazione salvata e che il default marcato esista dopo il boot, non solo dopo che l'hai digitato.

Se qualcosa fallisce, togli prima il mark e guarda se il traffico normale torna, poi togli la tabella. Quell'ordine ti dice se stai inseguendo un problema di routing o uno di firewall, e lascia alla famiglia una stampante funzionante mentre finisci il lavoro.

Articoli correlati