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

iptables 完全指南 / 第 18 章:最佳实践与运维规范

第 18 章:最佳实践与运维规范

本章目标:总结 17 章所学内容,形成可直接应用于生产环境的防火墙管理规范,包括安全基线、运维流程、自动化部署和审计方案。


18.1 安全基线

18.1.1 服务器防火墙最低要求

项目 要求 说明
默认策略 INPUT: DROP, FORWARD: DROP 白名单模式
ESTABLISHED 规则 必须有,放在第一条 提升性能,放行已建立连接
无效包处理 必须丢弃 INVALID 状态的包 防异常包
回环接口 必须允许 lo 本地服务通信
ICMP 限制速率 允许必要类型,限制速率
SSH 限制来源 IP 不要对所有 IP 开放
日志 记录被拒绝的流量 便于审计和排错
持久化 规则必须持久化 重启后自动恢复

18.1.2 基线规则模板

#!/bin/bash
# ═══════════════════════════════════════════════════
# 服务器防火墙基线模板
# ═══════════════════════════════════════════════════

set -e

# ─── 变量定义 ───
IPT="/usr/sbin/iptables"
IP6T="/usr/sbin/ip6tables"
SSH_SOURCES="10.0.0.0/8"        # SSH 允许的源网段
LOG_LIMIT="10/minute"            # 日志速率限制
LOG_BURST="30"                   # 日志突发上限

# ─── 清空规则 ───
$IPT -F && $IPT -t nat -F && $IPT -t mangle -F && $IPT -t raw -F && $IPT -X
$IP6T -F && $IP6T -X

# ─── IPv4 INPUT 链 ───

$IPT -P INPUT DROP
$IPT -P FORWARD DROP
$IPT -P OUTPUT ACCEPT

# 1. 已建立的连接(最高优先级)
$IPT -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT

# 2. 丢弃无效包
$IPT -A INPUT -m conntrack --ctstate INVALID -j DROP

# 3. 回环接口
$IPT -A INPUT -i lo -j ACCEPT

# 4. 防端口扫描
$IPT -A INPUT -p tcp --tcp-flags ALL FIN,PSH,URG -j DROP
$IPT -A INPUT -p tcp --tcp-flags ALL NONE -j DROP
$IPT -A INPUT -p tcp --tcp-flags SYN,FIN SYN,FIN -j DROP
$IPT -A INPUT -p tcp --tcp-flags SYN,RST SYN,RST -j DROP

# 5. SSH(限速 + 来源限制)
$IPT -A INPUT -p tcp --dport 22 -s $SSH_SOURCES --syn \
  -m hashlimit --hashlimit-above 4/minute --hashlimit-burst 4 \
  --hashlimit-mode srcip --hashlimit-name ssh_rate -j DROP
$IPT -A INPUT -p tcp --dport 22 -s $SSH_SOURCES \
  -m connlimit --connlimit-above 3 -j DROP
$IPT -A INPUT -p tcp --dport 22 -s $SSH_SOURCES -j ACCEPT

# 6. ICMP(限速)
$IPT -A INPUT -p icmp --icmp-type echo-request \
  -m limit --limit 5/sec --limit-burst 10 -j ACCEPT

# 7. 日志
$IPT -A INPUT -m limit --limit $LOG_LIMIT --limit-burst $LOG_BURST \
  -j LOG --log-prefix "IPT-INPUT-DROP: " --log-level 4

# 8. 最终拒绝
$IPT -A INPUT -j DROP

# ─── IPv6 INPUT 链 ───

$IP6T -P INPUT DROP
$IP6T -P FORWARD DROP
$IP6T -P OUTPUT ACCEPT

# 已建立的连接
$IP6T -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
$IP6T -A INPUT -m conntrack --ctstate INVALID -j DROP
$IP6T -A INPUT -i lo -j ACCEPT

# ICMPv6(必须允许关键类型)
$IP6T -A INPUT -p ipv6-icmp --icmpv6-type neighbor-solicitation -j ACCEPT
$IP6T -A INPUT -p ipv6-icmp --icmpv6-type neighbor-advertisement -j ACCEPT
$IP6T -A INPUT -p ipv6-icmp --icmpv6-type router-solicitation -j ACCEPT
$IP6T -A INPUT -p ipv6-icmp --icmpv6-type router-advertisement -j ACCEPT
$IP6T -A INPUT -p ipv6-icmp --icmpv6-type echo-request \
  -m limit --limit 5/sec -j ACCEPT
