应选 REJECT 而非 DROP,因其立即返回 RST 或 ICMP 不可达报文,使客户端快速明确拒绝原因;需按协议指定 --reject-with 类型(如 tcp-reset 或 icmp-port-unreachable),置于规则链末尾并配合 LOG 链实现可追溯。

为什么不用 DROP 而选 REJECT?
直接丢弃连接(DROP)会让客户端卡在 SYN_SENT 或超时重试,看起来像服务宕机或网络不通;而 REJECT 会立即返回一个明确的 ICMP 或 TCP RST 包,让客户端快速得知“端口被策略拒绝”,便于诊断和自动化脚本判断。这对运维排查、健康检查、CI/CD 探活等场景更友好。
REJECT 的类型必须匹配协议,否则无效
iptables 不会自动推断该用哪种拒绝响应——你得手动指定 --reject-with 参数,且类型要和匹配的协议一致:
- TCP 连接(如 SSH、HTTP)建议用
--reject-with tcp-reset:发 RST 包,客户端立刻收到 “Connection refused” - UDP 请求(如 DNS 查询、NTP)可用
--reject-with icmp-port-unreachable:返回标准 ICMP 不可达报文 - ICMP 本身不建议用
REJECT,容易引发环路;若真要拦,优先用DROP - 别写错拼写:
tcp-rst是常见笔误,正确是tcp-reset
把 REJECT 放在规则链末尾才安全
REJECT 是终止动作,一旦命中就不再继续匹配后续规则。如果你把它放在开放端口规则之前,比如:
iptables -A INPUT -p tcp --dport 22 -j REJECT --reject-with tcp-reset iptables -A INPUT -p tcp --dport 22 -s 192.168.1.0/24 -j ACCEPT
那内网用户连 SSH 也会被拒——因为第一条规则已先匹配并终止。正确顺序是:
- 先放行可信流量(如本地回环、已建立连接、白名单 IP、必要端口)
- 最后加一条兜底
REJECT,例如:iptables -A INPUT -j REJECT --reject-with icmp-host-prohibited - 这条兜底规则应紧挨在默认策略(
iptables -P INPUT DROP)之前,避免策略覆盖掉REJECT的语义
日志 + REJECT 才算真正可追溯
单纯 REJECT 不留痕迹,出问题时无法确认是谁、何时、因哪条规则被拒。务必搭配 LOG 链使用:
iptables -A INPUT -p tcp --dport 22 -m state --state NEW -j LOG --log-prefix "SSH-REJECT: " iptables -A INPUT -p tcp --dport 22 -m state --state NEW -j REJECT --reject-with tcp-reset
注意点:
-
LOG必须在REJECT前,且不能加-j终止,否则后续规则不执行 -
--log-prefix最好控制在 29 字节内,避免截断(内核限制) - 日志默认输出到
/var/log/messages或journald,需确保rsyslog或systemd-journald正常运行
最易忽略的是:REJECT 本身不记录源端口、UID 或应用层信息,它只作用于网络层;想定位具体进程,得结合 ss -tuln 或 conntrack -L 补充分析。


















