Ainsi, dans votre configuration, tous les paquets que vous essayez d'envoyer au réseau proviennent initialement de 10.0.0.1
(car ils passent par l' tun0
interface et son adresse locale est 10.0.0.1
). Vous capturez les paquets, tout va bien jusqu'à présent.
Maintenant, tun0
envoie les paquets plus loin. L'adresse source est 10.0.0.1
et vous voulez que les paquets partent via une interface différente ( wlp2s0
dans votre cas). C'est le routage, alors activons d'abord le routage:
sysctl -w net.ipv4.ip_forward=1
Après cela, si vous regardez tcpdump
pour wlp2s0
vous pouvez remarquer les paquets partent avec adresse source 10.0.0.1
et non pas avec l'adresse source de l'interface wlan (ce que vous attendez , je suppose). Nous devons donc changer l'adresse source et cela s'appelle NAT source . Sous Linux, c'est facile avec l'aide de netfilter / iptables :
iptables -t nat -A POSTROUTING -o wlp2s0 -s 10.0.0.1 -j MASQUERADE
Veuillez également vérifier que votre FORWARD
chaîne a une ACCEPT
politique ou vous devez autoriser le transfert avec quelque chose comme:
iptables -A FORWARD -i tun0 -o wlp2s0 -s 10.0.0.1 -j ACCEPT
iptables -A FORWARD -i wlp2s0 -o tun0 -d 10.0.0.1 -j ACCEPT
Tout devrait fonctionner maintenant: le noyau linux fait le routage, il déplace les paquets de l' tun0
interface vers wlp2s0
. netfilter devrait changer l'adresse IP source en l' adresse assignée 10.0.0.1
à votre wlp2s0
interface pour les paquets de sortie. Il mémorise toutes les connexions et lorsque les paquets de réponse reviennent (s'ils le sont), il change l'adresse de destination de l' wlp2s0
adresse affectée à l' interface en 10.0.0.1
(la fonction "conntrack").
Eh bien, cela devrait, mais ce n'est pas le cas. Il semble que netfilter soit confondu avec cette configuration de routage compliquée et le fait que le même paquet passe d'abord par la OUTPUT
chaîne, puis est routé et arrive en PREROUTING
chaîne. Au moins sur Debian 8, cela ne fonctionne pas.
La meilleure façon de dépanner netfilter est la TRACE
fonctionnalité:
modprobe ipt_LOG
iptables -t raw -A OUTPUT -p icmp -j TRACE
iptables -t raw -A PREROUTING -p icmp -j TRACE
J'active uniquement le traçage pour les paquets ICMP, vous pouvez utiliser un autre filtre pour déboguer.
Il montrera quelles tables et chaînes le paquet traverse. Et je peux voir que le paquet ne va pas plus loin dans la FORWARD
chaîne (et qu'il n'est pas attrapé par la nat/POSTROUTING
chaîne qui le fait SNAT
).
Vous trouverez ci-dessous plusieurs approches pour que cela fonctionne.
APPROCHE # 1
La meilleure façon de ne pas confondre netfilter est de changer l'adresse IP source des paquets dans l' tun0.c
application. C'est aussi le moyen le plus naturel. Nous devons changer 10.0.0.1 en 10.0.0.2 à l'aller et 10.0.0.2 à 10.0.0.1 au retour.
J'ai modifié tun0.c
avec le code de changement d'adresse source. Voici le nouveau fichier et voici le fichier patch pour votre tun0.c
. Les modifications apportées à l'en-tête IP impliquent également une correction de la somme de contrôle , j'ai donc pris du code du projet OpenVPN . Voici la liste complète des commandes que j'exécute après un redémarrage et un tun0_changeip.c
lancement propres :
ifconfig tun0 inet 10.0.0.1/30 up
sysctl -w net.ipv4.ip_forward=1
ip route add default dev tun0 table John
ip rule add from all lookup John
ip rule add from 10.0.0.2 lookup main priority 500
iptables -t nat -A POSTROUTING -o wlp2s0 -s 10.0.0.2 -j MASQUERADE
Veuillez noter que vous n'avez pas besoin de désactiver le filtrage de chemin inverse dans ce cas, car tout est légal - tun0
ne reçoit et n'envoie que les paquets qui appartiennent à son sous-réseau. Vous pouvez également faire un routage basé sur la source au lieu d'une interface.
APPROCHE # 2
Il est possible de le faire SNAT
avant que l' tun0
interface atteigne le paquet . Ce n'est pas très correct cependant. Vous devrez certainement désactiver le filtrage de chemin inverse dans ce cas:
sysctl -w net.ipv4.conf.tun0.rp_filter=0
# It won't work without also changing the "all" value
sysctl -w net.ipv4.conf.all.rp_filter=0
Maintenant, faites SNAT
: iptables -t nat -A POSTROUTING -o tun0 -s 10.0.0.1 -j SNAT --to-source ip.address.of.your.wlan.interface
Ici, nous changeons l'adresse source juste avant que les paquets n'atteignent l' tun0
appareil. tun0.c
le code renvoie ces paquets "tels quels" (avec l'adresse source modifiée) et ils sont correctement acheminés via l'interface WLAN. Mais vous pourriez avoir une IP dynamique sur l'interface wlan et vouloir utiliser MASQUERADE
(afin de ne pas spécifier l'adresse d'interface explicitement). Voici comment vous pouvez utiliser MASQUERADE
:
iptables -t nat -A POSTROUTING -o tun0 -s 10.0.0.1 -j SNAT --to-source 10.0.55.1
iptables -t nat -A POSTROUTING -o wlp2s0 -s 10.0.55.1 -j MASQUERADE
Veuillez noter l' 10.0.55.1
adresse IP " " - c'est différent. Vous pouvez utiliser n'importe quelle adresse IP ici, peu importe. Les paquets atteignent la nat/POSTROUTING
chaîne sur l' wlp2s0
interface si nous changeons l'IP source avant. Et maintenant, il ne dépend pas d'une adresse IP statique pour l'interface WLAN.
APPROCHE # 3
Vous pouvez également utiliser fwmark
. De cette façon , vous n'avez pas besoin SNAT
mais vous capturer des paquets sortants seulement:
nous devons d'abord désactiver chemin inverse filtrage pour , tun0
car il transmet des paquets qui appartiennent à un autre réseau:
sysctl -w net.ipv4.conf.tun0.rp_filter=0
# It won't work without also changing the "all" value
sysctl -w net.ipv4.conf.all.rp_filter=0
Now let's alter the routing rules a bit:
# Delete old rules
ip rule del iif tun0 lookup main
ip rule del from all lookup John
# Packets will start going from wlan interface so they will have source address of it
iptables -t mangle -A OUTPUT -o wlp2s0 -j MARK --set-mark 1
ip rule add fwmark 0x1 lookup John
C'est un autre "hack" pour le routage et le netfilter qui fonctionne sur ma boîte Debian 8, mais je recommande quand même de prendre la première approche car elle est plus naturelle et n'utilise pas de hacks.
Vous pouvez également envisager de créer votre application en tant que proxy transparent . Je pense que ce serait beaucoup plus facile au lieu d'analyser les paquets du périphérique tun.
-j SNAT
, pas-s SNAT
sudo ip rule add iif tun0 lookup main priority 500
elle, mais cela n'a toujours pas fonctionné. J'aime cette approche, dommage que je ne puisse pas la reproduire.