Eu sei que isso é um pouco tarde, no entanto ... O host sabe é responsável por esse IP? Aqui está um esquema que eu coloco no topo dos arquivos de regras que eu crio. Você pode encontrar diagramas de fluxo semelhantes em outro lugar, mas tê-lo em ASCII (não gostaria de chamar de arte;)) pode ser bastante útil no terminal.
Na maior parte eu sei disso de coração, mas hey, não faz mal ter uma referência se o esquecimento ataca.
###############################################################################
###
### PACKET FLOW THROUGH NETFILTER TABLES AND CHAINS
###
###
### {Packet in}
### |
### v
### +-----------------+
### |mangle/PREROUTING|
### +-----------------+
### |
### v
### +-----------------+
### | nat/PREROUTING |
### +-----------------+
### |
### v
### *~~~~~~~~~~~~~~~~~*
### | kernel routing |
### *~~~~~~~~~~~~~~~~~*
### |
### v
### .------------{?for this host?}------------.
### yes! | | no!
### v v
### +-----------------+ +-----------------+
### | mangle/INPUT | | mangle/FORWARD |
### +-----------------+ +-----------------+
### | |
### v v
### +-----------------+ +-----------------+
### | filter/INPUT | | filter/FORWARD |
### +-----------------+ +-----------------+
### | |
### v |
### *~~~~~~~~~~~~~~~~~~~~* |
### | response & routing | |
### *~~~~~~~~~~~~~~~~~~~~* |
### | |
### v |
### +-----------------+ |
### | mangle/OUTPUT | |
### +-----------------+ |
### | |
### v |
### +-----------------+ |
### | nat/OUTPUT | |
### +-----------------+ |
### | |
### v |
### +-----------------+ |
### | filter/OUTPUT | |
### +-----------------+ |
### | |
### .-------------------+---------------------.
### |
### v
### +------------------+
### |mangle/POSTROUTING|
### +------------------+
### |
### v
### +------------------+
### | nat/POSTROUTING |
### +------------------+
### |
### v
### {Packet out}
###
###############################################################################
Agora, o que isso significa?
O roteamento pode acontecer usando a tabela de roteamento ("roteamento de kernel" no fluxograma acima) ou usando o netfilter. Agora, se - e esse é o cenário mais provável no seu caso - você não configurou a tabela de roteamento de acordo, o kernel não saberia onde o pacote deve ir e, eventualmente, descartá-lo. Btw: em tais casos, é útil criar uma cadeia personalizada que LOG
e DROP
ou adicione as regras nessa ordem. Desta forma, você verá quais regras foram atingidas. Também é útil iptables-save -c
, que irá preceder os contadores de pacotes e bytes para cada linha de regra, semelhante à forma como ela é anexada às cadeias (formato [packets:bytes]
).
Para portas encaminhadas para uma VM via DNAT
, tenho a seguinte receita (explicarei abaixo):
#!/bin/bash
VMNET=192.168.1.0/24
MAINIP=66.249.67.195
CONTIP=192.168.1.2
VMPORT=80
INPORT=80
ACTION="-I"
iptables -t nat $ACTION PREROUTING -d $MAINIP -p tcp --dport $INPORT -j DNAT --to-destination $CONTIP:$VMPORT
iptables -t nat $ACTION POSTROUTING -s $VMNET ! -d $VMNET -p tcp -j MASQUERADE --to-ports 1024-65535
iptables -t nat $ACTION POSTROUTING -s $VMNET ! -d $VMNET -p udp -j MASQUERADE --to-ports 1024-65535
iptables -t nat $ACTION POSTROUTING -s $VMNET ! -d $VMNET -j MASQUERADE
iptables -t filter $ACTION INPUT -p tcp -d $MAINIP --dport $INPORT -j ACCEPT
iptables -t filter $ACTION FORWARD -p tcp --dport $INPORT -d $VMNET -j ACCEPT
iptables -t filter $ACTION FORWARD -p tcp --dport $INPORT -d $MAINIP -j ACCEPT
Lembre-se de que você pode querer alterar a ordem para se adequar às regras com a sua. Além disso, se a cadeia OUTPUT
não tiver ACCEPT
como sua política padrão, adicione uma regra de saída, embora, para todos os fins práticos, isso deva ser fornecido com uma regra de estado RELATED,ESTABLISHED
. Você também pode refinar as interfaces para corresponder ou corresponder por curinga. Por exemplo, eu forneci às pontes de meus convidados virtuais todo o prefixo _
(um sublinhado) e, portanto, posso corresponder a -i _+
e -o _+
. Da mesma forma, para várias placas de rede ( eth0
, eth1
) você corresponderia a -i eth+
.
Então, o que acontece aqui é que:
- uma regra
DNAT
é inserida, recebendo entrada na porta (host)$INPORT
para o TCP e "encaminhando" para$CONTIP:$VMPORT
, ou seja, o IP do contêiner e a porta no contêiner. Sim, eles poderiam diferir. Se não, não há problema em deixar de fora a parte de destino (ou seja, apenas '' $ CONTIP ''). - três regras para mascarar o tráfego que é da sub-rede dos convidados virtuais, mas não para outro convidado virtual.
- uma regra
INPUT
para permitir pacotes de entrada no IP público (sem interface dada, mas poderia ser!) para a porta$INPORT
through. Eu acho que esta regra não é estritamente necessária, pelo menos não se você amarrá-lo à interface pública. - uma regra para encaminhar tráfego para
$INPORT
para a sub-rede virtual convidada ($VMNET
) - uma regra para encaminhar tráfego para
$INPORT
no IP público ($MAINIP
)
Por último, mas não menos importante, o valor de sysctl
( /proc/sys/net/ipv4/ip_forward
) deve ser:
# cat /proc/sys/net/ipv4/ip_forward
1
para tornar seu host um roteador.
Se não for usado echo 1
para escrever no "arquivo" acima, em procfs
, ou melhor ainda, usar sysctl -w net.ipv4.ip_forward=1
as root
.