Testando iptables Regra DNAT usando localmente o NetCat

1

Minha pergunta geral é esta: Qual é a melhor maneira (mais simples, mais fácil, mais rápida, menos propensa a erros, etc.) para verificar as regras NAT do iptables localmente em um único host (ou seja, sem uma conexão de rede) na linha de comando ?

A seguir, os detalhes de tentativas específicas (com falha) de verificar uma regra DNAT simples usando o NetCat. Eu estou esperando por uma resolução do meu problema específico neste caso, mas também por uma resposta à minha pergunta geral.

Estou trabalhando em uma máquina virtual VirtualBox rodando Debian 8 (Jessie). Eu quero usar o netcat para executar um teste básico de uma regra DNAT simples.

Para o meu teste, tudo o que quero fazer é enviar alguns dados para um endereço local (por exemplo, 192.168.0.1 ) e fazer com que ele chegue em outro endereço local (por exemplo, 192.168.0.2 ).

Já experimentei várias abordagens diferentes:

  1. Interfaces fictícias e a cadeia PREROUTING

  2. Interfaces virtuais e a cadeia PREROUTING

  3. Usando a cadeia OUTPUT em vez de PREROUTING

Interfaces fictícias e a cadeia PREROUTING

Minha primeira tentativa foi adicionar uma regra DNAT à cadeia PREROUTING e adicionar duas interfaces fictícias com os endereços apropriados.

Aqui está minha regra:

sudo iptables \
-t nat \
-A PREROUTING \
-d 192.168.0.1 \
-j DNAT --to-destination 192.168.0.2

Não existem outras regras do netfilter no meu firewall. Mas só para ter certeza, aqui está a saída de iptables-save :

# Generated by iptables-save v1.4.21

*nat
:PREROUTING ACCEPT [0:0]
:INPUT ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
-A PREROUTING -d 192.168.0.1/32 -j DNAT --to-destination 192.168.0.2
COMMIT

*filter
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
COMMIT

Para reiterar, tudo o que quero fazer é enviar alguns dados para o endereço 192.168.0.1 e chegar ao endereço 192.168.0.2 .

Provavelmente vale a pena mencionar que a sub-rede 192.168.0.0/24 não é usada em minha VM. Primeiro, adiciono algumas interfaces fictícias:

sudo ip link add dummy1 type dummy

sudo ip link add dummy2 type dummy

Em seguida, atribuo os endereços IP às interfaces fictícias no intervalo de sub-rede desejado:

sudo ip addr add 192.168.0.1/24 dev dummy1

sudo ip addr add 192.168.0.2/24 dev dummy2

E então eu trago as interfaces para cima:

sudo ip link set dummy1 up

sudo ip link set dummy2 up

Aqui está a aparência da minha tabela de roteamento agora:

default via 10.0.2.2 dev eth0
10.0.2.0/24     dev eth0    proto kernel  scope link  src 10.0.2.15
192.168.0.0/24  dev dummy1  proto kernel  scope link  src 192.168.0.1
192.168.0.0/24  dev dummy2  proto kernel  scope link  src 192.168.0.2
192.168.56.0/24 dev eth1    proto kernel  scope link  src 192.168.56.100

Agora eu escuto o primeiro endereço (fonte) usando o netcat:

nc -l -p 1234 -s 192.168.0.1

E eu me conecto ao servidor netcat com um cliente netcat (em uma janela de terminal separada):

nc 192.168.0.1 1234

O texto digitado em uma janela aparece no outro - exatamente como esperado.

Eu também faço o mesmo com o segundo endereço:

nc -l -p 1234 -s 192.168.0.2

nc 192.168.0.2 1234

Mais uma vez, o texto digitado em uma janela aparece no outro - como esperado.

Por fim, tento ouvir o endereço de destino (DNAT) e conectar-me pelo endereço de origem (DNAT):

nc -l -p 1234 -s 192.168.0.2

nc 192.168.0.1 1234

Infelizmente, a conexão falha com o seguinte erro:

(UNKNOWN) [192.168.0.1] 1234 (?) : Connection refused

Eu também tentei usar ping -c 1 -R 192.168.0.1 para ver se o DNAT estava entrando em vigor, mas não parece que é o caso:

