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

iptables 完全指南 / 第 09 章:扩展目标与动作

第 09 章:扩展目标与动作

本章目标:掌握 iptables 的各种扩展目标(Target),能够使用 LOG、REJECT、TEE、NFQUEUE 等高级动作实现日志记录、流量镜像、用户态处理等功能。


9.1 目标(Target)分类

9.1.1 基本目标 vs 扩展目标

类型目标说明
基本目标ACCEPT接受数据包(不需要加载模块)
基本目标DROP丢弃数据包(不需要加载模块)
基本目标RETURN返回调用链
扩展目标REJECT拒绝并返回错误(需要 ipt_REJECT 模块)
扩展目标LOG记录日志(需要 ipt_LOG 模块)
扩展目标MASQUERADE动态 SNAT
扩本目标DNAT/SNAT目的/源地址转换
扩展目标REDIRECT端口重定向
扩展目标MARK设置标记
扩展目标TEE流量镜像
扩展目标NFQUEUE传递到用户态
扩展目标NOTRACK跳过连接跟踪

9.2 LOG 目标

9.2.1 用途

LOG 目标将匹配的数据包信息记录到系统日志,而不终止规则遍历(与 ACCEPT/DROP 不同)。这是调试防火墙规则的重要工具。

9.2.2 语法

# 基本日志记录
iptables -A INPUT -j LOG

# 带前缀的日志
iptables -A INPUT -p tcp --dport 22 -j LOG --log-prefix "SSH-ACCESS: "

# 指定日志级别
iptables -A INPUT -j LOG --log-level 4  # warning

# 同时记录 TCP 序列号(调试用)
iptables -A INPUT -j LOG --log-tcp-sequence

# 同时记录 IP 选项
iptables -A INPUT -j LOG --log-ip-options

# 同时记录 TCP 选项
iptables -A INPUT -j LOG --log-tcp-options

9.2.3 参数说明

参数说明默认值
--log-prefix日志前缀(最多 29 字符)
--log-level日志级别(0-7)4 (warning)
--log-tcp-sequence记录 TCP 序列号关闭
--log-tcp-options记录 TCP 选项关闭
--log-ip-options记录 IP 选项关闭
--log-uid记录发起进程的 UID关闭

9.2.4 日志级别

级别名称说明
0emerg紧急
1alert警报
2crit临界
3err错误
4warning警告(推荐)
5notice通知
6info信息
7debug调试

9.2.5 日志配置

# iptables 日志默认写入 /var/log/messages 或 /var/log/kern.log
# 可以通过 rsyslog 配置分离 iptables 日志

# 创建 /etc/rsyslog.d/iptables.conf
cat > /etc/rsyslog.d/iptables.conf << 'EOF'
:msg, contains, "IPT-" /var/log/iptables.log
& stop
EOF

# 重启 rsyslog
systemctl restart rsyslog

# 配合 logrotate 防止日志过大
cat > /etc/logrotate.d/iptables << 'EOF'
/var/log/iptables.log {
    daily
    rotate 30
    compress
    delaycompress
    missingok
    notifempty
    create 0640 root root
    postrotate
        /usr/bin/systemctl reload rsyslog > /dev/null 2>&1 || true
    endscript
}
EOF

9.2.6 业务场景

#!/bin/bash
# ═══════════════════════════════════════════════════
# 日志记录方案
# ═══════════════════════════════════════════════════

# 已建立的连接(不记录,减少日志量)
iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT

# 允许 SSH,记录登录尝试
iptables -A INPUT -p tcp --dport 22 --syn \
  -j LOG --log-prefix "IPT-SSH-NEW: " --log-level 4
iptables -A INPUT -p tcp --dport 22 -j ACCEPT

# 记录被拒绝的 HTTP 请求
iptables -A INPUT -p tcp --dport 80 --syn \
  -m hashlimit --hashlimit-above 50/sec --hashlimit-mode srcip \
  --hashlimit-name http_log --hashlimit-burst 100 \
  -j LOG --log-prefix "IPT-HTTP-RATE: " --log-level 4

# 记录所有被丢弃的数据包(限速,防止日志泛洪)
iptables -A INPUT \
  -m limit --limit 10/min --limit-burst 20 \
  -j LOG --log-prefix "IPT-INPUT-DROP: " --log-level 4

