Hacia rutas salvajes

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.

Comments

  1. Interesante entrada, Jose.

    Saludos