PING 192.168.0.1 (192.168.0.1) 56(124) bytes of data.
64 bytes from 192.168.0.1: icmp_seq=1 ttl=64 time=0.047 ms
RR:     192.168.0.1
        192.168.0.1
        192.168.0.1
        192.168.0.1


--- 192.168.0.1 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.047/0.047/0.047/0.000 ms

Por que isso não está funcionando? O que estou fazendo errado?

Diagnóstico com o tcpdump

Para diagnosticar esse problema, tentei usar tcpdump para ouvir o tráfego nas interfaces fictícias. Eu tentei ouvir todas as interfaces (e filtrar SSH e DNS):.

sudo tcpdump -i any -e port not 22 and port not 53

Em seguida, fiz o ping na interface dummy1 :

ping -n -c 1 -I dummy1 192.168.0.1

Isso produziu os seguintes resultados:

listening on any, link-type LINUX_SLL (Linux cooked), capture size 262144 bytes
In 00:00:00:00:00:00 (oui Ethernet) ethertype IPv4 (0x0800), length 100: 192.168.0.1 > 192.168.0.1: ICMP echo request, id 8071, seq 1, length 64
In 00:00:00:00:00:00 (oui Ethernet) ethertype IPv4 (0x0800), length 100: 192.168.0.1 > 192.168.0.1: ICMP echo reply, id 8071, seq 1, length 64

Portanto, parece que as interfaces fictícias estão conectadas à interface de loopback. Isso pode significar que as regras do iptables estão sendo totalmente contornadas.

Interfaces virtuais e a cadeia PREROUTING

Como segunda tentativa, tentei usar os chamados endereços IP virtuais em vez de interfaces fictícias.

Veja como adicionei os endereços IP "virtuais" às interfaces eth0 e eth1:

sudo ip addr add 192.168.0.100/24 dev eth0
sudo ip addr add 192.168.0.101/24 dev eth1

OBSERVAÇÃO: eu usei diferentes endereços IP para eles do que para a interface fictícia.

Então corri e atualizei as regras NAT do iptables:

sudo iptables -F -t nat

sudo iptables \
-t nat \
-A PREROUTING \
-d 192.168.0.100 \
-j DNAT --to-destination 192.168.0.101

Eu tentei novamente o teste de ping:

ping -n -c 1 -R 192.168.0.100

Sem dados:

PING 192.168.0.100 (192.168.0.100) 56(124) bytes of data.
64 bytes from 192.168.0.100: icmp_seq=1 ttl=64 time=0.023 ms
RR:     192.168.0.100
        192.168.0.100
        192.168.0.100
        192.168.0.100


--- 192.168.0.100 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.023/0.023/0.023/0.000 ms

Em seguida, o teste netcat novamente. Inicie o servidor:

nc -l -p 1234 -s 192.168.0.101

Tente conectar o cliente:

nc 192.168.0.100 1234

Também não há dados:

(UNKNOWN) [192.168.0.100] 1234 (?) : Connection refused

Usando a cadeia OUTPUT em vez de PREROUTING

Então eu tentei mover ambas as regras DNAT da cadeia PREROUTING para a cadeia OUTPUT:

sudo iptables -F -t nat

sudo iptables \
-t nat \
-A OUTPUT \
-d 192.168.0.1 \
-j DNAT --to-destination 192.168.0.2

sudo iptables \
-t nat \
-A OUTPUT \
-d 192.168.0.100 \
-j DNAT --to-destination 192.168.0.101

Agora, tento ping nas interfaces fictícias e virtuais:

user@host:~$ ping -c 1 -R 192.168.0.1
PING 192.168.0.1 (192.168.0.1) 56(124) bytes of data.
64 bytes from 192.168.0.1: icmp_seq=1 ttl=64 time=0.061 ms
RR:     192.168.0.1
        192.168.0.2
        192.168.0.2
        192.168.0.1


--- 192.168.0.1 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.061/0.061/0.061/0.000 ms

user@host:~$ ping -c 1 -R 192.168.0.100

PING 192.168.0.100 (192.168.0.100) 56(124) bytes of data.
64 bytes from 192.168.0.100: icmp_seq=1 ttl=64 time=0.058 ms
RR:     192.168.0.100
        192.168.0.101
        192.168.0.101
        192.168.0.100


