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

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 管理前端
ModSecurityWeb 应用防火墙
CIS Benchmarks安全基线标准

本章小结

攻击类型防御手段
端口扫描tcp-flags 检测 + recent 封禁
SYN FloodSYN Cookie + hashlimit + connlimit
UDP Floodhashlimit + 大包丢弃
ICMP Floodlimit + hashlimit
HTTP Floodhashlimit + connlimit
IP 欺骗rp_filter + 反欺骗规则
ICMP 信息泄露白名单 ICMP 类型

下一章第 13 章:IPv6 防火墙 ip6tables,将学习 IPv6 环境下的防火墙配置。