Forçar o tráfego IP local para uma interface externa

30

Eu tenho uma máquina com várias interfaces que eu posso configurar como eu quero, por exemplo:

  • eth1: 192.168.1.1
  • eth2: 192.168.2.2

Gostaria de encaminhar todo o tráfego enviado para um desses endereços locais através da outra interface. Por exemplo, todas as solicitações para um servidor iperf, ftp, http em 192.168.1.1 devem não apenas ser roteadas internamente, mas encaminhadas através do eth2 (e a rede externa cuidará do roteamento do pacote para o eth1).

Eu tentei e olhei para vários comandos, como iptables, ip route, etc ... mas nada funcionou.

O comportamento mais próximo que pude ter foi feito com:

ip route change to 192.168.1.1/24 dev eth2

que envia todo o 192.168.1.x no eth2, exceto o 192.168.1.1 que ainda é roteado internamente. Pode ser que eu possa fazer o encaminhamento NAT de todo o tráfego direcionado para 192.168.1.2 falso no eth1, redirecionado para 192.168.1.1 internamente? Na verdade, estou lutando com o iptables, mas é muito difícil para mim.

O objetivo dessa configuração é fazer o teste do driver de interface sem usar dois PCs.

Estou usando o Linux, mas se você souber fazer isso com o Windows, eu compro!

Editar:

A rede externa é apenas um cabo cruzado entre eth1 e eth2. Digamos que eu tenha um servidor http na minha máquina. Agora, quero acessar esse servidor da mesma máquina, mas quero forçar o tráfego TCP / IP a passar por esse cabo eth1 / eth2. Como devo configurar minhas interfaces para isso?

calandoa
fonte
Você está dizendo que deseja que todo o tráfego seja espelhado pelas interfaces 1 e 2, mas retorne à interface 2 apenas de outro roteador? Isso não poderia fazer algumas coisas bem estranhas na rede? Seria melhor direcionar o tráfego espelhado da interface 2 para outro sistema que apenas reduziu o tráfego e você pode monitorá-lo ou usar o software de virtualização para capturar o tráfego? Talvez esteja faltando alguma coisa na descrição.
Bart Silverstrim
Parece que ele deseja gerar um pacote para, digamos, 192.168.1.1, que é o IP do eth1. Mas, em vez de a pilha do Linux receber esse pacote inteiramente internamente, ele deseja que o pacote seja expulso do eth2 (que será entregue externamente de volta ao eth1 e depois à pilha do Linux). Não tenho certeza se isso é possível; uma vez que a camada de rede detecte o endereço como uma interface interna, ela terá poucos motivos para examinar as tabelas de roteamento. Outra pessoa pode saber melhor.
PP.

Respostas:

14

Expandi a resposta de caladona, pois não conseguia ver os pacotes de resposta. Para este exemplo:

  1. No meu PC local, tenho placas de rede em diferentes sub-redes, 192.168.1 / 24 , 192.168.2 / 24
  2. Há um roteador / PC externo que tem acesso às duas sub-redes.
  3. Desejo enviar tráfego bidirecional pelas NICs no PC local.
  4. A configuração requer dois endereços IP não utilizados para cada sub-rede.

As rotas iptable do PC local são definidas para o tráfego de saída SNAT e DNAT para o IP 'falso'.

iptables -t nat -A POSTROUTING -d 192.168.1.100 -s 192.168.2.0/24 -j SNAT --to-source      192.168.2.100
iptables -t nat -A PREROUTING  -d 192.168.1.100 -i eth0           -j DNAT --to-destination 192.168.1.1
iptables -t nat -A POSTROUTING -d 192.168.2.100 -s 192.168.1.0/24 -j SNAT --to-source      192.168.1.100
iptables -t nat -A PREROUTING  -d 192.168.2.100 -i eth1           -j DNAT --to-destination 192.168.2.1

As regras fazem o seguinte:

  1. Reescreva a fonte 192.168.2.1 para 192.168.2.100 nos pacotes de saída
  2. Reescreva o destino 192.168.1.100 para 192.168.1.1 nos pacotes recebidos
  3. Reescreva a fonte 192.168.1.1 para 192.168.1.100 nos pacotes de saída
  4. Reescreva o destino 192.168.2.100 para 192.168.2.1 nos pacotes recebidos

Para resumir, o sistema local agora pode conversar com uma máquina 'virtual' com os endereços 192.168.1.100 e 192.168.2.100.

Em seguida, você deve forçar seu PC local a usar o roteador externo para alcançar seu IP falso. Você faz isso criando uma rota direta para os IPs através do roteador. Você deseja garantir que você force os pacotes para o lado oposto da sub-rede de destino.

