Perdón si el título es malo, pero quiero mostrarles una manera elegante de poder enrutar las conexiones de cualquier dispositivo para que pueda conectarse a Internet como si estuviera en otro lugar, ya sea a Internet o una VPN.
Desktop
Mi problema original era poder utilizar Netflix como si estuviera en Estados Unidos, ya que el contenido es distinto. En OSX la solución es bastante simple: basta con conectarse por SSH a un servidor en Estados Unidos abriendo un proxy SOCKS (parámetro -Dpuerto) y luego configurar el navegador para que utilice ese proxy.
Por ejemplo, supongamos que tenemos un servidor llamado servidor (¡qué original!). Podemos ejecutar la siguiente línea en el terminal:
ssh usuario@servidor -D1080
Este comando se conectará a servidor y abrirá un puerto en el ambiente local (1080) el cual funciona como proxy SOCKS. Luego, en Firefox u otro navegador, podemos configurar el proxy SOCKS localhost puerto 1080.
Esta solución me funcionó bastante bien hasta que quise utilizar el dispositivo Apple TV. En este caso, como su conexión era por WiFi, y no tiene opción de configurar una VPN, necesité encontrar una solución más rebuscada.
Dispositivos
En el caso de dispositivos como Apple TV o similares, la única opción es enrutar el tráfico transparentemente, es decir, que el dispositivo no se de cuenta de que se está desviando el tráfico. Esto podría ser simple si su router estuviera conectado a una VPN, ya que podría enrutar ciertas conexiones (o todas) a través de esta VPN, sin embargo, el escenario cambia al usar SSH.
Tenía dos desafíos:
-
Conectar el dispositivo a Internet a través de un PC
-
Enrutar el tráfico a través de la conexión SSH
1.- Conectar el dispositivo a Internet a través de un PC
Supongamos que tenemos este esquema original:

Para poder controlar el tráfico entre el dispositivo e Internet, podemos intervenir el router o agregar un nuevo eslabón en la cadena. Opté por lo segundo y el diagrama queda así:

Para esto, en mi caso, utilicé un cable ethernet entre el Dispositivo y el PC. Para la conexión entre el PC y el Router ISP, utilicé Wi-Fi. Este escenario es muy común. Para permitir que el PC sea capaz de enrutar el tráfico, se utiliza NAT (network address translation). En Linux, se utiliza iptables para esta tarea.
NAT funciona modificando cada paquete. Cuando un paquete de datos va desde el Dispositivo a Internet, se modifica la dirección de origen reemplazándola por la dirección del PC. Cuando el paquete llega al PC desde Internet, se cambia la dirección de destino para que apunte al Dispositivo y luego se reenvía al dispositivo. De esta forma, el Router ISP sólo sabe que está recibiendo y enviando paquetes desde y hacia el PC. Todo el trabajo de conversión se lo lloeva el PC, en este caso.
Supongamos que el PC tiene las siguientes interfaces de red:
-
eth0 hacia el Router ISP
-
eth1 hacia el Dispositivo
Para configurar NAT, debemos ejecutar los siguientes comandos (como root):
# Habilitar el reenvío de paquetes en el sistema
echo 1 > /proc/sys/net/ipv4/ip_forward
# Enmascarar el tráfico hacia Internet
iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
# Permitir que los paquetes que vienen desde Internet y que pertenecen a una conexión ya establecida,
# puedan pasar hacia el dispositivo
iptables -A FORWARD -i eth0 -o eth1 -m state --state RELATED,ESTABLISHED -j ACCEPT
# Permitir el tráfico desde el Dispositivo hacia Internet
iptables -A FORWARD -i eth1 -o eth0 -j ACCEPT
Una vez hecho esto, sólo basta configurar manualmente las interfaces tanto en el PC como en el dispositivo. También es posible habilitar DHCP en la interfaz eth1, lo que evitaría tener que configurar la dirección IP manualmente en el Dispositivo. Pueden Googlearlo :)
Un punto importante a tener claro es que las direcciones de red en eth0 y eth1 deben ser distintas. Por ejemplo, si el router ISP nos entrega una dirección IP de la red 192.168.0.0/24 (la máscara 24 significa que la red es 192.168.0.X), la dirección en eth1 debe pertenecer a otra red (por ejemplo, 192.168.1.0/24).
En este punto, ya deberíamos poder utilizar el PC como puente para el Dispositivo, aunque todavía falta enrutar el tráfico hacia el servidor SSH.
2.- Enrutar el tráfico a través de la conexión SSH
Si bien, muchas veces he configurado un puente con NAT, el enrutamiento hacia un servidor SSH era lo novedoso para mí :) Para esto, la forma más simple que encontré es utilizando la conexión SOCKS que provee SSH; la misma que utilicé en el ambiente de escritorio, pero esta vez sin configurar el proxy en el Dispositivo, sino en el puente.
Para lograrlo, podemos crear una tercera interfaz de red en el PC, pero esta vez, esta interfaz es virtual y envía todo el tráfico hacia un servidor SOCKS. Este proceso es muy simple utilizando tun2socks, disponible
aquí.
tun2socks se encarga de subir una interfaz virtual y enrutar todo el tráfico que recibe a través de un servidor SOCKS. Para poder utilizarlo, antes debemos tener nuestra conexión SSH abierta, de la misma forma que lo hice en el ambiente de escritorio:
ssh usuario@servidor -D1080
Ahora, podemos ejecutar tun2socks:
./badvpn-tun2socks --tundev tun0 \
--netif-ipaddr 192.168.100.2 \
--netif-netmask 255.255.255.0 \
--socks-server-addr 127.0.0.1:1080
Los parámetros utilizados aquí son:
-
--netif-ipaddr 192.168.100.2: Configura la dirección IP del gateway virtual que tendremos en la interfaz. Es decir, esta no es la dirección que tendrá nuestro PC en esta interfaz virtual, sino el gateway o router [también virtual] que deberemos utilizar en esa interfaz.
-
--netif-netmask 255.255.255.0: La máscara de la interfaz. Generalmente 255.255.255.0 (24 bits) está bien.
-
--socks-server-addr 127.0.0.1:1080: Dirección y puerto donde está corriendo el servidor SOCKS. Ya que utilizamos -D1080 en el comando SSH, ése es el puerto que definimos aquí.
Una vez ejecutado este comando, ya se habrá creado una nueva Interfaz, sin embargo, aún tenemos que configurar la interfaz en el PC y las rutas para que el tráfico a ciertas -o todas- las direcciones vaya a través de esta interfaz virtual.
Para configurar la interfaz en el PC local, debemos ejecutar:
ifconfig tun0 192.168.100.1 netmask 255.255.255.0
Pueden notar que la dirección local en la interfaz virtual (192.168.100.1) está en la misma red que la dirección del router virtual (192.168.100.2). Esto es imprescindible.
Éste debería ser el estado actual:

