Quindi, nella tua configurazione, tutti i pacchetti che provi a inviare alla rete originariamente originari 10.0.0.1
(perché stanno attraversando l' tun0
interfaccia e il suo indirizzo locale è 10.0.0.1
). Catturi i pacchetti, tutto va bene finora.
Ora tun0
invia ulteriormente i pacchetti. L'indirizzo di origine è 10.0.0.1
e vuoi che i pacchetti escano attraverso un'interfaccia diversa ( wlp2s0
nel tuo caso). Questo è il routing, quindi abilitiamo prima il routing:
sysctl -w net.ipv4.ip_forward=1
Dopo di che, se si guarda a tcpdump
per wlp2s0
è possibile notare i pacchetti in uscita con indirizzo sorgente 10.0.0.1
e non con l'indirizzo sorgente dell'interfaccia wlan (quello che ti aspetteresti credo). Quindi dobbiamo cambiare l'indirizzo di origine e si chiama sorgente NAT . In linux è facile con l'aiuto di netfilter / iptables :
iptables -t nat -A POSTROUTING -o wlp2s0 -s 10.0.0.1 -j MASQUERADE
Controlla anche che la tua FORWARD
catena abbia una ACCEPT
politica o che dovresti consentire l'inoltro con qualcosa come:
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
Ora tutto dovrebbe funzionare: il kernel Linux esegue il routing, sta spostando i pacchetti tun0
dall'interfaccia a wlp2s0
. netfilter dovrebbe cambiare l'IP di origine 10.0.0.1
al vostro wlp2s0
interfaccia indirizzo assegnato per i pacchetti in uscita. Memorizza tutte le connessioni e quando i pacchetti di risposta tornano (se presenti) cambia l'indirizzo di destinazione dell'indirizzo wlp2s0
assegnato all'interfaccia in 10.0.0.1
(la funzione "conntrack").
Bene, dovrebbe ma non lo fa. Sembra che netfilter si confonda con questa complicata configurazione di routing e con il fatto che lo stesso pacchetto passa prima attraverso la OUTPUT
catena e poi viene instradato e arriva alla PREROUTING
catena. Almeno su Debian 8 box non funziona.
Il modo migliore per risolvere netfilter è la TRACE
funzione:
modprobe ipt_LOG
iptables -t raw -A OUTPUT -p icmp -j TRACE
iptables -t raw -A PREROUTING -p icmp -j TRACE
Abilito solo la traccia per i pacchetti ICMP, è possibile utilizzare altri filtri per il debug.
Mostrerà quali tabelle e catene attraversa il pacchetto. E vedo che il pacchetto non va oltre la FORWARD
catena (e non viene catturato dalla nat/POSTROUTING
catena che effettivamente lo fa SNAT
).
Di seguito sono riportati diversi approcci per farlo funzionare.
APPROCCIO # 1
Il modo migliore per annullare la confusione di netfilter è cambiare l'indirizzo IP di origine dei pacchetti tun0.c
nell'applicazione. È anche il modo più naturale. Dobbiamo cambiare da 10.0.0.1 a 10.0.0.2 sulla strada verso l'esterno e da 10.0.0.2 a 10.0.0.1 sulla via del ritorno.
Ho modificato tun0.c
con il codice di modifica dell'indirizzo di origine. Ecco il nuovo file ed ecco il file di patch per il tuo tun0.c
. Le modifiche all'intestazione IP implicano anche la correzione del checksum , quindi ho preso del codice dal progetto OpenVPN . Ecco l'elenco completo dei comandi che eseguo dopo un riavvio pulito e tun0_changeip.c
lancio:
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
In questo caso non è necessario disattivare il filtro del percorso inverso , poiché tutto è legale: tun0
riceve e invia solo pacchetti che appartengono alla sua sottorete. Inoltre è possibile eseguire un routing basato sull'origine anziché basato sull'interfaccia.
APPROCCIO # 2
È possibile farlo SNAT
prima che l' tun0
interfaccia del pacchetto raggiunga . Non è molto corretto però. In questo caso dovrai sicuramente disattivare il filtro del percorso inverso :
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
Ora, SNAT
esegui: iptables -t nat -A POSTROUTING -o tun0 -s 10.0.0.1 -j SNAT - to-source ip.address.of.your.wlan.interface
Qui cambiamo l'indirizzo sorgente appena prima che i pacchetti raggiungano il tun0
dispositivo. tun0.c
il codice invia nuovamente questi pacchetti "così come sono" (con l'indirizzo di origine modificato) e vengono instradati correttamente attraverso l'interfaccia wlan. Ma potresti avere un IP dinamico sull'interfaccia wlan e vuoi usarlo MASQUERADE
(per non specificare esplicitamente l'indirizzo dell'interfaccia). Ecco come è possibile utilizzare 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
Si prega di notare l '" 10.0.55.1
" indirizzo IP - è diverso. Puoi usare qualsiasi IP qui, non importa. I pacchetti raggiungono la nat/POSTROUTING
catena wlp2s0
sull'interfaccia se prima cambiamo l'IP di origine. E ora non dipende da un IP statico per l'interfaccia wlan.
APPROCCIO # 3
Puoi anche usare fwmark
. In questo modo non è necessario SNAT
ma dovrete catturare i pacchetti solo in uscita:
In primo luogo abbiamo bisogno di disabilitare il percorso inverso di filtraggio per tun0
perché sarà inoltrare i pacchetti che appartengono a un'altra rete:
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
Questo è un altro "hack" per routing e netfilter che funziona sul mio Debian 8 box, ma consiglio comunque di adottare il primo approccio in quanto è più naturale e non usa alcun hack.
Puoi anche considerare di creare la tua applicazione come proxy trasparente . Penso che sarebbe molto più semplice invece di analizzare i pacchetti dal dispositivo tun.
-j SNAT
, non-s SNAT