Linux Routing com dois NICs (LAN vs Internet) com NAT e ponte para VMs

3

Minha configuração:

Existe apenas uma máquina física nesta configuração, um Sistema Host para Máquinas Virtuais (VMs) com dois adaptadores de rede.

Uma NIC (eth0) está conectada a uma rede interna (sub-rede LAN, por exemplo, 10.x.x.x / 24) e deve ser usada para tráfego interno.

A outra NIC (eth1) está conectada à internet pública (tem um IP público roteado configurado). Essa conexão deve ser usada para encaminhar pela porta o tráfego público da Internet para IPs internos das VMs (tráfego de entrada) e para permitir que as VMs acessem a Internet pública (tráfego de saída) via NAT.

Máquinas virtuais usam endereços IP na sub-rede da LAN (10.x.x.x / 24, igual a eth0)

Eu tenho um dispositivo de ponte (br0) configurado para interfaces de rede virtuais das VMs (vnet0, vnet1, ...) e o LAN-NIC (eth0). Isso significa:

  • br0 tem um endereço IP na sub-rede da LAN (10.x.x.x / 24)
  • eth0 é adicionado à ponte
  • vnet0, vnet1, ... (usado pelas VMs) são adicionados dinamicamente à ponte

Problemas

A comunicação dentro da LAN funciona bem. Além disso, o VM-Host é acessível através do IP público e tem acesso à Internet.

Meu problema é a configuração NAT para permitir que as VMs acessem a Internet pública também.

Eu tentei usar uma regra de NAT simples (S):

iptables -t nat -I POSTROUTING -s 10.x.x.x/24 ! -d 10.x.x.x/24 -j SNAT --to-source y.y.y.102

Considerando que y.y.y.102 é o IP público roteável do segundo NIC (eth1).

Descobri que preciso ativar "ip_forward" e "bridge-nf-call-iptables":

echo 1 > /proc/sys/net/ipv4/ip_forward
echo 1 > /proc/sys/net/bridge/bridge-nf-call-iptables

Caso os pacotes em ponte não sejam processados pelo iptables.

Agora os pacotes das VMs parecem passar pelas seguintes cadeias de iptables:

  • "FORWARD" (normal) - aceito-os lá (-j ACCEPT, o contador sobe)
  • "PREROUTING" (nat) - Eu aceito lá (política ACCEPT, o contador sobe)
  • "POSTROUTING" (nat) - Eles correspondem à regra SNAT

Mas nem todos os pacotes parecem chegar a PRE / POSTROUTING por qualquer motivo que eu não consegui descobrir até agora.

No entanto, mais interessante tcpdump -i eth0 vs. tcpdump -i eth1 mostra que os pacotes (tentei pingar um IP externo de dentro de uma VM) parecem ser enviados pela interface errada eth0 (= LAN-NIC). Mesmo a regra NAT foi aplicada, então o endereço de origem foi alterado para o IP da outra NIC (eth1).

PERGUNTA:

Como posso configurar o sistema para enviar os pacotes NAT com o IP público como endereço de origem a ser enviado pela NIC correta (eth1)?

Eu de alguma forma preciso adicionar eth1 à bridge (br0)? Se sim, como atribuo o endereço IP público corretamente? Normalmente, o IP precisa ser configurado no dispositivo de ponte. Eu precisaria atribuir um endereço de alias à bridge (IP público em br0: 0)?

Detalhes da configuração

A configuração de roteamento no sistema host:

# ip r
default via y.y.y.126 dev eth1
10.x.x.0/24 dev br0  proto kernel  scope link  src 10.x.x.11
y.y.y.96/27 dev eth1 proto kernel  scope link  src y.y.y.102
  • IP: y.y.y.126 é o nosso roteador para internet pública.
  • IP: y.y.y.102 é o IP público da máquina host
  • IP: 10.x.x.11 é o IP da LAN da máquina host
  • SUBNET: 10.x.x.0 / 24 é a LAN
  • SUBNET: y.y.y.96 / 27 é a sub-rede IP pública

Configuração da NIC:

