nftables 实现容器防火墙隔离的关键在于“进对环境”而非单纯加规则:每个容器独享 network namespace,拥有独立协议栈与规则空间,宿主机规则不继承;须在对应 netns 内加载规则,推荐启动时注入或用 nsenter 操作。

nftables 本身不直接管理命名空间,但能天然适配 Linux network namespace 实现真正的防火墙隔离——关键不是“加规则”,而是“进对环境”。每个 network namespace 拥有独立的网络协议栈、路由表和 nftables 规则空间,宿主机规则不会自动继承,容器内规则也不会影响其他容器或宿主机。
确认容器是否运行在独立 network namespace
这是隔离的前提。Docker 默认启用 --network=bridge,会为每个容器创建新 netns。验证方法简单:
- 进入容器执行:
readlink /proc/1/ns/net,输出类似net:[4026532567] - 在宿主机执行相同命令,对比 ID 是否不同
- 同一台机器上不同容器的 netns ID 必然互异,这是内核级隔离的标志
规则只作用于当前 namespace
nftables 命令默认操作的是当前进程所在的 netns,因此:
- 在宿主机 root namespace 中运行
nft list ruleset,看到的是宿主机规则 - 在容器内运行相同命令,看到的是该容器 netns 内的规则(初始为空)
- 容器启动后若未显式加载规则,其防火墙状态是干净的,默认放行所有流量
向容器 netns 注入规则的实用方式
必须在目标 netns 内执行规则加载,常见做法有三种:
-
启动时注入(推荐):容器启动加
--cap-add=NET_ADMIN,并在 entrypoint 脚本中执行规则,例如:nft add table inet filternft add chain inet filter input { type filter hook input priority 0 \; policy drop \; }nft add rule inet filter input iifname "lo" acceptnft add rule inet filter input ct state established,related acceptnft add rule inet filter input tcp dport { 80, 443 } ct state new accept -
用 nsenter 动态注入:先建立 netns 符号链接:
ln -sf /proc/<pid>/ns/net /run/netns/<name>,再执行:nsenter -n -t <pid> nft add table inet filternsenter -n -t <pid> nft add chain inet filter input { type filter hook input priority 0 \; policy drop \; } -
配合 CNI 自动同步:在 Kubernetes 或容器平台中,由 CNI 插件在 Pod 创建/销毁时调用 nft 命令,将 IP 加入预定义集合(如
nft add element inet filter ns-prod { 10.244.1.45 }),并在 FORWARD 链中基于集合做跨网段限制
避免常见误区
很多问题源于混淆作用域:
- 不要在宿主机执行 nft 命令期望控制容器流量——它只影响 root netns
- Docker 默认使用 iptables 后端,若启用了
--iptables=false,需手动把 docker0 等网桥流量纳入 nftables FORWARD 链管理 - 多个容器共用一个 netns(如
--network=container:xxx)时,它们共享同一套 nftables 规则,无法单独隔离 - 规则持久化需按 namespace 分别处理:宿主机规则存于
/etc/nftables.conf,容器内规则应由容器生命周期管理,而非依赖全局配置

















