Eu uso o AlmaLinux 9 e entendo que há um novo serviço de backend nftables que pode ser gerenciado pelo comando iptables-nft, então eu defini algumas regras e meu conjunto de regras se parece com:
# Warning: table ip nat is managed by iptables-nft, do not touch!
table ip nat {
chain DOCKER {
iifname "docker0" counter packets 0 bytes 0 return
iifname != "docker0" tcp dport 8080 counter packets 3 bytes 180 dnat to 172.17.0.2:80
iifname != "docker0" tcp dport 9001 counter packets 4 bytes 240 dnat to 172.17.0.3:9001
}
chain POSTROUTING {
type nat hook postrouting priority srcnat; policy accept;
ip saddr 172.17.0.0/16 oifname != "docker0" counter packets 0 bytes 0 masquerade
ip saddr 172.17.0.0/16 oifname != "docker0" counter packets 0 bytes 0 masquerade
ip saddr 172.17.0.0/16 oifname != "docker0" counter packets 0 bytes 0 masquerade
ip saddr 172.17.0.2 ip daddr 172.17.0.2 tcp dport 9001 counter packets 0 bytes 0 masquerade
ip saddr 172.17.0.2 ip daddr 172.17.0.2 tcp dport 9001 counter packets 0 bytes 0 masquerade
ip saddr 172.17.0.2 ip daddr 172.17.0.2 tcp dport 80 counter packets 0 bytes 0 masquerade
ip saddr 172.17.0.3 ip daddr 172.17.0.3 tcp dport 9001 counter packets 0 bytes 0 masquerade
}
chain PREROUTING {
type nat hook prerouting priority dstnat; policy accept;
fib daddr type local counter packets 236 bytes 12653 jump DOCKER
fib daddr type local counter packets 39 bytes 1732 jump DOCKER
fib daddr type local counter packets 39 bytes 1732 jump DOCKER
fib daddr type local counter packets 23 bytes 1056 jump DOCKER
fib daddr type local counter packets 23 bytes 1056 jump DOCKER
}
chain OUTPUT {
type nat hook output priority dstnat; policy accept;
ip daddr != 127.0.0.0/8 fib daddr type local counter packets 0 bytes 0 jump DOCKER
ip daddr != 127.0.0.0/8 fib daddr type local counter packets 0 bytes 0 jump DOCKER
ip daddr != 127.0.0.0/8 fib daddr type local counter packets 0 bytes 0 jump DOCKER
}
}
# Warning: table ip filter is managed by iptables-nft, do not touch!
table ip filter {
chain FORWARD {
type filter hook forward priority filter; policy drop;
counter packets 178 bytes 55546 jump DOCKER-USER
counter packets 178 bytes 55546 jump DOCKER-ISOLATION-STAGE-1
oifname "docker0" ct state related,established counter packets 84 bytes 11338 accept
oifname "docker0" counter packets 7 bytes 420 jump DOCKER
iifname "docker0" oifname != "docker0" counter packets 87 bytes 43788 accept
iifname "docker0" oifname "docker0" counter packets 0 bytes 0 accept
}
chain DOCKER-USER {
counter packets 178 bytes 55546 return
}
chain INPUT {
type filter hook input priority filter; policy drop;
ct state established,related counter packets 195 bytes 18089 accept
tcp dport 22 counter packets 2 bytes 120 accept
tcp dport 443 counter packets 0 bytes 0 accept
}
chain DOCKER {
ip daddr 172.17.0.2 iifname != "docker0" oifname "docker0" tcp dport 80 counter packets 3 bytes 180 accept
ip daddr 172.17.0.3 iifname != "docker0" oifname "docker0" tcp dport 9001 counter packets 4 bytes 240 accept
}
chain DOCKER-ISOLATION-STAGE-1 {
iifname "docker0" oifname != "docker0" counter packets 87 bytes 43788 jump DOCKER-ISOLATION-STAGE-2
counter packets 178 bytes 55546 return
}
chain DOCKER-ISOLATION-STAGE-2 {
oifname "docker0" counter packets 0 bytes 0 drop
counter packets 87 bytes 43788 return
}
}
esse conjunto de regras é salvo para /etc/sysconfig/nftables.conf
ser carregado toda vez que o servidor é reiniciado, como você pode ver na cadeia INPUT, tudo deve ser descartado, exceto as portas 22 e 443, então tentei executar o teste do servidor nginx na porta 8080 e ainda consigo acessá-lo, meu firewall não está bloqueando nada... por quê? mesmo quando a política INPUT está definida para ser descartada.
EDITAR2:
então eu li que o docker usa a cadeia DOCKER-USER para regras definidas pelo usuário, então eu fiz:
table ip filter {
chain FORWARD {
type filter hook forward priority filter; policy drop;
counter packets 0 bytes 0 jump DOCKER-USER
counter packets 0 bytes 0 jump DOCKER-ISOLATION-STAGE-1
oifname "docker0" ct state related,established counter packets 0 bytes 0 accept
oifname "docker0" counter packets 0 bytes 0 jump DOCKER
iifname "docker0" oifname != "docker0" counter packets 0 bytes 0 accept
iifname "docker0" oifname "docker0" counter packets 0 bytes 0 accept
oifname "docker0" ct state established,related counter packets 184 bytes 27570 accept
oifname "docker0" ct state established,related counter packets 85 bytes 28483 accept
}
chain DOCKER-USER {
counter packets 534 bytes 178277 return
tcp dport 8080 drop
tcp dport 9001 drop
}
chain INPUT {
type filter hook input priority filter; policy drop;
ct state established,related counter packets 584 bytes 54071 accept
tcp dport 22 counter packets 8 bytes 460 accept
}
chain DOCKER {
ip daddr 172.17.0.2 iifname != "docker0" oifname "docker0" tcp dport 80 counter packets 0 bytes 0 accept
ip daddr 172.17.0.3 iifname != "docker0" oifname "docker0" tcp dport 9001 counter packets 0 bytes 0 accept
}
chain DOCKER-ISOLATION-STAGE-1 {
iifname "docker0" oifname != "docker0" counter packets 0 bytes 0 jump DOCKER-ISOLATION-STAGE-2
counter packets 0 bytes 0 return
}
chain DOCKER-ISOLATION-STAGE-2 {
oifname "docker0" counter packets 0 bytes 0 drop
counter packets 0 bytes 0 return
}
}
e ainda não funciona, consigo acessar as portas 8080 e 9001, tentei até reiniciar o servidor.
EDIÇÃO 3:
mudei minha corrente para isso:
chain DOCKER-USER {
tcp dport 8080 drop
tcp dport 9001 drop
return
}
servidor reiniciado e a porta 8080 ainda está acessível
Então o tráfego não é "entrada" da perspectiva do sistema operacional do host - pode parecer que deveria ser, mas você tem
nat/prerouting
regras que reescrevem os pacotes para irem para um endereço IP diferente (do contêiner), fazendo com que o host atue como um roteador na frente dos contêineres e, na verdade, fazendo com que ele seja tráfego encaminhado (ou seja, roteado), que então se enquadra emhook forward
.(Em outras palavras: a etapa de 'roteamento' é onde a decisão entre entrada e encaminhamento é tomada, portanto, depende do resultado das cadeias de 'pré-roteamento'.)