Portanto, na sua configuração, todos os pacotes que você tenta enviar para a rede inicialmente originários 10.0.0.1
(porque estão passando pela tun0
interface e seu endereço local é 10.0.0.1
). Você captura os pacotes, está tudo bem até agora.
Agora, tun0
envia os pacotes ainda mais. O endereço de origem é 10.0.0.1
e você deseja que os pacotes saiam por uma interface diferente ( wlp2s0
no seu caso). Esse é o roteamento, então vamos habilitar o roteamento primeiro:
sysctl -w net.ipv4.ip_forward=1
Depois disso, se você olhar tcpdump
para wlp2s0
você pode notar os pacotes sair com endereço de origem 10.0.0.1
e não com o endereço de origem da interface WLAN (o que você esperaria eu acho). Então, precisamos alterar o endereço de origem e isso se chama NAT de origem . No linux, é fácil com a ajuda do netfilter / iptables :
iptables -t nat -A POSTROUTING -o wlp2s0 -s 10.0.0.1 -j MASQUERADE
Verifique também se sua FORWARD
cadeia possui ACCEPT
política ou se você precisa permitir o encaminhamento com algo como:
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
Tudo deve funcionar agora: o kernel linux faz o roteamento, está movendo pacotes da tun0
interface para wlp2s0
. O netfilter deve alterar o IP de origem 10.0.0.1
para o wlp2s0
endereço atribuído à interface para pacotes de saída. Ele memoriza todas as conexões e, quando os pacotes de resposta retornam (se houver), altera o endereço de destino do endereço wlp2s0
atribuído à interface para 10.0.0.1
(o recurso "conntrack").
Bem, deveria, mas não. Parece que o netfilter se confunde com essa complicada configuração de roteamento e o fato de que o mesmo pacote passa primeiro pela OUTPUT
cadeia e depois é roteado e chega à PREROUTING
cadeia. Pelo menos na caixa Debian 8, ele não funciona.
A melhor maneira de solucionar problemas do netfilter é o TRACE
recurso:
modprobe ipt_LOG
iptables -t raw -A OUTPUT -p icmp -j TRACE
iptables -t raw -A PREROUTING -p icmp -j TRACE
Eu só habilito o rastreamento para pacotes ICMP, você pode usar outro filtro para depurar.
Ele mostrará quais tabelas e cadeias o pacote passa. E posso ver que o pacote não vai além da FORWARD
cadeia (e não está sendo capturado pela nat/POSTROUTING
cadeia que realmente funciona SNAT
).
Abaixo estão várias abordagens para fazer isso funcionar.
ABORDAGEM # 1
A melhor maneira de confundir o netfilter é alterar o endereço IP de origem dos pacotes no tun0.c
aplicativo. É também a maneira mais natural. Precisamos mudar 10.0.0.1 para 10.0.0.2 no caminho para o exterior e 10.0.0.2 para 10.0.0.1 no caminho de volta.
Eu modifiquei tun0.c
com o código de alteração de endereço de origem. Aqui está o novo arquivo e o patchfile para você tun0.c
. Alterações no cabeçalho IP também envolvem correção de soma de verificação , então peguei algum código do projeto OpenVPN . Aqui está a lista completa de comandos que executo após uma reinicialização limpa e tun0_changeip.c
inicio:
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
Observe que você não precisa desativar a filtragem de caminho inverso nesse caso, porque tudo é legal - tun0
apenas recebe e envia pacotes que pertencem à sua sub-rede. Além disso, você pode fazer um roteamento baseado na origem em vez de baseado na interface.
ABORDAGEM # 2
É possível fazer isso SNAT
antes que o pacote chegue à tun0
interface. Não é muito correto. Você definitivamente precisará desativar a filtragem de caminho reverso neste caso:
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
Agora, faça SNAT
: iptables -t nat -A POSTROUTING -o tun0 -s 10.0.0.1 -j SNAT --para o endereço ip.address.of.your.wlan.interface
Aqui, alteramos o endereço de origem antes dos pacotes chegarem ao tun0
dispositivo. tun0.c
O código reenvia esses pacotes "como estão" (com o endereço de origem alterado) e eles são roteados com êxito pela interface wlan. Mas você pode ter um IP dinâmico na interface wlan e deseja usar MASQUERADE
(para não especificar explicitamente o endereço da interface). Aqui está como você pode fazer uso de 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
Observe o " 10.0.55.1
" endereço IP - é diferente. Você pode usar qualquer IP aqui, não importa. Os pacotes alcançam a nat/POSTROUTING
cadeia na wlp2s0
interface se mudarmos o IP de origem antes. E agora não depende de um IP estático para a interface wlan.
ABORDAGEM # 3
Você também pode usar fwmark
. Dessa forma, você não precisa SNAT
, mas você vai capturar pacotes única saída:
Primeiro, precisamos desabilitar o caminho inverso filtragem para tun0
porque ele vai encaminhar pacotes que pertencem a outra rede:
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
Esse é outro "truque" para roteamento e filtro de rede que funciona na minha caixa Debian 8, mas ainda assim eu recomendo adotar a primeira abordagem, pois é mais natural e não usa hacks.
Você também pode considerar criar seu aplicativo como um proxy transparente . Eu acho que seria muito mais fácil, em vez de analisar pacotes do dispositivo tun.
-j SNAT
, não-s SNAT
sudo ip rule add iif tun0 lookup main priority 500
a ela, mas ainda assim não funcionou. Eu gosto dessa abordagem, pena que não posso reproduzi-la.