# 默认拒绝
iptables -P INPUT DROP

9.2.7 NFLOG 目标(推荐)

NFLOGLOG 的替代方案,它将日志通过 Netlink 传递给用户态的 ulogd2 守护进程,性能更好、功能更强大:

# 使用 NFLOG 记录日志到 NFLOG group 1
iptables -A INPUT -j NFLOG --nflog-group 1 --nflog-prefix "IPT-DROP"

# ulogd2 配置可以将日志写入文件、数据库等
# 安装:apt install ulogd2
# 配置文件:/etc/ulogd.conf
特性LOGNFLOG
性能较低(同步写入内核日志)高(异步 Netlink)
目标syslogulogd2(可配置多种输出)
格式文本可配置(文本、JSON、数据库)
适用场景简单日志需求大规模日志收集

9.3 REJECT 目标

9.3.1 拒绝类型

# 默认拒绝(ICMP port unreachable)
iptables -A INPUT -p tcp --dport 8080 -j REJECT

# TCP RST 拒绝(适用于 TCP 协议)
iptables -A INPUT -p tcp --dport 8080 -j REJECT --reject-with tcp-reset

# ICMP 网络不可达
iptables -A INPUT -j REJECT --reject-with icmp-net-unreachable

# ICMP 主机不可达
iptables -A INPUT -j REJECT --reject-with icmp-host-unreachable

# ICMP 协议不可达
iptables -A INPUT -p tcp --dport 22 -j REJECT --reject-with icmp-proto-unreachable

9.3.2 拒绝类型一览

类型说明适用协议
icmp-net-unreachable网络不可达所有
icmp-host-unreachable主机不可达所有
icmp-port-unreachable端口不可达(默认)所有
icmp-proto-unreachable协议不可达所有
icmp-net-prohibited网络被禁止所有
icmp-host-prohibited主机被禁止所有
icmp-admin-prohibited管理禁止所有
tcp-resetTCP RST仅 TCP

9.3.3 DROP vs REJECT 选择指南

                    ┌──────────────────┐
                    │ 使用场景?        │
                    └────────┬─────────┘
                       ┌─────┼──────┐
                       ▼     ▼      ▼
                  生产环境  内部网络  调试/开发
                  外部接口  服务器间     环境
                       │     │      │
                       ▼     ▼      ▼
                    DROP   REJECT   REJECT
                   (安全)  (友好)   (调试方便)

9.4 MASQUERADE 目标

9.4.1 与 SNAT 的对比

# SNAT(固定公网 IP)
iptables -t nat -A POSTROUTING -s 10.0.0.0/24 -o eth0 \
  -j SNAT --to-source 203.0.113.1

# MASQUERADE(动态 IP,如 DHCP 或拨号)
iptables -t nat -A POSTROUTING -s 10.0.0.0/24 -o eth0 \
  -j MASQUERADE

# MASQUERADE 指定端口范围
iptables -t nat -A POSTROUTING -s 10.0.0.0/24 -o eth0 \
  -j MASQUERADE --to-ports 1024-65535

9.5 TEE 目标

9.5.1 用途

TEE 目标将数据包的副本发送到另一个网关地址,实现流量镜像。原始数据包继续正常处理。

9.5.2 语法

# 将所有入站流量镜像到分析服务器
iptables -t mangle -A PREROUTING -i eth0 \
  -j TEE --gateway 10.0.0.200

# 只镜像 HTTP 流量
iptables -t mangle -A PREROUTING -i eth0 -p tcp --dport 80 \
  -j TEE --gateway 10.0.0.200

# 使用外部网关(跨网段需要路由可达)
iptables -t mangle -A PREROUTING -i eth0 \
  -j TEE --gateway 192.168.100.1

9.5.3 业务场景

#!/bin/bash
# ═══════════════════════════════════════════════════
# 流量镜像到 IDS/IPS 入侵检测系统
# ═══════════════════════════════════════════════════

# 镜像所有入站流量到 Suricata/Snort 分析服务器
iptables -t mangle -A PREROUTING -i eth0 \
  -m comment --comment "Mirror to IDS" \
  -j TEE --gateway 10.0.0.200

