防火墙入门:iptables 核心概念

不讲复杂的企业级规则,只讲日常够用的核心知识点。


iptables 不是防火墙,是规则引擎

大多数人说的"iptables 防火墙",实际上指的是 Linux 内核的 netfilter 框架。iptables 只是用户态的命令行工具,用来往 netfilter 里写规则。

你输 iptables 命令
    ↓
iptables 工具
    ↓
内核 netfilter 框架  →  对经过的每个网络包,按规则匹配处理

核心概念:链(chain)和表(table)

链:包经过的几个检查点

一个网络包从进来到离开,会依次经过几个固定的检查点,这些点就叫

                    ┌───────────┐
    进来 ─────────→ │ PREROUTING │ ──→ 路由判断 ──→ ┌───────────┐
                    └───────────┘    │              │  FORWARD  │ ──→ 出去
                                     │              └───────────┘
                                     ↓
                                  ┌──────┐
                                  │ INPUT │ → 本机进程
                                  └──────┘

     本机进程发出 ──→ ┌────────┐ ──→ ┌──────────┐ ──→ 出去
                      │ OUTPUT │     │ POSTROUTING│
                      └────────┘     └──────────┘

日常只用到三个链:

什么时候触发 常见用途
INPUT 包要发给本机进程 放行或阻止别人访问本机服务
OUTPUT 本机进程发出的包 限制本机对外访问
FORWARD 包经过本机转发(路由器模式) NAT、容器网络

表:不同类型规则的存放处

每个链里又分成多个,不同表干不同的事:

作用 常用场景
filter 过滤包,放行或阻止 日常防火墙规则
nat 修改包的源/目标地址 端口转发、共享上网
mangle 修改包的 TOS/TTL 等 特殊需求,日常很少用

最常用的组合:filter 表的 INPUT 链——控制谁能访问本机。


规则的匹配流程

规则是一条一条从上往下匹配的。遇到第一条匹配的规则就执行动作(ACCEPT/DROP),后面的规则不再看

包进来
  ↓
第 1 条规则:来自 192.168.1.0/24  →  接受
  ↓ 匹配 → 放行,结束
第 2 条规则:端口 22             →  接受
  ↓ 不匹配 → 继续
第 3 条规则:端口 80             →  接受
  ↓ 不匹配 → 继续
第 4 条规则:全部拒绝
  ↓ 匹配 → 丢弃,结束

规则顺序很重要。如果把"全部拒绝"放在前面,后面的放行规则就不会被执行了。


看懂一条 iptables 规则

iptables -A INPUT -s 192.168.1.0/24 -p tcp --dport 22 -j ACCEPT

拆开看每个参数:

参数 含义
-A INPUT 追加到 INPUT 链的末尾
-s 192.168.1.0/24 来源 IP 段
-p tcp 协议是 TCP
--dport 22 目标端口 22
-j ACCEPT 匹配后执行的动作:放行

用人话翻译:来自 192.168.1.x 网段访问本机 22 端口的 TCP 连接,放行

常用匹配条件

-s 192.168.1.100          # 来源 IP
-d 10.0.0.1               # 目标 IP
-p tcp                    # 协议(tcp/udp/icmp)
--dport 80                # 目标端口
--sport 12345             # 来源端口
-i eth0                   # 从哪个网卡进来
-o eth1                   # 从哪个网卡出去
-m state --state NEW      # 连接状态(NEW/ESTABLISHED/RELATED)

常用动作(-j)

动作 含义
ACCEPT 放行
DROP 丢弃(不回复,对方会卡住直到超时)
REJECT 拒绝(回复一个"端口不可达")
LOG 记录日志,继续匹配下一条
RETURN 返回上级链

DROP vs REJECT:DROP 让对方干等到超时,REJECT 立刻告诉对方"连不上"。对外服务建议用 DROP(暴露信息更少),内网调试用 REJECT 更友好。


常用命令

# 查看当前规则
iptables -L -n -v           # 列出规则(-n 不解析 IP,更快)
iptables -L INPUT -n -v     # 只看 INPUT 链
iptables -t nat -L -n -v    # 看 nat 表的规则

# 添加规则
iptables -A INPUT -p tcp --dport 80 -j ACCEPT    # 追加到最后
iptables -I INPUT -p tcp --dport 22 -j ACCEPT    # 插入到最前面

# 删除规则
iptables -D INPUT -p tcp --dport 80 -j ACCEPT    # 删除匹配的规则
iptables -F                                         # 清空所有规则

# 修改默认策略
iptables -P INPUT DROP    # 默认拒绝所有进入的包
iptables -P INPUT ACCEPT  # 默认接受所有

实战:搭一个安全的服务器

场景

你有一台公网服务器,跑 Nginx(80/443)和 SSH(22),希望只放行业务端口,其他全拦。

脚本

#!/bin/bash

# 先清空已有规则
iptables -F
iptables -X

# 默认策略:INPUT 和 FORWARD 默认拒绝,OUTPUT 默认放行
iptables -P INPUT DROP
iptables -P FORWARD DROP
iptables -P OUTPUT ACCEPT

# 放行回环接口(本机程序互相通信)
iptables -A INPUT -i lo -j ACCEPT

# 放行已建立的连接(不然放行了 80 端口,但响应包回不来)
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT

