第 03 章:基本语法与操作
第 03 章:基本语法与操作
本章目标:掌握 iptables 命令行的所有基本操作,能够独立完成规则的添加、删除、插入、查看和管理。
3.1 命令格式总览
3.1.1 通用语法
iptables [-t 表名] 命令 [链名] [匹配条件...] [-j 目标动作]
| 组成部分 | 说明 | 默认值 |
|---|---|---|
-t 表名 | 指定操作的表 | filter |
命令 | 执行的操作(-A、-I、-D 等) | 必填 |
链名 | 操作的目标链 | 必填 |
匹配条件 | 数据包匹配规则 | 可选 |
-j 目标动作 | 匹配后执行的动作 | 可选 |
3.1.2 命令速查表
| 命令 | 长选项 | 说明 |
|---|---|---|
-A | --append | 追加规则到链末尾 |
-I | --insert | 插入规则到指定位置(默认第 1 位) |
-D | --delete | 删除指定规则 |
-R | --replace | 替换指定位置的规则 |
-L | --list | 列出链中的规则 |
-F | --flush | 清空链中的所有规则 |
-Z | --zero | 将规则的计数器清零 |
-N | --new-chain | 创建自定义链 |
-X | --delete-chain | 删除自定义链 |
-P | --policy | 设置链的默认策略 |
-E | --rename-chain | 重命名自定义链 |
3.2 查看规则(-L)
3.2.1 基本查看
# 查看 filter 表所有链的规则
sudo iptables -L
# 查看指定链的规则
sudo iptables -L INPUT
# 查看 nat 表的规则
sudo iptables -t nat -L
3.2.2 常用选项组合
# -n:以数字形式显示地址和端口(不做 DNS 反解,速度更快)
sudo iptables -L -n
# -v:显示详细信息(包计数、字节计数、接口信息)
sudo iptables -L -n -v
# --line-numbers:显示规则编号(便于删除和插入操作)
sudo iptables -L -n -v --line-numbers
# -x:显示精确的字节数(不使用 K/M/G 等缩写)
sudo iptables -L -n -v -x
3.2.3 输出解读
$ sudo iptables -L INPUT -n -v --line-numbers
Chain INPUT (policy ACCEPT 1042 packets, 89536 bytes)
num pkts bytes target prot opt in out source destination
1 156 12096 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:22 /* SSH */
2 89 7120 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:80
3 23 1840 DROP all -- * * 10.0.0.0/8 0.0.0.0/0
| 字段 | 含义 |
|---|---|
num | 规则编号(需 --line-numbers) |
pkts | 该规则已匹配的数据包数量 |
bytes | 该规则已匹配的字节数 |
target | 匹配后执行的动作 |
prot | 协议(tcp/udp/icmp/all) |
opt | 选项(通常为 --) |
in | 入接口(* 表示任意) |
out | 出接口 |
source | 源地址 |
destination | 目的地址 |
技巧:
pkts和bytes是排查规则是否命中的重要依据。如果某条规则的pkts为 0,说明它从未匹配过任何数据包。
3.3 添加规则(-A / -I)
3.3.1 追加规则(-A)
-A 将规则添加到链的末尾:
# 在 INPUT 链末尾追加一条允许 HTTP 的规则
sudo iptables -A INPUT -p tcp --dport 80 -j ACCEPT
# 在 OUTPUT 链末尾追加一条允许 DNS 的规则
sudo iptables -A OUTPUT -p udp --dport 53 -j ACCEPT
3.3.2 插入规则(-I)
-I 将规则插入到链的指定位置,默认是第 1 位:
# 插入到 INPUT 链的第 1 位(最前面)
sudo iptables -I INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
# 插入到 INPUT 链的第 3 位
sudo iptables -I INPUT 3 -p tcp --dport 443 -j ACCEPT
3.3.3 常用匹配条件
# 按源 IP
sudo iptables -A INPUT -s 192.168.1.100 -j ACCEPT
# 按网段
sudo iptables -A INPUT -s 192.168.1.0/24 -j ACCEPT
# 按目的端口
sudo iptables -A INPUT -p tcp --dport 3306 -j ACCEPT
# 按入接口
sudo iptables -A INPUT -i eth0 -j ACCEPT
# 按出接口
sudo iptables -A OUTPUT -o eth0 -j ACCEPT
# 组合条件
sudo iptables -A INPUT -i eth0 -p tcp -s 10.0.0.0/8 --dport 8080 -j ACCEPT
3.3.4 添加注释
# 使用 comment 模块为规则添加注释
sudo iptables -A INPUT -p tcp --dport 22 \
-m comment --comment "Allow SSH from management network" \
-j ACCEPT
# 查看时会显示注释
sudo iptables -L INPUT -n | grep ssh
# ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:22 /* Allow SSH from management network */
最佳实践:为每条规则添加注释,标注规则的用途、创建日期和负责人,便于后续维护。
3.4 删除规则(-D)
3.4.1 按规则内容删除
# 删除一条规则(必须完全匹配)
sudo iptables -D INPUT -p tcp --dport 80 -j ACCEPT
3.4.2 按规则编号删除
# 先查看规则编号
sudo iptables -L INPUT -n --line-numbers
# 输出:
# Chain INPUT (policy ACCEPT)
# num target prot opt source destination
# 1 ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:22
# 2 ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:80
# 3 DROP all -- 10.0.0.0/8 0.0.0.0/0
# 删除第 2 条规则
sudo iptables -D INPUT 2
注意:删除一条规则后,后面的规则编号会自动前移。如果要删除多条规则,建议从后往前删,避免编号变化导致误删。
# 从后往前删除(安全做法)
sudo iptables -D INPUT 3
sudo iptables -D INPUT 2
sudo iptables -D INPUT 1
3.5 插入与替换(-I / -R)
3.5.1 在指定位置插入
# 查看当前规则
sudo iptables -L INPUT -n --line-numbers
# 1 ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:22
# 2 ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:80
# 3 DROP all -- 0.0.0.0/0 0.0.0.0/0
# 在第 2 位插入一条新规则(原来的第 2 条变成第 3 条)
sudo iptables -I INPUT 2 -p tcp --dport 443 -j ACCEPT
# 插入后的结果:
# 1 ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:22
# 2 ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:443 ← 新插入
# 3 ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:80
# 4 DROP all -- 0.0.0.0/0 0.0.0.0/0
3.5.2 替换规则(-R)
# 替换第 2 条规则
sudo iptables -R INPUT 2 -p tcp --dport 8443 -j ACCEPT
3.6 清空规则(-F / -Z)
3.6.1 清空指定链
# 清空 INPUT 链的所有规则
sudo iptables -F INPUT
# 清空 OUTPUT 链的所有规则
sudo iptables -F OUTPUT
3.6.2 清空所有表
# 清空 filter 表所有链
sudo iptables -F
# 清空 nat 表所有链
sudo iptables -t nat -F
# 清空 mangle 表所有链
sudo iptables -t mangle -F
# 清空 raw 表所有链
sudo iptables -t raw -F
3.6.3 清零计数器(-Z)
# 清零所有链的计数器
sudo iptables -Z
# 清零指定链的计数器
sudo iptables -Z INPUT
# 清零指定链的指定规则的计数器
sudo iptables -Z INPUT 2
3.7 默认策略(-P)
3.7.1 设置默认策略
# 设置 INPUT 链默认策略为 DROP
sudo iptables -P INPUT DROP
# 设置 FORWARD 链默认策略为 DROP
sudo iptables -P FORWARD DROP
# 设置 OUTPUT 链默认策略为 ACCEPT
sudo iptables -P OUTPUT ACCEPT
限制:默认策略只能设置为
ACCEPT或DROP,不能设置为REJECT或其他动作。
3.7.2 业务场景:Web 服务器加固
# 第一步:允许已建立的连接(避免中断现有 SSH 会话)
sudo iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
# 第二步:允许回环接口
sudo iptables -A INPUT -i lo -j ACCEPT
# 第三步:允许 SSH
sudo iptables -A INPUT -p tcp --dport 22 -j ACCEPT
# 第四步:允许 HTTP/HTTPS
sudo iptables -A INPUT -p tcp -m multiport --dports 80,443 -j ACCEPT
# 第五步:允许 ICMP(ping)
sudo iptables -A INPUT -p icmp --icmp-type echo-request -j ACCEPT
# 第六步:设置默认拒绝策略
sudo iptables -P INPUT DROP
3.8 自定义链管理
3.8.1 创建自定义链
# 创建名为 HTTP_RULES 的自定义链
sudo iptables -N HTTP_RULES
# 在自定义链中添加规则
sudo iptables -A HTTP_RULES -s 192.168.1.0/24 -j ACCEPT
sudo iptables -A HTTP_RULES -s 10.0.0.0/8 -j ACCEPT
sudo iptables -A HTTP_RULES -j LOG --log-prefix "HTTP-DENIED: "
sudo iptables -A HTTP_RULES -j DROP
# 在主链中引用自定义链
sudo iptables -A INPUT -p tcp --dport 80 -j HTTP_RULES
3.8.2 删除自定义链
# 先清空自定义链中的规则
sudo iptables -F HTTP_RULES
# 再删除自定义链
sudo iptables -X HTTP_RULES
注意:删除自定义链前必须先清空其中的规则,并且不能有其他链引用该自定义链。
3.8.3 重命名自定义链
# 将 HTTP_RULES 重命名为 WEB_FILTER
sudo iptables -E HTTP_RULES WEB_FILTER
3.9 规则导出与导入
3.9.1 导出规则
# 以 iptables-save 格式导出所有规则
sudo iptables-save
# 只导出 filter 表
sudo iptables-save -t filter
# 只导出 nat 表
sudo iptables-save -t nat
# 保存到文件
sudo iptables-save > /tmp/iptables-rules-backup.rules
3.9.2 导入规则
# 从文件恢复规则
sudo iptables-restore < /tmp/iptables-rules-backup.rules
# 原子性恢复(使用 --noflush 保留现有规则)
sudo iptables-restore --noflush < /tmp/new-rules.rules
3.9.3 iptables-save 输出格式解读
$ sudo iptables-save
# Generated by iptables-save v1.8.7
*filter # ← 表名
:INPUT ACCEPT [0:0] # ← 链的默认策略和计数器
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
-A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
-A INPUT -i lo -j ACCEPT
-A INPUT -p tcp -m tcp --dport 22 -j ACCEPT
-A INPUT -p tcp -m multiport --dports 80,443 -j ACCEPT
-A INPUT -p icmp -m icmp --icmp-type 8 -j ACCEPT
-A INPUT -j DROP
COMMIT # ← 提交该表
*nat # ← nat 表
:PREROUTING ACCEPT [0:0]
:INPUT ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
COMMIT
3.10 实战:完整的服务器防火墙脚本
#!/bin/bash
# ==================================================
# 基础防火墙脚本 - 适用于 Web 服务器
# ==================================================
# 定义变量
IPT="/usr/sbin/iptables"
SSH_PORT="22"
HTTP_PORTS="80,443"
# 清空所有现有规则
$IPT -F
$IPT -t nat -F
$IPT -t mangle -F
$IPT -t raw -F
# 删除自定义链
$IPT -X
$IPT -t nat -X
$IPT -t mangle -X
$IPT -t raw -X
# 设置默认策略:全部 DROP
$IPT -P INPUT DROP
$IPT -P FORWARD DROP
$IPT -P OUTPUT ACCEPT
# ─────────────── INPUT 链规则 ───────────────
# 1. 允许已建立的连接
$IPT -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED \
-m comment --comment "Allow established connections" -j ACCEPT
# 2. 允许回环接口
$IPT -A INPUT -i lo \
-m comment --comment "Allow loopback" -j ACCEPT
# 3. 允许 SSH(限管理网段)
$IPT -A INPUT -p tcp --dport $SSH_PORT -s 192.168.1.0/24 \
-m comment --comment "Allow SSH from management network" -j ACCEPT
# 4. 允许 HTTP/HTTPS
$IPT -A INPUT -p tcp -m multiport --dports $HTTP_PORTS \
-m comment --comment "Allow HTTP/HTTPS" -j ACCEPT
# 5. 允许 ICMP
$IPT -A INPUT -p icmp --icmp-type echo-request \
-m comment --comment "Allow ping" -j ACCEPT
# 6. 记录并丢弃其他所有数据包
$IPT -A INPUT \
-m comment --comment "Log and drop everything else" \
-j LOG --log-prefix "IPT-INPUT-DROP: " --log-level 4
$IPT -A INPUT -j DROP
echo "Firewall rules applied successfully."
3.11 常用操作速查
| 操作 | 命令 |
|---|---|
| 查看所有规则 | iptables -L -n -v --line-numbers |
| 查看 nat 表 | iptables -t nat -L -n -v |
| 添加允许规则 | iptables -A INPUT -p tcp --dport <端口> -j ACCEPT |
| 删除规则(按编号) | iptables -D INPUT <编号> |
| 插入规则到首位 | iptables -I INPUT <规则> |
| 清空所有规则 | iptables -F && iptables -t nat -F |
| 设置默认拒绝 | iptables -P INPUT DROP |
| 导出规则 | iptables-save > rules.bak |
| 导入规则 | iptables-restore < rules.bak |
3.12 注意事项
⚠️ 不要在远程会话中直接执行
iptables -F:清空规则后,如果默认策略是 DROP,你会立即断开连接。
⚠️ 使用脚本时加入断路器:在自动化脚本中加入超时机制,如果脚本执行失败,自动恢复旧规则。
# 安全的规则应用方式
RULES_FILE="/tmp/new-rules.rules"
BACKUP_FILE="/tmp/backup-rules.rules"
# 备份当前规则
iptables-save > $BACKUP_FILE
# 应用新规则
iptables-restore < $RULES_FILE
# 设置 30 秒超时,如果管理员没有确认则自动回滚
echo "New rules applied. Press Enter within 30s to confirm, or they will be rolled back."
if ! read -t 30; then
iptables-restore < $BACKUP_FILE
echo "Rules rolled back due to timeout."
fi
3.13 扩展阅读
| 资源 | 说明 |
|---|---|
man iptables | 官方手册 |
man iptables-save | 规则导出手册 |
man iptables-restore | 规则导入手册 |
iptables --help | 快速查看所有命令选项 |
本章小结
| 操作 | 命令 | 说明 |
|---|---|---|
| 追加规则 | -A | 添加到链末尾 |
| 插入规则 | -I [num] | 插入到指定位置 |
| 删除规则 | -D [num] | 按内容或编号删除 |
| 查看规则 | -L -n -v | 数字形式、详细信息 |
| 清空规则 | -F | 清空指定表的所有规则 |
| 默认策略 | -P | 设置链的默认动作 |
| 自定义链 | -N / -X | 创建/删除自定义链 |
| 导出/导入 | iptables-save/restore | 规则的备份与恢复 |
下一章:第 04 章:filter 表详解,将深入讲解最常用的 filter 表的三大链。