容器内网防火墙隔离的关键在于利用独立 network namespace 实现自治:每个容器拥有专属网络协议栈和 nftables 规则空间,规则须在对应 namespace 内加载,宿主机规则不继承,推荐启动时注入或通过 nsenter 操作指定 netns。

容器内网防火墙隔离的关键不在“加规则”,而在“分环境”——每个容器自带独立的 network namespace,天然拥有自己的网络协议栈、路由表和防火墙规则空间。nftables 本身不直接操作命名空间,但可以配合命名空间实现真正隔离的防火墙控制。
确认容器是否运行在独立 network namespace
Docker 或 containerd 启动容器时默认启用 --network=bridge,会自动创建新 network namespace。验证方式:
- 进入容器:
docker exec -it <container> sh - 查看 netns ID:
readlink /proc/1/ns/net(输出类似net:[4026532567]) - 对比宿主机:
readlink /proc/1/ns/net(ID 不同即已隔离)
同一宿主机上不同容器的 netns ID 必然不同,这是隔离的前提。
nftables 规则只作用于当前 namespace
nftables 默认操作的是当前进程所在 namespace 的规则集。这意味着:
- 在宿主机 root namespace 中执行
nft list ruleset,看到的是宿主机规则 - 在容器内执行相同命令,看到的是该容器 namespace 内的规则(初始为空)
- 容器启动后若未显式加载规则,其 netns 中 nftables 是干净的,不继承宿主机策略
所以,想让某个容器有专属防火墙,必须在该容器内部或对应 netns 中加载规则。
向容器 netns 注入 nftables 规则的三种方式
-
方式一:容器启动时注入(推荐)
使用--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注意:需确保容器镜像含
nft命令,且/etc/nftables.conf不被覆盖。 -
方式二:从宿主机操作指定 netns(适合调试或运维)
先查容器 netns 路径(以 PID 为例):mkdir -p /run/netns ln -sf /proc/<PID>/ns/net /run/netns/<container-name>
再用
nsenter加载规则:nsenter -n -t <PID> nft add table inet filter nsenter -n -t <PID> nft add chain inet filter input { type filter hook input priority 0 \; policy drop \; }此法无需容器特权,适合批量配置或临时加固。
方式三:绑定 host 网络时禁用共享(慎用)
若容器使用--network=host,它将共享宿主机 netns,此时所有 nftables 规则共用。如需隔离,应避免 host 模式,改用--network=bridge或自定义 CNI 网络。
避免常见陷阱
- Docker 默认通过 iptables/nftables 兼容层管理端口映射(如
-p 8080:80),若容器内自行配置 nftables drop all,可能阻断自身服务;建议仅对input链设限,保留output和forward默认行为。 - 容器重启后规则丢失:nftables 规则不持久化,需通过 entrypoint、init 容器或挂载配置文件(如
/etc/nftables.conf)并启用nftablessystemd 服务(容器内需支持 systemd)。 - 不要试图在宿主机用
nft直接过滤某容器的流量:容器流量经过 veth pair 和网桥,属于宿主机forward链范畴;精细控制应在宿主机forward链按iifname或ip saddr匹配,而非容器内部。
本质上,容器内网防火墙隔离不是靠“外部拦截”,而是靠“内部自治”——每个容器在自己的 network namespace 里,用自己的一套 nftables 规则说话。

















