"DC 层规则 + 节点层开关"的配合关系


一、PVE 防火墙的三层架构(从内到外)

┌─────────────────────────────────────────────────┐
│                数据中心层                        │
│  /etc/pve/firewall/cluster.fw                    │
│  [RULES] 全局规则                                │
│  [group xxx] 规则组                              │
│  [IPSET] 仅用 GUI 管理                           │
│  ┌─────────────────────────────────────────────┐ │
│  │   节点层(宿主机)                           │ │
│  │   /etc/pve/nodes/<主机名>/host.fw            │ │
│  │   [RULES] 仅节点自己的 INPUT 规则             │ │
│  │   ┌───────────────────────────────────────┐ │ │
│  │   │  VM/CT 层                              │ │ │
│  │   │  /etc/pve/firewall/<VMID>.fw           │ │ │
│  │   │  每个 VM 独立的规则                     │ │ │
│  │   └───────────────────────────────────────┘ │ │
│  └─────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────┘

二、两个独立开关

PVE 有两个物理上独立的开关,不是总开关和子开关的关系,而是"总开关"和"宿主开关"并列:

开关位置文件控制什么
① 数据中心开关数据中心 → 防火墙 → 选项dc/fw.cfg 或 cluster.fw [OPTIONS] enable整个防火墙系统是否运行(编译规则、生成链)
② 节点开关节点 bitsDE → 防火墙 → 选项host.fw [OPTIONS] enable是否把规则挂到这台宿主的 INPUT 链上

都开 = 正常工作;只开①不开② = 规则编译了但没挂到宿主 INPUT(表现为你的 8006 DROP 无效)。

类比:① 是"是否造房子"(编译规则);② 是"是否把门打开让房子能进风"(挂 INPUT 链)。你的水泥(规则)已经浇好了,但门没开,风进不来。

三、规则气流图(数据包走哪条路)

以从外部访问 bitsDE 的 8006 为例:

外部 IP 访问 bitsDE:8006
       ↓
① 网卡收到包
       ↓
② INPUT 链(内核)
       ↓
③ pve-firewall 的挂钩(仅当节点开关 ② 开启时才存在)
       ↓
④ PVEFW-INPUT 链
       ↓  (里面内容按顺序处理)
   ┌─────────────────────────────────┐
   │ 自动规则:                       │
   │   INVALID DROP                  │
   │   ESTABLISHED/RELATED ACCEPT    │
   ├─────────────────────────────────┤
   │ 节点层规则: host.fw [RULES]     │  ← 你有空,所以跳过
   ├─────────────────────────────────┤
   │ 数据中心层规则: cluster.fw      │  ← 你的 8006 DROP 在这里
   │   [RULES]                       │
   │   GROUP nm-tail                 │
   │   IN DROP -dport 8006           │
   ├─────────────────────────────────┤
   │ 默认策略(policy_in)           │
   └─────────────────────────────────┘
       ↓
⑤ 匹配 DROP → 包被丢弃 ✓

关键:③ 只在节点开关开启时存在。不开 → 流量直接跳过整个④ → 规则不生效。

四、规则优先级和覆盖关系

数据包到达宿主机 INPUT 后,依次匹配:

  1. PVEFW-Drop(自动保护规则)      ← 自动,不可配置
  2. ESTABLISHED/RELATED ACCEPT     ← 自动,不可配置
  3. host.fw 的节点层规则            ← 节点层,优先级最高
  4. cluster.fw 的数据中心层规则     ← 数据中心层,优先级次之
  5. policy_in 默认策略              ← 没被任何规则匹配时走这里

重要原则:

  • 节点层规则(host.fw)先于数据中心层规则(cluster.fw)匹配。 同一条规则,在 host.fw 写比在 cluster.fw 写优先级更高。
  • 同一层内,先写先匹配(所以你的 8006 DROP 必须放在 GROUP 后面,否则 GROUP 的 ACCEPT 永远不生效)。
  • 节点层规则只针对这一台机器;数据中心层规则对集群内所有节点都生效(前提是各节点开关都开了)。

五、你现在的最佳实践(确诊后)

配置建议
数据中心开关保持开启(已开)
所有节点的开关全部开启(你之前不开,是那次失效的根本原因)
规则写在 DC 层放 cluster.fw,一次配置,所有节点共享
节点层 host.fw留空 [RULES] 即可,只放 enable: 1;不写规则,全部继承 DC 层

你的节点已经统一啦:bitsDE 开了节点开关,原先 DC 层的 8006 DROP 就能生效了。ultra4 和 solidla 如果也开了节点开关,同样的规则会同步生效——但前提是它们在同一个集群内。如果不在同一集群,每台集群的 cluster.fw 需要各自配置。

六、验证方法(你现在已经知道怎么看了)

# 看 compile 是否有 "ignore INPUT" —— 没有 = 节点开关生效
pve-firewall compile 2>&1 | grep -i "ignore INPUT"

# 看规则是否在 iptables 里
iptables -L PVEFW-INPUT -n --line-numbers | grep 8006

# 看双开关状态
echo "DC 开关:"; cat /etc/pve/firewall/dc/fw.cfg 2>/dev/null | grep enable
echo "节点开关:"; cat /etc/pve/nodes/$(hostname -s)/host.fw | grep enable

现在你理解了"双开关"机制,之后配置其他节点就知道:**DC 层写规则,每台节点开自己的开关,规则就统一生效了。