eu estou correndodois contêineres Docker no mesmo hostmoro no Docker na mesma rede bridge e tenho o nftables configurado para restringir mais ou menos todo o tráfego (regras abaixo).
Meu único problema (que eu saiba) é queo tráfego de um contêiner para outro está bloqueado, se um contêiner usara URL pública do serviço fornecido pelo outro contêiner.
Por exemplo, o serviço A é um servidor SMTP que possui uma entrada DNS pública mail.acme.com
e o serviço B é um aplicativo que deseja enviar e-mails para o servidor webusando este URL. O servidor SMTP é configurado para ser acessível externamente (ou seja, encaminhamento de porta como 0.0.0.0:25:25
no docker compose).
Neste caso específico, a interface de entrada em nftables não é minha interface externa, mas sim a interface da rede Docker em que o contêiner está. O tráfego não é roteado FORWARD
, as regras adicionadas pelo Docker não se aplicam e o tráfego acaba onde INPUT
ele é descartado.
Não quero configurar regras individuais para permitir o tráfego das interfaces do Docker para as portas permitidas.
Procuro uma solução que permita aos serviços utilizar seus respectivos URLs e que seja independente de portas e interfaces utilizadas na configuração do Docker. Isso é possível apenas com nftables?
A única coisa que descobri até agora foi pular de INPUT
para FORWARD
se a interface de entrada não for uma interface externa, mas parece que não devo fazer isso.
Aqui estão minhas INPUT
regras:
chain INPUT {
type filter hook input priority filter; policy drop;
ct state vmap { invalid : drop, established : accept, related : accept }
iifname "lo" accept
iifname "externalif0" icmp type echo-request accept
iifname "externalif0" icmpv6 type echo-request accept
}
Isto é o que acontece quando um contêiner tenta alcançar outro contêinerno mesmo host: (trunquei um pouco da saída do rastreamento que não parecia muito relevante)
trace id 196c1ae6 ip filter trace_chain packet: iif "dockerbr0" ip saddr <containerip> ip daddr <public host ip> tcp sport 33546 tcp dport 443
trace id 196c1ae6 ip nat PREROUTING packet: iif "dockerbr0" ip saddr <containerip> ip daddr <public host ip> tcp sport 33546 tcp dport 443
trace id e7c2ca4b ip filter INPUT packet: iif "dockerbr0" ip saddr <containerip> ip daddr <public host ip> tcp sport 33546 tcp dport 443
E aqui estátráfego externopara o mesmo serviço:
trace id 29f9da6c ip filter trace_chain packet: iif "externalif0" ip saddr <someip> ip daddr <public host ip> sport 36382 tcp dport 443
trace id 29f9da6c ip nat PREROUTING packet: iif "externalif0" ip saddr <someip> ip daddr <public host ip> sport 36382 tcp dport 443
trace id 29f9da6c ip nat DOCKER rule iifname != "dockerbr0" dport 443 dnat to <dockerip>:443 (verdict accept)
trace id 29f9da6c ip filter FORWARD packet: iif "externalif0" oif "dockerbr0" ip saddr <someip> daddr <containerip> sport 36382 tcp dport 443
trace id 29f9da6c ip filter DOCKER rule iifname != "dockerbr0" oifname "dockerbr0" daddr <containerip> tcp dport 443 accept (verdict accept)
trace id 29f9da6c ip nat POSTROUTING packet: iif "externalif0" oif "dockerbr0" ip saddr <someip> ip daddr <containerip> sport 36382 tcp dport 443
Também no host:
iptables-legacy -S
-P INPUT ACCEPT
-P FORWARD ACCEPT
-P OUTPUT ACCEPT