Encadear dous clientes OpenVPN nun só host Linux con fwmark
Ambos os clientes queren a ruta por defecto. Fixa o servidor interior cunha ruta de host, evita que o segundo cliente reescriba as táboas e despois dirixe os fluxos con fwmark.
Apilar un segundo cliente OpenVPN nun só host Linux falla nun de dous puntos. Ou o cliente interior non pode acadar o seu propio servidor porque o túnel exterior capturou ese transporte, ou o segundo cliente reescribe a táboa de rutas e o primeiro túnel deixa de funcionar. Ambos os problemas están no encamiñamento, non no cifrado, e ambos se resolven antes de que o novo túnel transporte tráfico de aplicacións. Os enderezos aquí son ilustrativos: tun0 é o túnel exterior, 203.0.113.9 é o servidor interior e TCP 9999 é o fluxo que debe usar a ruta interior.
Dous modos de fallo, unha táboa de rutas
Un cliente interior abre un socket UDP cara ao seu servidor, e ese socket segue a táboa de rutas actual coma calquera outro. Se o túnel exterior xa posúe a ruta por defecto, os paquetes do handshake entran no túnel exterior. Iso só funciona cando o servidor exterior pode acadar o servidor interior e o outro lado acepta transportar o fluxo; doutro xeito o handshake detense e o cliente volve tentar.
O segundo fallo vén do push do servidor. O push habitual é redirect-gateway def1, que instala 0.0.0.0/1 e 128.0.0.0/1 en vez de substituír a ruta por defecto. Dous clientes que instalan cada un o seu propio par /1 chocan por iso, e o par máis novo gaña para case todos os destinos. Busca eses dous prefixos na táboa cando un túnel morre despois de conectarse o segundo, porque pode que a propia ruta por defecto nunca cambiase.
Marca o fluxo e dálle unha táboa
Dirixe o tráfico seleccionado marcándoo na táboa mangle e facendo coincidir a marca nunha regra de política. A regra apunta a unha táboa dedicada cuxa ruta por defecto é o dispositivo interior, de modo que só os paquetes marcados toman a ruta interior.
iptables -t mangle -A PREROUTING -p tcp -m multiport --dport 9999 -j MARK --set-mark 0x9999
ip rule add fwmark 0x9999 table 200 pref 1000
ip route add default dev tun1 table 200A maioría dos fallos neste conxunto de regras veñen de dous erros. O valor de marca que fixa o firewall e o valor que coincide coa regra deben ser idénticos, porque unha discrepancia non produce erro nin efecto. E PREROUTING só ve paquetes que chegan de fóra, así que unha conexión iniciada neste host precisa unha regra OUTPUT coa mesma coincidencia antes de ser marcada.
Quítalle a propiedade das rutas ao segundo cliente
Dúas opcións impiden que o segundo cliente edite a táboa, e actúan en puntos distintos. route-nopull ignora as opcións de ruta enviadas, así que non se instala nada. route-noexec acepta as opcións enviadas na contorna do cliente pero deixa o cambio da táboa a un hook, que é o que queres cando necesitas ver o que ofreceu o servidor.
O hook execútase cos valores enviados na súa contorna, e só debería engadir as entradas que aprobaches. Faino idempotente: baleira a táboa que posúe antes de reconstruíla, e non deas por feito que a execución anterior deixou un estado limpo. Unha reconexión invoca o hook de novo, e un hook que engade sen limpar acumula rutas duplicadas.
Escolle un propietario e déixao por escrito. Un perfil que fixa ambas as opcións, ou un hook que compite cun script manual, produce unha táboa que ninguén pode explicar despois.
Fixa os enderezos dos dous servidores
O servidor interior necesita unha ruta de host a través do dispositivo exterior antes de que se conecte o cliente interior. Esa entrada é a que mantén o transporte interior dentro do túnel exterior en vez de deixalo seguir a ruta por defecto.
ip route add 203.0.113.9/32 dev tun0
ip route get 203.0.113.9Engade tamén unha ruta de host coincidente para o servidor exterior na táboa principal, ou unha reconexión pode encamiñar o transporte do propio cliente exterior cara ao seu propio túnel. A orde non é opcional: engade estas entradas despois de que exista a interface correspondente, é dicir, un hook ou un script que se execute tras a conexión. Unha ruta que apunta a un dispositivo caído elimínase ou ignórase, así que unha entrada escrita no arranque non sobrevive á secuencia que supuxeches.
Comproba a busca en lugar de ler toda a táboa. A saída da busca de ruta nomea o dispositivo e o enderezo de orixe que usará o kernel, que é exactamente o que recibe o cliente cando abre o seu socket.
Proba a cadea e fai visible o fallo
Captura na interface exterior mentres o cliente interior se conecta. O handshake interior debería aparecer como carga cifrada dentro do túnel exterior; se aparece como UDP simple cara a 203.0.113.9, falta a ruta de host e a cadea nunca se construíu.
Unha cadea que volve silenciosamente ao uplink físico é o peor resultado, porque o estado da interface non anuncia nada e o tráfico interior sae desde o enderezo de orixe incorrecto. Se o segundo cliente pode reconectar directamente cando cae o túnel exterior, desactiva esa ruta ou lígala á interface exterior para que o fallo sexa visible.
Remata con dous fluxos e un volcado de regras: unha conexión marcada e outra sen marcar deberían tomar camiños distintos, e ip rule show debería listar a preferencia que pretendías. Se ambos os fluxos toman o mesmo camiño, a marca non se está aplicando onde pensas.