🔗 自定义链详解
为什么要用自定义链?
想象你管理一台对外的 Web 服务器,有来自全球的流量。如果把所有规则都塞在 INPUT 链里,几十条规则排下来,排查问题时就像在一堆乱线里找线头。
自定义链就像给你的规则分了文件夹——SSH 的规则放一个链,HTTP 的放一个,数据库的放另一个。清晰、可维护、可复用。
💡 提示: 💡 类比:内置链(INPUT/OUTPUT/FORWARD)是操作系统自带的"收件箱/发件箱",自定义链是你自己建的"分类文件夹"。数据包不会自动进入自定义链,必须在内置链里用-j跳转过去。
创建和使用自定义链
bash
# 创建一个叫 WEBSERVER 的自定义链
iptables -N WEBSERVER
# 查看——它会出现在 -L 的输出末尾
iptables -L -n
Chain INPUT (policy DROP)
target prot opt source destination
...
Chain WEBSERVER (0 references)
target prot opt source destination
# 往自定义链里添加规则
iptables -A WEBSERVER -p tcp --dport 80 -j ACCEPT
iptables -A WEBSERVER -p tcp --dport 443 -j ACCEPT
iptables -A WEBSERVER -p tcp --dport 8080 -j ACCEPT
# 在 INPUT 链里跳转到自定义链(注意是 -j 不是 -A)
iptables -A INPUT -p tcp -m multiport --dports 80,443,8080 -j WEBSERVER
# 查看统计——哪个规则匹配了多少包
iptables -L WEBSERVER -v -n
Chain WEBSERVER (1 references)
pkts bytes target prot opt in out source destination
15K 960K ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:80
23K 1400K ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:443
0 0 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:8080💡 提示: 💡 看到1 references了吗?这表示有 1 条规则引用了这个链。如果 references 是 0,说明没有任何规则跳转到这个链——它等于没挂上去的文件夹。
实战:按服务分类的防火墙
这是生产环境推荐的组织方式——每个服务一个自定义链,主链只做路由分发:
bash
#!/bin/bash
# ============================================
# 生产服务器防火墙——按服务分类
# ============================================
# 清空
iptables -F
iptables -X # 删除所有自定义链
# 加载规则时先保持 INPUT 放行,避免脚本中途失败把 SSH 锁在门外
iptables -P INPUT ACCEPT
iptables -P FORWARD DROP
iptables -P OUTPUT ACCEPT
# 回环 + 已建立连接
iptables -A INPUT -i lo -j ACCEPT
iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
# ---- 创建服务链 ----
iptables -N SVC_SSH
iptables -N SVC_HTTP
iptables -N SVC_MONITOR
# ---- SSH 服务 ----
iptables -A SVC_SSH -p tcp --dport 22 -m conntrack --ctstate NEW -m recent \
--set --name SSH
iptables -A SVC_SSH -p tcp --dport 22 -m conntrack --ctstate NEW -m recent \
--update --seconds 60 --hitcount 5 --name SSH -j DROP
iptables -A SVC_SSH -p tcp --dport 22 -j ACCEPT
# ---- HTTP/HTTPS 服务 ----
iptables -A SVC_HTTP -p tcp -m multiport --dports 80,443 -j ACCEPT
# ---- 监控服务(Prometheus + Grafana)----
iptables -A SVC_MONITOR -p tcp --dport 9090 -s 10.0.0.0/8 -j ACCEPT
iptables -A SVC_MONITOR -p tcp --dport 3000 -s 10.0.0.0/8 -j ACCEPT
# ---- 挂载到 INPUT 链 ----
iptables -A INPUT -p tcp --dport 22 -j SVC_SSH
iptables -A INPUT -p tcp -m multiport --dports 80,443 -j SVC_HTTP
iptables -A INPUT -p tcp -m multiport --dports 9090,3000 -j SVC_MONITOR
# ---- 记录并丢弃其余 ----
iptables -A INPUT -j LOG --log-prefix "IPT-DROP: " --log-level 4
iptables -A INPUT -j DROP
# 所有允许规则都加载成功后,再把默认策略改为 DROP
iptables -P INPUT DROP
echo "防火墙规则加载完成"
iptables -L -v -n | head -30⚠️ 注意: ⚠️ 注意:iptables -X会删除所有自定义链。如果链被其他规则引用(references ≠ 0),-X会报错。必须先清空引用它的规则。
重命名和清空自定义链
bash
# 清空一个自定义链的规则(保留链本身)
iptables -F WEBSERVER
# 重命名自定义链
iptables -E WEBSERVER WEB_RULES
# 现在 -j WEBSERVER 要改成 -j WEB_RULES
# 删除单个自定义链(必须先清空引用)
iptables -D INPUT -p tcp -m multiport --dports 80,443 -j WEBSERVER
iptables -X WEBSERVER