$IP6T -A INPUT -p ipv6-icmp --icmpv6-type destination-unreachable -j ACCEPT
$IP6T -A INPUT -p ipv6-icmp --icmpv6-type packet-too-big -j ACCEPT
$IP6T -A INPUT -p ipv6-icmp --icmpv6-type time-exceeded -j ACCEPT
$IP6T -A INPUT -p ipv6-icmp -j DROP

# SSH
$IP6T -A INPUT -p tcp --dport 22 -s 2001:db8::/32 -j ACCEPT

# 日志
$IP6T -A INPUT -m limit --limit $LOG_LIMIT --limit-burst $LOG_BURST \
  -j LOG --log-prefix "IP6-INPUT-DROP: " --log-level 4

$IP6T -A INPUT -j DROP

# ─── 内核安全参数 ───
sysctl -w net.ipv4.tcp_syncookies=1
sysctl -w net.ipv4.conf.all.rp_filter=1
sysctl -w net.ipv4.conf.default.rp_filter=1
sysctl -w net.ipv4.icmp_echo_ignore_broadcasts=1
sysctl -w net.ipv6.conf.all.accept_ra=0
sysctl -w net.ipv6.conf.default.accept_ra=0

echo "Baseline firewall applied."

18.1.3 内核安全参数基线

# /etc/sysctl.d/99-firewall-baseline.conf

# ─── IPv4 安全参数 ───
net.ipv4.tcp_syncookies = 1
net.ipv4.conf.all.rp_filter = 1
net.ipv4.conf.default.rp_filter = 1
net.ipv4.icmp_echo_ignore_broadcasts = 1
net.ipv4.conf.all.accept_redirects = 0
net.ipv4.conf.default.accept_redirects = 0
net.ipv4.conf.all.send_redirects = 0
net.ipv4.conf.default.send_redirects = 0
net.ipv4.conf.all.accept_source_route = 0
net.ipv4.conf.default.accept_source_route = 0
net.ipv4.conf.all.log_martians = 1
net.ipv4.conf.default.log_martians = 1

# ─── IPv6 安全参数 ───
net.ipv6.conf.all.accept_redirects = 0
net.ipv6.conf.default.accept_redirects = 0
net.ipv6.conf.all.accept_source_route = 0
net.ipv6.conf.default.accept_source_route = 0
net.ipv6.conf.all.accept_ra = 0
net.ipv6.conf.default.accept_ra = 0

# ─── conntrack 优化 ───
net.netfilter.nf_conntrack_max = 262144
net.netfilter.nf_conntrack_tcp_timeout_established = 1800
net.netfilter.nf_conntrack_tcp_timeout_time_wait = 15
net.netfilter.nf_conntrack_tcp_timeout_fin_wait = 15
net.netfilter.nf_conntrack_tcp_timeout_close_wait = 10
net.netfilter.nf_conntrack_tcp_timeout_syn_sent = 15
net.netfilter.nf_conntrack_tcp_timeout_syn_recv = 10
net.netfilter.nf_conntrack_udp_timeout = 10
net.netfilter.nf_conntrack_udp_timeout_stream = 60

18.2 运维规范

18.2.1 规则变更流程

┌─────────────────────────────────────────────┐
│ 步骤 1:提交变更申请                          │
│ - 变更原因                                   │
│ - 变更内容(具体规则)                         │
│ - 影响范围                                   │
│ - 回滚方案                                   │
└──────────────────┬──────────────────────────┘
                   ▼
┌─────────────────────────────────────────────┐
│ 步骤 2:测试环境验证                          │
│ - 在测试环境应用规则                          │
│ - 验证功能正常                               │
│ - 确认不影响其他服务                          │
└──────────────────┬──────────────────────────┘
                   ▼
┌─────────────────────────────────────────────┐
│ 步骤 3:备份当前规则                          │
│ - iptables-save > backup.rules.v4            │
│ - ip6tables-save > backup.rules.v6           │
└──────────────────┬──────────────────────────┘
                   ▼
┌─────────────────────────────────────────────┐
│ 步骤 4:应用变更                              │
│ - 在维护窗口期执行                            │
│ - 确保有带外访问方式                          │
│ - 执行规则变更                                │
└──────────────────┬──────────────────────────┘
                   ▼
┌─────────────────────────────────────────────┐
│ 步骤 5:验证和监控                            │
│ - 确认服务正常                               │
│ - 监控错误日志                               │
│ - 确认规则持久化                              │
└──────────────────┬──────────────────────────┘
                   ▼
