iptables

2377 字
12 分钟
iptables

一、iptables#

iptables 是 Linux 内核态包过滤防火墙,主流用于 CentOS 7/6、Debian 等传统发行版;CentOS 8+/Ubuntu 20.04+ 默认改用 nftables,但 iptables 语法仍广泛兼容。


1.1 核心理论基础#

1.1.1 四表五链#

iptables 用表(table) 区分功能,链(chain) 是规则挂载点,数据包按顺序经过链上规则匹配执行动作。

1.1.1.1 四大表(优先级从高到低)#

  1. raw:优先级最高,关闭连接追踪(conntrack),极少用

  2. mangle:修改数据包标记、TTL、QoS,多用于高级路由 / 流量控制

  3. nat:网络地址转换(端口转发、IP 映射、共享上网)

  4. filter默认表、最常用,负责包过滤(放行 / 拒绝流量)

1.1.1.2 五条内置链(数据包流转链路)#

链名作用场景所属常用表
PREROUTING数据包进入网卡后、路由判断前raw、mangle、nat
INPUT目标是本机的数据包filter、mangle
FORWARD经本机转发、目标不是本机的数据包filter、mangle
OUTPUT本机主动发出的数据包raw、mangle、nat、filter
POSTROUTING路由判断后、离开网卡前mangle、nat

数据包流转路径(两种核心场景)

  1. 访问本机:外网 → 网卡 → PREROUTING → INPUT → 本机进程

  2. 本机做路由转发:外网 → 网卡 → PREROUTING → FORWARD → POSTROUTING → 内网主机

  3. 本机向外发包:本机进程 → OUTPUT → POSTROUTING → 外网

数据包流向图:

[外部网络]
┌──────▼──────┐
│ PREROUTING │ ◄── raw, mangle, nat (DNAT在此做)
└──────┬──────┘
┌──────▼──────┐ ┌─────────────┐
│ 路由判断 │───►│ OUTPUT │ ◄── 本机进程发出的包
└──────┬──────┘ └──────┬──────┘
│ │
┌──────▼──────┐ │
│ FORWARD │ │
└──────┬──────┘ │
│ │
┌──────▼──────┐ ┌──────▼──────┐
│ POSTROUTING │◄───│ POSTROUTING │ ◄── mangle, nat (SNAT/MASQUERADE在此做)
└──────┬──────┘ └──────┬──────┘
│ │
[内部网络] [外部网络]
* 发给本机的包: PREROUTING -> INPUT -> 本机进程
* 本机发出的包: 本机进程 -> OUTPUT -> POSTROUTING
* 转发的包: PREROUTING -> FORWARD -> POSTROUTING

1.1.2 规则匹配三要素#

一条 iptables 规则格式:

Terminal window
iptables [-t 表名] 链名 匹配条件 -j 动作
  1. :不写默认 filter

  2. 匹配条件:源 IP、目标 IP、端口、协议、网卡、状态等

  3. 动作(target):匹配后执行的操作

Terminal window
# 详细规则格式
iptables [-t 表名] [-A/I/D/R] <链名> [规则号] <-i/o 网卡名> -p 协议名 <-s 源IP/源子网> --sport 源端口 <-d 目标IP/目标子网> --dport 目标端口> -j 动作

参数释义#

  1. -A/I/D/R

    - `-A`:追加规则;`-I`:插入规则;`-D`:删除规则;`-R`:替换修改规则
  2. <链名称>:INPUT 、OUTPUT 、FORWARD 、PREROUTING 、POSTROUTING,可选填写规则序号

  3. -i 入网卡:匹配入站网卡;-o 出网卡:匹配出站网卡

  4. -p:指定协议(tcp/udp/icmp/all)

  5. -s:源地址(IP / 网段),! -s 取反

  6. --sport:源端口;--dport:目标端口

  7. -j:动作:ACCEPT放行 / DROP丢弃 / REJECT拒绝等

1.1.2.1 常用动作(Target)#

对规则的具体处理方法:-j 动作,以下为常用动作:

  • ACCEPT:放行数据包

  • DROP:丢弃数据包(无回应,客户端直接超时)

  • REJECT:拒绝数据包(返回拒绝报文,客户端立刻提示无法连接)

  • SNAT:源地址转换(nat 表 POSTROUTING 链,内网主机共享公网 IP 上网)

  • DNAT:目标地址转换(nat 表 PREROUTING 链,端口转发、外网访问内网服务)

  • MASQUERADE:动态 SNAT(适配动态公网 IP,如拨号上网)

  • LOG:记录日志到 /var/log/messages,不中断流量

1.1.2.2 协议与常用匹配参数#

  • 协议:-p tcp -p udp -p icmp -p all

  • 源 IP:-s 192.168.1.0/24(源地址)

  • 目标 IP:-d 10.0.0.1(目标地址)

  • 源端口:--sport 1024-65535

  • 目标端口:--dport 80(仅 tcp/udp 可用)

  • 网卡:-i eth0(入网卡)、-o eth1(出网卡)

  • 连接状态(-m state 模块):

    • NEW:新连接请求

    • ESTABLISHED:已建立的连接

    • RELATED:关联连接(如 FTP 被动模式)

    • INVALID:无效数据包