ip route 192.168.1.100 via $ROUTER_2_SUBNET_IP 
ip route 192.168.2.100 via $ROUTER_1_SUBNET_IP

Finalmente, para fazer tudo isso funcionar, o roteador externo precisa saber como alcançar os IPs falsificados no seu PC local. Você pode fazer isso ativando os ARPs de proxy no seu sistema.

echo 1 | sudo tee /proc/sys/net/ipv4/conf/all/proxy_arp
echo 1 | sudo tee /proc/sys/net/ipv4/ip_forward

Com essa configuração, agora você pode tratar os IPs falsos como um sistema real no seu PC local. Enviar dados para a sub-rede .1 forçará os pacotes a sair da interface .2. Enviar dados para a sub-rede .2 forçará os pacotes a sair da interface .1.

ping 192.168.1.100
ping 192.168.2.100
cmcginty
fonte
Muito melhor do seu jeito! Note que eu também preciso de um ip_forward ter o material ARP trabalho: echo 1> / proc / sys / net / ipv4 / ip_forward
calandoa
28

Usei com êxito o seguinte no Linux para testar a taxa de transferência em uma nova placa de 10 Gbps de porta dupla no modo "loopback", ou seja, uma porta conectada diretamente à outra. Isso é apenas um pouco de vodu apenas para forçar os pacotes a sair, mas se não o fizer, o Linux apenas entrará em curto-circuito com o kernel (daí a pergunta do OP). Na resposta de Casey acima, não tenho certeza se era realmente necessário ter um roteador externo ou não acima, mas o seguinte é completamente independente. As duas interfaces são eth2 e eth3.

Dê IPs para as interfaces e coloque-os em redes separadas:

ifconfig eth2 10.50.0.1/24
ifconfig eth3 10.50.1.1/24

Em seguida, configuraremos um cenário NAT duplo: duas novas redes falsas usadas para alcançar o outro. Na saída, forneça o NAT à sua rede falsa. No caminho, fixe o destino. E vice-versa para a outra rede:

# nat source IP 10.50.0.1 -> 10.60.0.1 when going to 10.60.1.1
iptables -t nat -A POSTROUTING -s 10.50.0.1 -d 10.60.1.1 -j SNAT --to-source 10.60.0.1

# nat inbound 10.60.0.1 -> 10.50.0.1
iptables -t nat -A PREROUTING -d 10.60.0.1 -j DNAT --to-destination 10.50.0.1

# nat source IP 10.50.1.1 -> 10.60.1.1 when going to 10.60.0.1
iptables -t nat -A POSTROUTING -s 10.50.1.1 -d 10.60.0.1 -j SNAT --to-source 10.60.1.1

# nat inbound 10.60.1.1 -> 10.50.1.1
iptables -t nat -A PREROUTING -d 10.60.1.1 -j DNAT --to-destination 10.50.1.1

Agora diga ao sistema como chegar a cada rede falsa e preencha as entradas arp (certifique-se de substituir seus endereços MAC, não use o meu):

ip route add 10.60.1.1 dev eth2
arp -i eth2 -s 10.60.1.1 00:1B:21:C1:F6:0F # eth3's mac address

ip route add 10.60.0.1 dev eth3 
arp -i eth3 -s 10.60.0.1 00:1B:21:C1:F6:0E # eth2's mac address

Isso engana o Linux o suficiente para realmente colocar pacotes no fio. Por exemplo:

ping 10.60.1.1

sai eth2, o IP de origem 10.50.0.1 recebe NAT para 10.60.0.1 e, quando entra em eth3, o destino 10.60.1.1 recebe NAT para 10.50.1.1. E a resposta segue uma jornada semelhante.

Agora use o iperf para testar a taxa de transferência. Ligue-se aos IPs corretos e verifique com qual IP você está entrando em contato (o endereço falso da outra extremidade):

# server
./iperf -B 10.50.1.1 -s

# client: your destination is the other end's fake address
./iperf -B 10.50.0.1 -c 10.60.1.1 -t 60 -i 10

Verifique se o tráfego está realmente saindo para o fio:

tcpdump -nn -i eth2 -c 500

Você também pode assistir / proc / interrupts apenas para ter certeza absoluta de que o cartão está sendo usado:

while true ; do egrep 'eth2|eth3' /proc/interrupts ; sleep 1 ; done

De qualquer forma, encontrei este post procurando como fazer isso, obrigado pela equipe de perguntas e respostas e espero que isso ajude outras pessoas a encontrar este post no futuro.

