强曰为道

与天地相似,故不违。知周乎万物,而道济天下,故不过。旁行而不流,乐天知命,故不忧.
文档目录

第 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 iprangeIP 地址范围匹配
owner-m owner进程/用户/组匹配
recent-m recent最近访问记录匹配
statistic-m statistic统计匹配(概率/每N包)
mac-m macMAC 地址匹配
length-m length数据包长度匹配
ttl-m ttlTTL 值匹配
tos-m tosTOS 值匹配
mark-m markMARK 值匹配
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 用途

hashlimitlimit 的增强版,它为每个源 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哈希键:srcipdstipsrcportdstport 及其组合
--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 对比

特性limithashlimit
速率桶全局共享每个键独立
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固定速率限制全局限速
hashlimitPer-IP 速率限制精细化限速
time时间段匹配时间策略
string字符串匹配内容过滤
iprangeIP 范围匹配连续 IP 匹配
owner进程/用户匹配出口控制
recent最近访问列表动态封禁
statistic概率/统计匹配简单负载均衡

下一章第 09 章:扩展目标与动作,将学习 LOG、REJECT 等高级目标动作。