一句话理解 iptables

iptables 是 Linux 内核 netfilter 的用户态客户端。内核真正干活的叫 netfilter,iptables 只是写规则、改规则、查规则的命令行工具。

iptables 规则的组织方式:

  • 表(table):按用途分组,常见两张表:
    • filter:默认表,存放防火墙规则(接受/丢弃/拒绝)
    • nat:网络地址转换、端口转发
  • 链(chain):表里的检查点,决定规则何时生效:
    • INPUT:进入本机的数据包
    • OUTPUT:本机发出的数据包
    • FORWARD:本机转发的数据包(多网卡/网关场景)
    • PREROUTING:路由前(DNAT 经常用)
    • POSTROUTING:路由后(SNAT/MASQUERADE 经常用)
  • 规则(rule):链里的一条匹配 + 动作,从上到下依次匹配,命中即执行;都没命中走链的默认策略。

基本命令

查帮助:

iptables -h > ~/iptables_help    # 把帮助信息存到文本,方便搜索

查看规则:

# 查看 filter 表(默认)
iptables -L -n

# 查看 nat 表
iptables -L -n -t nat

三参数含义:-L 列出规则;-n 不做 DNS 反查,直接显示 IP;-t 表名 指定表。

五个实战场景

场景 1:禁止本机 ping 某个地址

需求:本机不允许 ping 百度。先 ping 一下确认能通:

ping -c 4 www.baidu.com

然后插一条 OUTPUT 链规则:

iptables -I OUTPUT -p icmp -d www.baidu.com -j DROP

参数含义:

  • -I OUTPUT:插入到 OUTPUT 链最前面(-A 是追加末尾,-I 是插入开头)
  • -p icmp:匹配协议
  • -d:匹配目的地址(域名会先解析成 IP)
  • -j DROP:动作为悄悄丢弃

再次 ping:

ping -c 4 www.baidu.com
# ping: sendmsg: Operation not permitted
顺序很重要。规则是从上到下依次匹配的:拒绝规则放最后面、允许规则放它前面;不然所有包进来第一行就被拒,业务直接全断。

场景 2:导出 / 编辑 / 导入规则

复杂规则不要直接命令行改——一个 typo 就可能锁死自己。最佳实践:先导出现有规则到文件,编辑文本,再重新导入。

导出:

iptables-save > /home/ubuntu/iptables_rules

编辑:iptables_rules 是普通文本,每行一条规则。常见操作是在某条链下面加 -A 行:

*filter
:INPUT ACCEPT
:FORWARD ACCEPT
:OUTPUT ACCEPT
-A OUTPUT -p icmp -d 114.114.114.114 -j DROP   # 新增:禁止 ping 114 DNS
COMMIT

导入:

iptables-restore < /home/ubuntu/iptables_rules
iptables -L -n                                # 校验规则是否生效
清空所有规则(核弹级操作,仅在能进 console 时使用):iptables -F。清自定义链用 -X,重置计数器用 -Z。

场景 3:黑/白名单(按源 IP 限制)

需求:让本机作为网关时,特定 PC(按 IP 识别)不能访问某些网站,其他设备不受限。

思路:建一条名为 BLACKLIST 的自定义链,里面放要屏蔽的目的地址;然后让"特定 PC 的出流量"跳进这条链。

# 清环境
iptables -F
iptables -X

# 建一条自定义链
iptables -N BLACKLIST

# 源 IP 是 10.135.166.86(本机)时跳进 BLACKLIST
iptables -A OUTPUT -s 10.135.166.86 -j BLACKLIST

# BLACKLIST 里加具体屏蔽的目标
iptables -A BLACKLIST -d 114.114.114.114    -j DROP
iptables -A BLACKLIST -d 220.181.111.188    -j DROP

扩展示例(限制另一台 PC 通过本机转发):再加一条 -A OUTPUT -s <另一台 IP> -j BLACKLIST。要新增屏蔽目标,只需往 BLACKLIST 链追加。

场景 4:端口映射 / 转发

需求:把访问 8080 的请求转到 80 端口。本地实例:

# 本地 8080 → 80
iptables -t nat -A OUTPUT -p tcp -d 127.0.0.1 --dport 8080 -j DNAT --to 127.0.0.1:80

外网 8080 → 本机 80(走 PREROUTING,更常见):

iptables -t nat -A PREROUTING -p tcp --dport 8080 -j REDIRECT --to-ports 80

两个动作区别:

  • DNAT:目标地址改写。可以转到另一台机器的另一个端口。
  • REDIRECT:把包转到本机的另一个端口(本质是 DNAT 的本地特化)。
能改应用就别用 iptables。端口转发是「实在没办法」时的兜底——优先让应用直接监听目标端口,或在前面架 Nginx/HAProxy。

场景 5:把自己锁在外面了怎么办

加了规则后 SSH 连不上(最常见的翻车):

  • 云厂商控制台:登录 VNC / serial console,执行 iptables -F。
  • 物理机:用本地显示器或 IPMI。
  • 容器/VM:宿主机上 docker exec 或虚拟化层 shell。

防患于未然的两条规矩:

  1. 改规则前先 iptables-save 备份,保留 5–10 分钟再 iptables-restore 兜底。
  2. 在 cron 里挂一条 10 分钟后自动恢复的"安全网"规则:
at now + 10 minutes << 'EOF'
iptables-restore < /root/iptables.bak
EOF

与 nftables 的关系

CentOS 7 / Debian 10 之前的发行版默认是 iptables;从 CentOS 8 / Debian 10 / Ubuntu 20.04 起,新装系统默认是 nftables,iptables 在很多发行版里已经是 iptables-nft 的兼容层。

判断当前用的是哪一套:

iptables --version
# iptables v1.8.7 (nf_tables)   ← 说明走 nftables 后端
# iptables v1.8.7 (legacy)      ← 说明还走旧 xtables

迁移建议:

  • 新项目直接写 nftables 规则(语法更清晰、支持集合与字典、性能更好)。
  • 老项目先保留 iptables 兼容层,迁移时用 nft list-ruleset 导出后逐条转写。

使用准则

  1. 永远先 iptables-save 备份,再改。
  2. 复杂规则用脚本 / 配置管理(Ansible、systemd unit)部署,不要手敲。
  3. 任何 -F / -I INPUT -j DROP 前先想清楚一条"逃生路径"。
  4. 新机器直接用 nftables,iptables 当兼容层理解即可。
参考资料