Portanto, na sua configuração, todos os pacotes que você tentar enviar para a rede inicialmente originados de 10.0.0.1
(porque eles estão passando pela interface tun0
e seu endereço local são 10.0.0.1
). Você captura os pacotes, tudo está 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). Isso é roteamento então vamos ativar o roteamento primeiro:
sysctl -w net.ipv4.ip_forward=1
Depois disso, se você olhar para tcpdump
para wlp2s0
, poderá notar que os pacotes saem com o 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 mudar o endereço de origem e é chamado fonte NAT . 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 a sua corrente FORWARD
tem ACCEPT
política ou se é necessário 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: linux kernel faz o roteamento, ele está movendo os pacotes da interface tun0
para wlp2s0
. O netfilter deve alterar o IP de origem 10.0.0.1
para o endereço atribuído à interface wlp2s0
dos pacotes de saída. Ele memoriza todas as conexões e quando os pacotes de resposta retornam (se eles), ele altera o endereço de destino do endereço atribuído da interface wlp2s0
para 10.0.0.1
(o recurso "conntrack").
Bem, deveria, mas isso não acontece. Parece que o netfilter se confunde com essa configuração de roteamento complicada e com o fato de que o mesmo pacote primeiro passa pela cadeia OUTPUT
e depois é encaminhado e chega a PREROUTING
chain. Pelo menos na caixa Debian 8, não funciona.
A melhor maneira de solucionar problemas do netfilter é o recurso TRACE
:
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 eu posso ver que o pacote não vai mais longe da corrente FORWARD
(e não está sendo pego pela corrente nat/POSTROUTING
que realmente faz 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 aplicativo tun0.c
. É também o caminho mais natural.
Precisamos mudar 10.0.0.1 para 10.0.0.2 no caminho para fora e 10.0.0.2 para 10.0.0.1 no caminho de volta.
Eu modifiquei tun0.c
com código de mudança de endereço de origem. Aqui está o novo arquivo e aqui é patchfile para seu código%. Mudanças no cabeçalho IP também envolvem correção de checksum , então eu peguei um código do projeto OpenVPN .
Aqui está a lista completa de comandos que eu executo depois de uma reinicialização limpa e tun0.c
launch:
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
Por favor, note que você não precisa desligar o caminho reverso de filtragem nesse caso, porque tudo é legal - tun0_changeip.c
apenas recebe e envia pacotes que pertencem à sua sub-rede. Além disso, você pode fazer um roteamento baseado em origem em vez de baseado em interface.
ABORDAGEM # 2
É possível fazer tun0
antes que o pacote atinja a interface SNAT
. Não é muito correto embora. Você definitivamente precisará desativar o caminho reverso de filtragem 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 tun0
:
iptables -t nat -A POSTROUTANDO -o tun0 -s 10.0.0.1 -j SNAT --to-source ip.address.of.your.wlan.interface
Aqui, alteramos o endereço de origem apenas antes que os pacotes atinjam o dispositivo SNAT
. O código tun0
reenvia esses pacotes "como estão" (com endereço de origem alterado) e eles são roteados com sucesso pela interface wlan.
Mas você pode ter um IP dinâmico na interface wlan e deseja usar tun0.c
(para não especificar explicitamente o endereço da interface). Veja como você pode usar 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 endereço IP " MASQUERADE
" - é diferente. Você pode usar qualquer IP aqui, não importa. Os pacotes alcançam 10.0.55.1
chain na interface nat/POSTROUTING
se alterarmos 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 wlp2s0
. Dessa forma, você não precisa de fwmark
, mas capturará somente os pacotes de saída:
Primeiro, precisamos desabilitar a filtragem de caminho reverso para SNAT
, porque ele encaminhará os 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 "hack" para roteamento e netfilter que funciona na minha caixa Debian 8, mas ainda assim eu recomendo usar a primeira abordagem, pois é mais natural e não t use qualquer 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 os pacotes do dispositivo tun.