# 放行 SSH
iptables -A INPUT -p tcp --dport 22 -j ACCEPT

# 放行 HTTP / HTTPS
iptables -A INPUT -p tcp --dport 80 -j ACCEPT
iptables -A INPUT -p tcp --dport 443 -j ACCEPT

# 放行 ping(可选)
iptables -A INPUT -p icmp --icmp-type echo-request -j ACCEPT

# 记录被丢弃的包(方便排错)
iptables -A INPUT -j LOG --log-prefix "IPTABLES-DROP: "

保存并执行:

chmod +x setup-firewall.sh
sudo ./setup-firewall.sh

警告:如果你在远程执行这个脚本,确保 SSH 那条规则在默认 DROP 之前加了。规则清空到默认 DROP 之间的瞬间,你的 SSH 连接可能会断。

更安全的做法是先写默认 ACCEPT,配好规则再改默认策略:

iptables -P INPUT ACCEPT   # 先放行所有
# ... 加规则 ...
iptables -P INPUT DROP     # 确认规则生效之后才锁

保存规则

iptables 命令改了之后,重启机器就丢了。需要手动保存:

# Ubuntu
apt install iptables-persistent
netfilter-persistent save

# CentOS 6
service iptables save

# CentOS 7+(默认用 firewalld)
yum install iptables-services
systemctl enable iptables
service iptables save

另一种方法是把规则写成一个 shell 脚本,开机执行。


端口转发(NAT 表)

这是 iptables 的一个典型用途:把本机的 80 端口转发到另一台机器。

# 开启 IP 转发(临时)
echo 1 > /proc/sys/net/ipv4/ip_forward

# 永久启用
vim /etc/sysctl.conf
# 去掉 net.ipv4.ip_forward=1 的注释
sysctl -p

# 把访问本机 80 端口的请求转发到 10.0.0.100:8080
iptables -t nat -A PREROUTING -p tcp --dport 80 -j DNAT --to-destination 10.0.0.100:8080

# 让响应包能正确回来(SNAT 改写源 IP)
iptables -t nat -A POSTROUTING -d 10.0.0.100 -p tcp --dport 8080 -j MASQUERADE

常用放行规则模版

只允许特定 IP 访问

# 只允许公司 IP 访问 SSH
iptables -A INPUT -p tcp --dport 22 -s 114.114.114.0/24 -j ACCEPT
iptables -A INPUT -p tcp --dport 22 -j DROP

限制单位时间内的连接数(防爆破)

# 每 60 秒内最多 5 次 SSH 连接尝试
iptables -A INPUT -p tcp --dport 22 -m state --state NEW -m recent --set
iptables -A INPUT -p tcp --dport 22 -m state --state NEW -m recent --update --seconds 60 --hitcount 5 -j DROP

允许特定网段访问特定端口

# 只允许内网访问 MySQL
iptables -A INPUT -p tcp --dport 3306 -s 10.0.0.0/8 -j ACCEPT
iptables -A INPUT -p tcp --dport 3306 -j DROP

查看哪些规则被命中了

iptables -L -n -v
Chain INPUT (policy DROP 1234 packets, 123456 bytes)
 pkts bytes target     prot opt in     out     source           destination
 5678  5M   ACCEPT     tcp  --  *      *       0.0.0.0/0        0.0.0.0/0     tcp dpt:80

pkts 列显示每条规则被匹配了多少次。bytes 是匹配的流量大小。如果一条规则 pkts 常年是 0,说明没用到,可以考虑删掉。


iptables 和 firewalld / ufw 的关系

工具 说明
iptables 底层直接操作 netfilter,配置最灵活但也最繁琐
firewalld CentOS 7+ 默认,封装了 iptables,提供 zone/service 概念
ufw Ubuntu 默认,最简化的命令行工具
nftables iptables 的下一代,CentOS 8 / Ubuntu 22+ 默认

关系图:

ufw / firewalld         ← 更友好的前端
    ↓
iptables / nftables     ← 真正的规则引擎
    ↓
netfilter               ← 内核模块

日常使用选一个就够了:Ubuntu 用 ufw,CentOS 用 firewalld。但如果你的场景需要 IP 段限制、端口转发、防爆破,直接 iptables 反而更清晰


排查:防火墙是不是在捣乱

# 先看当前规则
iptables -L -n --line-numbers

# 临时关掉所有规则确认(只用于排查,别长期开着)
iptables -P INPUT ACCEPT
iptables -P FORWARD ACCEPT
iptables -P OUTPUT ACCEPT
iptables -F

# 如果关了就好了,说明规则配的有问题,一条一条加回去测试

总结

你想干什么 命令
放行 80 端口 iptables -A INPUT -p tcp --dport 80 -j ACCEPT
阻止某个 IP iptables -A INPUT -s 1.2.3.4 -j DROP
默认拒绝所有入站 iptables -P INPUT DROP
看当前规则 iptables -L -n -v
清空所有规则 iptables -F
端口转发到内网 iptables -t nat -A PREROUTING -p tcp --dport 80 -j DNAT --to 10.0.0.100:8080

核心就两句话:

  1. 规则从上往下匹配,匹配到了就执行动作,后面的不看了
  2. 一定要先放行已建立的连接(ESTABLISHED,RELATED),否则放行了端口也连不上
Logo

openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构

更多推荐