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