# 只镜像特定端口的流量(减少分析服务器负载)
iptables -t mangle -A PREROUTING -i eth0 -p tcp \
  -m multiport --dports 22,80,443,3306 \
  -m comment --comment "Mirror critical ports to IDS" \
  -j TEE --gateway 10.0.0.200

注意:TEE 需要目标网关在同一个广播域(二层可达),或者有路由可达。TEE 在 mangle 表中使用效果最佳。


9.6 NFQUEUE 目标

9.6.1 用途

NFQUEUE 将数据包传递到用户态程序进行处理。用户态程序可以决定接受(ACCEPT)、丢弃(DROP)或修改数据包。

9.6.2 语法

# 将数据包传递到队列 0
iptables -A INPUT -p tcp --dport 80 -j NFQUEUE --queue-num 0

# 传递到队列 0,不修改数据包(旁路模式)
iptables -A INPUT -j NFQUEUE --queue-num 0 --queue-bypass

# 多队列(多核并行处理)
iptables -A INPUT -p tcp --dport 80 -j NFQUEUE --queue-num 0
iptables -A INPUT -p tcp --dport 443 -j NFQUEUE --queue-num 1

9.6.3 用户态处理程序

#!/usr/bin/env python3
# 使用 nfqueue 库处理数据包
# 安装:pip3 install netfilterqueue

from netfilterqueue import NetfilterQueue

def packet_handler(packet):
    """处理每个数据包"""
    print(f"Packet: {len(packet.get_payload())} bytes")
    # 接受数据包
    packet.accept()

nfqueue = NetfilterQueue()
nfqueue.bind(0, packet_handler)  # 绑定队列 0

try:
    nfqueue.run()
except KeyboardInterrupt:
    nfqueue.unbind()
# 配置 iptables 规则
iptables -A INPUT -p tcp --dport 80 -j NFQUEUE --queue-num 0

# 运行用户态处理程序
sudo python3 nfqueue_handler.py

9.6.4 业务场景:WAF(Web 应用防火墙)

NFQUEUE 常用于实现用户态的 Web 应用防火墙,如基于 Python/Go 的自定义 WAF。它可以检查 HTTP 请求内容,识别并阻止 SQL 注入、XSS 等攻击。


9.7 CLASSIFY 目标

9.7.1 用途

CLASSIFY 目标为数据包设置 tc(traffic control)的类标识,配合 Linux 流量控制使用。

# 将 SSH 流量分类到高优先级类别
iptables -t mangle -A FORWARD -p tcp --dport 22 \
  -j CLASSIFY --set-class 1:10

# 将 HTTP 流量分类到普通类别
iptables -t mangle -A FORWARD -p tcp --dport 80 \
  -j CLASSIFY --set-class 1:20

# 将 P2P 流量分类到低优先级类别
iptables -t mangle -A FORWARD -p tcp --dport 6881:6889 \
  -j CLASSIFY --set-class 1:40

9.8 SNAT 和 DNAT 的高级用法

9.8.1 多目标 NAT(负载均衡)

# 将 HTTP 流量随机分发到三台后端服务器
iptables -t nat -A PREROUTING -p tcp --dport 80 \
  -m statistic --mode random --probability 0.33 \
  -j DNAT --to-destination 10.0.0.10:80

iptables -t nat -A PREROUTING -p tcp --dport 80 \
  -m statistic --mode random --probability 0.50 \
  -j DNAT --to-destination 10.0.0.11:80

iptables -t nat -A PREROUTING -p tcp --dport 80 \
  -j DNAT --to-destination 10.0.0.12:80

9.8.2 SNAT 端口范围

# 指定 SNAT 的源端口范围
iptables -t nat -A POSTROUTING -s 10.0.0.0/24 -o eth0 \
  -j SNAT --to-source 203.0.113.1:1024-65535

9.8.3 端口映射

# 将公网 8080 映射到内网 80
iptables -t nat -A PREROUTING -p tcp --dport 8080 \
  -j DNAT --to-destination 10.0.0.10:80