┌─────────────────────────────────────────────┐
│ 步骤 6:记录变更                              │
│ - 更新防火墙文档                             │
│ - 提交版本控制                               │
│ - 关闭变更单                                 │
└─────────────────────────────────────────────┘

18.2.2 规则命名和注释规范

# ─── 注释规范 ───
# 格式:# [日期] [负责人] [用途] [工单号]
# 示例:
iptables -A INPUT -p tcp --dport 80 -m comment \
  --comment "2026-05-10/zhangsan/Web服务/TICKET-1234" -j ACCEPT

# ─── 自定义链命名规范 ───
# 格式:服务名_方向_动作
# 示例:
iptables -N WEB_INPUT_ACCEPT     # Web 入站允许
iptables -N DB_INPUT_ACCEPT       # 数据库入站允许
iptables -N MGMT_INPUT_ACCEPT     # 管理入站允许
iptables -N MONITOR_INPUT_ACCEPT  # 监控入站允许

18.2.3 定期审计流程

#!/bin/bash
# /usr/local/bin/firewall-audit.sh
# 防火墙规则定期审计脚本

REPORT="/var/log/firewall-audit-$(date +%Y%m%d).txt"

{
echo "========================================"
echo "防火墙审计报告 - $(date)"
echo "========================================"
echo ""

echo "一、规则统计"
echo "----------------------------------------"
echo "INPUT 链规则数: $(iptables -L INPUT -n | tail -n +3 | wc -l)"
echo "FORWARD 链规则数: $(iptables -L FORWARD -n | tail -n +3 | wc -l)"
echo "OUTPUT 链规则数: $(iptables -L OUTPUT -n | tail -n +3 | wc -l)"
echo "NAT PREROUTING 规则数: $(iptables -t nat -L PREROUTING -n | tail -n +3 | wc -l)"
echo "NAT POSTROUTING 规则数: $(iptables -t nat -L POSTROUTING -n | tail -n +3 | wc -l)"
echo ""

echo "二、默认策略"
echo "----------------------------------------"
iptables -L INPUT -n | head -1
iptables -L FORWARD -n | head -1
iptables -L OUTPUT -n | head -1
echo ""

echo "三、未命中的规则(潜在无用规则)"
echo "----------------------------------------"
iptables -L INPUT -n -v | awk 'NR>2 && $2+0 == 0 {print}'
echo ""

echo "四、最常命中的规则"
echo "----------------------------------------"
iptables -L INPUT -n -v --line-numbers | sort -k2 -n -r | head -10
echo ""

echo "五、连接跟踪状态"
echo "----------------------------------------"
echo "当前连接数: $(conntrack -C)"
echo "最大连接数: $(sysctl -n net.netfilter.nf_conntrack_max)"
COUNT=$(conntrack -C)
MAX=$(sysctl -n net.netfilter.nf_conntrack_max)
echo "使用率: $(( COUNT * 100 / MAX ))%"
echo ""

echo "六、内核安全参数"
echo "----------------------------------------"
for param in net.ipv4.tcp_syncookies \
             net.ipv4.conf.all.rp_filter \
             net.ipv4.icmp_echo_ignore_broadcasts \
             net.ipv4.conf.all.accept_redirects \
             net.ipv6.conf.all.accept_ra; do
    echo "$param = $(sysctl -n $param)"
done
echo ""

echo "七、自定义链列表"
echo "----------------------------------------"
iptables -L -n | grep "^Chain" | grep -v -E "(INPUT|OUTPUT|FORWARD)"
echo ""

echo "八、端口扫描防护规则"
echo "----------------------------------------"
iptables -L INPUT -n | grep -E "(FIN,PSH,URG|SYN,FIN|SYN,RST|ALL NONE)"
echo ""

} > "$REPORT"

echo "审计报告已生成: $REPORT"

18.3 自动化管理

18.3.1 Ansible 自动化部署

