自定义链是提升iptables规则可维护性、清晰度和复用性的核心手段。它将功能模块化(如ssh-guard、http-limiter),主链仅作路由决策,避免INPUT等主链规则堆砌导致的排查难、易误改问题。

iptables 自定义链不是炫技,而是让复杂规则更清晰、可维护、易复用的核心手段。直接在 INPUT/OUTPUT/FORWARD 主链里堆上百条规则,出问题时排查困难,修改容易误伤,团队协作也难对齐。
为什么需要自定义链
主链(如 INPUT)本质是线性执行的规则列表,一旦规则变多,逻辑就容易缠绕。比如既要防暴力破解 SSH,又要限速 HTTP,还要放行特定内网服务——全塞进 INPUT,条件判断嵌套、跳转混乱,后期加一条规则可能得从头数 37 行才能确定该插在哪。
自定义链相当于把一类功能封装成“子模块”:比如 ssh-guard 专管 SSH 访问控制,http-limiter 负责 Web 流量限速,trusted-services 统一放行内部 API。主链只做“路由决策”,大幅降低认知负荷。
创建与调用自定义链
自定义链必须先创建,再被主链或其它链通过 -j 跳转调用:
- 创建空链:
iptables -N ssh-guard(链名不能含下划线以外的特殊字符,建议小写+短横) - 在 INPUT 中调用:
iptables -A INPUT -p tcp --dport 22 -j ssh-guard - 链内添加具体规则,例如限速+封禁:
iptables -A ssh-guard -m state --state NEW -m recent --name ssh --setiptables -A ssh-guard -m state --state NEW -m recent --name ssh --update --seconds 60 --hitcount 5 -j DROP
注意:自定义链默认策略是 RETURN,即执行完自动返回上一级链;若想让它终止匹配(类似 DROP),需显式写 -j DROP 或 -j REJECT。
链的组织与复用技巧
避免“一个链包打天下”,按职责分层设计:
-
入口过滤链(如
pre-filter):放在 INPUT/FORWARD 开头,统一做 conntrack 状态检查、无效包丢弃、基础 geoip 过滤 -
协议专用链(如
tcp-services):主链识别 TCP 后跳入,再按端口分发到ssh-guard、http-limiter等子链 -
策略链(如
allow-from-trusted):集中管理 IP 段、主机名或 ipset,方便全局调整白名单
多个链可互相调用,但避免循环跳转(如 A → B → A),iptables 会报错并拒绝载入规则。
保存、调试与清理
自定义链不随 reboot 保留,需主动保存:
- Debian/Ubuntu:
iptables-save > /etc/iptables/rules.v4 - RHEL/CentOS:
service iptables save或使用iptables-save > /etc/sysconfig/iptables
调试时用 iptables -L -n -v --line-numbers 查看各链命中计数,确认流量是否进入预期链;清空某自定义链用 iptables -F ssh-guard,删除链本身(必须先清空)用 iptables -X ssh-guard。
不复杂但容易忽略:链名区分大小写,且不能与内建目标(ACCEPT/DROP/LOG 等)同名;生产环境上线前,建议在测试链中模拟跳转路径,避免主链中断连接。










