iptables 完全指南 / 第 12 章:安全加固规则
第 12 章:安全加固规则
本章目标:掌握使用 iptables 实现服务器安全加固的各种技巧,包括防端口扫描、防 SYN Flood、速率限制、IP 白名单/黑名单等。
12.1 防端口扫描
12.1.1 识别端口扫描行为
端口扫描工具(如 Nmap)通过发送特定类型的数据包来探测目标主机的开放端口。常见的扫描类型:
| 扫描类型 | 数据包特征 | Nmap 选项 |
|---|---|---|
| TCP SYN 扫描 | 仅发送 SYN 包 | -sS |
| TCP FIN 扫描 | 仅发送 FIN 包 | -sF |
| TCP XMAS 扫描 | FIN+PSH+URG 标志 | -sX |
| TCP NULL 扫描 | 无任何标志 | -sN |
| UDP 扫描 | UDP 包 | -sU |
| ACK 扫描 | ACK 包 | -sA |
12.1.2 防御规则
#!/bin/bash
# ═══════════════════════════════════════════════════
# 防端口扫描规则
# ═══════════════════════════════════════════════════
# ─── 1. 检测并丢弃 XMAS 扫描(FIN+PSH+URG)───
iptables -A INPUT -p tcp --tcp-flags ALL FIN,PSH,URG \
-j LOG --log-prefix "SCAN-XMAS: "
iptables -A INPUT -p tcp --tcp-flags ALL FIN,PSH,URG -j DROP
# ─── 2. 检测并丢弃 NULL 扫描(无标志)───
iptables -A INPUT -p tcp --tcp-flags ALL NONE \
-j LOG --log-prefix "SCAN-NULL: "
iptables -A INPUT -p tcp --tcp-flags ALL NONE -j DROP
# ─── 3. 检测并丢弃 FIN 扫描(仅 FIN)───
iptables -A INPUT -p tcp --tcp-flags ALL FIN \
-j LOG --log-prefix "SCAN-FIN: "
iptables -A INPUT -p tcp --tcp-flags ALL FIN -j DROP
# ─── 4. 检测并丢弃 SYN-FIN 组合(非法)───
iptables -A INPUT -p tcp --tcp-flags SYN,FIN SYN,FIN \
-j LOG --log-prefix "SCAN-SYNFIN: "
iptables -A INPUT -p tcp --tcp-flags SYN,FIN SYN,FIN -j DROP
# ─── 5. 检测并丢弃 SYN-RST 组合(非法)───
iptables -A INPUT -p tcp --tcp-flags SYN,RST SYN,RST \
-j LOG --log-prefix "SCAN-SYNRST: "
iptables -A INPUT -p tcp --tcp-flags SYN,RST SYN,RST -j DROP
# ─── 6. 检测并丢弃 FIN-RST 组合(非法)───
iptables -A INPUT -p tcp --tcp-flags FIN,RST FIN,RST \
-j LOG --log-prefix "SCAN-FINRST: "
iptables -A INPUT -p tcp --tcp-flags FIN,RST FIN,RST -j DROP
# ─── 7. 检测 ACK 扫描 ───
iptables -A INPUT -p tcp --tcp-flags ALL ACK \
-m conntrack --ctstate NEW \
-j LOG --log-prefix "SCAN-ACK: "
iptables -A INPUT -p tcp --tcp-flags ALL ACK \
-m conntrack --ctstate NEW -j DROP
# ─── 8. 使用 recent 模块封禁扫描者 ───
# 如果 60 秒内对关闭端口的探测超过 10 次,封禁该 IP
iptables -A INPUT -p tcp -m conntrack --ctstate INVALID \
-m recent --set --name PORTSCAN --rsource
iptables -A INPUT -p tcp -m conntrack --ctstate INVALID \
-m recent --update --seconds 60 --hitcount 10 \
--name PORTSCAN --rsource \
-j LOG --log-prefix "SCAN-BLOCKED: "
iptables -A INPUT -p tcp -m conntrack --ctstate INVALID \
-m recent --update --seconds 60 --hitcount 10 \
--name PORTSCAN --rsource -j DROP
12.1.3 tcp-flags 参数详解
# 语法:--tcp-flags 检查的标志位 应该设置的标志位
# 标志位列表:SYN,ACK,FIN,RST,URG,PSH,ALL,NONE
# 检查所有标志位,其中只有 SYN 被设置(正常 SYN 包)
iptables -A INPUT -p tcp --tcp-flags ALL SYN -j ACCEPT
# 检查 SYN 和 ACK,只有 SYN 被设置(新连接请求)
iptables -A INPUT -p tcp --tcp-flags SYN,ACK SYN -j ACCEPT
# 检查 SYN,ACK,RST,只有 ACK 被设置(ACK 包)
iptables -A INPUT -p tcp --tcp-flags SYN,ACK,RST ACK -j ACCEPT
12.2 防 DDoS 攻击
12.2.1 SYN Flood 防御
#!/bin/bash
# ═══════════════════════════════════════════════════
# SYN Flood 防御
# ═══════════════════════════════════════════════════
# ─── 1. 启用 SYN Cookie(内核级防御)───
sysctl -w net.ipv4.tcp_syncookies=1
sysctl -w net.ipv4.tcp_max_syn_backlog=4096
sysctl -w net.ipv4.tcp_synack_retries=2
sysctl -w net.ipv4.tcp_syn_retries=2
# ─── 2. 限制 SYN 速率 ───
# 每个源 IP 每秒最多 10 个 SYN 包
iptables -A INPUT -p tcp --syn \
-m hashlimit \
--hashlimit-above 10/sec \
--hashlimit-burst 20 \
--hashlimit-mode srcip \
--hashlimit-name syn_flood \
--hashlimit-htable-expire 30000 \
-j DROP
# ─── 3. 全局 SYN 速率限制 ───
# 总体 SYN 包速率不超过 1000/sec
iptables -A INPUT -p tcp --syn \
-m limit --limit 1000/sec --limit-burst 2000 \
-j ACCEPT
iptables -A INPUT -p tcp --syn -j DROP
# ─── 4. 限制半开连接数 ───
# 每个源 IP 最多 50 个 SYN_RECV 状态连接
iptables -A INPUT -p tcp --syn \
-m connlimit --connlimit-above 50 \
-j DROP
12.2.2 UDP Flood 防御
#!/bin/bash
# ═══════════════════════════════════════════════════
# UDP Flood 防御
# ═══════════════════════════════════════════════════
# 限制每个源 IP 的 UDP 速率
iptables -A INPUT -p udp \
-m hashlimit \
--hashlimit-above 50/sec \
--hashlimit-burst 100 \
--hashlimit-mode srcip \
--hashlimit-name udp_flood \
-j DROP
# 限制特定端口的 UDP 速率(DNS 放大攻击防护)
iptables -A INPUT -p udp --dport 53 \
-m hashlimit \
--hashlimit-above 20/sec \
--hashlimit-burst 50 \
--hashlimit-mode srcip \
--hashlimit-name dns_flood \
-j DROP
# 丢弃 UDP 大包(通常是放大攻击)
iptables -A INPUT -p udp -m length --length 512:65535 \
-m conntrack --ctstate NEW \
-j DROP
12.2.3 ICMP Flood 防御
# 限制 ICMP 速率
iptables -A INPUT -p icmp --icmp-type echo-request \
-m hashlimit \
--hashlimit-above 5/sec \
--hashlimit-burst 10 \
--hashlimit-mode srcip \
--hashlimit-name icmp_flood \
-j DROP
# 全局 ICMP 限制
iptables -A INPUT -p icmp --icmp-type echo-request \
-m limit --limit 100/sec --limit-burst 200 \
-j ACCEPT
iptables -A INPUT -p icmp --icmp-type echo-request -j DROP
12.2.4 HTTP Flood 防御
#!/bin/bash
# ═══════════════════════════════════════════════════
# HTTP Flood / CC 攻击防御
# ═══════════════════════════════════════════════════
# 每个 IP 每秒最多 50 个 HTTP 新连接
iptables -A INPUT -p tcp -m multiport --dports 80,443 --syn \
-m hashlimit \
--hashlimit-above 50/sec \
--hashlimit-burst 100 \
--hashlimit-mode srcip \
--hashlimit-name http_flood \
--hashlimit-htable-expire 60000 \
-j DROP
# 每个 IP 最多 200 个并发 HTTP 连接
iptables -A INPUT -p tcp -m multiport --dports 80,443 \
-m connlimit --connlimit-above 200 \
-j DROP
# 记录可疑 IP(频繁连接但被拒绝的)
iptables -A INPUT -p tcp -m multiport --dports 80,443 --syn \
-m hashlimit \
--hashlimit-above 30/sec \
--hashlimit-mode srcip \
--hashlimit-name http_warn \
-j LOG --log-prefix "HTTP-FLOOD-WARN: "
12.3 速率限制综合方案
12.3.1 分层限速架构
┌──────────────────────────────────────────────┐
│ Layer 1: 连接跟踪限制 (connlimit) │
│ - 限制单 IP 并发连接数 │
├──────────────────────────────────────────────┤
│ Layer 2: 新连接速率限制 (hashlimit) │
│ - 限制单 IP 新连接速率 │
├──────────────────────────────────────────────┤
│ Layer 3: 全局速率限制 (limit) │
│ - 限制服务器整体新连接速率 │
├──────────────────────────────────────────────┤
│ Layer 4: 日志记录 (LOG + limit) │
│ - 限速日志,防日志泛洪 │
└──────────────────────────────────────────────┘
12.3.2 综合限速脚本
#!/bin/bash
# ═══════════════════════════════════════════════════
# 综合限速方案
# ═══════════════════════════════════════════════════
iptables -F INPUT
iptables -P INPUT DROP
# ─── 1. 已建立连接放行 ───
iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
# ─── 2. 丢弃无效包 ───
iptables -A INPUT -m conntrack --ctstate INVALID -j DROP
# ─── 3. 回环接口 ───
iptables -A INPUT -i lo -j ACCEPT
# ─── 4. 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_rate \
--hashlimit-htable-expire 120000 \
-j DROP
# 每 IP 最多 3 个并发连接
iptables -A INPUT -p tcp --dport 22 \
-m connlimit --connlimit-above 3 -j DROP
iptables -A INPUT -p tcp --dport 22 -j ACCEPT
# ─── 5. HTTP/HTTPS:限速 + 并发限制 ───
# 每 IP 每秒最多 30 个新连接
iptables -A INPUT -p tcp -m multiport --dports 80,443 --syn \
-m hashlimit \
--hashlimit-above 30/sec \
--hashlimit-burst 60 \
--hashlimit-mode srcip \
--hashlimit-name web_rate \
--hashlimit-htable-expire 30000 \
-j DROP
# 每 IP 最多 150 个并发连接
iptables -A INPUT -p tcp -m multiport --dports 80,443 \
-m connlimit --connlimit-above 150 -j DROP
iptables -A INPUT -p tcp -m multiport --dports 80,443 -j ACCEPT
# ─── 6. ICMP:限速 ───
iptables -A INPUT -p icmp --icmp-type echo-request \
-m hashlimit \
--hashlimit-above 5/sec \
--hashlimit-burst 10 \
--hashlimit-mode srcip \
--hashlimit-name icmp_rate \
-j DROP
iptables -A INPUT -p icmp --icmp-type echo-request -j ACCEPT
# ─── 7. DNS(如果本机是 DNS 服务器)───
iptables -A INPUT -p udp --dport 53 \
-m hashlimit \
--hashlimit-above 20/sec \
--hashlimit-burst 50 \
--hashlimit-mode srcip \
--hashlimit-name dns_rate \
-j DROP
iptables -A INPUT -p udp --dport 53 -j ACCEPT
# ─── 8. 日志限速 ───
iptables -A INPUT \
-m limit --limit 10/minute --limit-burst 30 \
-j LOG --log-prefix "IPT-DROP: "
# ─── 9. 最终丢弃 ───
iptables -A INPUT -j DROP
12.4 IP 白名单/黑名单
12.4.1 白名单模式
#!/bin/bash
# ═══════════════════════════════════════════════════
# 白名单模式:只允许指定 IP 访问
# 适用于:数据库服务器、内网管理接口
# ═══════════════════════════════════════════════════
# 白名单 IP 列表
WHITELIST=(
"192.168.1.100" # 管理员 1
"192.168.1.101" # 管理员 2
"10.0.1.0/24" # 应用服务器网段
"10.0.2.0/24" # 监控服务器网段
)
# 已建立连接
iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
# 回环接口
iptables -A INPUT -i lo -j ACCEPT
# 白名单 IP 允许
for IP in "${WHITELIST[@]}"; do
iptables -A INPUT -s $IP -j ACCEPT
done
# 其他全部拒绝
iptables -P INPUT DROP
12.4.2 黑名单模式
#!/bin/bash
# ═══════════════════════════════════════════════════
# 黑名单模式:封禁已知恶意 IP
# ═══════════════════════════════════════════════════
# 创建黑名单自定义链
iptables -N BLACKLIST
# 恶意 IP 列表
BLACKLIST=(
"1.2.3.4"
"5.6.7.0/24"
"10.20.30.0/24"
)
# 添加黑名单规则
for IP in "${BLACKLIST[@]}"; do
iptables -A BLACKLIST -s $IP -j LOG --log-prefix "BLACKLIST: "
iptables -A BLACKLIST -s $IP -j DROP
done
# 在 INPUT 链的最前面调用黑名单
iptables -I INPUT 1 -j BLACKLIST
# 从外部文件加载黑名单
while IFS= read -r IP; do
[[ "$IP" =~ ^#.*$ || -z "$IP" ]] && continue
iptables -A BLACKLIST -s "$IP" -j DROP
done < /etc/iptables/blacklist.txt
12.4.3 动态黑名单(fail2ban 风格)
#!/bin/bash
# ═══════════════════════════════════════════════════
# 动态黑名单:自动封禁可疑 IP
# ═══════════════════════════════════════════════════
# 创建动态封禁链
iptables -N DYNAMIC_BLOCK
# 规则 1:SSH 暴力破解检测
# 60 秒内超过 5 次新连接尝试 → 封禁 10 分钟
iptables -A INPUT -p tcp --dport 22 --syn \
-m recent --set --name SSH_BRUTE --rsource
iptables -A INPUT -p tcp --dport 22 --syn \
-m recent --update --seconds 60 --hitcount 5 \
--name SSH_BRUTE --rsource \
-j DYNAMIC_BLOCK
# 规则 2:HTTP 暴力破解检测
# 60 秒内超过 50 次新连接 → 封禁
iptables -A INPUT -p tcp --dport 80 --syn \
-m recent --set --name HTTP_BRUTE --rsource
iptables -A INPUT -p tcp --dport 80 --syn \
-m recent --update --seconds 60 --hitcount 50 \
--name HTTP_BRUTE --rsource \
-j DYNAMIC_BLOCK
# 动态封禁链动作
iptables -A DYNAMIC_BLOCK \
-m recent --set --name BLOCKED --rsource \
-j LOG --log-prefix "DYNAMIC-BLOCK: "
iptables -A DYNAMIC_BLOCK -j DROP
# 检查是否已被封禁
iptables -I INPUT 1 -m recent --update --seconds 600 \
--name BLOCKED --rsource -j DROP
12.5 防 ICMP 信息泄露
#!/bin/bash
# ═══════════════════════════════════════════════════
# 防 ICMP 信息泄露
# ═══════════════════════════════════════════════════
# 允许必要的 ICMP 类型
# echo-request(ping)
iptables -A INPUT -p icmp --icmp-type echo-request \
-m limit --limit 5/sec -j ACCEPT
# echo-reply(ping 回复)
iptables -A INPUT -p icmp --icmp-type echo-reply -j ACCEPT
# destination-unreachable(路径 MTU 发现需要)
iptables -A INPUT -p icmp --icmp-type destination-unreachable -j ACCEPT
# time-exceeded(traceroute 需要)
iptables -A INPUT -p icmp --icmp-type time-exceeded -j ACCEPT
# 参数问题
iptables -A INPUT -p icmp --icmp-type parameter-problem -j ACCEPT
# 拒绝其他 ICMP 类型
# (source-quench、redirect、router-* 等可能泄露网络拓扑信息)
iptables -A INPUT -p icmp -j DROP
12.6 防 ARP 欺骗
#!/bin/bash
# ═══════════════════════════════════════════════════
# ARP 欺骗防御(需要 ebtables 或 arptables)
# ═══════════════════════════════════════════════════
# 使用 arptables 限制 ARP 响应
# 安装:apt install arptables
# 只允许网关 IP 对应的 MAC 地址发送 ARP 响应
arptables -A INPUT --source-mac 00:11:22:33:44:55 -j ACCEPT
arptables -A INPUT -j DROP
# 使用静态 ARP 表
arp -s 192.168.1.1 00:11:22:33:44:55
# 内核参数:限制 ARP 响应
sysctl -w net.ipv4.conf.all.arp_ignore=1
sysctl -w net.ipv4.conf.all.arp_announce=2
12.7 防常见攻击模式
12.7.1 防 Land 攻击
# Land 攻击:源地址和目的地址相同
iptables -A INPUT -s 10.0.0.1 -d 10.0.0.1 -j DROP
# 通用防御:源地址等于目的地址
iptables -A INPUT -m addrtype --src-type LOCAL \
-m addrtype --dst-type LOCAL \
-i != lo -j DROP
12.7.2 防 Smurf 攻击
# Smurf 攻击:发送 ICMP 到广播地址
# 丢弃发往广播地址的 ICMP
iptables -A INPUT -d 255.255.255.255 -p icmp -j DROP
iptables -A INPUT -d 10.0.0.255 -p icmp -j DROP
# 内核参数:禁止响应广播 ping
sysctl -w net.ipv4.icmp_echo_ignore_broadcasts=1
12.7.3 防 IP 欺骗
# ═══════════════════════════════════════════════════
# 防 IP 欺骗(反欺骗规则)
# ═══════════════════════════════════════════════════
# 丢弃声称来自内网但来自外网接口的数据包
iptables -A INPUT -i eth0 -s 10.0.0.0/8 -j DROP
iptables -A INPUT -i eth0 -s 172.16.0.0/12 -j DROP
iptables -A INPUT -i eth0 -s 192.168.0.0/16 -j DROP
iptables -A INPUT -i eth0 -s 127.0.0.0/8 -j DROP
# 丢弃来自多播地址的数据包
iptables -A INPUT -s 224.0.0.0/4 -j DROP
# 丢弃来自保留地址的数据包
iptables -A INPUT -s 0.0.0.0/8 -j DROP
iptables -A INPUT -s 169.254.0.0/16 -j DROP
iptables -A INPUT -s 192.0.2.0/24 -j DROP
iptables -A INPUT -s 240.0.0.0/4 -j DROP
# 内核参数:启用反向路径过滤(rp_filter)
sysctl -w net.ipv4.conf.all.rp_filter=1
sysctl -w net.ipv4.conf.default.rp_filter=1
12.8 安全加固检查清单
#!/bin/bash
# ═══════════════════════════════════════════════════
# Linux 防火墙安全加固检查清单
# ═══════════════════════════════════════════════════
echo "=== 防火墙安全检查 ==="
# 1. 检查默认策略
echo -n "1. INPUT 默认策略: "
iptables -L INPUT -n | head -1 | grep -q "DROP" && echo "OK (DROP)" || echo "WARN (not DROP)"
# 2. 检查 FORWARD 默认策略
echo -n "2. FORWARD 默认策略: "
iptables -L FORWARD -n | head -1 | grep -q "DROP" && echo "OK (DROP)" || echo "WARN (not DROP)"
# 3. 检查 ESTABLISHED 规则
echo -n "3. ESTABLISHED 规则: "
iptables -L INPUT -n | grep -q "ESTABLISHED" && echo "OK" || echo "MISSING"
# 4. 检查防扫描规则
echo -n "4. XMAS 扫描防护: "
iptables -L INPUT -n | grep -q "XMAS\|FIN,PSH,URG" && echo "OK" || echo "MISSING"
# 5. 检查 ICMP 限制
echo -n "5. ICMP 限速: "
iptables -L INPUT -n | grep -q "limit" && echo "OK" || echo "MISSING"
# 6. 检查 SSH 限制
echo -n "6. SSH 来源限制: "
iptables -L INPUT -n | grep "dpt:22" | grep -q "192.168\|10.0" && echo "OK" || echo "WARN (开放)"
# 7. 检查 conntrack 参数
echo -n "7. conntrack_max: "
cat /proc/sys/net/netfilter/nf_conntrack_max
# 8. 检查 SYN Cookie
echo -n "8. SYN Cookie: "
sysctl net.ipv4.tcp_syncookies | grep -q "1" && echo "OK" || echo "DISABLED"
# 9. 检查 rp_filter
echo -n "9. 反向路径过滤: "
sysctl net.ipv4.conf.all.rp_filter | grep -q "1" && echo "OK" || echo "DISABLED"
# 10. 检查广播 ICMP 忽略
echo -n "10. 广播 ICMP 忽略: "
sysctl net.ipv4.icmp_echo_ignore_broadcasts | grep -q "1" && echo "OK" || echo "DISABLED"
12.9 注意事项
⚠️ 限速值需要根据实际业务调整:上面示例中的限速值是参考值,需要根据服务器的实际流量和业务特点进行调整。
⚠️ 防 DDoS 的局限性:iptables 运行在服务器内核中,当遭受大流量 DDoS 攻击时,即使 iptables 能处理,网络带宽和 CPU 也可能被耗尽。大规模 DDoS 需要在上游(运营商/CDN)层面防护。
⚠️ 动态封禁的内存消耗:
recent模块的列表存储在内核内存中,大量封禁 IP 会消耗内存。
⚠️ 不要封禁自己:在添加反欺骗规则时,注意不要误封本地管理地址。
12.10 扩展阅读
| 资源 | 说明 |
|---|---|
| fail2ban | 自动化封禁工具 |
| CrowdSec | 社区驱动的入侵检测 |
| CSF (ConfigServer Security & Firewall) | iptables 管理前端 |
| ModSecurity | Web 应用防火墙 |
| CIS Benchmarks | 安全基线标准 |
本章小结
| 攻击类型 | 防御手段 |
|---|---|
| 端口扫描 | tcp-flags 检测 + recent 封禁 |
| SYN Flood | SYN Cookie + hashlimit + connlimit |
| UDP Flood | hashlimit + 大包丢弃 |
| ICMP Flood | limit + hashlimit |
| HTTP Flood | hashlimit + connlimit |
| IP 欺骗 | rp_filter + 反欺骗规则 |
| ICMP 信息泄露 | 白名单 ICMP 类型 |
下一章:第 13 章:IPv6 防火墙 ip6tables,将学习 IPv6 环境下的防火墙配置。