# playbook: deploy-firewall.yml
---
- name: Deploy iptables firewall rules
  hosts: all
  become: yes
  vars:
    ssh_sources:
      - "10.0.0.0/8"
      - "192.168.1.0/24"
    web_ports:
      - "80"
      - "443"
    db_ports:
      - "3306"
      - "5432"
    log_limit: "10/minute"
    log_burst: "30"

  tasks:
    - name: Install iptables-persistent
      apt:
        name: iptables-persistent
        state: present
      when: ansible_os_family == "Debian"

    - name: Create iptables rules directory
      file:
        path: /etc/iptables
        state: directory
        mode: '0755'

    - name: Deploy IPv4 rules file
      template:
        src: templates/rules.v4.j2
        dest: /etc/iptables/rules.v4
        mode: '0600'
      notify: Restore iptables

    - name: Deploy IPv6 rules file
      template:
        src: templates/rules.v6.j2
        dest: /etc/iptables/rules.v6
        mode: '0600'
      notify: Restore ip6tables

    - name: Deploy sysctl security params
      template:
        src: templates/99-firewall.conf.j2
        dest: /etc/sysctl.d/99-firewall.conf
        mode: '0644'
      notify: Apply sysctl

    - name: Deploy firewall management scripts
      copy:
        src: "files/{{ item }}"
        dest: "/usr/local/bin/{{ item }}"
        mode: '0755'
      loop:
        - firewall-save.sh
        - firewall-restore.sh
        - firewall-audit.sh

    - name: Set up audit cron job
      cron:
        name: "Firewall audit"
        minute: "0"
        hour: "8"
        job: "/usr/local/bin/firewall-audit.sh"
        user: root

  handlers:
    - name: Restore iptables
      shell: iptables-restore < /etc/iptables/rules.v4

    - name: Restore ip6tables
      shell: ip6tables-restore < /etc/iptables/rules.v6

    - name: Apply sysctl
      shell: sysctl --system
# templates/rules.v4.j2
# Generated by Ansible - DO NOT EDIT MANUALLY
*filter
:INPUT DROP [0:0]
:FORWARD DROP [0:0]
:OUTPUT ACCEPT [0:0]
# Established connections
-A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A INPUT -m conntrack --ctstate INVALID -j DROP
# Loopback
-A INPUT -i lo -j ACCEPT
# Port scan protection
-A INPUT -p tcp --tcp-flags ALL FIN,PSH,URG -j DROP
-A INPUT -p tcp --tcp-flags ALL NONE -j DROP
-A INPUT -p tcp --tcp-flags SYN,FIN SYN,FIN -j DROP
-A INPUT -p tcp --tcp-flags SYN,RST SYN,RST -j DROP
# SSH
{% for source in ssh_sources %}
-A INPUT -p tcp --dport 22 -s {{ source }} -j ACCEPT
{% endfor %}
# Web ports
{% for port in web_ports %}
-A INPUT -p tcp --dport {{ port }} -j ACCEPT
{% endfor %}
# Database ports (app servers only)
{% for port in db_ports %}
-A INPUT -p tcp --dport {{ port }} -s 10.0.1.0/24 -j ACCEPT
{% endfor %}
# ICMP
-A INPUT -p icmp --icmp-type echo-request -m limit --limit 5/sec -j ACCEPT
# Logging
-A INPUT -m limit --limit {{ log_limit }} --limit-burst {{ log_burst }} -j LOG --log-prefix "IPT-INPUT-DROP: "
# Default deny
-A INPUT -j DROP
COMMIT

18.3.2 Puppet 模块

# manifests/init.pp
class firewall_baseline (
  Array[String] $ssh_sources = ['10.0.0.0/8'],
  Array[String] $web_ports   = ['80', '443'],
) {

  package { 'iptables-persistent':
    ensure => installed,
  }

  file { '/etc/iptables/rules.v4':
    ensure  => file,
    owner   => 'root',
    group   => 'root',
    mode    => '0600',
    content => epp('firewall/rules.v4.epp', {
      'ssh_sources' => $ssh_sources,
      'web_ports'   => $web_ports,
    }),
    notify  => Exec['restore-iptables'],
  }

  exec { 'restore-iptables':
    command     => '/sbin/iptables-restore < /etc/iptables/rules.v4',
    refreshonly => true,
  }

  sysctl { 'net.ipv4.tcp_syncookies': value => '1' }
  sysctl { 'net.ipv4.conf.all.rp_filter': value => '1' }
  sysctl { 'net.ipv4.icmp_echo_ignore_broadcasts': value => '1' }
}

18.3.3 Shell 脚本自动化

#!/bin/bash
# /usr/local/bin/firewall-manager.sh
# 防火墙管理工具

CONF="/etc/iptables/firewall.conf"
BACKUP_DIR="/etc/iptables/backup"
LOG_FILE="/var/log/firewall-manager.log"

