我在跑步同一主机上有两个 Docker 容器生活在 Docker 同一个桥接网络中,并且我已经设置了 nftables 来或多或少地限制所有流量(下面的规则)。
我唯一的问题(我知道的)是从一个容器到另一个容器的流量被阻止,如果容器使用另一个容器提供的服务的公共 URL。
例如,服务 A 是一个具有公共 DNS 条目的 SMTP 服务器mail.acme.com
,服务 B 是一个想要向 Web 服务器发送邮件的应用程序使用此 URL。SMTP 服务器已配置为可从外部访问(即像0.0.0.0:25:25
在 docker compose 中一样进行端口转发)。
在这种特殊情况下,nftables 中的输入接口不是我的外部接口,而是容器所在的 Docker 网络的接口。流量不会通过路由FORWARD
,Docker 添加的规则不适用,并且流量最终会到达被INPUT
丢弃的地方。
我不想设置单独的规则来允许从 Docker 接口到允许端口的流量。
我正在寻找一种解决方案,允许服务使用各自的 URL,并且与 Docker 设置中使用的端口和接口无关。仅使用 nftables 是否可行?
到目前为止我想到的唯一办法就是,如果输入接口不是外部接口,则从跳转到INPUT
,FORWARD
但感觉我不应该这样做。
以下是我的INPUT
规则:
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
}
当一个容器尝试到达另一个容器时会发生以下情况在同一主机上:(我截断了一些看起来不太相关的跟踪输出)
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
这是外部交通到同一服务:
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
同样在主机上:
iptables-legacy -S
-P INPUT ACCEPT
-P FORWARD ACCEPT
-P OUTPUT ACCEPT