Configurez le routage et les iptables pour une nouvelle connexion VPN pour rediriger ** uniquement ** les ports 80 et 443


8

J'ai une nouvelle connexion VPN (utilisant openvpn) pour me permettre de contourner certaines restrictions FAI. Tandis qu'il fonctionne très bien, il prend tout le trafic sur le VPN. Cela me pose des problèmes de téléchargement (ma connexion Internet est beaucoup plus rapide que le vpn le permet) et d'accès à distance. J'exécute un serveur ssh et j'ai un démon en cours d'exécution qui me permet de planifier les téléchargements via mon téléphone.

J'ai ma connexion Ethernet existante sur eth0 et la nouvelle connexion VPN sur tun0.

Je crois que je dois configurer la route par défaut pour utiliser ma connexion eth0 existante sur le réseau 192.168.0.0/24, et définir la passerelle par défaut sur 192.168.0.1 (ma connaissance est fragile car je ne l'ai pas fait depuis un certain nombre d'années ). Si c'est correct, alors je ne sais pas exactement comment le faire!. Ma table de routage actuelle est:

Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface    MSS   Window irtt
0.0.0.0         10.51.0.169     0.0.0.0         UG    0      0        0 tun0     0     0      0
10.51.0.1       10.51.0.169     255.255.255.255 UGH   0      0        0 tun0     0     0      0
10.51.0.169     0.0.0.0         255.255.255.255 UH    0      0        0 tun0     0     0      0
85.25.147.49    192.168.0.1     255.255.255.255 UGH   0      0        0 eth0     0     0      0
169.254.0.0     0.0.0.0         255.255.0.0     U     1000   0        0 eth0     0     0      0
192.168.0.0     0.0.0.0         255.255.255.0   U     1      0        0 eth0     0     0      0

Après avoir corrigé le routage, je pense que je dois utiliser iptables pour configurer le pré-routage ou le masquage pour forcer tout pour le port de destination 80 ou 443 sur tun0. Encore une fois, je ne sais pas exactement comment procéder!

Tout ce que j'ai trouvé sur Internet essaie de faire quelque chose de beaucoup plus compliqué, et essayer de trier le bois des arbres s'avère difficile.

Toute aide serait très appréciée.

MISE À JOUR

Jusqu'à présent, à partir des différentes sources, j'ai bricolé les éléments suivants:

#!/bin/sh

DEV1=eth0
IP1=`ifconfig|perl -nE'/dr:(\S+)/&&say$1'|grep 192.`
GW1=192.168.0.1
TABLE1=internet
TABLE2=vpn
DEV2=tun0
IP2=`ifconfig|perl -nE'/dr:(\S+)/&&say$1'|grep 10.`
GW2=`route -n | grep 'UG[ \t]' | awk '{print $2}'`

ip route flush table $TABLE1
ip route flush table $TABLE2
ip route show table main | grep -Ev ^default | while read ROUTE ; do
    ip route add table $TABLE1 $ROUTE
    ip route add table $TABLE2 $ROUTE
done
ip route add table $TABLE1 $GW1 dev $DEV1 src $IP1
ip route add table $TABLE2 $GW2 dev $DEV2 src $IP2
ip route add table $TABLE1 default via $GW1
ip route add table $TABLE2 default via $GW2

echo "1" > /proc/sys/net/ipv4/ip_forward
echo "1" > /proc/sys/net/ipv4/ip_dynaddr

ip rule add from $IP1 lookup $TABLE1
ip rule add from $IP2 lookup $TABLE2
ip rule add fwmark 1 lookup $TABLE1
ip rule add fwmark 2 lookup $TABLE2

iptables -t nat -A POSTROUTING -o $DEV1 -j SNAT --to-source $IP1
iptables -t nat -A POSTROUTING -o $DEV2 -j SNAT --to-source $IP2