log() {
    echo "$(date '+%Y-%m-%d %H:%M:%S') $1" >> "$LOG_FILE"
}

backup() {
    mkdir -p "$BACKUP_DIR"
    local ts=$(date +%Y%m%d_%H%M%S)
    iptables-save > "$BACKUP_DIR/rules.v4.$ts"
    ip6tables-save > "$BACKUP_DIR/rules.v6.$ts"
    # 保留最近 50 个备份
    ls -t "$BACKUP_DIR"/rules.v4.* | tail -n +51 | xargs -r rm
    ls -t "$BACKUP_DIR"/rules.v6.* | tail -n +51 | xargs -r rm
    log "Backup created: $ts"
}

apply() {
    backup
    iptables-restore < /etc/iptables/rules.v4
    ip6tables-restore < /etc/iptables/rules.v6
    log "Rules applied from files"
}

save() {
    backup
    iptables-save > /etc/iptables/rules.v4
    ip6tables-save > /etc/iptables/rules.v6
    log "Rules saved to files"
}

rollback() {
    local latest=$(ls -t "$BACKUP_DIR"/rules.v4.* 2>/dev/null | head -1)
    if [ -z "$latest" ]; then
        echo "No backup found"
        exit 1
    fi
    local v6=$(echo "$latest" | sed 's/rules.v4/rules.v6/')
    iptables-restore < "$latest"
    [ -f "$v6" ] && ip6tables-restore < "$v6"
    log "Rollback to: $(basename $latest)"
}

status() {
    echo "=== IPv4 INPUT 规则 ==="
    iptables -L INPUT -n -v --line-numbers
    echo ""
    echo "=== 连接跟踪状态 ==="
    echo "当前: $(conntrack -C) / 最大: $(sysctl -n net.netfilter.nf_conntrack_max)"
}

case "$1" in
    apply)    apply ;;
    save)     save ;;
    rollback) rollback ;;
    status)   status ;;
    backup)   backup ;;
    *)
        echo "Usage: $0 {apply|save|rollback|status|backup}"
        exit 1
        ;;
esac

18.4 规则文档化

18.4.1 规则清单模板

# 防火墙规则清单

## 服务器信息
- 主机名: web-prod-01
- IP: 10.0.0.10 (内网), 203.0.113.1 (公网)
- 操作系统: Ubuntu 22.04 LTS
- 负责人: 张三
- 最后更新: 2026-05-10

## INPUT 链规则

| # | 协议 | 源地址 | 目的端口 | 动作 | 用途 | 工单 |
|---|------|--------|----------|------|------|------|
| 1 | all  | all    | all      | ACCEPT | 已建立连接(ESTABLISHED,RELATED) | - |
| 2 | tcp  | 10.0.0.0/8 | 22 | ACCEPT | SSH 管理 | TICKET-001 |
| 3 | tcp  | all    | 80       | ACCEPT | HTTP | TICKET-002 |
| 4 | tcp  | all    | 443      | ACCEPT | HTTPS | TICKET-002 |
| 5 | icmp | all    | echo-request | ACCEPT | Ping (限速 5/s) | - |
| 6 | all  | all    | all      | DROP   | 默认拒绝 | - |

## NAT 规则

| 链 | 源 | 目的端口 | 动作 | 转换目标 | 用途 |
|----|-----|----------|------|----------|------|
| PREROUTING | eth0 | 80 | DNAT | 10.0.0.10:80 | Web 入站 |
| POSTROUTING | 10.0.0.0/24 | eth0 | MASQUERADE | - | 内网出站 |

18.4.2 自动生成文档

#!/bin/bash
# /usr/local/bin/generate-firewall-doc.sh
# 自动生成防火墙规则文档

DOC="/var/doc/firewall-rules-$(date +%Y%m%d).md"

