O cliente VPN conéctase, o navegador funciona, e o único comando que de verdade che importa segue saíndo pola túa conexión de casa. Ou ocorre o contrario: o túnel fíxase coa ruta por defecto e o servidor de ficheiros local desaparece do escritorio. Atopei isto cun axente de compilación que tiña que chegar a un espello interno de artefactos mentres o resto do host ficaba na LAN da oficina, e o cliente ofrecía exactamente dúas opcións: todo o tráfico ou nada. A petición en ambos os sentidos é a mesma, este programa e non toda a máquina, e a maioría dos clientes non teñen casilla para iso, porque a táboa de rutas nunca soubo que é un programa.

Por que a táboa de rutas non pode ver o teu programa

Cando un proceso envía un paquete, a pila busca o enderezo de destino na táboa de rutas. Nin o nome do executábel nin o porto entran nesa busca. Os nomes de dominio fallan polo mesmo motivo: un túnel leva o tráfico a un enderezo, e para cando un nome se resolve nun, o encamiñamento é a única panca que lle queda ao núcleo. Por iso «VPN só para este sitio» acaba significando un proxy, e «VPN só para este programa» acaba significando un dun pequeno conxunto de mecanismos.

MechanismWhat selectsCoversOn tunnel drop
Socket bindsource addressa client you controlconnections fail
UID rule (Linux)owning userevery process of one accountconnections fail
Firewall profile (Windows)adapter profileone programfails closed
Network namespacenamespace membershipeverything started insideconnections fail
SOCKS hopapp proxy settingone app or one browser profileconnections fail

Ningunha destas é unha ruta por proceso. Cada unha traslada a decisión a unha capa que pode ver o programa, o usuario ou a propia configuración da aplicación.

Un só destino segue sendo unha ruta, non unha regra de programa. En macOS a receita habitual é desmarcar «Enviar todo o tráfico por VPN» e engadir unha ruta de host: sudo route add -host internal-tuner.example -interface ppp0, que se retira outra vez con sudo route delete -host internal-tuner.example -interface ppp0. Lea primeiro o nome da interface en ifconfig, porque ppp0 é só un exemplo. Os comodíns non funcionan nunha ruta de host, así que un servizo que fala con varios nomes precisa unha entrada por nome, e a regra cobre todos os procesos da máquina, non o que tiña en mente.

Vincule o socket ao enderezo do túnel

Cando controlas o cliente, vincular é o selector máis barato. Un socket vinculado ao enderezo local do túnel sae por esa interface mentres exista alí unha ruta cara ao destino, e todo o demais da máquina conserva o seu camiño normal. A sutileza é que a vinculación escolle o enderezo de orixe mentres a táboa de rutas segue escollendo a saída. A vinculación por si soa non move o tráfico que non ten ruta cara ao túnel, e ese é o erro detrás da maioría dos informes de «vincul e segue saíndo polo lado equivocado».

import socket
s = socket.socket()
s.bind(("10.8.0.2", 0))
s.connect(("build.internal.example", 443))

As ferramentas de máis alto nivel expoñen a mesma idea: curl --interface 10.8.0.2, CURLOPT_INTERFACE en PHP e o argumento source_address nos clientes HTTP de Python. O enderezo ten que pertencer ao túnel, e unha errata aquí falla como un erro de conexión corrente, non como unha queixa de encamiñamento. Vincular a un nome de dispositivo en lugar de a un enderezo é un privilexio de Linux e non se traslada a Windows nin a macOS, por iso os scripts portátiles pasan o enderezo.

Linux: faga coincidir o propietario, non o nome do programa

O núcleo pode facer coincidir o usuario propietario dun socket, así que unha conta dedicada convértese no selector. Pon o túnel na súa propia táboa de rutas e envía alí só o tráfico desa conta:

ip rule add uidrange 1001-1001 lookup 100
ip route add default dev tun0 table 100

Isto só funciona se o túnel non é xa a ruta por defecto. Inicie o cliente con --route-nopull, ou filtre o redireccionamento empurrado con --pull-filter ignore "redirect-gateway" en OpenVPN 2.4 e posteriores, e logo engada vostede mesmo a entrada na táboa. Se non, existen as dúas rutas por defecto e gaña a de menor prioridade. A versión deliberada diso é apuntar a ruta por defecto á porta de enlace do túnel, ou facelo desde un script de desconexión: mantén o tráfico fóra de internet cando o túnel cae, pero iso é un interruptor de seguridade, non un selector, e queda ata que alguén o retire.