iptables -t nat -A PREROUTING           -m state --state ESTABLISHED,RELATED          -j CONNMARK --restore-mark
iptables        -A OUTPUT               -m state --state ESTABLISHED,RELATED          -j CONNMARK --restore-mark
iptables -t nat -A PREROUTING -i $DEV1  -m state --state NEW                          -j CONNMARK --set-mark 1
iptables -t nat -A PREROUTING -i $DEV2  -m state --state NEW                          -j CONNMARK --set-mark 2
iptables -t nat -A PREROUTING           -m connmark --mark 1                          -j MARK --set-mark 1
iptables -t nat -A PREROUTING           -m connmark --mark 2                          -j MARK --set-mark 2
iptables -t nat -A PREROUTING           -m state --state NEW -m connmark ! --mark 0   -j CONNMARK --save-mark

iptables -t mangle -A PREROUTING -i $DEV2 -m state --state NEW -p tcp --dport  80 -j CONNMARK --set-mark 2
iptables -t mangle -A PREROUTING -i $DEV2 -m state --state NEW -p tcp --dport 443 -j CONNMARK --set-mark 2

route del default
route add default gw 192.168.0.1 eth0

Maintenant, cela semble fonctionner. Sauf que ce n'est pas le cas!

Les connexions aux sites bloqués sont traversent, les connexions non pas sur les ports 80 et 443 sont en utilisant la connexion non-VPN.

Cependant, les connexions des ports 80 et 443 qui ne sont pas vers les sites Web bloqués utilisent également la connexion non VPN!

Comme l'objectif général a été atteint, je suis relativement content, mais ce serait bien de savoir pourquoi cela ne fonctionne pas exactement.

Des idées?

Pour référence, j'ai maintenant 3 tables de routage, principale, Internet et VPN. Leur liste est la suivante ...

Principale:

default via 192.168.0.1 dev eth0 
10.38.0.1 via 10.38.0.205 dev tun0 
10.38.0.205 dev tun0  proto kernel  scope link  src 10.38.0.206 
85.removed via 192.168.0.1 dev eth0 
169.254.0.0/16 dev eth0  scope link  metric 1000 
192.168.0.0/24 dev eth0  proto kernel  scope link  src 192.168.0.73  metric 1 

L'Internet:

default via 192.168.0.1 dev eth0 
10.38.0.1 via 10.38.0.205 dev tun0 
10.38.0.205 dev tun0  proto kernel  scope link  src 10.38.0.206 
85.removed via 192.168.0.1 dev eth0 
169.254.0.0/16 dev eth0  scope link  metric 1000 
192.168.0.0/24 dev eth0  proto kernel  scope link  src 192.168.0.73  metric 1 
192.168.0.1 dev eth0  scope link  src 192.168.0.73

VPN:

default via 10.38.0.205 dev tun0 
10.38.0.1 via 10.38.0.205 dev tun0 
10.38.0.205 dev tun0  proto kernel  scope link  src 10.38.0.206 
85.removed via 192.168.0.1 dev eth0 
169.254.0.0/16 dev eth0  scope link  metric 1000 
192.168.0.0/24 dev eth0  proto kernel  scope link  src 192.168.0.73  metric 1

Le script ci-dessus fonctionne comme prévu. Je m'attendais juste à voir du trafic provenant de l'adresse 10. dans netstat. Cependant, tout le trafic provient de 192., mais les ports 80 et 443 sont dirigés sur VPN. Je vais mettre toute la solution dans une réponse, mais des accessoires à @anttir pour avoir suggéré iproute2 et fwmark. Je ne les avais pas rencontrés et sans eux, je me cognais toujours la tête contre un mur de briques!
Steve

Réponses:


4

Donc, la plupart de cela est ci-dessus, mais toute la solution était la suivante:

Editez / etc / iproute2 / rt_tables et ajoutez 2 lignes en bas:

101 internet
102 vpn

Vous pouvez donner à ces tables d'autres noms qui ont plus de sens, soyez juste cohérent.

