Voila un probleme sur lequel je m'étais penché il y a quelques mois (une douzaine?) de cela et que j'ai pu résoudre seulement récemment. Avec les 3-Strikes laws votées dans les différents pays[1], les services de VPN anonymes sont de plus a la mode. En particulier avec la sortie de Ipredator, service de VPN anonyme fourni par les créateurs et administrateur de ThePirateBay. Citons aussi UltraVPN et BlackVPN.

Comment ca marche ?

Le principe de ces services et de vous fournir un accès a un serveur OpenVPN ce qui vous permez d'avoir vos communication chiffrée de votre poste au serveur VPN et un anonymat garanti car ils[2] ne stockent pas de log ainsi la relation entre votre IP VPN et votre IP public ne peux-etre faite.

Cependant, lorsque vous faites passer tout votre trafic par un VPN, vous gagnez en latence et perdez en débit du haut de l'ajout d'un intermédiaire et du chiffrement des données. De plus vous vous trouvez avec une IP étrangere ce qui peut-etre genant dans certains cas.

Router seulement certaines applications

Ce que l'on souhaite, c'est pouvoir choisir quelles applications faire passer par le VPN (navigateur webs...) et quelles applications utilisent la connexion directe (ssh...). Pour cela on va utiliser une seconde table de routage, le module owner accompagnée de quelques regles iptables et les capacités de scripting d'openvpn.

La configuration

