在Linux环境中构建网络访问控制时,如果仅依赖单台主机的iptables或者nftables规则,一旦该机器宕机,整条访问链路就会失效。高可用网络访问控制的核心目标是让过滤策略在多个节点之间保持一致,并且当某个节点不可用时,流量能无缝切换到备用节点,同时安全规则不出现真空期。

一、高可用网络访问控制的整体架构
实现高可用通常借助VRRP协议来完成虚拟IP的漂移,Keepalived是Linux下最成熟的实现工具。我们可以在两块或多块网卡上运行Keepalived,定义一个虚拟路由器ID,主节点持有虚拟IP并承载外部请求,备节点实时监测主节点心跳。当主节点失效,备节点在秒级时间内接管虚拟IP,继续按照相同的防火墙规则处理数据包。
网络访问控制本身仍由iptables或nftables承担。区别在于,规则不能只在某一台机器上静态存在,而需要通过脚本或配置管理工具在集群内同步。更进一步的做法是把规则抽象成模板,在Keepalived的状态切换脚本(notify_master、notify_backup)中自动加载,保证无论哪台机器成为主节点,放行的端口、限流的策略都完全一致。
1.1 为什么不能直接复制规则文件
很多团队习惯用scp把iptables-save的输出传到备机,但这种做法在节点角色频繁变化时会出问题。例如主节点临时进入维护模式,备节点升主,此时若有人在主节点修改了规则,集群状态就出现了分歧。通过Keepalived的notify机制触发统一加载动作,可以从流程上杜绝人为遗漏。
另外,直接复制规则文件不会考虑连接追踪表(conntrack)的状态。高可用切换后,已有连接可能因为状态表为空被误丢。因此同步策略里还要包含对conntrack模块的预处理,或者在切换时允许已建立连接短暂放行,避免业务闪断。
二、使用Keepalived搭建虚拟IP层
下面给出一个最简化的Keepalived配置示例,展示如何通过VRRP实现虚拟IP高可用。假设两台机器分别是192.168.0.10和192.168.0.11,虚拟IP为192.168.0.100。
! /etc/keepalived/keepalived.conf 主节点示例
global_defs {
router_id HA_FW_1
}
vrrp_instance VI_FW {
state MASTER
interface eth0
virtual_router_id 51
priority 150
advert_int 1
authentication {
auth_type PASS
auth_pass ipipp_pass
}
virtual_ipaddress {
192.168.0.100
}
notify_master /usr/local/bin/load_fw.sh master
notify_backup /usr/local/bin/load_fw.sh backup
notify_fault /usr/local/bin/load_fw.sh fault
}
备节点只需把state改为BACKUP,priority改为100即可。Keepalived会依据priority和心跳决定是否升主。notify_master等脚本在角色变化时执行,我们正好在这里重载防火墙规则。
需要注意,如果集群部署在同一个二层网络,务必确认交换机没有开启IP地址防漂移限制,否则虚拟IP可能无法正常广播。此外auth_pass不要使用默认明文弱口令,避免VRRP被伪造接管。
2.1 防止脑裂的基本手段
脑裂指主备节点同时认为自己是主,导致虚拟IP在两台机器上同时生效。除了配置合理的priority和advert_int,还应使用多播或单播心跳,并在脚本中加入仲裁判断,例如检测网关连通性。下面脚本展示了在升主前先ping网关,失败则放弃升主:
#!/bin/bash
# /usr/local/bin/load_fw.sh
ROLE=$1
GATEWAY=192.168.0.1
if [ "$ROLE" = "master" ]; then
if ! ping -c 2 -W 1 $GATEWAY >/dev/null; then
echo "网关不可达,拒绝升主" >> /var/log/fw_ha.log
exit 1
fi
iptables-restore < /etc/fw/rules.v4
fi
if [ "$ROLE" = "backup" ]; then
iptables-restore < /etc/fw/rules_backup.v4
fi
该脚本在成为主节点前先验证网络出口,若网关异常说明本机网络分区,不应抢虚拟IP。备份角色加载的规则可以稍宽松,仅保证基本管理通道,减少误拦截。
实际运行中,可以把网关检测换成更可靠的仲裁服务,比如借助外部健康检查接口。只要保证任意时刻只有一个节点能通过仲裁,脑裂概率就能降到极低。
三、网络访问控制规则的同步与加载
防火墙规则建议用iptables-save导出为文件,集中存放在共享存储或配置仓库。Keepalived切换时调用restore命令,比逐条执行iptables命令更快也更原子化。以下示例展示规则模板如何限制仅允许虚拟IP上的80和443端口对外:
# 生成基础规则 iptables -F iptables -P INPUT DROP iptables -A INPUT -i lo -j ACCEPT iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT iptables -A INPUT -p tcp -d 192.168.0.100 --dport 80 -j ACCEPT iptables -A INPUT -p tcp -d 192.168.0.100 --dport 443 -j ACCEPT iptables -A INPUT -p icmp -j ACCEPT iptables-save > /etc/fw/rules.v4
上述规则默认丢弃所有入向包,仅放行本地回环、已建立连接、虚拟IP的Web端口以及ICMP。这样即使某节点意外暴露公网,攻击面也仅限于必要服务。
如果业务需要按来源IP细分,可以在规则中追加-s段,例如只允许办公网段访问SSH。由于规则文件随Keepalived切换统一加载,主备节点不会出现策略偏差。对于nftables用户,思路完全一致,只是把命令换成nft语法并在notify脚本中调用nft -f。
3.1 健康检查与自动降级
高可用不仅是IP漂移,还要保证承载节点确实能正常做访问控制。可以在Keepalived中配置vrrp_script,定期检测本机iptables模块或关键进程。若检测失败,主动降低priority让出主角色。
vrrp_script chk_fw {
script "/usr/local/bin/check_fw.sh"
interval 2
weight -30
}
vrrp_instance VI_FW {
...
track_script {
chk_fw
}
}
check_fw.sh可以简单检查iptables-restore最近是否成功,或者探测规则计数值是否在增长。一旦脚本返回非0,weight使priority减少,备节点自然接管。整个过程无需人工介入,符合高可用运维预期。
这种联动方式比单纯靠网络层心跳更贴近业务真实状态。因为有时机器在线但netfilter异常,仅靠VRRP无法发现,加入脚本检测后系统健壮性明显提升。
四、方案优缺点与适用场景
采用Keepalived加统一防火墙脚本的方案,优点是切换快、规则一致、运维成本低,且完全基于Linux原生组件,不引入额外商业软件。对中小规模集群、边缘网关、内网隔离区都非常合适。
缺点在于状态同步仅覆盖规则本身,连接追踪表仍可能丢失,极端情况下长连接会重连。若需要会话级无缝,应叠加conntrackd做状态同步,或直接在业务层支持重连。此外VRRP依赖二层互通,跨机房需改用单播加专线,配置复杂度上升。
| 对比项 | 单机iptables | Keepalived高可用 |
|---|---|---|
| 故障恢复 | 人工介入,分钟级 | 自动漂移,秒级 |
| 规则一致性 | 易出错 | 脚本统一加载 |
| 适用规模 | 单节点 | 双机或多机 |
总体来看,当访问控制系统成为业务入口时,花少量精力搭建上述高可用框架,远胜于故障后紧急抢修。理清VRRP与netfilter的职责边界,就能在Linux上构建出稳定且易维护的网络访问控制体系。