容器防火墙隔离核心在于network namespace自治:每个容器拥有独立协议栈和nftables规则空间,规则须在对应netns内加载,宿主机不继承;验证方式为比对readlink /proc/1/ns/net的id是否唯一。

容器环境下的防火墙流量隔离,核心不是“在宿主机上拦住容器”,而是让每个容器拥有独立、自治的防火墙上下文——关键在于 network namespace 的天然隔离,以及 nftables 规则必须加载到对应命名空间中才生效。
确认容器是否运行在独立 netns
这是所有隔离的前提。Docker 默认启用 --network=bridge,会为每个容器创建专属 network namespace:
- 进容器执行:
readlink /proc/1/ns/net,输出类似net:[4026532567] - 在宿主机执行相同命令,ID 必然不同;同一台机器上不同容器的 ID 也互不相同
- ID 不同 = 协议栈独立 = 防火墙规则空间独立
nftables 规则只作用于当前 namespace
宿主机执行 nft list ruleset 看不到容器里的规则,反之亦然。容器启动后默认不含任何 nftables 规则,也不继承宿主机策略。
- 想让容器有防火墙,必须在它自己的 netns 中加载规则
- 不能只在宿主机写一条“限制容器网卡”的规则——那只能控制转发或出向路径,无法约束容器内进程主动发起的连接
- 典型误区:用
iifname "docker0"在宿主机 FORWARD 链里做判断,这只能管东西向流量,管不住容器自己外连(OUTPUT 流量)
向容器注入规则的实用方式
推荐启动时注入,兼顾安全与可控性:
- 启动容器时加权限:
--cap-add=NET_ADMIN - 在容器 entrypoint 脚本中加载基础策略,例如:
nft add table inet filter
nft add chain inet filter input { type filter hook input priority 0 \; policy drop \; }
nft add rule inet filter input iifname "lo" accept
nft add rule inet filter input ct state established,related accept
nft add rule inet filter input tcp dport { 80, 443 } ct state new accept
- 若需运行时动态调整,可用
nsenter进入指定 netns 操作:nsenter -n -t <container-pid> nft add rule inet filter input ...</container-pid> - 注意:确保容器镜像包含
nft命令,且未被/etc/nftables.conf覆盖启动逻辑
区分容器内外的流量控制层级
真正健壮的隔离需要分层设防:
- 容器内部:INPUT/OUTPUT 链控制本容器进程的进出流量(如禁止反弹 shell、限制外连端口)
- 宿主机 DOCKER-USER 链:拦截所有容器发出的出站流量,是第一道可干预钩子点,适合统一限源、封 C2 端口
- 宿主机 OUTPUT 链:防止提权后绕过容器网络栈直连外网,必须单独配置默认 drop + 白名单
-
FORWARD 链:控制跨容器通信,配合
ip saddr或meta mark实现租户级或服务级互通策略