{
echo "# 防火墙规则文档"
echo ""
echo "生成时间: $(date)"
echo "主机名: $(hostname)"
echo ""

echo "## IPv4 INPUT 规则"
echo ""
echo "\`\`\`"
iptables -L INPUT -n -v --line-numbers
echo "\`\`\`"
echo ""

echo "## IPv4 FORWARD 规则"
echo ""
echo "\`\`\`"
iptables -L FORWARD -n -v --line-numbers
echo "\`\`\`"
echo ""

echo "## NAT PREROUTING 规则"
echo ""
echo "\`\`\`"
iptables -t nat -L PREROUTING -n -v --line-numbers
echo "\`\`\`"
echo ""

echo "## NAT POSTROUTING 规则"
echo ""
echo "\`\`\`"
iptables -t nat -L POSTROUTING -n -v --line-numbers
echo "\`\`\`"
echo ""

echo "## IPv6 INPUT 规则"
echo ""
echo "\`\`\`"
ip6tables -L INPUT -n -v --line-numbers
echo "\`\`\`"
echo ""

echo "## 内核参数"
echo ""
echo "\`\`\`"
sysctl net.ipv4.tcp_syncookies
sysctl net.ipv4.conf.all.rp_filter
sysctl net.ipv4.icmp_echo_ignore_broadcasts
sysctl net.netfilter.nf_conntrack_max
echo "\`\`\`"
echo ""

echo "## 连接跟踪统计"
echo ""
echo "\`\`\`"
conntrack -S 2>/dev/null || echo "conntrack 工具未安装"
echo "\`\`\`"

} > "$DOC"

echo "文档已生成: $DOC"

18.5 监控与告警

18.5.1 连接跟踪监控

#!/bin/bash
# /usr/local/bin/conntrack-monitor.sh
# 连接跟踪监控脚本

THRESHOLD_WARNING=80
THRESHOLD_CRITICAL=95

COUNT=$(cat /proc/sys/net/netfilter/nf_conntrack_count)
MAX=$(cat /proc/sys/net/netfilter/nf_conntrack_max)
USAGE=$(( COUNT * 100 / MAX ))

if [ $USAGE -ge $THRESHOLD_CRITICAL ]; then
    echo "CRITICAL: conntrack 使用率 ${USAGE}% ($COUNT/$MAX)"
    logger -t conntrack-monitor -p crit "conntrack usage CRITICAL: ${USAGE}%"
    # 发送告警(根据实际告警系统调整)
    # curl -X POST https://alert.example.com/api/send ...
    exit 2
elif [ $USAGE -ge $THRESHOLD_WARNING ]; then
    echo "WARNING: conntrack 使用率 ${USAGE}% ($COUNT/$MAX)"
    logger -t conntrack-monitor -p warning "conntrack usage WARNING: ${USAGE}%"
    exit 1
else
    echo "OK: conntrack 使用率 ${USAGE}% ($COUNT/$MAX)"
    exit 0
fi

18.5.2 规则变更告警

#!/bin/bash
# /usr/local/bin/firewall-change-detector.sh
# 检测防火墙规则是否被修改

HASH_FILE="/var/lib/iptables/rules.sha256"
CURRENT_HASH=$(iptables-save | sha256sum | awk '{print $1}')

if [ ! -f "$HASH_FILE" ]; then
    echo "$CURRENT_HASH" > "$HASH_FILE"
    exit 0
fi

SAVED_HASH=$(cat "$HASH_FILE")

if [ "$CURRENT_HASH" != "$SAVED_HASH" ]; then
    echo "WARNING: Firewall rules have been modified!"
    logger -t firewall-monitor -p warning "Firewall rules modified unexpectedly"
    
    # 对比差异
    iptables-save > /tmp/current-rules.v4
    diff /etc/iptables/rules.v4 /tmp/current-rules.v4
    
    # 更新哈希
    echo "$CURRENT_HASH" > "$HASH_FILE"
    exit 1
else
    echo "OK: Firewall rules unchanged."
    exit 0
fi

18.6 灾难恢复

18.6.1 应急响应流程

#!/bin/bash
# /usr/local/bin/firewall-emergency-reset.sh
# 应急恢复:清空所有规则,恢复到完全开放状态
# ⚠️ 仅在紧急情况下使用!

echo "WARNING: This will reset all firewall rules to ACCEPT!"
echo "Press Ctrl+C within 10 seconds to abort..."
sleep 10

# 备份当前规则
iptables-save > /tmp/emergency-backup-$(date +%Y%m%d%H%M%S).rules.v4
ip6tables-save > /tmp/emergency-backup-$(date +%Y%m%d%H%M%S).rules.v6

# 清空所有规则
iptables -F
iptables -t nat -F
iptables -t mangle -F
iptables -t raw -F
iptables -X

ip6tables -F
ip6tables -X

# 设置默认策略为 ACCEPT
iptables -P INPUT ACCEPT
iptables -P FORWARD ACCEPT
iptables -P OUTPUT ACCEPT

