防火墙入门:iptables 核心概念
本文介绍了iptables防火墙的核心概念和基本用法。主要内容包括:1)iptables本质是Linux内核netfilter框架的用户态工具;2)核心概念链(INPUT/OUTPUT/FORWARD)和表(filter/nat/mangle)的作用;3)规则匹配流程是自上而下执行;4)常见规则语法解析和常用命令;5)实战案例:搭建安全的服务器防火墙规则;6)端口转发等高级应用。文章强调规则顺序的
防火墙入门: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 |
核心就两句话:
- 规则从上往下匹配,匹配到了就执行动作,后面的不看了
- 一定要先放行已建立的连接(ESTABLISHED,RELATED),否则放行了端口也连不上
openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构
更多推荐


所有评论(0)