A versión máis forte é un espazo de nomes de rede. Créao, execute o cliente dentro e arrinque a aplicación con ip netns exec. Nada fóra do espazo de nomes ve a interface do túnel, así que a aplicación non pode volver por accidente á ruta do host. O custo é real: o espazo de nomes necesita un par veth para chegar á rede física e o seu propio ficheiro de resolución, porque o espazo de nomes de montaxe non comparte os axustes de resolución do host.

Dous modos de fallo explican a maioría das fugas. A resolución de nomes segue a ocorrer no resolutor do host, así que a consulta sae fóra do túnel incluso cando a conexión TCP entra dentro. E IPv6 necesita a súa propia ip -6 rule, porque unha regra v4 non a cobre.

Windows e macOS: acouta a devasa ou cede un proxy

Windows tampouco ten selector de ruta por aplicación, pero as súas regras de devasa poden acoutarse a un perfil, e un adaptador VPN pode clasificarse como «público» mentres a LAN de casa segue «privada». Cree regras de bloqueo de saída para o programa nos perfís «privado» e «dominio», deixe «público» aberto, e a aplicación só poderá chegar á rede polo túnel. Fixe primeiro a categoría de rede da conexión e logo confirme que a regra coincidiu no panel de supervisión da devasa. É un bloqueo, non unha ruta: falla pechado cando o túnel cae, e non pode deter unha aplicación que ignora a devasa.

macOS segue a mesma lóxica con outras ferramentas. Un oínte SOCKS alcanzado por SSH é a opción menos invasiva, porque ssh -D 1080 user@host crea un porto local e só as aplicacións configuradas para usalo toman ese camiño. Unha regra pf pode bloquear un programa por usuario ou grupo, pero segue sen poder escoller o túnel só para ese programa. Tunnelblick non pode filtrar por dominio de ningún xeito, porque as rutas traballan con enderezos; os usuarios de OpenConnect recorren a vpn-slice cando o servidor empurra unha lista de prefixos demasiado ampla.

Dúas solucións alternativas cobren o que as ferramentas da plataforma pasan por alto. As extensións de navegador que cambian o proxy por dominio son a resposta práctica para «só este sitio», porque actúan na capa de aplicación, onde os nomes aínda existen; cobren un navegador e nada máis. A solución tosca é executar o cliente do provedor dentro dunha máquina virtual para que o convidado sexa dono do cambio de ruta mentres o anfitrión conserva o seu camiño, a costa de dúas pilas de rede que manter.

Un salto SOCKS para ferramentas sen opción de vinculación

A maioría das aplicacións pódense apuntar a un proxy HTTP ou SOCKS mesmo cando non saben nada de interfaces. Un cliente SSH fornece un sen ningún cambio no lado do servidor:

ssh -N -D 127.0.0.1:9999 [email protected]

Todo o configurado para usar ese porto sae no bastión mentres o resto do escritorio conserva a súa conexión normal. Unha instancia local de 3proxy vinculada ao enderezo do túnel fai o mesmo para un porto sen SSH, e stunnel cobre un único porto envolto en TLS. Os límites son prácticos: un proxy só transporta protocolos que saben usalo, UDP necesita unha asociación UDP de SOCKS5 que o axuste «SOCKS5» de moitos clientes non activa, e o DNS debe resolvelo o proxy (socks5h en curl) ou o nome fíltrase ao resolutor local.

Manteña o oínte en loopback salvo que outra máquina o necesite.

Verifique o camiño cunha captura, non cunha mensaxe de estado

As ventás de estado da aplicación describen o axuste, non o paquete. Capture nas dúas interfaces e compare:

tcpdump -i any -n port 443
ss -tnp | grep 443

Se a conexión aparece na interface física sen unha entrada correspondente no túnel, o selector non está en efecto, diga o que diga o cliente. Comprobe IPv6 e o resolutor por separado, e busque un segundo camiño como un proceso auxiliar ou un proxy de sistema herdado.

Logo escolla a fronteira que encaixe co requisito: un proxy abonda para un sitio, unha regra UID abonda para unha conta, un perfil de devasa abonda cando a conexión debe fallar pechada, e un espazo de nomes é a única opción que esconde o túnel de todo o que está fóra.

Artigos relacionados