# 将公网 2222 映射到内网 SSH 服务器的 22 端口
iptables -t nat -A PREROUTING -p tcp --dport 2222 \
  -j DNAT --to-destination 10.0.0.5:22

# 映射整个端口段
iptables -t nat -A PREROUTING -p tcp --dport 5000:5100 \
  -j DNAT --to-destination 10.0.0.10

9.9 自定义链作为目标

9.9.1 使用自定义链组织规则

#!/bin/bash
# ═══════════════════════════════════════════════════
# 使用自定义链的完整防火墙方案
# ═══════════════════════════════════════════════════

# 清空规则和自定义链
iptables -F
iptables -X

# ─── 创建自定义链 ───

# SSH 访问规则链
iptables -N SSH_CHAIN
iptables -A SSH_CHAIN -s 192.168.1.0/24 -j ACCEPT
iptables -A SSH_CHAIN -s 10.0.0.0/8 -j ACCEPT
iptables -A SSH_CHAIN -j LOG --log-prefix "IPT-SSH-DENY: "
iptables -A SSH_CHAIN -j DROP

# Web 访问规则链
iptables -N WEB_CHAIN
iptables -A WEB_CHAIN -p tcp -m multiport --dports 80,443 -j ACCEPT
iptables -A WEB_CHAIN -j DROP

# 数据库访问规则链
iptables -N DB_CHAIN
iptables -A DB_CHAIN -s 10.0.1.0/24 -p tcp --dport 3306 -j ACCEPT
iptables -A DB_CHAIN -s 10.0.1.0/24 -p tcp --dport 5432 -j ACCEPT
iptables -A DB_CHAIN -j LOG --log-prefix "IPT-DB-DENY: "
iptables -A DB_CHAIN -j DROP

# 日志链
iptables -N LOG_DROP
iptables -A LOG_DROP -m limit --limit 10/min --limit-burst 20 \
  -j LOG --log-prefix "IPT-DROP: "
iptables -A LOG_DROP -j DROP

# ─── 主链规则 ───

# 已建立的连接
iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT

# 回环接口
iptables -A INPUT -i lo -j ACCEPT

# SSH
iptables -A INPUT -p tcp --dport 22 -j SSH_CHAIN

# Web
iptables -A INPUT -j WEB_CHAIN

# 数据库
iptables -A INPUT -p tcp -m multiport --dports 3306,5432 -j DB_CHAIN

# 其他未匹配的包记录日志并丢弃
iptables -A INPUT -j LOG_DROP

# 默认策略
iptables -P INPUT DROP

9.10 注意事项

⚠️ LOG 不终止规则遍历:LOG 目标只是记录日志,数据包会继续匹配后续规则。如果同时有 LOG 和 DROP,需要分别写两条规则。

# 正确做法:LOG + DROP 分开
iptables -A INPUT -j LOG --log-prefix "IPT-DROP: "
iptables -A INPUT -j DROP

# 或使用自定义链
iptables -N LOG_AND_DROP
iptables -A LOG_AND_DROP -j LOG --log-prefix "IPT-DROP: "
iptables -A LOG_AND_DROP -j DROP
iptables -A INPUT -j LOG_AND_DROP

⚠️ LOG 的性能影响:高频日志会显著影响系统性能。务必配合 limithashlimit 模块限速。

⚠️ TEE 的网络要求:TEE 需要目标网关在二层可达(同一广播域),否则需要配置 ARP 代理。

⚠️ NFQUEUE 的依赖:需要内核编译时启用 CONFIG_NETFILTER_XT_TARGET_NFQUEUE,并安装用户态库。


9.11 扩展阅读

资源说明
man iptables-extensions所有扩展目标的手册
man ulogd2NFLOG 用户态守护进程
man tc流量控制工具
Netfilter Queue用户态包处理库

本章小结

目标功能特点
LOG记录日志不终止遍历,继续匹配
NFLOGNetlink 日志高性能,配合 ulogd2
REJECT拒绝并回复友好,暴露主机存在
TEE流量镜像副本发送到指定网关
NFQUEUE用户态处理灵活,适合 WAF/IDS
CLASSIFYtc 分类流量控制

下一章第 10 章:连接跟踪机制,将深入学习 conntrack 的状态机和高级用法。