ip6tables -P INPUT ACCEPT
ip6tables -P FORWARD ACCEPT
ip6tables -P OUTPUT ACCEPT

echo "All firewall rules have been reset to ACCEPT."
echo "Backup saved to /tmp/emergency-backup-*.rules.v4"
echo ""
echo "⚠️  REMEMBER: Re-apply proper firewall rules ASAP!"

18.6.2 回滚脚本

#!/bin/bash
# /usr/local/bin/firewall-rollback.sh
# 回滚到最近的备份

BACKUP_DIR="/etc/iptables/backup"

# 查找最近的备份
LATEST_V4=$(ls -t "$BACKUP_DIR"/rules.v4.* 2>/dev/null | head -1)
LATEST_V6=$(ls -t "$BACKUP_DIR"/rules.v6.* 2>/dev/null | head -1)

if [ -z "$LATEST_V4" ]; then
    echo "ERROR: No backup found in $BACKUP_DIR"
    exit 1
fi

echo "Rolling back to: $(basename $LATEST_V4)"
echo "Press Ctrl+C within 5 seconds to abort..."
sleep 5

iptables-restore < "$LATEST_V4"
echo "IPv4 rules restored from $(basename $LATEST_V4)"

if [ -n "$LATEST_V6" ]; then
    ip6tables-restore < "$LATEST_V6"
    echo "IPv6 rules restored from $(basename $LATEST_V6)"
fi

echo "Rollback complete."

18.7 安全检查清单

18.7.1 定期检查项

每日检查:
 □ 防火墙规则计数器是否异常
 □ 连接跟踪使用率是否正常
 □ 日志文件大小是否合理
 □ 是否有异常的 DROP 记录

每周检查:
 □ 运行防火墙审计脚本
 □ 检查未命中的规则(可能需要清理)
 □ 检查是否有未授权的规则变更
 □ 备份当前规则并对比上周

每月检查:
 □ 审查所有规则的必要性
 □ 清理过期的临时规则
 □ 更新白名单/黑名单
 □ 检查内核安全参数
 □ 测试恢复流程

每季度检查:
 □ 安全基线合规性检查
 □ 文档更新
 □ 自动化脚本测试
 □ 应急恢复演练

18.8 多服务器统一管理

18.8.1 中心化管理架构

┌─────────────────────┐
│ 防火墙管理服务器     │
│ (Ansible/Puppet)    │
│ 规则仓库 (Git)      │
│ 审计中心            │
└──────────┬──────────┘
           │
     ┌─────┼─────┬───────────┐
     ▼     ▼     ▼           ▼
  ┌─────┐┌─────┐┌─────┐  ┌─────┐
  │Web-1││Web-2││DB-1 │  │App-1│
  └─────┘└─────┘└─────┘  └─────┘

18.8.2 分组管理

# Ansible inventory 分组示例
# inventory/hosts.yml

all:
  children:
    web_servers:
      hosts:
        web-prod-01:
          ansible_host: 10.0.0.10
        web-prod-02:
          ansible_host: 10.0.0.11
      vars:
        firewall_web_ports: [80, 443]

    db_servers:
      hosts:
        db-prod-01:
          ansible_host: 10.0.0.200
      vars:
        firewall_db_ports: [3306]
        firewall_ssh_sources: ["10.0.0.0/24"]

    monitoring:
      hosts:
        mon-prod-01:
          ansible_host: 10.0.2.10
      vars:
        firewall_mon_ports: [9090, 3000, 9100]

18.9 容器环境的特殊考虑

18.9.1 Docker 环境规范

规范 1:使用 DOCKER-USER 链控制外部访问
  - 不要修改 Docker 自动创建的链
  - 所有自定义规则放在 DOCKER-USER 链

规范 2:端口映射安全
  - 生产环境不要使用 -p 0.0.0.0:port:port
  - 使用 -p 127.0.0.1:port:port 或 DOCKER-USER 限制
  - 通过反向代理统一入口

规范 3:容器间通信
  - 使用 Docker 网络隔离(--internal)
  - 不要依赖 iptables 做容器间隔离

规范 4:持久化
  - DOCKER-USER 规则需要单独持久化
  - Docker 重启后 DOCKER-USER 链规则会保留
  - 但 iptables-restore 可能覆盖 Docker 规则

18.9.2 Docker 规则持久化

#!/bin/bash
# /usr/local/bin/docker-firewall-setup.sh
# Docker 环境的防火墙初始化
# 在 Docker 启动后执行