Ensuite, vous devez créer un script (je l'ai appelé rt_setup) dans /etc/init.d

#!/bin/sh

DEV1=eth0
IP1=`ifconfig|perl -nE'/dr:(\S+)/&&say$1'|grep 192.`
GW1=192.168.0.1
TABLE1=internet
TABLE2=vpn
DEV2=tun0
IP2=`ifconfig|perl -nE'/dr:(\S+)/&&say$1'|grep 10.`
GW2=`route -n | grep 'UG[ \t]' | awk '{print $2}'`

ip route flush table $TABLE1
ip route flush table $TABLE2
ip route show table main | grep -Ev ^default | while read ROUTE ; do
    ip route add table $TABLE1 $ROUTE
    ip route add table $TABLE2 $ROUTE
done
ip route add table $TABLE1 $GW1 dev $DEV1 src $IP1
ip route add table $TABLE2 $GW2 dev $DEV2 src $IP2
ip route add table $TABLE1 default via $GW1
ip route add table $TABLE2 default via $GW2

echo "1" > /proc/sys/net/ipv4/ip_forward
echo "1" > /proc/sys/net/ipv4/ip_dynaddr

ip rule add from $IP1 lookup $TABLE1
ip rule add from $IP2 lookup $TABLE2
ip rule add fwmark 1 lookup $TABLE1
ip rule add fwmark 2 lookup $TABLE2

iptables -t nat -A POSTROUTING -o $DEV1 -j SNAT --to-source $IP1
iptables -t nat -A POSTROUTING -o $DEV2 -j SNAT --to-source $IP2

iptables -t nat -A PREROUTING           -m state --state ESTABLISHED,RELATED          -j CONNMARK --restore-mark
iptables        -A OUTPUT               -m state --state ESTABLISHED,RELATED          -j CONNMARK --restore-mark
iptables -t nat -A PREROUTING -i $DEV1  -m state --state NEW                          -j CONNMARK --set-mark 1
iptables -t nat -A PREROUTING -i $DEV2  -m state --state NEW                          -j CONNMARK --set-mark 2
iptables -t nat -A PREROUTING           -m connmark --mark 1                          -j MARK --set-mark 1
iptables -t nat -A PREROUTING           -m connmark --mark 2                          -j MARK --set-mark 2
iptables -t nat -A PREROUTING           -m state --state NEW -m connmark ! --mark 0   -j CONNMARK --save-mark

iptables -t mangle -A PREROUTING -i $DEV2 -m state --state NEW -p tcp --dport  80 -j CONNMARK --set-mark 2
iptables -t mangle -A PREROUTING -i $DEV2 -m state --state NEW -p tcp --dport 443 -j CONNMARK --set-mark 2

route del default
route add default gw 192.168.0.1 eth0

Ensuite, évidemment, liez-le à partir de /etc/rc2.d (j'utilise ubuntu, le niveau d'exécution peut différer pour vous). Assurez-vous de lui donner un numéro S supérieur au lien openvpn!

Le script fait un certain nombre de choses. La partie supérieure configure les variables, avec certaines instructions perl et awk utilisées pour récupérer les adresses IP et les passerelles dynamiques.La deuxième section nettoie les tables que vous configurez dans ipruote2 et leur copie la table de routage actuelle. Il crée ensuite deux nouveaux itinéraires et deux passerelles par défaut pour eux, le VPN passant par le VPN et Internet passant par mon réseau local.

Je ne suis pas convaincu que les 2 lignes suivantes soient nécessaires, mais elles permettent le transfert IP pour une utilisation dans iptables.

Ensuite, le script crée des règles sur où rechercher le trafic provenant de l'adresse IP appropriée et où chercher si le trafic est spécifiquement marqué.

Le POSTROUTING et le PREROUTING garantissent que le trafic provenant d'une adresse obtient la réponse!

Le dernier iptables PREROUTING est la partie qui marque le trafic et garantit que tout ce qui va aux ports 80 ou 443 est marqué pour utiliser le tableau 2 (VPN)

Les deux dernières lignes suppriment la passerelle VPN de la table de routage par défaut et rajoutent ma passerelle de réseau local.

En l'état, le processus fonctionne avec brio. Le VPN est démarré au démarrage de la machine, et ce script est exécuté quelques secondes plus tard (je peux ajouter une instruction de veille juste pour m'assurer que le VPN est complètement initialisé avant d'exécuter ce script). Ma connexion d'accès à distance (ssh, etc.) fonctionne très bien. Mes connexions qui ne vont pas aux ports 80 ou 443 utilisent ma connexion locale, mais tout le trafic Web passe par le VPN et contourne les contrôles mis en place par mon FAI!

Comme je l'ai dit dans mon commentaire sous ma question, je n'aurais même pas commencé à regarder cet itinéraire sans la suggestion de @anttir. À l'arrière de cette suggestion, les sites http://blog.khax.net/2009/11/28/multi-gateway-routing-with-iptables-and-iproute2/ et http://linux-ip.net/ html / adv-multi-internet.html ont été très utiles (même si le code n'est pas complet à 100%!)


