Linux - duas sub-redes, uma interface, um gateway - NAT a sub-rede adicional

4

Atualmente, temos alguns servidores que usam a mesma LAN:

Host1: eth0 10.0.0.1/24
Host2: eth0 10.0.0.2/24
Host3: eth0 10.0.0.3/24
Gateway: 10.0.0.254 

Queremos executar algumas VMs (VirtualBox) nesses servidores. Podemos configurá-los para fazer a ponte sobre a eth0 do host, mas não podemos usar endereços da faixa 10.0.0.0/24, pois eles podem ser alocados no futuro.

Então, achamos que usaríamos uma sub-rede diferente:

Host1VM: eth0 192.168.0.1/24 (bridge to host eth0)
Host2VM: eth0 192.168.0.2/24 (bridge to host eth0)
Host3VM: eth0 192.168.0.3/24 (bridge to host eth0)

Tudo bem e todas as VMs podem se comunicar umas com as outras, pois estão na mesma sub-rede que usa a mesma interface física.

O problema que enfrentamos é que precisamos dar acesso a essas VMs à Internet através do gateway 10.0.0.254. Então nós imaginamos porque não escolher um dos hosts e usá-lo como um roteador / NAT?

Host1: eth0 10.0.0.1/24, eth0:0 192.168.0.254/24

Agora podemos fornecer às VMs um gateway de 192.168.0.254. O problema que vemos então é que o Host1 não parece corretamente ao NAT.

iptables -t nat -A POSTROUTING -s 192.168.0.0/24 -o eth0 -j SNAT --to 10.0.0.1

Eu achei que funcionaria, e nós vemos pacotes correspondentes. Se uma VM pinga a internet, vemos o pacote ICMP entrar no Host1 (já que é o roteador) e, em seguida, o host reenvia o ICMP porque é NAT, o host da Internet responde ao host - mas, em seguida, morre lá. Eu esperava que o host enviasse o pacote de volta para a VM, mas isso não acontece.

O que estou perdendo ou essa configuração simplesmente não é possível?

Editar : Só para esclarecer, não temos regras DENY dentro do iptables, tudo é o padrão ACCEPT. Também habilitamos o encaminhamento de IP.

Update1 - iptables

Ignore o virbr0 - que não está relacionado a VMs do VirtualBox

# Completed on Fri Sep 20 16:50:45 2013
# Generated by iptables-save v1.4.12 on Fri Sep 20 16:50:45 2013
*nat
:PREROUTING ACCEPT [171383:10358740]
:INPUT ACCEPT [1923:115365]
:OUTPUT ACCEPT [192:21531]
:POSTROUTING ACCEPT [169544:10254463]
-A POSTROUTING -s 192.168.0.0/24 -o eth0 -j SNAT --to-source 10.0.0.1
COMMIT
# Completed on Fri Sep 20 16:50:45 2013
# Generated by iptables-save v1.4.12 on Fri Sep 20 16:50:45 2013
*filter
:INPUT ACCEPT [96628707:25146145432]
:FORWARD ACCEPT [195035595:22524430122]
:OUTPUT ACCEPT [44035412:304951330498]
-A INPUT -i virbr0 -p udp -m udp --dport 53 -j ACCEPT
-A INPUT -i virbr0 -p tcp -m tcp --dport 53 -j ACCEPT
-A INPUT -i virbr0 -p udp -m udp --dport 67 -j ACCEPT
-A INPUT -i virbr0 -p tcp -m tcp --dport 67 -j ACCEPT
-A FORWARD -d 192.168.122.0/24 -o virbr0 -m state --state RELATED,ESTABLISHED -j ACCEPT
-A FORWARD -s 192.168.122.0/24 -i virbr0 -j ACCEPT
-A FORWARD -i virbr0 -o virbr0 -j ACCEPT
-A FORWARD -o virbr0 -j REJECT --reject-with icmp-port-unreachable
-A FORWARD -i virbr0 -j REJECT --reject-with icmp-port-unreachable
COMMIT
# Completed on Fri Sep 20 16:50:45 2013
# Generated by iptables-save v1.4.12 on Fri Sep 20 16:50:45 2013
*mangle
:PREROUTING ACCEPT [291641356:47665886851]
:INPUT ACCEPT [96628707:25146145432]
:FORWARD ACCEPT [195035595:22524430122]
:OUTPUT ACCEPT [44035838:304951365412]
:POSTROUTING ACCEPT [239078922:327477732680]
-A POSTROUTING -o virbr0 -p udp -m udp --dport 68 -j CHECKSUM --checksum-fill
-A POSTROUTING -o virbr0 -p udp -m udp --dport 68 -j CHECKSUM --checksum-fill
COMMIT
# Completed on Fri Sep 20 16:50:45 2013

Atualização 2 - tcpdump

16:58:37.189758 IP 192.168.0.2 > 74.125.128.106: ICMP echo request, id 1, seq 2, length 40
16:58:37.189805 IP 10.0.0.1 > 74.125.128.106: ICMP echo request, id 1, seq 2, length 40
16:58:37.194607 IP 74.125.128.106 > 10.0.0.1: ICMP echo reply, id 1, seq 2, length 40
(no final reply back to the VM)
    
