Microordenadores - Desarrollos modernos para sistemas retro

Road warrior VPN con OpenSSH
20 de Octubre de 2015

En computación el término Road warrior se refiere a alguien que viaja y hace uso intenso de su ordenador desde localizaciones distintas e inseguras como cibercafés u hoteles. En este tutorial (algo antiguo) se explica como configurar un gateway con OpenSSH y la interfaz tun.

Este tutorial es antiguo y es posible que no esté del todo actualizado, de todas formas publiqué otro tutorial para configurar un VPN Gateway con OpenIKED que es una solución mucho mejor.

Objetivos

Configurar un VPN seguro y automatizado de forma que todo nuestro tráfico salga a internet a través de un servidor de confianza mediante un túnel cifrado entre cliente y servidor.

Esta configuración la he probado en OpenBSD 5.7 y, aunque funciona, no la recomiendo directamente ni aseguro que sea correcta, ni para nada sustituye leer las páginas de manual y el FAQ de OpenBSD. Esto pretende ser tan sólo una ayuda y no reemplaza la lectura de la documentación oficial.

Software VPN

Hay distintas opciones, cada cual con sus ventajas y sus desventajas:

  • IPSec.
  • OpenVPN.
  • OpenIKED.
  • OpenSSH.

En este artículo explicaré como hacer el túnel con OpenSSH por sencillez. Aunque hacer túneles con OpenVPN es más sencillo y versátil, es software de terceros lo que va contra mi principio de simplicidad, y me dan muchísima más confianza los desarrolladores de OpenBSD que son los autores de OpenSSH. Otra opción más versátil y moderna es OpenIKED.

OpenSSH está bien testeado y funciona bien para el propósito de este tutorial. Desde hace un tiempo incluye la opción -w para crear túnel, gracias a la cual podemos enrutar todo el tráfico de nuestro ordenador a través de un túnel cifrado. Necesitas acceso root por ssh al servidor, lo cual es un inconveniente; si quieres evitar esto puedes usar el programa sshuttle.

Lectura recomendada

La red

En este ejemplo tengo un servidor con una instalación limpia de OpenBSD y conexión a internet con IP x.x.x.x. El cliente será un ordenador cuya IP local es 192.168.1.150, que sale a internet a través de un router 192.168.1.1 con una ip externa y.y.y.y.

Configuración del servidor

Necesitas lo siguiente:

  • Activar la opción PermitTunnel point-to-point en /etc/ssh/sshd_config.
  • # sysctl net.inet.ip.forwarding=1. Esto permitirá la función de enrutado, para automatizar usamos el archivo /etc/sysctl.conf.
  • PermitRootLogin yes. Imprescindible para poder crear el túnel (recomiendo desactivar autenticación por password y usar llaves ssh).
  • Opcionalmente (por seguridad): PasswordAuthentication no.
  • Configurar NAT en el firewall.

Configuración del firewall

friends = "{ laptop }"

# Config
set limit { states 6144, frags 6144 }
set skip on { lo0, tun0 }
antispoof for { lo0, vio0, tun0 }
match in all scrub (no-df random-id max-mss 1440)
set block-policy drop
block all

# Blocked zones
table  persist file "/etc/pf-files/blocked_zones"
block quick from

# Road warrior NAT VPN
table  const { 10/8, 172.16/12, 192.168/16 }
pass out quick on vio0 inet from  to any nat-to (vio0)

# Block IPv6
block return out quick inet6 all
block in quick inet6 all

pass in quick on vio0 proto tcp from $friends to any port { https }

De esta forma sólo se permiten s conexiones al puerto 443 al host laptop con ip y.y.y.y (que debemos configurar en /etc/hosts). Es buena idea poner ssh a funcionar en el puerto 443 (https) porque en algunas redes filtran el puerto 22. No olvides reactivar el firewall (# pftcl -f /etc/pf.conf) y reiniciar sshd (/etc/rc.d/sshd restart) después de poner la configuración.

Configuración de tun0

Es muy sencillo, simplemente crea el archivo /etc/hostname.tun0 con este contenido:

10.0.0.1 10.0.0.2 netmask 0xfffffffc

Esto configura la interfaz de red tun0 con IP 10.0.0.1 punto a punto con la IP 10.0.0.2 (la del cliente) con máscara de red 255.255.255.0. Al crear este archivo la red se activa al iniciar el sistema o bien al hacer # ifconfig tun0 up.

Configuración del cliente

  1. Configurar la red con IP estática (no dhcp). La razón para no usar dhcp es que periódicamente sobreescribe el archivo /etc/resolv.conf y encuentro más sencillo hacerlo de esta forma.
  2. Generar un par de llaves OpenSSH (# ssh-keygen -b 2048 -t rsa). La pública la copiamos al archivo /root/.ssh/authorized_keys del servidor. De esta forma no nos pedirá la contraseña del servidor cada vez que inciemos el túnel. Es conveniente poner una contraseña local a la llave de todas formas.
  3. Configurar tun0 con IP 10.0.0.2.
  4. Enrutar a través de 10.0.0.1.
  5. Opcional: Configurar DNS Cache local.

Para configurar el túnel y activar el nuevo enrutado lo hacemos como anteriormente, aunque cambiando el orden de las IPs y agregando comandos para cambiar el enrutado. x.x.x.x es la IP de nuestro servidor. /etc/hostname.tun0:

10.0.0.2 10.0.0.1 netmask 0xfffffffc
!route add x.x.x.x 192.168.1.1
!route change default 10.0.0.1

DNS Cache local

Esto es conveniente configurarlo para resolver los nombres directmente desde el cliente gracias a unbound(8). Es muy sencillo y no hay que instalar ningún software de terceros:

sudo rcctl enable unbound
sudo rcctl start unbound

Y cambiamos el nameserver en /etc/resolv.conf a 127.0.0.1. Podemos comprobar que funciona simplemente haciendo $ dig @127.0.0.1 example.com

Automatización

Para probar que todo funciona semiautomáticamente (tienes que poner la contraseña de la llave SSH en caso de que la hayamos configurado) reinicia servidor y cliente, al arrancar te pedirá la contraseña de la llave y si todo va bien se habrá creado el túnel y enrutado el tráfico. Para comprobar haz un $ traceroute example.com y comprueba que la primera linea tenga 10.0.0.1 para que el tráfico pase a través de este túnel. Ahora falta que se inicie el túnel al arrancar el ordenador. Para ello ponemos esto en /etc/rc.local:

echo -n 'Starting OpenSSH VPN\n'
/usr/bin/ssh -f -p 443 -w 0:0 x.x.x.x true

Resolución de problemas

En caso de problemas, comprueba si desde ambos puntos (cliente y servidor) se puede hacer ping a 10.0.0.1 y 10.0.0.2. Puedes cambiar a la ruta por defecto haciendo simplemente # route change default 192.168.1.1. Si el ping funciona, lo que falla puede ser el firewall, en ese caso usa tcpdump(8) para ver el tráfico en la interfaz de red del servidor.


Contenido relacionado: