Como fazer todo o tráfego para passar por uma interface no Linux

9

Eu tenho uma interface auto-escrita, tun0 ( Base TUN / TAP ) que gera o que recebe.
Preciso que todo o tráfego do sistema flua por essa interface.
O papel da interface é:

  1. Para descobrir os pacotes que podem ser censurados e encapsulá-los.
  2. Passe todos os outros tráfegos intocados.

Como você adivinhou, estou tentando construir uma ferramenta anticensora.
Decisão sobre tunelamento deve ser tomada dentro do processo tun0 | porque só lá podemos usar DNS confiável.

Preciso da sua ajuda para me mostrar como fazer todo o tráfego fluir por meio de uma interface auto-escrita tun0. Se tun0 precisar de mudanças, peço-lhe para fornecer tais mudanças.

Abaixo, mostramos como tentei fazer todo o tráfego passar pelo tun0 e falhar (pings falharem).

Compilando

  1. gcc tun0.c
  2. sudo ./a.out

Configurando

  1. sudo ip addr add 10.0.0.1/24 dev tun0
  2. criar tabela John

    $ cat /etc/iproute2/rt_tables 
    #
    # reserved values
    #
    255     local
    254     main
    253     default
    0       unspec
    #
    # local
    #
    #1      inr.ruhep
    
    200 John
    

A ordem é importante:

  1. sudo ip rule add from all lookup John
  2. sudo ip route add default dev tun0 table John
  3. sudo ip rule add iif tun0 lookup main priority 500

    $ ip rule
    0:      from all lookup local 
    500:    from all iif tun0 lookup main 
    32765:  from all lookup John 
    32766:  from all lookup main 
    35000:  from all lookup default 
    

Resolução de problemas

  1. sudo tcpdump -i wlp2s0 -qtln icmp e, em seguida, ping -I tun0 8.8.8.8 não mostra nenhum pacote capturado, isso significa que nenhum pacote é transmitido de tun0 para wlp2s0 por meio da regra iif tun0 lookup main .

  2. Quando substituí tun0 por lo em todos os lugares, funcionou para mim.

Também tentei

  1. Desativando a filtragem do caminho inverso, rp_filter=0 in /etc/sysctl.conf

Resposta à solução de problemas

iptables -I FORWARD -j LOG --log-prefix "filter/FORWARD " 
iptables -t nat -I OUTPUT -j LOG --log-prefix "nat/OUTPUT " 
iptables -t nat -I PREROUTING -j LOG --log-prefix "nat/PREROUTING " 
iptables -t nat -I POSTROUTING -j LOG --log-prefix "nat/POSTROUTNG "
tail -f /var/log/syslog

As fontes modificadas da resposta também são aqui .

    
por TheNamelessOne 27.11.2017 / 07:11

1 resposta

6

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.

    
por 30.11.2017 / 02:31