Steve Kehlet
fonte
+1 Ótima solução - nem é necessário ativar o encaminhamento de ip! Isso é exatamente o que eu precisava agora (para testes de 10 GB via loopback).
Nils
16

Como sempre - estou um pouco atrasado - mas hoje em dia é possível usar namespaces de rede para isolar as interfaces e impedir o encaminhamento local (e mexer com o iptables :)).

Crie namespaces (todos feitos com as permissões necessárias, por exemplo, como root):

ip netns add ns_server
ip netns add ns_client

Observe que o status / configuração das interfaces agora deve ser acessado no contexto do espaço para nome atribuído - para que não apareçam se você executar um link IP sem proteção, pois é executado no contexto do espaço para nome padrão. A execução de um comando em um espaço para nome pode ser feita usando

ip netns exec <namespace-name> <command>

como prefixo.

Agora atribua namespaces às interfaces, aplique a configuração e configure as interfaces:

ip link set eth1 netns ns_server
ip netns exec ns_server ip addr add dev eth1 192.168.1.1/24
ip netns exec ns_server ip link set dev eth1 up
ip link set eth2 netns ns_client
ip netns exec ns_client ip addr add dev eth2 192.168.1.2/24
ip netns exec ns_client ip link set dev eth2 up

Agora você pode executar os aplicativos dentro do namespace - para o servidor iperf, execute

ip netns exec ns_server iperf -s -B 192.168.1.1

e o cliente:

ip netns exec ns_client iperf -c 192.168.1.1 -B 192.168.1.2

O tráfego agora será enviado pelas interfaces físicas, pois todo o pilha de rede, interface, roteamento ... é isolado pelos espaços de nomes, para que o kernel não consiga corresponder os endereços usados ​​no tráfego com as interfaces locais (disponíveis).

Se você concluiu suas experiências, exclua os espaços para nome:

ip netns del <namespace-name>

As interfaces serão reatribuídas ao espaço para nome padrão e todas as configurações feitas no espaço para nome desaparecem (por exemplo, não é necessário excluir os endereços IP atribuídos).

Thomas Tannhäuser
fonte
Isso é muito mais direto do que a magia de dupla natureza que está sendo sugerida e não requer nenhuma coordenação de outros computadores na rede nem assume nenhuma topologia física. Meu único pedido seria que você adicionasse comandos para adicionar rotas.
Huckle
2

Ok, finalmente consegui configurar minha configuração.

A idéia é usar outro endereço falso, forçar a rota desse endereço falso para a interface 2 e depois traduzir o endereço falso com o endereço real 2 com NAT / iptables.

Minha configuração é na verdade feita de um roteador que eu posso telnetar entre IF1 (interface 1) e IF2

Na minha configuração, FAKE_ADDR e IF1_ADDR estão na mesma sub-rede.

ifconfig $IF1 $IF1_ADDR netmask 255.255.255.0
ifconfig $IF2 $IF2_ADDR netmask 255.255.255.0

iptables -t nat -A PREROUTING -d $FAKE_ADDR -i $IF2 -j DNAT --to-destination $IF2_ADDR
iptables -t nat -A POSTROUTING -s $IF2_ADDR -d $IF1_ADDR/24 -j SNAT --to-source $FAKE_ADDR

route add $FAKE_ADDR gw $ROUTER_ADDR

E no roteador:

route add $FAKE_ADDR gw $IF2_ADDR

Se eu enviar algo para FAKE_ADDR, o pkt será encaminhado pelo IF1 para o roteador, encaminhado novamente para o IF2, e o FAKE_IP será substituído pelo IF2_ADDR. O pacote é processado pelo servidor, o resultado é enviado de volta para IF1_ADDR, a partir de IF2_ADDR, que é substituído por FAKE_ADDR.

Pode ser possível usar uma configuração mais simples com apenas um cabo cruzado, mas como eu não tentei, prefiro dar a minha solução de trabalho.

calandoa
fonte
se o roteador estiver enviando $ FAKE_ADDR para $ IF2_ADDR, sua regra DNAT não precisa ser "-i $ IF2" em vez de "-i $ IF1"?
cmcginty
Você está certo Casey, correção feita.
Calandoa 31/03/10
1

A resposta dada acima por Thomas Tannhäuser foi imediata!

Eu tive uma situação semelhante: uma única máquina com duas interfaces enet. Meu plano era usar uma interface como servidor (receptor) e a outra como cliente (remetente). Cada interface seria conectada ao roteador e o iperf direcionaria o tráfego através do roteador para medir a taxa de transferência, PPS, atraso, etc.