--- 192.168.0.100 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.058/0.058/0.058/0.000 ms

E também testei o teste cliente-servidor netcat para cada par de endereços IP:

nc -l -p 1234 -s 192.168.0.2

nc 192.168.0.1 1234

e:

nc -l -p 1234 -s 192.168.0.101

nc 192.168.0.100 1234

Este teste também é bem sucedido.

Portanto, parece que as interfaces fictícia e virtual funcionam quando a regra DNAT está na cadeia OUTPUT, em vez da cadeia PREROUTING.

Parece que parte do meu problema é que não estou claro em quais pacotes percorrem as cadeias.

    
por igal 15.11.2017 / 22:31

1 resposta

0

Breve Explicação: As interfaces fictícias e os endereços IP virtuais enviam pacotes através da interface de loopback, que não é afetada pela cadeia PREROUTING. Usando namespaces de rede com interfaces veth, podemos enviar tráfego de um endereço IP para outro de forma a modelar com mais precisão o tráfego de rede de vários hosts e nos permite testar a regra DNAT na cadeia PREROUTING, conforme desejado.

Uma descrição mais detalhada da solução segue.

Aqui está um script Bash que configura um par de interfaces de rede e testa que a regra DNAT está funcionando conforme o esperado:

# Create a network namespace to represent a client
sudo ip netns add 'client'

# Create a network namespace to represent a server
sudo ip netns add 'server'

# Create a veth virtual-interface pair
sudo ip link add 'client-eth0' type veth peer name 'server-eth0'

# Assign the interfaces to the namespaces
sudo ip link set 'client-eth0' netns 'client'
sudo ip link set 'server-eth0' netns 'server'

# Change the names of the interfaces (I prefer to use standard interface names)
sudo ip netns exec 'client' ip link set 'client-eth0' name 'eth0'
sudo ip netns exec 'server' ip link set 'server-eth0' name 'eth0'

# Assign an address to each interface
sudo ip netns exec 'client' ip addr add 192.168.1.1/24 dev eth0
sudo ip netns exec 'server' ip addr add 192.168.2.1/24 dev eth0

# Bring up the interfaces (the veth interfaces the loopback interfaces)
sudo ip netns exec 'client' ip link set 'lo' up
sudo ip netns exec 'client' ip link set 'eth0' up
sudo ip netns exec 'server' ip link set 'lo' up
sudo ip netns exec 'server' ip link set 'eth0' up

# Configure routes
sudo ip netns exec 'client' ip route add default via 192.168.1.1 dev eth0
sudo ip netns exec 'server' ip route add default via 192.168.2.1 dev eth0

# Test the connection (in both directions)
sudo ip netns exec 'client' ping -c 1 192.168.2.1
sudo ip netns exec 'server' ping -c 1 192.168.1.1

# Add a DNAT rule to the server namespace
sudo ip netns exec 'server' \
iptables \
-t nat \
-A PREROUTING \
-d 192.168.2.1 \
-j DNAT --to-destination 192.168.2.2

# Add a dummy interface to the server (we need a target for the destination address)
sudo ip netns exec 'server' ip link add dummy type dummy
sudo ip netns exec 'server' ip addr add 192.168.2.2/24 dev dummy
sudo ip netns exec 'server' ip link set 'dummy' up

# Test the DNAT rule using ping
sudo ip netns exec 'client' ping -c 1 -R 192.168.2.1

A saída do teste de ping mostra que a regra está funcionando:

PING 192.168.2.1 (192.168.2.1) 56(124) bytes of data.
64 bytes from 192.168.2.1: icmp_seq=1 ttl=64 time=0.025 ms
RR:     192.168.1.1
        192.168.2.2
        192.168.2.2
        192.168.1.1


--- 192.168.2.1 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.025/0.025/0.025/0.000 ms

Agora também posso realizar meu teste do NetCat. Primeiro eu escuto no servidor:

sudo ip netns exec 'server' nc -l -p 1234 -s 192.168.2.2

E depois me conecto via cliente (em uma janela de terminal separada):

sudo ip netns exec 'client' nc 192.168.2.1 1234

O texto digitado em uma janela do terminal aparece no outro - sucesso!

    
por 20.11.2017 / 17:43