La box est une ubuntu, n'importe quelle distribution Linux fera l'affaire, il est possible de faire la même avec pf sur des systèmes *BSD (c'est meme plus facile) mais cela ne sera pas traité ici.

OpenVPN

Il s'agit d'une connexion a un serveur OpenVPN. On reprend le fichier de configuration par le prestataire en y ajoutant quelques lignes :

...
# On stock le user/password dans un fichier externe
# Login sur la première ligne, password sur la deuxième
auth-user-pass <nomvpn>_userpass
# On ne récupère pas les routes fournies
# Car on ne souhaite pas utiliser le VPN comme default gateway sur la main table de routage
route-nopull

# On autorise l'exécution de scripts perso
script-security 2
# On utilise des scripts a exécuter au démarrage et a l'arrêt de la connexion
up /usr/local/vpn/<nomvpn>-up
down /usr/local/vpn/<nomvpn>-down

Ne pas oublier de générer le fichier d'authentification, user et password sont fournis par le prestataire :

echo -e "<user>\n<password>" > /etc/openvpn/<nomvpn>_userpass

Routage

La c'est la grosse manipulation qui permet de configurer une table de routage spécifique a ce VPN et de faire passer le trafic d'un gid donné a travers le VPN.

Script de up

ce script sera exécuté par OpenVPN a l'établissement de la connexion avec le serveur distant. Les scripts sont appelés avec les arguments suivants par OpenVPN (voir le man) :

cmd tun_dev tun_mtu link_mtu ifconfig_local_ip ifconfig_remote_ip [ init | restart ]
#!/bin/bash

TUNDEV=$1
TUNIP=$4
# Ici on met le réseau du VPN, pour le connaitre veuillez vous connecter au VPN avec la 
# configuration fournie sans le "route-nopull" et faire un ifconfig sur l'interface tun créée
# Faites pareil pour la gateway avec un `route`
VPNNET="10.8.0.0/24" 
VPNGW="108.0.1"

EXTIF=eth0
VPNNAME=<nomvpn>
MARK=100 # spécifique a ce VPN, vous choisissez, mettez en un différent par vpn

# On commence par nettoyer au cas ou OpenVPN aurait violemment redémarré dans le passé
echo "- Flushing iptables"
iptables -t mangle -D OUTPUT -o $EXTIF -m owner --uid-owner $VPNNAME -j MARK --set-mark $MARK
iptables -t nat -D POSTROUTING -m mark --mark $MARK -j MASQUERADE
iptables -t nat -D POSTROUTING -m mark --mark $MARK -j SNAT --to-source $TUNIP
echo "- Flushing iproutes"
ip route flush table $VPNNAME
ip rule del fwmark $MARK
echo "- Flushing rp_filter"
for f in all $TUNDEV
do echo 1 > /proc/sys/net/ipv4/conf/$f/rp_filter ; done

echo "+ adding iptables"
# On marque tous les paquets appartenant au group $VPNNAME
iptables -t mangle -A OUTPUT -o $EXTIF -m owner --gid-owner $VPNNAME -j MARK --set-mark $MARK
iptables -t nat -A POSTROUTING -m mark --mark $MARK -j MASQUERADE
# L'IP source des paquets doit etre changée vu que l'on va les faire passer par l'interface VPN tun
iptables -t nat -A POSTROUTING -m mark --mark $MARK -j SNAT --to-source $TUNIP

echo "+ adding iproutes"
echo " + net ${NET} on main table"
ip route add $VPNNET dev $TUNDEV proto kernel scope link src $TUNIP
echo " + net ${NET} on ${VPNNAME} table"
ip route add $VPNNET dev $TUNDEV proto kernel scope link src $TUNIP table ${VPNNAME}
echo " + gw"
ip route add default via $VPNGW dev $TUNDEV table ${VPNNAME}
ip rule add fwmark $MARK table ${VPNNAME}
ip route flush cache table ${VPNNAME}
ip route flush cache

echo "+ adding rp_filter" # ca c'est la commande magique
for f in all $TUNDEV
do echo 0 > /proc/sys/net/ipv4/conf/$f/rp_filter ; done

echo "+ adding dns" # On utilise les DNS de google qui ont une meilleure latence quelque soit la position du serveur VPN
echo "nameserver 8.8.8.8
nameserver 8.8.4.4
nameserver 213.186.33.99
" > /etc/resolv.conf

Script de down

#!/bin/bash

TUNDEV=$1
TUNIP=$4
VPNNET="10.8.0.0/16"
VPNGW="10.8.0.1"
EXTIF=eth0
VPNNAME=<nomvpn>
MARK=100 # spécifique au vpn, meme que pour le up

echo "- Flushing iptables"
iptables -t mangle -D OUTPUT -o $EXTIF -m owner --gid-owner $VPNNAME -j MARK --set-mark $MARK
iptables -t nat -D POSTROUTING -m mark --mark $MARK -j MASQUERADE
iptables -t nat -D POSTROUTING -m mark --mark $MARK -j SNAT --to-source $TUNIP
echo "- Flushing iproutes"
ip route flush table $VPNNAME
ip rule del fwmark $MARK
echo "- Flushing rp_filter"
for f in all $TUNDEV
do echo 1 > /proc/sys/net/ipv4/conf/$f/rp_filter ; done

echo "+ flushing dns"
echo "nameserve XXX.XXX.XXX.XXX # votre nameserver habituel, au choix
" > /etc/resolv.conf

L'utilisation

Ainsi, tout les processus lancés avec le gid <vpnname> se verront routés a travers le VPN. Pour lancer une telle application, vous pouvez paramétrer le groupid dans le configuration de votre application, comme pour tinyproxy par exemple avec Group <vpnname> dans le fichier tinyproxy.conf.

Ou vous pouvez directement aller sur http://mire.ipadsl.net/ avec links et sudo:

sudo -g <vpnname> links mire.ipadsl.net

Cependant n'oubliez pas de modifier votre fichier sudoers pour autoriser dante a executer des programmes avec le gid <vpnname>:

visudo
...
dante   ALL=(:<vpnname>) NOPASSWD: ALL

Notes

[1] France et Angleterre pour l'instant, l'ACTA est en train de préparer un paquet telecom international pour aider les gouvernements a se prémunir contre la violation de droits d'auteur sur l'Internet

[2] Du moins c'est le cas pour BlackVPN et Ipredator