# 等待 Docker 启动
sleep 5

# 清空 DOCKER-USER 链
iptables -F DOCKER-USER

# 允许已建立的连接
iptables -A DOCKER-USER -m conntrack --ctstate ESTABLISHED,RELATED -j RETURN

# 允许内部网络
iptables -A DOCKER-USER -i eth1 -j RETURN

# 允许外部访问 Web 端口
iptables -A DOCKER-USER -i eth0 -p tcp -m multiport --dports 80,443 -j RETURN

# 拒绝其他外部访问
iptables -A DOCKER-USER -i eth0 -j DROP

# 默认返回
iptables -A DOCKER-USER -j RETURN

echo "Docker firewall rules applied."
# /etc/systemd/system/docker-firewall.service
# 在 Docker 启动后执行防火墙配置

[Unit]
Description=Docker Firewall Rules
After=docker.service
Requires=docker.service

[Service]
Type=oneshot
ExecStart=/usr/local/bin/docker-firewall-setup.sh
RemainAfterExit=yes

[Install]
WantedBy=multi-user.target

18.10 常见反模式(Anti-patterns)

18.10.1 应该避免的做法

❌ 反模式 1:在生产环境直接执行 iptables -F
✅ 正确做法:使用脚本,先备份再清空,设置超时自动回滚

❌ 反模式 2:默认策略设为 ACCEPT,靠规则列表做限制
✅ 正确做法:默认策略设为 DROP,使用白名单模式

❌ 反模式 3:SSH 端口对所有 IP 开放
✅ 正确做法:限制 SSH 来源 IP 或使用 VPN

❌ 反模式 4:不做规则持久化
✅ 正确做法:每次修改后立即保存到文件

❌ 反模式 5:在 Docker DOCKER 链中添加规则
✅ 正确做法:在 DOCKER-USER 链中添加规则

❌ 反模式 6:直接修改 iptables-save 导出的文件
✅ 正确做法:使用版本控制的脚本管理规则

❌ 反模式 7:不做日志记录
✅ 正确做法:记录被 DROP 的流量,便于排错和审计

❌ 反模式 8:忘记 ICMPv6 的关键类型(IPv6 环境)
✅ 正确做法:始终允许 ICMPv6 的邻居发现和路径 MTU 类型

❌ 反模式 9:规则过多且无注释
✅ 正确做法:使用自定义链分组,每条规则添加注释

❌ 反模式 10:不做定期审计
✅ 正确做法:定期审计规则,清理无用规则

18.11 注意事项

⚠️ 文档先行:任何防火墙规则变更都应该先更新文档,再执行变更。

⚠️ 备份是底线:在任何操作前都必须备份当前规则。

⚠️ 带外访问:生产环境的防火墙变更必须确保有 IPMI/KVM/串口等带外访问方式。

⚠️ 最小权限原则:只开放必要的端口和 IP,宁可严一点也不要松一点。

⚠️ 持续监控:防火墙配置不是一劳永逸的,需要持续监控和定期审计。


18.12 扩展阅读

资源 说明
CIS Benchmarks 安全基线标准
NIST SP 800-123 服务器安全指南
PCI DSS 支付卡行业数据安全标准
Ansible Documentation 自动化工具文档
fail2ban 自动化封禁工具
CrowdSec 社区安全防护

本章小结

实践 要点
安全基线 默认 DROP,白名单模式,双栈配置
运维规范 变更流程,注释规范,定期审计
自动化 Ansible/Puppet,脚本管理,版本控制
监控告警 conntrack 监控,规则变更检测
灾难恢复 应急重置脚本,回滚方案
文档化 规则清单,自动生成文档

全教程回顾

恭喜你完成了 iptables 完全指南的全部 18 章学习!让我们回顾一下:

部分 章节 核心能力
基础篇 01-07 理解 Netfilter 架构、四表五链、基本操作、各表用法
进阶篇 08-13 掌握扩展匹配、安全加固、连接跟踪、IPv6 防火墙
实战篇 14-18 规则持久化、Docker 集成、nftables 迁移、故障排查、运维规范

继续学习建议

  1. 实践:在测试环境中反复练习,熟练掌握常用命令
  2. nftables:在新项目中开始使用 nftables,了解未来方向
  3. LVS/DPDK:了解高性能四层负载均衡方案
  4. eBPF:关注 eBPF/XDP 等新一代网络过滤技术
  5. 零信任网络:了解 BeyondCorp 等零信任架构