Mucho se está hablando últimamente de VPN anónimas, y en este post no pretendo descubrir las américas a nadie, pero aún así espero que le pueda ser de utilidad a alguien.
Para ponernos en situación, tengo un servidor contratado en un proveedor extranjero que me ofrece varios servicios, entre ellos una VPN (openVPN) que me permite navegar con una IP extranjera. Hasta aquí ningún misterio, para redirigir todo el tráfico basta con añadir las siguientes opciones a la configuración del servicio:
ifconfig-push IPCliente 255.255.255.0 push "dhcp-option DOMAIN ejemplo" push "dhcp-option DNS DNS1" push "route IPRedInterna 255.255.255.0" push "redirect-gateway def1”
Y ejecutar los siguientes comandos:
echo "1" > /proc/sys/net/ipv4/ip_forward iptables -t nat -A POSTROUTING -s IPVPNInterna/24 -o enp1s0 -j MASQUERADE
Sin embargo, como hago uso de cierto tipo de servicios que no están permitidos por mi proveedor, me he visto obligado a recurrir a servicios de VPN anónima (“Internet Private Access” en este caso). Lo cual también permite que mis saltos realicen un segundo salto y que viajen cifrados a dos países distintos antes de salir into the wild, además de burlar el límite de número de distintos dispositivos conectados a la vez (3 en este caso) permitidos por Internet Provider Access.
Entrando en harina, si alguien conecta con la VPN de InternetPrivateAccess con la configuración que ofrecen por defecto de manera remota, lo primero que le va a pasar es que perderá el acceso total a su servidor, ya que se modifican las rutas y los paquetes viajan de vuelta por una salida diferente. Para evitar este comportamiento, antes de conectar nada, vamos a crear la tabla de rutas. En el fichero /etc/iproute2/rt_tables , pondremos:
1 services
Y crearemos un script que se ejecute al arranque del sistema:
#!/bin/bash ip route add RedServidor/24 dev enp1s0 src IPPublicaServidor table services ip route add default via GatewayServidor dev enp1s0 table services ip rule add from IPPublicaServidor/32 table services ip rule add to IPPublicaServidor/32 table services ip rule add fwmark 1 table services ip route flush cache
De este modo, todas las conexiones que lleguen a la IP pública del servidor no pasarán por la VPN de Internet Provider Access, lo que nos permitirá seguir ofreciendo servicios (siempre y cuando funcionen a través de TCP).
Para redirigir el tráfico desde una VPN hasta la otra, bastará con ejecutar:
iptables -t nat -A POSTROUTING -s IPVPNInterna/24 -o tun1 -j MASQUERADE # Sólo si antes hemos añadido la ruta anterior: iptables -t nat -D POSTROUTING -s IPVPNInterna/24 -o enp1s0 -j MASQUERADE
Como bonus, decir que es posible abrir puertos en la VPN de Internet Private Access con un software que han desarrollado ellos, pero que por desgracia no tiene soporte para sistemas GNU/Linux. No obstante, se puede realizar un pequeño apaño:
$ cat /home/USUARIO/.pia_client ID= #Resultado de ejecutar head -n 100 /dev/urandom | md5sum | tr -d " -" PORT= #Puerto que nos abre la API de Internet Private Access IP="IP” # IP asignada por Internet Private Access
El siguiente script se debe añadir en el crontab (con ejecutarse cada 30 minutos, bastaría):
#!/bin/bash CONFIG=/home/USUARIO/.pia_client . $CONFIG function getIP { NEWIP="" while true; do NEWIP=$(ip addr show dev tun1 | grep inet | awk '{print $2}') if [ "$NEWIP" != "" ]; then break; fi sleep 10 done echo $NEWIP } function closePort { iptables -D INPUT -i tun1 -p tcp -m tcp --dport $PORT -j ACCEPT iptables -D INPUT -i tun1 -p udp -m udp --dport $PORT -j ACCEPT } function openPort { iptables -A INPUT -i tun1 -p tcp -m tcp --dport $NEWPORT -j ACCEPT iptables -A INPUT -i tun1 -p udp -m udp --dport $NEWPORT -j ACCEPT } function getPort { NEWPORT=$(sudo -u USUARIO -- curl -d "user=USUARIOIPV&pass=PASSWORDIPV&client_id=$ID&local_ip=$NEWIP" https://www.privateinternetaccess.com/vpninfo/port_forward_assignment 2>/dev/null); NEWPORT=$(echo $NEWPORT | awk -F'[{:}]' '{print $3}') echo $NEWPORT } function replaceConfig { sed -i.bak "s/^PORT=.*$/PORT=$NEWPORT/" $CONFIG || exit sed -i.bak "s/^IP=.*$/IP=\"$NEWIP\"/" $CONFIG || exit #Acciones que queremos hacer tras abrir un puerto } NEWIP=$(getIP) NEWPORT=$(getPort) if [ "$NEWIP" != "$IP" -o "$NEWPORT" != "$PORT" ]; then closePort openPort replaceConfig fi
De este modo, cada 30 minutos se verificará que la IP de la VPN y el puerto que nos natea la API son el mismo, y en caso de que cambien se cerrará el puerto viejo y se abrirá el nuevo. No hay que olvidarse de reiniciar aquellas aplicaciones que dependan de los puertos nateados.
Interesante entrada, Jose.
Saludos