# ifconfig
br0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 10.x.x.11  netmask 255.255.255.0  broadcast 10.x.x.255
        inet6 ####::###:####:####:####  prefixlen 64  scopeid 0x20<link>
        ether ##:##:##:##:##:##  txqueuelen 0  (Ethernet)
        RX packets 2139490  bytes 243693436 (232.4 MiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 29085  bytes 2398024 (2.2 MiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet6 ####::###:####:####:####  prefixlen 64  scopeid 0x20<link>
        ether ##:##:##:##:##:##  txqueuelen 1000  (Ethernet)
        RX packets 2521995  bytes 290600491 (277.1 MiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 383089  bytes 48876399 (46.6 MiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
        device memory 0xdfa60000-dfa7ffff

eth1: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet y.y.y.102  netmask 255.255.255.224  broadcast y.y.y.127
        inet6 ####::###:####:####:####  prefixlen 64  scopeid 0x20<link>
        ether ##:##:##:##:##:##  txqueuelen 1000  (Ethernet)
        RX packets 2681476  bytes 597532550 (569.8 MiB)
        RX errors 0  dropped 130  overruns 0  frame 0
        TX packets 187755  bytes 21894113 (20.8 MiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
        device memory 0xdfa00000-dfa1ffff

Configuração de ponte:

# brctl show
bridge name     bridge id               STP enabled     interfaces
br0             8000.002590eb1900       no              eth0
                                                        vnet0

E regras do iptables:

# iptables -vnL
Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination
  723  106K DROP       udp  --  *      *       y.y.y.0/24           0.0.0.0/0            udp spt:5404
  586 40052 ACCEPT     all  --  *      *       0.0.0.0/0            0.0.0.0/0            state RELATED,ESTABLISHED
    5   420 ACCEPT     icmp --  *      *       0.0.0.0/0            0.0.0.0/0
    0     0 ACCEPT     all  --  lo     *       0.0.0.0/0            0.0.0.0/0
    0     0 ACCEPT     tcp  --  *      *       0.0.0.0/0            0.0.0.0/0            state NEW tcp dpt:22
    2   458 LOG        all  --  *      *       0.0.0.0/0            0.0.0.0/0            LOG flags 0 level 4
    2   458 REJECT     all  --  *      *       0.0.0.0/0            0.0.0.0/0            reject-with icmp-host-prohibited

Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination
 1343  173K ACCEPT     tcp  --  *      *       10.x.x.2             0.0.0.0/0            tcp spt:3389
 1648  127K ACCEPT     tcp  --  *      *       0.0.0.0/0            10.x.x.2             tcp dpt:3389
   18  1040 LOG        all  --  *      *       0.0.0.0/0            0.0.0.0/0            LOG flags 0 level 4
   18  1040 ACCEPT     all  --  *      *       0.0.0.0/0            0.0.0.0/0

Chain OUTPUT (policy ACCEPT 525 packets, 84016 bytes)
 pkts bytes target     prot opt in     out     source               destination


# iptables -vnL -t nat
Chain PREROUTING (policy ACCEPT 13 packets, 1218 bytes)
 pkts bytes target     prot opt in     out     source               destination

Chain INPUT (policy ACCEPT 5 packets, 420 bytes)
 pkts bytes target     prot opt in     out     source               destination

Chain OUTPUT (policy ACCEPT 13 packets, 880 bytes)
 pkts bytes target     prot opt in     out     source               destination

Chain POSTROUTING (policy ACCEPT 14 packets, 920 bytes)
 pkts bytes target     prot opt in     out     source               destination
    5   300 SNAT       all  --  *      *       10.x.x.0/24          !10.x.x.0/24           to:y.y.y.102

E aqui um pacote NATed capturado (ping da VM) na placa de interface LAN:

# tcpdump -i eth0
12:53:55.243350 IP y.y.y.102 > y.y.y.110: ICMP echo request, id 2, seq 5, length 40

Saída da "regra ip":

# ip rule
0:      from all lookup local
32766:  from all lookup main
32767:  from all lookup default
    
por SDwarfs 12.06.2015 / 13:11

3 respostas

4
  1. Verifique se suas VMs possuem endereços IP em 10.x.x.x / 24 (máscara de rede 255.255.255.0)

  2. Defina 10.x.x.11 (endereço IP br0) como o gateway padrão de suas VMs

  3. Ativar o encaminhamento de ip no host físico

  4. Ativar SNAT com:

    iptables -t nat -A POSTROUTING -s 10.x.x.x/24 -o eth1 -j SNAT --to y.y.y.102
    
por 17.06.2015 / 10:51
1

iptables -t nat -I POSTROUTING -s 10.x.x.x/24 ! -d 10.x.x.x/24 -j SNAT --to-source y.y.y.102

isso deve ser alterado para

iptables -t nat -I POSTROUTING --out-interface eth1 -j SNAT --to-source y.y.y.102

De acordo com sua primeira regra, somente pacotes com destino a 10.x.x.x devem ser processados. Então, e o tráfego de fora para a sua rede? (fonte - de todo o mundo, o destino é o seu IP público:)

How can I configure the system to output the NATed packets with the public IP as source address to be sent over the correct NIC (eth1)?

leia acima. Apenas mude a regra NAT.

Do I somehow need to add eth1 to the bridge (br0)? If so, how do I assign the public IP address correctly? Usually the IP needs to be configured on the bridge device. Would I need to assign an alias adress to the bridge (public IP on br0:0)?

De maneira nenhuma, a menos que você esteja ciente do que e por que você está fazendo isso. Mantenha as interfaces internas e externas separadas. Permitir somente roteamento.

Eu descrevi sua configuração ao vivo (produção) por mais de 5 anos. Funcionando sem problemas para 3 servidores host e 25 VMs, incluindo links de ponte sobre túneis openvpn.

    
por 15.06.2015 / 23:40
0

O post de Silvio me ajudou a obter uma configuração semelhante funcionando. Além de seu post, aqui estão algumas coisas que eu precisava fazer também.

  1. Em versões mais recentes de kernels Linux (Redhat 7 por exemplo), você precisará habilitar o módulo do kernel de bridge:

    modprobe br_netfilter
    

e, em seguida, para tornar essa alteração persistente nas reinicializações do servidor, adicione a mesma linha a um arquivo chamado /etc/modules-load.d/.conf

  1. Depois que eu habilitei o br_netfilter, eu também tive que habilitar as regras de encaminhamento do iptable para a (s) VM (s), por exemplo:

    iptables -I FORWARD -d 10.x.x.x/24 -j ACCEPT
    iptables -I FORWARD -s 10.x.x.x/24 -j ACCEPT
    
  2. Em vez de SNAT, usei uma regra de mascaramento, pois só precisava de uma única rota em uma instalação de hospedagem de servidor.

    iptables -t nat -A POSTROUTING -s <single-local-vm-ip>/32 -d <my-destination-subnet>/24 -p tcp -j MASQUERADE --to-ports 1024-65535
    
por 21.11.2017 / 23:07