por AndyC 20.09.2013 / 09:53

4 respostas

2

Vou responder a minha própria pergunta, pois é assim que resolvi isso. Tenho certeza de que as outras respostas são mais do que precisas em circunstâncias normais, mas acredito que elas não funcionaram devido a um bug ou a uma limitação do uso de aliases de interface.

Então, pensando que o alias da interface estava causando o problema, procurei outras maneiras de fornecer uma interface virtual, e existe um tipo de interface virtual chamado MAC-VLAN, que essencialmente se anexa à interface física como um virtual. interface com seu próprio endereço MAC.

Usando isso, o NAT funcionou perfeitamente na primeira vez, então eu presumo que foi simplesmente devido a interface MAC-VLAN aparecer no kernel como uma interface completamente separada, enquanto aliases de interface estão causando alguma confusão em algum lugar.

Para referência, o comando para criar uma MAC-VLAN é simplesmente:

ip link add dev macvlan0 link eth0 type macvlan

É um recurso muito legal, não posso acreditar que não tenha ouvido falar disso antes.

    
por 21.09.2013 / 06:09
2

Isso está dizendo:

16:58:37.189758 IP 192.168.0.2 > 74.125.128.106: ICMP echo request, id 1, seq 2, length 40
16:58:37.189805 IP 10.0.0.1 > 74.125.128.106: ICMP echo request, id 1, seq 2, length 40
16:58:37.194607 IP 74.125.128.106 > 10.0.0.1: ICMP echo reply, id 1, seq 2, length 40

O roteador upstream ( 10.0.0.254 ) está enviando a resposta de volta ao Host1, portanto, seu roteamento e SNAT estão funcionando. O problema é que o Host1 não está passando essa resposta de volta para a rede 192.168.0.0/24 .

Você tem os módulos do kernel de rastreamento de conexão apropriados carregados?

Verifique se o tráfego está indo para a tabela de acompanhamento de conexões:

grep src=192.168.0.2 /proc/1/net/nf_conntrack

Eu vi um problema parecido com os pacotes TCP no outro dia que acabou sendo devido a rp_filter no kernel. Não vejo como isso seria o problema, mas é muito parecido. Você pode postar a tabela de rotas ( ip route show ) do Host1 e verificar sua configuração do rp_filter? ( cat /proc/sys/net/ipv4/conf/default/rp_filter )

    
por 21.09.2013 / 00:53
1

Eu me pergunto por que é que você precisa para NAT deles? Como os prefixos são diferentes e você está roteando o tráfego, por que não definir uma rota através da máquina virtual no gateway para a rede 10.0.0.0/24?

Além disso, quando você configura eth0:0 , geralmente você configura eth0 e vice-versa. Use eth0:1 ou, melhor ainda, pare de usar ferramentas antigas de ferramentas de rede e use iproute2 ( ip addr add 192.168.0.254/24 dev eth0 , etc.). Esse pode ser o problema, pois sua regra SNAT está correta. Se o seu roteador não sabe que é 10.0.0.1, o NAT não retornará o tráfego de volta.

Se ip addr show dev eth0 mostrar os dois endereços que você definiu, seu NAT está configurado corretamente e deve estar funcionando. Você pode ter acertado um bug, já que o NAT está enviando os pacotes para fora na mesma interface com um endereço de origem diferente, o que é um cenário incomum.

No entanto, parte do que torna esse cenário confuso é a existência de redirecionamentos de ICMP. Geralmente se considera que eles são malignos (já que eles permitem que invasores modifiquem suas tabelas de roteamento em algumas circunstâncias), e por isso eles estão quase sempre desabilitados, mas o linux normalmente os envia quando encaminha o tráfego para a mesma interface em que ele entrou. Neste caso, é basicamente uma mensagem dizendo "que o host está em seu segmento local, você não precisa encaminhá-lo através de mim". Isso normalmente seria certo, exceto que por causa do SNAT, o host (salto anterior) na verdade precisa fazer isso. Para desativá-los, use estas configurações de sysctl:

net.ipv4.conf.eth0.send_redirects = 0
net.ipv4.conf.eth0.accept_redirects = 0

Dependendo do dispositivo de próximo salto, você pode ter que reiniciar o dispositivo, configurá-lo de alguma forma ou aguardar algum tempo até que o redirecionamento desapareça, se foi isso que causou o problema.

    
por 20.09.2013 / 11:10
0

Dada a topologia, como eu entendi, sua melhor aposta seria dar acesso à rede 192.168.0.0/24 à Internet no roteador. Você teria que dar ao roteador um endereço na rede 192.168.0.0/24 para que isso funcionasse.

Se você não puder fazer isso, precisará usar o MASQUERADE, mas restringi-lo a destinos que não estejam na rede da VM. Algo como isso em todos os hosts:

iptables -A POSTROUTING -o eth0 ! -d 192.168.0.0/24 -j MASQUERADE

Dessa forma, todo o tráfego entre as VMs permanece inalterado, todo o tráfego formado por VMs para outras redes aparece com o endereço dos hosts na rede.

    
por 20.09.2013 / 15:10