iptables -A INPUT -p udp --dport 123 -m limit 无法防御 NTP monlist 放大攻击,因其仅限制单位时间连接数,而 monlist 攻击单包即可触发数百倍响应;真正有效的是禁用 ntpd 的 monlist 功能或迁移到 chrony/ntpsec。

为什么 iptables -A INPUT -p udp --dport 123 -m limit 不能防住 NTP monlist 放大攻击
这条规则只限制「单位时间内的总连接数」,而 monlist 攻击本质是单个 UDP 包触发服务器返回数百倍体积的响应(典型放大比 1:200+),--limit 对每个包都放行,完全不阻止响应生成。攻击者发 100 个伪造源 IP 的 monlist 请求,你的 NTP 服务照常回复,带宽就被打满了。
真正有效的 iptables 防御要匹配 NTP 请求特征
NTP monlist 请求在协议层表现为特定的 Mode=7(Control Mode)、Query Type=18(READSTAT)组合,普通时间同步请求(Mode=3/4)不会触发。Linux 内核 netfilter 无法解析 NTP payload,所以必须靠应用层或更早拦截:
- 禁用 ntpd 的 monlist 功能:在
/etc/ntp.conf中添加restrict default noquery notrap nomodify nopeer noselect,再单独放开可信网段的query - 若必须保留部分查询能力,用
xt_nfacct+ 用户态工具(如ntpq -c rv日志分析)做行为识别,iptables 本身做不到 - 最简方案:直接丢弃所有来自非可信源的 Control Mode 请求,但需配合 ntpd 配置,仅靠 iptables 无法区分 Mode
如果硬要用 iptables 做初步过滤,这些条件更关键
单纯限速没用,但可以结合状态和来源做粗筛:
-
-m state --state NEW:只匹配新连接(对 UDP 实际是首个包),避免重复匹配 -
-s 192.168.0.0/16 -d 10.0.0.0/8:严格限制允许查询的源网段,公网接口上应默认DROP所有--dport 123 -
-m u32 --u32 "6&0xFF=0x11 && 8&0xFFFF=0x007B":匹配 UDP 头(偏移6字节是协议号,0x11=UDP;偏移8字节是目的端口,0x007B=123),但依然无法识别 monlist payload
注意:u32 模块需内核启用,且规则易出错,线上慎用。
现代 NTP 服务的替代方案更可靠
ntpd 已被 chrony 和 ntpsec 明确弃用 monlist(chrony 默认禁用所有控制命令,ntpsec 移除了该功能)。迁移后:
- chrony 配置中
cmdport 0彻底关闭控制端口 - ntpsec 编译时加
--disable-mode7,运行时无monlist相关逻辑 - 哪怕 iptables 规则写错,底层也没法响应了
别在旧 ntpd 上死磕 iptables 规则——协议漏洞得靠协议层修复,防火墙只是补丁里的补丁。