En este paso debemos tener mucho cuidado. Ya que esta interfaz virtual depende de nuestra conexión SSH, debemos asegurarnos de que el tráfico hacia el servidor SSH siga saliendo directamente por el Router ISP. También debemos tener claro que SOCKS sólo soporta conexiones TCP (y no UDP, ICMP o cualquier otro tipo). Esto previene que usemos la configuración actual para enrutar las consultas al DNS, ya que el protocolo DNS utiliza principalmente UDP. A fin de cuentas, necesitamos mantener tanto el tráfico al servidor SSH como al DNS a través del router ISP. Para esto, ejecutamos los siguientes comandos:
# Agregamos el servidor SSH (en este ejemplo 1.2.3.4)
# hacia 192.168.0.1 suponiendo que es la dirección del Router ISP.
# Utilizamos la métrica 5 para que tenga prioridad sobre otras reglas
route add 1.2.3.4 gw 192.168.0.1 metric 5
# Agregamos el servidor DNS (en este caso, un servidor de Google)
route add 8.8.8.8 gw 192.168.0.1 metric 5
En este momento, ya podemos eliminar la ruta por defecto actual, que utiliza el Router ISP, y cambiarla por una ruta hacia nuestro router virtual en la interfaz virtual tun0:
route del default
route add default gw 192.168.100.2 metric 6
Este comando toma todo el tráfico (excepto hacia nuestro servidor SSH, hacia el DNS o hacia redes locales) y los envía a través del router virtual. Para comprobar que el tráfico esté saliendo por la interfaz virtual, podemos visitar
http://www.whatismyip.com/. La dirección en pantalla debería ser la dirección del servidor SSH.
El último paso consiste en habilitar las reglas de iptables que permitan utilizar NAT, pero ahora hacia la interfaz virtual:
iptables -t nat -A POSTROUTING -o tun0 -j MASQUERADE
iptables -A FORWARD -i tun0 -o eth1 -m state --state RELATED,ESTABLISHED -j ACCEPT
iptables -A FORWARD -i eth1 -o tun0 -j ACCEPT
¡Ya está! Ya podemos utilizar el Dispositivo como si estuviéramos utilizando el servidor SSH :) Suficiente, me voy a ver una película. ¡Suerte!