iptables 完全指南 / 第 08 章:扩展匹配模块
第 08 章:扩展匹配模块
本章目标:掌握 iptables 的主要扩展匹配模块,能够使用 multiport、connlimit、time、hashlimit、string 等模块实现精细的数据包匹配。
8.1 扩展匹配概述
扩展匹配模块通过 -m 参数加载,提供了超越基本五元组(源/目的 IP、源/目的端口、协议)的匹配能力。
8.1.1 隐式匹配 vs 显式匹配
| 类型 | 语法 | 说明 |
|---|---|---|
| 隐式匹配 | -p tcp --dport 80 | 基于协议内置,不需要 -m |
| 显式匹配 | -m multiport --dports 80,443 | 需要显式加载模块 |
8.1.2 常用扩展模块一览
| 模块 | 加载参数 | 功能 |
|---|---|---|
multiport | -m multiport | 匹配多个端口 |
conntrack | -m conntrack | 连接状态匹配 |
connlimit | -m connlimit | 限制单 IP 并发连接数 |
limit | -m limit | 固定速率限制 |
hashlimit | -m hashlimit | 基于哈希的速率限制 |
time | -m time | 时间段匹配 |
string | -m string | 字符串内容匹配 |
iprange | -m iprange | IP 地址范围匹配 |
owner | -m owner | 进程/用户/组匹配 |
recent | -m recent | 最近访问记录匹配 |
statistic | -m statistic | 统计匹配(概率/每N包) |
mac | -m mac | MAC 地址匹配 |
length | -m length | 数据包长度匹配 |
ttl | -m ttl | TTL 值匹配 |
tos | -m tos | TOS 值匹配 |
mark | -m mark | MARK 值匹配 |
comment | -m comment | 添加注释 |
8.2 multiport 模块
8.2.1 用途
multiport 模块允许在一条规则中匹配多个不连续的端口,减少规则数量。
8.2.2 语法
# 匹配多个目的端口
iptables -A INPUT -p tcp -m multiport --dports 22,80,443,3306 -j ACCEPT
# 匹配多个源端口
iptables -A INPUT -p tcp -m multiport --sports 80,443 -j ACCEPT
# 同时匹配源和目的端口
iptables -A INPUT -p tcp -m multiport --sports 1024:65535 --dports 80,443 -j ACCEPT
8.2.3 限制
- 最多匹配 15 个端口
- 只能用于
-p tcp或-p udp,不能用于-p all - 端口范围和单个端口可以混用:
--dports 22,80,443,8000:9000
8.2.4 业务场景
# Web 服务器常用端口
iptables -A INPUT -p tcp -m multiport --dports 80,443,8080,8443 \
-m comment --comment "Web service ports" -j ACCEPT
# 数据库端口(仅限应用服务器访问)
iptables -A INPUT -p tcp -m multiport --dports 3306,5432,6379,27017 \
-s 10.0.1.0/24 -m comment --comment "DB ports from app servers" -j ACCEPT
# 监控系统端口
iptables -A INPUT -p tcp -m multiport --dports 9090,3000,9100,9093 \
-s 10.0.2.0/24 -m comment --comment "Monitoring ports" -j ACCEPT
8.3 connlimit 模块
8.3.1 用途
connlimit 模块限制单个源 IP 的并发连接数,用于防止单个客户端消耗过多资源。
8.3.2 语法
# 限制每个 IP 最多 20 个 SSH 连接
iptables -A INPUT -p tcp --dport 22 -m connlimit --connlimit-above 20 \
-j REJECT --reject-with tcp-reset
# 限制每个 IP 最多 50 个 HTTP 连接
iptables -A INPUT -p tcp --dport 80 -m connlimit --connlimit-above 50 \
-j DROP
# 使用掩码限制(对子网整体限制)
iptables -A INPUT -p tcp --dport 80 \
-m connlimit --connlimit-above 100 --connlimit-mask 24 \
-j DROP
# 允许范围内,超过则拒绝
iptables -A INPUT -p tcp --dport 22 -m connlimit --connlimit-above 10 -j DROP
iptables -A INPUT -p tcp --dport 22 -j ACCEPT
8.3.3 参数说明
| 参数 | 说明 |
|---|---|
--connlimit-above N | 当并发连接数超过 N 时匹配 |
--connlimit-mask N | 按子网掩码聚合(默认 32,即单 IP) |
--connlimit-upto N | 当并发连接数不超过 N 时匹配(等价于 --connlimit-above N 取反) |
--connlimit-saddr | 限制源地址(默认) |
--connlimit-daddr | 限制目的地址 |
8.3.4 业务场景
#!/bin/bash
# ═══════════════════════════════════════════════════
# 防止单 IP 资源耗尽
# ═══════════════════════════════════════════════════
# SSH 限制:每个 IP 最多 3 个连接
iptables -A INPUT -p tcp --dport 22 \
-m connlimit --connlimit-above 3 -j REJECT --reject-with tcp-reset
# HTTP 限制:每个 IP 最多 100 个连接
iptables -A INPUT -p tcp --dport 80 \
-m connlimit --connlimit-above 100 -j DROP
# HTTPS 限制:每个 IP 最多 100 个连接
iptables -A INPUT -p tcp --dport 443 \
-m connlimit --connlimit-above 100 -j DROP
# MySQL 限制:每个应用服务器最多 50 个连接
iptables -A INPUT -p tcp --dport 3306 -s 10.0.1.0/24 \
-m connlimit --connlimit-above 50 -j DROP
# DNS 限制:每个 /24 子网最多 100 个并发查询
iptables -A INPUT -p udp --dport 53 \
-m connlimit --connlimit-above 100 --connlimit-mask 24 -j DROP
8.4 limit 模块
8.4.1 用途
limit 模块以固定平均速率匹配数据包,用于速率限制。
8.4.2 语法
# 限制 ping 速率为每秒 1 个
iptables -A INPUT -p icmp --icmp-type echo-request \
-m limit --limit 1/s --limit-burst 5 -j ACCEPT
iptables -A INPUT -p icmp --icmp-type echo-request -j DROP
# 限制新建连接速率为每秒 50 个
iptables -A INPUT -p tcp --syn \
-m limit --limit 50/s --limit-burst 100 -j ACCEPT
iptables -A INPUT -p tcp --syn -j DROP
8.4.3 参数说明
| 参数 | 说明 | 默认值 |
|---|---|---|
--limit | 平均速率 | 3/hour |
--limit-burst | 突发上限(令牌桶) | 5 |
令牌桶算法示意:
┌─────── 桶容量 = burst
│
▼
┌───────┐
│ ● ● │ ← 令牌(每个代表一个允许的数据包)
│ ● │
│ ● │
└───────┘
↑
│ 每 1/limit 秒添加一个令牌
│
规则匹配时消耗一个令牌
桶空时拒绝
8.4.4 业务场景
# 限速 ICMP(防止被用于 DDoS 反射)
iptables -A INPUT -p icmp --icmp-type echo-request \
-m limit --limit 5/s --limit-burst 10 -j ACCEPT
iptables -A INPUT -p icmp --icmp-type echo-request -j DROP
# 限制 SSH 暴力破解(每分钟最多 6 次新连接)
iptables -A INPUT -p tcp --dport 22 --syn \
-m limit --limit 6/minute --limit-burst 3 -j ACCEPT
iptables -A INPUT -p tcp --dport 22 --syn -j DROP
# 限制日志输出速率(防止日志泛洪)
iptables -A INPUT -j LOG --log-prefix "IPT-DROP: " \
-m limit --limit 10/minute --limit-burst 20
8.5 hashlimit 模块
8.5.1 用途
hashlimit 是 limit 的增强版,它为每个源 IP(或自定义键)独立维护一个速率桶,实现 per-IP 速率限制。
8.5.2 语法
# 每个源 IP 最多每秒 10 个新 HTTP 连接
iptables -A INPUT -p tcp --dport 80 --syn \
-m hashlimit --hashlimit-above 10/s \
--hashlimit-burst 20 \
--hashlimit-mode srcip \
--hashlimit-name http_rate \
-j DROP
8.5.3 参数说明
| 参数 | 说明 |
|---|---|
--hashlimit-above | 速率阈值(超过则匹配) |
--hashlimit-upto | 速率阈值(不超过则匹配,与 above 取反) |
--hashlimit-burst | 突发上限 |
--hashlimit-mode | 哈希键:srcip、dstip、srcport、dstport 及其组合 |
--hashlimit-name | 规则名称(全局唯一) |
--hashlimit-htable-expire | 条目过期时间(毫秒) |
--hashlimit-htable-size | 哈希表大小 |
--hashlimit-htable-max | 最大条目数 |
8.5.4 业务场景
#!/bin/bash
# ═══════════════════════════════════════════════════
# 基于 hashlimit 的精细化限速
# ═══════════════════════════════════════════════════
# ─── HTTP 连接限速 ───
# 每个 IP 每秒最多 20 个新连接,突发不超过 50
iptables -A INPUT -p tcp --dport 80 --syn \
-m hashlimit \
--hashlimit-above 20/sec \
--hashlimit-burst 50 \
--hashlimit-mode srcip \
--hashlimit-name http_conn \
--hashlimit-htable-expire 30000 \
-j DROP
# ─── SSH 连接限速 ───
# 每个 IP 每分钟最多 4 次新连接
iptables -A INPUT -p tcp --dport 22 --syn \
-m hashlimit \
--hashlimit-above 4/minute \
--hashlimit-burst 4 \
--hashlimit-mode srcip \
--hashlimit-name ssh_conn \
--hashlimit-htable-expire 60000 \
-j DROP
# ─── DNS 查询限速 ───
# 每个源 IP 每秒最多 10 个查询
iptables -A INPUT -p udp --dport 53 \
-m hashlimit \
--hashlimit-above 10/sec \
--hashlimit-burst 20 \
--hashlimit-mode srcip \
--hashlimit-name dns_query \
-j DROP
# ─── 登录接口限速(基于目的端口 + 源 IP)───
iptables -A INPUT -p tcp --dport 443 --syn \
-m hashlimit \
--hashlimit-above 5/sec \
--hashlimit-burst 10 \
--hashlimit-mode srcip,dstport \
--hashlimit-name login_rate \
-j DROP
8.5.5 limit vs hashlimit 对比
| 特性 | limit | hashlimit |
|---|---|---|
| 速率桶 | 全局共享 | 每个键独立 |
| Per-IP 限制 | 不支持 | 支持 |
| 哈希键 | 无 | srcip/dstip/srcport/dstport |
| 内存消耗 | 低 | 较高(维护哈希表) |
| 适用场景 | 全局限速 | Per-IP 限速 |
8.6 time 模块
8.6.1 用途
time 模块根据时间段匹配数据包,用于实现时间策略。
8.6.2 语法
# 工作时间(周一至周五 9:00-18:00)允许访问
iptables -A INPUT -p tcp --dport 80 \
-m time --timestart 09:00 --timestop 18:00 \
--weekdays Mon,Tue,Wed,Thu,Fri \
-j ACCEPT
# 非工作时间拒绝
iptables -A INPUT -p tcp --dport 80 -j DROP
8.6.3 参数说明
| 参数 | 说明 | 格式 |
|---|---|---|
--timestart | 开始时间 | HH:MM |
--timestop | 结束时间 | HH:MM |
--weekdays | 星期几 | Mon,Tue,Wed,Thu,Fri,Sat,Sun |
--monthdays | 几号 | 1-31 |
--datestart | 开始日期 | YYYY[-MM[-DD[Thh[:mm[:ss]]]]] |
--datestop | 结束日期 | YYYY[-MM[-DD[Thh[:mm[:ss]]]]] |
--kerneltz | 使用内核时区 | 默认使用 UTC |
8.6.4 业务场景
#!/bin/bash
# ═══════════════════════════════════════════════════
# 基于时间的访问控制
# ═══════════════════════════════════════════════════
# 工作日 9:00-18:00 允许外部访问管理后台
iptables -A INPUT -p tcp --dport 8080 -s 10.0.0.0/8 \
-m time --timestart 09:00 --timestop 18:00 \
--weekdays Mon,Tue,Wed,Thu,Fri \
--kerneltz \
-m comment --comment "Admin panel: work hours only" \
-j ACCEPT
# 夜间批量任务窗口(23:00-05:00)允许备份流量
iptables -A INPUT -p tcp --dport 873 -s 10.0.2.0/24 \
-m time --timestart 23:00 --timestop 05:00 \
-m comment --comment "Backup window: 23:00-05:00" \
-j ACCEPT
# 维护窗口(每月第一个周日 02:00-06:00)
iptables -A INPUT -p tcp --dport 22 -s 0.0.0.0/0 \
-m time --datestart 2026-01-04T02:00 --datestop 2026-01-04T06:00 \
-m comment --comment "Maintenance window" \
-j ACCEPT
注意:
time模块使用 UTC 时间,除非指定--kerneltz。在中国时区(UTC+8)下,请确保时间参数正确。
8.7 string 模块
8.7.1 用途
string 模块匹配数据包载荷中的字符串,用于简单的应用层过滤。
8.7.2 语法
# 匹配包含 "malware" 的数据包
iptables -A FORWARD -m string --string "malware" --algo bm -j DROP
# 匹配包含特定域名的 HTTP 请求
iptables -A FORWARD -p tcp --dport 80 \
-m string --string "example.com" --algo bm -j DROP
# 匹配包含特定 User-Agent 的请求
iptables -A INPUT -p tcp --dport 80 \
-m string --string "sqlmap" --algo kmp -j DROP
8.7.3 参数说明
| 参数 | 说明 |
|---|---|
--string | 要匹配的字符串 |
--hex-string | 十六进制格式的字符串 |
--algo | 匹配算法:bm(Boyer-Moore)或 kmp(Knuth-Morris-Pratt) |
--from | 开始偏移量 |
--to | 结束偏移量 |
8.7.4 算法选择
| 算法 | 特点 | 适用场景 |
|---|---|---|
bm | 短模式更快 | 一般场景推荐 |
kmp | 长模式更稳定 | 长字符串匹配 |
8.7.5 业务场景
#!/bin/bash
# ═══════════════════════════════════════════════════
# 应用层内容过滤
# ═══════════════════════════════════════════════════
# 阻止常见扫描工具的 User-Agent
iptables -A INPUT -p tcp --dport 80 \
-m string --string "nikto" --algo bm -j DROP
iptables -A INPUT -p tcp --dport 80 \
-m string --string "sqlmap" --algo bm -j DROP
iptables -A INPUT -p tcp --dport 80 \
-m string --string "Nmap" --algo bm -j DROP
iptables -A INPUT -p tcp --dport 80 \
-m string --string "masscan" --algo bm -j DROP
# 阻止特定 URL 路径的访问
iptables -A INPUT -p tcp --dport 80 \
-m string --string "/etc/passwd" --algo bm -j DROP
iptables -A INPUT -p tcp --dport 80 \
-m string --string "phpMyAdmin" --algo bm -j DROP
# 记录可疑 SQL 注入尝试
iptables -A INPUT -p tcp -m multiport --dports 80,443 \
-m string --string "UNION SELECT" --algo bm \
-j LOG --log-prefix "SQL-INJECT: "
iptables -A INPUT -p tcp -m multiport --dports 80,443 \
-m string --string "UNION SELECT" --algo bm -j DROP
注意:
string模块对每个数据包的载荷进行检查,不是对整个 TCP 流进行检查。如果字符串跨越了两个数据包,将无法匹配。对于 HTTPS 流量(加密),string模块无法检查内容。
8.8 iprange 模块
8.8.1 用途
iprange 模块匹配一个连续的 IP 地址范围。
# 匹配 IP 范围
iptables -A INPUT -m iprange --src-range 192.168.1.100-192.168.1.200 -j ACCEPT
# 匹配目的 IP 范围
iptables -A OUTPUT -m iprange --dst-range 10.0.0.1-10.0.0.50 -j ACCEPT
# 排除特定范围
iptables -A INPUT -m iprange ! --src-range 10.0.0.1-10.0.0.255 -j DROP
8.9 owner 模块
8.9.1 用途
owner 模块根据数据包关联的进程属性(用户、组、PID)进行匹配。只能用于 OUTPUT 链。
# 按用户 ID 匹配
iptables -A OUTPUT -m owner --uid-owner 1000 -j ACCEPT
iptables -A OUTPUT -m owner --uid-owner www-data -j ACCEPT
# 按组 ID 匹配
iptables -A OUTPUT -m owner --gid-owner 1001 -j DROP
# 按进程 PID 匹配
iptables -A OUTPUT -m owner --pid-owner 1234 -j ACCEPT
# 排除特定用户
iptables -A OUTPUT -m owner ! --uid-owner root -j DROP
8.9.2 业务场景
# 只允许特定用户的出站网络访问
# 场景:限制服务器上只有 nginx 和 root 用户可以发起网络连接
iptables -A OUTPUT -m owner --uid-owner 0 -j ACCEPT # root
iptables -A OUTPUT -m owner --uid-owner www-data -j ACCEPT # nginx
iptables -A OUTPUT -m owner --uid-owner nobody -j ACCEPT # nobody
iptables -A OUTPUT -j DROP # 其他用户
8.10 recent 模块
8.10.1 用途
recent 模块维护一个最近匹配过的 IP 地址列表,可用于实现动态的速率限制或临时封禁。
8.10.2 语法
# 将访问过的 IP 加入列表
iptables -A INPUT -p tcp --dport 22 --syn \
-m recent --set --name SSH --rsource
# 如果该 IP 在 60 秒内已出现 5 次以上,拒绝
iptables -A INPUT -p tcp --dport 22 --syn \
-m recent --update --seconds 60 --hitcount 5 --name SSH --rsource \
-j DROP
# 允许正常连接
iptables -A INPUT -p tcp --dport 22 -j ACCEPT
8.10.3 参数说明
| 参数 | 说明 |
|---|---|
--set | 将当前 IP 添加到列表 |
--rset | 将当前 IP 添加到列表(与 –set 类似) |
--update | 如果 IP 在列表中,更新时间戳 |
--remove | 如果 IP 在列表中,移除它 |
--seconds N | 时间窗口(秒) |
--hitcount N | 命中次数阈值 |
--name | 列表名称 |
--rsource | 匹配源地址 |
--rdest | 匹配目的地址 |
8.10.4 业务场景
#!/bin/bash
# ═══════════════════════════════════════════════════
# SSH 暴力破解防护
# ═══════════════════════════════════════════════════
# 清空规则
iptables -F INPUT
# 已建立连接
iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
# 回环接口
iptables -A INPUT -i lo -j ACCEPT
# SSH 防暴力破解
# 步骤 1:记录 SSH 连接尝试
iptables -A INPUT -p tcp --dport 22 --syn \
-m recent --set --name SSHBRUTE --rsource
# 步骤 2:如果 60 秒内超过 4 次尝试,丢弃
iptables -A INPUT -p tcp --dport 22 --syn \
-m recent --update --seconds 60 --hitcount 4 --name SSHBRUTE --rsource \
-m limit --limit 1/min --limit-burst 1 \
-j LOG --log-prefix "SSH-BRUTE: "
iptables -A INPUT -p tcp --dport 22 --syn \
-m recent --update --seconds 60 --hitcount 4 --name SSHBRUTE --rsource \
-j DROP
# 步骤 3:允许正常的 SSH 连接
iptables -A INPUT -p tcp --dport 22 -j ACCEPT
# 默认策略
iptables -P INPUT DROP
8.11 statistic 模块
8.11.1 用途
statistic 模块按概率或每 N 个包匹配数据包,用于负载均衡或采样。
# 概率匹配:50% 的流量
iptables -A FORWARD -m statistic --mode random --probability 0.5 \
-j MARK --set-mark 1
# 每 N 个包匹配:每 10 个包匹配第 1 个
iptables -A FORWARD -m statistic --mode nth --every 10 --packet 0 \
-j MARK --set-mark 2
8.11.2 业务场景:简单负载均衡
#!/bin/bash
# 将 HTTP 流量 50/50 分配到两台后端服务器
# DNAT + statistic 实现简单负载均衡
# 50% 流量 → Web Server 1
iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 80 \
-m statistic --mode random --probability 0.50 \
-j DNAT --to-destination 10.0.0.10:80
# 剩余 50% 流量 → Web Server 2
iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 80 \
-j DNAT --to-destination 10.0.0.11:80
8.12 mac 模块
8.12.1 用途
mac 模块匹配源 MAC 地址,只能用于 PREROUTING 和 INPUT 链。
# 允许特定 MAC 地址访问
iptables -A INPUT -m mac --mac-source 00:11:22:33:44:55 -j ACCEPT
# 阻止特定 MAC 地址
iptables -A INPUT -m mac --mac-source AA:BB:CC:DD:EE:FF -j DROP
注意:MAC 地址只在同一广播域内有效。跨路由器(三层设备)后,源 MAC 地址会被替换为路由器的 MAC。
8.13 length 模块
8.13.1 用途
length 模块匹配数据包的总长度。
# 匹配大包(可能用于分片攻击防护)
iptables -A INPUT -m length --length 1500:65535 -j LOG --log-prefix "LARGE-PKT: "
# 匹配异常小包
iptables -A INPUT -p tcp --syn -m length --length :40 \
-j LOG --log-prefix "TINY-SYN: "
8.14 模块组合使用
8.14.1 组合示例
# 工作时间限制 + 源 IP + 并发连接限制
iptables -A INPUT -p tcp --dport 8080 \
-s 10.0.0.0/8 \
-m time --timestart 09:00 --timestop 18:00 --weekdays Mon,Tue,Wed,Thu,Fri \
-m connlimit --connlimit-above 10 \
-m comment --comment "Admin panel: work hours, limited connections" \
-j ACCEPT
# Per-IP 速率限制 + 字符串匹配
iptables -A INPUT -p tcp --dport 80 \
-m hashlimit --hashlimit-above 100/sec --hashlimit-mode srcip --hashlimit-name web \
-m string --string "SELECT" --algo bm \
-j LOG --log-prefix "SQL-WARN: "
8.15 注意事项
⚠️ 模块组合性能:每多加载一个模块,匹配开销就增加一层。在高吞吐场景下,应精简模块的使用。
⚠️ string 模块局限:不能检查加密流量(HTTPS),不能跨包匹配,对大文件传输的中间数据包可能无法命中关键字。
⚠️ hashlimit 内存消耗:哈希表会占用内核内存。
--hashlimit-htable-max应根据预期的并发 IP 数设置,避免浪费内存。
⚠️ recent 模块的并发:在多核系统中,
recent模块使用自旋锁保护列表,高并发下可能成为性能瓶颈。
8.16 扩展阅读
| 资源 | 说明 |
|---|---|
man iptables-extensions | 所有扩展模块的完整手册 |
iptables -m <module> --help | 查看特定模块的帮助 |
本章小结
| 模块 | 功能 | 典型用途 |
|---|---|---|
multiport | 多端口匹配 | 减少规则数量 |
connlimit | 并发连接限制 | 防资源耗尽 |
limit | 固定速率限制 | 全局限速 |
hashlimit | Per-IP 速率限制 | 精细化限速 |
time | 时间段匹配 | 时间策略 |
string | 字符串匹配 | 内容过滤 |
iprange | IP 范围匹配 | 连续 IP 匹配 |
owner | 进程/用户匹配 | 出口控制 |
recent | 最近访问列表 | 动态封禁 |
statistic | 概率/统计匹配 | 简单负载均衡 |
下一章:第 09 章:扩展目标与动作,将学习 LOG、REJECT 等高级目标动作。