1.1.3 基础命令语法#

1.1.3.1 查看规则#

Terminal window
# 查看 filter 表所有规则(常用)
iptables -L -n -v
# 查看 nat 表规则
iptables -t nat -L -n
参数说明:
-L 列出规则
-n 不解析域名/端口(加速,必加)
-v 详细信息
--line-numbers 显示规则行号(删除规则用)

1.1.3.2 增 / 删 / 改规则#

Terminal window
# 1. 在链末尾追加规则(-A append)
iptables -A 链名 匹配 动作
# 2. 在指定行号插入规则(-I insert,插在最前面/指定位置)
iptables -I 链名 行号 匹配 动作
# 3. 删除指定行号规则
iptables -D 链名 行号
# 4. 清空某条链所有规则(不指定默认为filter链)
iptables -F 链名
# 5. 清空整张表所有规则
iptables -t nat -F
# 6. 设置链默认策略(重要!默认拒绝/放行所有流量)
iptables -P 链名 ACCEPT/DROP
# 7. 删除自定义链
iptables -X
# 8. 计数器归零
iptables -Z

安全原则:先放行必要流量,再把默认策略设为 DROP,避免服务器暴露端口。

1.3.3.3 规则持久化(重启不失效)#

不同系统保存方式不同:

/etc/sysconfig/iptables
# CentOS 6/7
service iptables save
# 导出规则
iptables-save > /opt/rule.txt
# 导入规则
iptables-restore < /opt/rule.txt

1.2 基础练习#

前置说明:

  1. 使用docker创建一个模拟环境进行练习
    1. 拉取镜像:docker pull ubuntu:latest
    2. iptables 需要操作网络内核模块,必须加 --privileged
      1. docker run -d -it --privileged --name iptables-linux ubuntu:latest /bin/bash
      2. 进入容器,docker exec -it iptables-linux /bin/bash
    3. 进入容器安装iptables,apt update && apt install -y iptables
    4. 查看版本,iptables --version
  2. 先执行 iptables -F && iptables -t nat -F 清空原有规则,避免冲突
  3. 练习顺序:基础过滤 → 状态规则 → 端口 / IP 限制 → NAT 转发

1.2.1 filter表练习#

Terminal window
# 追加规则:所有IP访问本机80端口,放行
iptables -A INPUT -p tcp --dport 80 -j ACCEPT
# 拒绝192.168.1.100访问本机所有端口
iptables -A INPUT -s 192.168.1.100 -j DROP
# 放行ssh
iptables -A INPUT -p tcp --dport 22 -j ACCEPT

需求:放行已建立 / 关联连接,只拦截新非法连接,本机对外访问的回应包属于 ESTABLISHED,需要放行。

Terminal window
# 放行所有已建立、关联的入站连接
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
# 仅放行本机主动向外发起的连接回应(OUTPUT 链)
iptables -A OUTPUT -m state --state ESTABLISHED,RELATED -j ACCEPT

组合完整安全基线规则:

Terminal window
# 清空规则
iptables -F
iptables -t nat -F
# 1. 放行本地回环网卡 lo(本机程序互访,必须加)
iptables -A INPUT -i lo -j ACCEPT
# 2. 放行已建立连接
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
# 3. 放行SSH、HTTP、HTTPS
iptables -A INPUT -p tcp --dport 22 -j ACCEPT
iptables -A INPUT -p tcp --dport 80 -j ACCEPT
iptables -A INPUT -p tcp --dport 443 -j ACCEPT
# 4. 允许 ICMP ping
iptables -A INPUT -p icmp --icmp-type echo-request -j ACCEPT
# 5. 默认拒绝所有入站
iptables -P INPUT DROP
iptables -P FORWARD DROP
iptables -P OUTPUT ACCEPT
Terminal window
# 仅允许 192.168.1.0/24网段访问本机3306端口
iptables -A INPUT -s 192.168.1.0/24 -p tcp --dport 3306 -j ACCEPT
# 禁止所有主机 ping 本机
iptables -A INPUT -p icmp -j DROP
# 限制单个 IP 最多同时发起 10 个 TCP 连接
iptables -A INPUT -p tcp --dport 80 -m connlimit --connlimit-above 10 -j DROP

1.2.2 FORWARD 链(路由转发基础)#

场景:当前 Linux 作为网关,转发内网流量。

  1. 开启内核转发(必须,否则 FORWARD 和NAT不生效)
Terminal window
# 临时开启
echo 1 > /proc/sys/net/ipv4/ip_forward
# 永久开启(CentOS7)
vi /etc/sysctl.conf
# 添加/修改
net.ipv4.ip_forward = 1
sysctl -p # 生效
  1. 放行转发流量