1
Un dernier ajout, j'ai ajouté un sleep 20en haut du script car la connexion openvpn ne se terminait pas à temps. J'ai également ajouté echo 2 > /proc/sys/net/ipv4/conf/tun0/rp_filterau script car il est nécessaire de désactiver le filtre de paquets inversé pour tun0. Lorsqu'une réponse revient de tun0 avec l'adresse source S, le filtre de paquets inversé vérifie "si je devais acheminer un paquet vers l'adresse S, et qu'il ne passerait pas par tun0, je laisserais tomber le paquet" - et parce qu'en faisant cela recherche il n'y a pas de fwmark valide, il détermine que la route serait la route par défaut habituelle, donc il abandonne le paquet.
Steve

J'ai dû éditer votre script pour le faire fonctionner pour moi. La dernière ligne route add default gw 192.168.0.1 eth0semblait acheminer le trafic du port 80/443 via la passerelle locale au lieu du tun0 comme prévu. Changer la dernière ligne route add default tun0semble faire l'affaire pour moi.

1

le routage par protocole est un peu compliqué. La table de routage est généralement utilisée pour vérifier la passerelle en fonction de l'adresse IP de destination et utiliser la passerelle par défaut openvpn ou 192.168.0.1.

Il serait plus facile de configurer, par exemple, un proxy http Squid à l'autre extrémité du VPN et de configurer le navigateur pour utiliser le proxy.

Vous n'utiliseriez pas les iptables car cela changerait l'adresse IP de destination de la connexion HTTP et cela ne fonctionnerait pas.

Vous pouvez créer une nouvelle table de routage (/ etc / iproute2 / rt_tables) avec une route par défaut définie vers le point de terminaison VPN, utiliser iptables fwmark (-j MARK) pour marquer tous les paquets HTTP, puis utiliser la règle ip pour créer une règle personnalisée pour le packages marqués pour utiliser la nouvelle table de routage.


Merci de votre aide. Je vais certainement y jeter un œil. Les choses sont un peu délicates dans la mesure où je n'ai pas le contrôle de l'extrémité serveur, juste de mon côté. De plus, je ne peux pas utiliser Squid car j'ai besoin d'acheminer le trafic https sur la connexion, et Squid ne fonctionne pas si bien avec cela.
Steve

Que diriez-vous de router seulement quelques adresses IP sur le VPN et le reste du monde en dehors du VPN?
Antti Rytsölä

J'ai pensé à ne router que quelques adresses IP, mais la liste change au fur et à mesure que les sites se déplacent, et je dois rendre cela facile à utiliser pour les autres utilisateurs du PC. J'ai commencé à chercher à mettre en place une nouvelle table de routage et à marquer les paquets. Le marquage des paquets était le plus simple, ce sont les tables de routage dont je ne suis pas si sûr. Je peux en configurer un pour un VPN qui semble correct, et un pour tout le reste qui semble correct, mais je ne sais pas quoi faire avec principal car il est toujours défini sur les paramètres par défaut (qui est VPN). Joue toujours ...
Steve

linux-ip.net/html/adv-multi-internet.html afficher la règle ip et la règle ip ajouter fwmark 4 table 4 priorité 10000
Antti Rytsölä

Ajout d'une mise à jour de l'original qui détaille où j'en suis jusqu'à présent! Ah! Je viens de réaliser que j'ai modifié votre réponse, pas ma question. Désolé! Je n'ai pas beaucoup utilisé et je ne savais pas que je pouvais modifier la réponse d'une autre personne!
Steve
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.