miércoles, 5 de diciembre de 2012

OpenVPN y tablas de enrutamiento

Hoy configuré mi máquina con un servidor OpenVPN y otra máquina a la que tengo acceso con un cliente. Pero no se hablaban.

El servidor me decía que
Dec  5 19:51:29 host ovpn-server[16743]: read UDPv4 [ECONNREFUSED]: Connection refused (code=111)

Pero la cosa es que no tenía ningún problema de NAT: los paquetes llegaban:
Dec  5 19:51:29 host ovpn-server[16743]: xx.xx.xx.xx:22122 TLS: Initial packet from [AF_INET]xx.xx.xx.xx:22122, sid=12345678 90abcdef

Por otro lado el cliente era un poco más explícito:
Dec  5 21:33:47 client ovpn-client[5128]: NOTE: OpenVPN 2.1 requires '--script-security 2' or higher to call user-defined scripts or executables
Dec  5 21:33:47 client ovpn-client[5128]: Re-using SSL/TLS context
Dec  5 21:33:47 client ovpn-client[5128]: UDPv4 link local: [undef]
Dec  5 21:33:47 client ovpn-client[5128]: UDPv4 link remote: [AF_INET]yy.yy.yy.yy:1194
Dec  5 21:34:47 client ovpn-client[5128]: TLS Error: TLS key negotiation failed to occur within 60 seconds (check your network connectivity)
Dec  5 21:34:47 client ovpn-client[5128]: TLS Error: TLS handshake failed
Dec  5 21:34:47 client ovpn-client[5128]: SIGUSR1[soft,tls-error] received, process restarting

Un caso difícil. Tuve que ponerme a hacer otras cosas durante un rato para entender el problema: El paquete inicial llega, pero la negociación TLS falla. Y no podía deberse a que los certificados estuvieran mal: acababa de revisarlos.

Luego recordé que mi sistema tiene dos direcciones IP distintas, ya que tengo dos conexiones a Internet en casa. De repente estuve seguro de que el problema estaba ahí.

Me senté y desactivé la tarjeta de red a la que llega la IP dinámica. Todo empezó a funcionar. Pero no detectaba la causa del problema. Súbitamente caí en la cuenta: OpenVPN utiliza UDP, y UDP es un protocolo sin estado. Es decir: OpenVPN no envía un paquete de respuesta al saludo TLS, como haría a través de TCP, sino que envía un paquete independiente conteniendo la respuesta al saludo TLS. Y esta diferencia es crucial.

Los paquetes de respuesta a las solicitudes normales a mi máquina salen siempre por la tarjeta de red a la que llega la IP estática, gracias a unas reglas de enrutamiento:
ip route add table 1 192.168.1.0/24 dev eth1  proto kernel  scope link  src 192.168.1.25 
ip route add table 1 default via 192.168.1.1 dev eth1
ip rule add from 192.168.1.25 lookup 1

Pero esas reglas no se aplicaban a los paquetes salientes de OpenVPN porque no son paquetes de respuesta: en UDP no existen los paquetes de respuesta.

Rápidamente la documentación oficial de OpenVPN me dio la solución:
#Dirección y máscara de red que utilizaremos
server 10.9.0.0 255.255.255.0
local 192.168.1.25

La orden local le dice al servidor OpenVPN que utilice la IP especificada.

Y listo. Todo funcionando. Ya tengo un túnel permanente para entrar a la máquina remota con IP dinámica.