允许内网 192.168.2.0/24 网段转发流量:

Terminal window
iptables -A FORWARD -s 192.168.2.0/24 -j ACCEPT
iptables -A FORWARD -d 192.168.2.0/24 -j ACCEPT

1.2.3 NAT表练习#

场景 1:SNAT 内网主机共享公网 IP 上网#

网卡:eth0(公网 IP:203.0.113.10),eth1(内网 192.168.2.0/24)

Terminal window
# nat表 POSTROUTING 链,内网访问外网做源地址转换
iptables -t nat -A POSTROUTING -s 192.168.2.0/24 -o eth0 -j SNAT --to-source 203.0.113.10

场景 2:MASQUERADE(动态 IP 上网,如宽带拨号)#

公网 IP 不固定时用此替代 SNAT:

Terminal window
iptables -t nat -A POSTROUTING -s 192.168.3.0/24 -o eth0 -j MASQUERADE

场景 3:DNAT 端口转发(外网访问内网服务)#

需求:访问网关公网 IP 203.0.113.10:8080,转发到内网 192.168.2.10:80

Terminal window
# PREROUTING 链:目标端口转发
iptables -t nat -A PREROUTING -d 203.0.113.10 -p tcp --dport 8080 -j DNAT --to-destination 192.168.2.10:80

1.2.4 recent 模块练习(防御暴力破解)#

限制同一 IP 在 60 秒内最多新建 4 次 SSH 连接。

Terminal window
# 标记新连接的 SSH 请求
iptables -A INPUT -p tcp --dport 22 -m state --state NEW -m recent --name SSH_BRUTE --set
# 如果 60秒内超过4次,则 DROP
iptables -A INPUT -p tcp --dport 22 -m state --state NEW \
-m recent --name SSH_BRUTE --update --seconds 60 --hitcount 4 -j DROP
# 正常放行
iptables -A INPUT -p tcp --dport 22 -m state --state NEW -j ACCEPT

1.2.5 日志审计练习#

记录被 DROP 的数据包以便排查问题

Terminal window
# 在所有 DROP 规则之前添加 LOG 规则
iptables -A INPUT -j LOG --log-prefix "IPT_INPUT_DROP: " --log-level 4
# 查看日志
dmesg | grep "IPT_INPUT_DROP"
# 或
journalctl -k | grep "IPT_INPUT_DROP"

1.2.6 取反符号#

!取反匹配,放在匹配参数前面,含义:不满足后面条件的报文才匹配本条规则

语法格式:! + 匹配项,空格必须隔开 ! 和参数

Terminal window
# 除了 192.168.1.1 之外,所有 IP 禁止访问 22 端口
iptables -A INPUT -p tcp --dport 22 ! -s 192.168.1.1 -j DROP
# 放行除 3306 以外本机所有 TCP 端口
iptables -A INPUT -p tcp ! --dport 3306 -j ACCEPT
# 除 eth0 网卡外,其他入网卡全部丢弃入站流量
iptables -A INPUT ! -i eth0 -j DROP
# 放行非 ICMP 协议所有入站流量
iptables -A INPUT ! -p icmp -j ACCEPT
# 状态取反:不是 ESTABLISHED 状态的新连接全部丢弃
iptables -A INPUT -m state ! --state ESTABLISHED -j DROP
# 网段取反:非 10.0.0.0/24 全部拒绝访问 80
iptables -A INPUT ! -s 10.0.0.0/24 -p tcp --dport 80 -j DROP

1.2.7 规则管理与持久化#

Terminal window
# 保存规则(Debian/Ubuntu)
sudo apt install iptables-persistent
sudo netfilter-persistent save
# 保存规则(CentOS/RHEL)
sudo service iptables save
# 或
sudo iptables-save > /etc/sysconfig/iptables
# 删除特定规则(按行号)
sudo iptables -D INPUT 3
# 插入规则到指定位置
sudo iptables -I INPUT 2 -p tcp --dport 3306 -j ACCEPT

文章分享

如果这篇文章对你有帮助,欢迎分享给更多人!

iptables
https://2233941.xyz/posts/iptables/
作者
lumifly
发布于
2026-04-18
许可协议
CC BY-NC-SA 4.0
Profile Image of the Author
lumifly
不逐世间万丈星河,自守一隅细碎明光
✨ 今日一言
" 加载中... "
——
公告
欢迎来到我的博客!这是一则示例公告。
音乐
封面

音乐

暂未播放

0:00 0:00
暂无歌词
分类
标签
本年还剩 -- --%
本月还剩 -- --%
本周还剩 -- --%
距离--
--
--
天气预报
站点统计
文章
7
分类
1
标签
3
总字数
38,070
运行时长
0
最后活动
0 天前
站点信息
构建平台
Local
博客版本
Firefly v6.12.1
文章许可
CC BY-NC-SA 4.0

文章目录