Infelizmente, a abordagem do iptables não era intuitiva e cheia de problemas. Depois de algumas horas frustrantes, abandonei esse plano de ataque. Inspirado pela sugestão de Thomas, fiz um pouco de lição de casa nos namespaces IP do Linux e comecei a apreciar a simplicidade e a elegância dessa solução.

Abaixo está uma lista dos comandos exatos que eu usei para configurar o meu Fedora FC26 para servir nessa capacidade. As duas interfaces são enp1s0 e enp3s0. O roteador possui duas interfaces com os endereços 192.168.2.112 e 172.16.16.2. Cada conector FC26 ENET é diretamente conectado à interface do roteador correspondente.

# How to configure the IP Namespaces
ip netns add iperf-server
ip netns add iperf-client
ip link set enp1s0 netns iperf-server
ip link set enp3s0 netns iperf-client
ip netns exec iperf-server ip addr add dev enp1s0 192.168.2.139/20
ip netns exec iperf-client ip addr add dev enp3s0 172.16.16.2/24
ip netns exec iperf-client ip link set dev enp3s0 up
ip netns exec iperf-server ip link set dev enp1s0 up
ip netns exec iperf-server route add default gw 192.168.2.112
ip netns exec iperf-client route add default gw 172.16.16.1

# Test the interfaces and network using ping
ip netns exec iperf-client ping -c1 172.16.16.1
ip netns exec iperf-server ping -c1 192.168.2.112
ip netns exec iperf-server ping -c1 172.16.16.2
ip netns exec iperf-client ping -c1 192.168.2.139

# Start Iperf Server for UDP test
ip netns exec iperf-server iperf -u -s
# Run Client against Iperf server for UDP test
ip netns exec iperf-client iperf -u -c 192.168.2.139
RarkyMan
fonte
0

Parece que você deseja transformar sua caixa Linux em uma caixa do tipo roteador / ponte / gateway / firewall. Os seguintes recursos podem ser o que você está procurando:

O projeto do roteador Linux

Lista de distribuições de roteador ou firewall

Roteador Linux LiveCD

Linux Journal - O roteador Linux

Atualização com base em mais informações:

Eu não acho que você será capaz de fazer o que quiser. O sistema operacional sempre examinará sua tabela de roteamento interno e 'verá' os dois endereços IP localmente. Em seguida, ele encaminhará o tráfego no sistema operacional e nunca o ligará. Você precisará de uma segunda máquina ou duas máquinas virtuais (confira o Xen ).

Pedro
fonte
0

Um monte de coisas para passar por aqui, então não posso garantir totalmente minha precisão, mas a pergunta original parece estar procurando o que é conhecido como técnica "enviar para si mesmo" . A pesquisa vinculada mostra o que eu acho que é o patch de kernel mais bem mantido, como principais links + discussões e patches com outras abordagens em várias listas de discussão, esp. LKML.

Eu acho que também devemos olhar para os namespaces da rede , feitos com os "ip netns" do iproute2 . Isso também requer alguma interface extra e mágica de roteamento, portanto, pode até não ser menos complexo do que o enorme tumulto do iptables nas outras respostas.

Os comentários são definitivamente bem-vindos se alguém encontrar algo útil com eles - o como, o quê e o que acontece com sua implementação.

lkraav
fonte
-1

aqui está como eu consegui trabalhar para IPV6

ips estáticos atribuídos

/sbin/ifconfig eth1 inet6 add 2001:db8::1/127 
/sbin/ifconfig eth3 inet6 add 2001:db8::2/127 

configurar somente rotas de host para endereços "FAKE"

ip -6 route add 2001:db8::2/128 dev eth1 metric 1
ip -6 route add 2001:db8::1/128 dev eth3 metric 1

preencheu a tabela Vizinho ... como o arp

ip -6 neighbor add 2001:db8::1 lladdr 90:e2:ba:0d:75:e8 dev eth3 # eth1's mac address
ip -6 neighbor add 2001:db8::2 lladdr 90:e2:ba:0d:75:e9 dev eth1 # eth3's mac address

adicionadas as entradas ip6tables

ip6tables -t nat -A POSTROUTING -s 2001:db8::1 -d 2013::2 -j SNAT --to-source 2001:db8::1
ip6tables -t nat -A PREROUTING -d 2001:db8::1 -j DNAT --to-destination 2001:db8::1
ip6tables -t nat -A POSTROUTING -s 2001:db8::2 -d 2013::1 -j SNAT --to-source 2001:db8::2
ip6tables -t nat -A PREROUTING -d 2001:db8::2 -j DNAT --to-destination 2001:db8::2
robm
fonte
Que distribuição você está usando? Na última vez que verifiquei, o kernel não possui uma tabela NAT para IPv6.
Fkawi2