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

11

Eu tenho uma interface auto-escrita tun0 ( baseada em TUN / TAP ) que gera o que recebe.
Eu preciso que todo o tráfego do sistema flua através dessa interface.
O papel da interface é:

  1. Para descobrir pacotes que provavelmente serão censurados e encapsulá-los.
  2. Passe todo o outro tráfego intocado.

Como você acha que estou tentando criar uma ferramenta anticensura.
A decisão sobre o encapsulamento deve ser tomada dentro do processo tun0,
porque somente lá podemos usar DNS confiável.

Preciso da sua ajuda para me mostrar como fazer todo o tráfego fluir através de uma interface auto-escrita tun0. Se tun0 precisar de alterações, peço que forneça essas alterações.

Abaixo está como eu tentei fazer todo o tráfego passar por tun0 e falhar (pings falham).

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 
    

Solução de problemas

  1. sudo tcpdump -i wlp2s0 -qtln icmpe, em seguida ping -I tun0 8.8.8.8, não mostra pacotes capturados, significa que nenhum pacote é transmitido de tun0 para wlp2s0 via iif tun0 lookup mainregra.

  2. Quando substituí tun0por lotodos os lugares, funcionou para mim.

Também tentei

  1. Desativando a filtragem de caminho reverso, rp_filter=0em/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 estão aqui .

ilyaigpetrov
fonte

Respostas:

10

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 tun0interface e seu endereço local é 10.0.0.1). Você captura os pacotes, está tudo bem até agora.
Agora, tun0envia os pacotes ainda mais. O endereço de origem é 10.0.0.1e você deseja que os pacotes saiam por uma interface diferente ( wlp2s0no seu caso). Esse é o roteamento, então vamos habilitar o roteamento primeiro:

sysctl -w net.ipv4.ip_forward=1

Depois disso, se você olhar tcpdumppara wlp2s0você pode notar os pacotes sair com endereço de origem 10.0.0.1e 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 FORWARDcadeia possui ACCEPTpolí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 tun0interface para wlp2s0. O netfilter deve alterar o IP de origem 10.0.0.1para o wlp2s0endereç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 wlp2s0atribuí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 OUTPUTcadeia e depois é roteado e chega à PREROUTINGcadeia. Pelo menos na caixa Debian 8, ele não funciona.
A melhor maneira de solucionar problemas do netfilter é o TRACErecurso:

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 FORWARDcadeia (e não está sendo capturado pela nat/POSTROUTINGcadeia 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.caplicativo. É 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.ccom 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.cinicio:

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 - tun0apenas 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 SNATantes que o pacote chegue à tun0interface. 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 tun0dispositivo. tun0.cO 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/POSTROUTINGcadeia na wlp2s0interface 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 tun0porque 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.

tifssoft
fonte
Eu tive que usar -j SNAT, não-s SNAT
ilyaigpetrov
Funciona, mas o desempenho é muito intermitente (pode parar por 10 segundos e continuar funcionando). Vou descobrir por que isso acontece e como consertar isso.
ilyaigpetrov
1
Desculpe, foi o meu erro de digitação. Eu adicionei outra abordagem à minha resposta. Não tenho idéia sobre o problema de desempenho. A propósito, por que não usar um proxy transparente com o iptables DNAT para filtrar e desviar o tráfego?
Tifssoft 30/11/2017
Não sou capaz de reproduzir a abordagem da sua marca, adicionei apenas sudo ip rule add iif tun0 lookup main priority 500a ela, mas ainda assim não funcionou. Eu gosto dessa abordagem, pena que não posso reproduzi-la.
ilyaigpetrov
1
Obrigado por sua nova abordagem, eu a segui passo a passo e funcionou perfeitamente. No entanto, não entendo por que precisamos mudar os ips, o mais importante é que funciona. Caso meus planos com o proxy TCP falhem, poderei retornar à sua resposta. Você mostrou muitas habilidades de rede aqui e não duvido que suas habilidades serão cobiçadas. Boa sorte!
Ilyaigpetrov 04/12