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 四大表(优先级从高到低)
-
raw:优先级最高,关闭连接追踪(conntrack),极少用
-
mangle:修改数据包标记、TTL、QoS,多用于高级路由 / 流量控制
-
nat:网络地址转换(端口转发、IP 映射、共享上网)
-
filter:默认表、最常用,负责包过滤(放行 / 拒绝流量)
1.1.1.2 五条内置链(数据包流转链路)
| 链名 | 作用场景 | 所属常用表 |
|---|---|---|
| PREROUTING | 数据包进入网卡后、路由判断前 | raw、mangle、nat |
| INPUT | 目标是本机的数据包 | filter、mangle |
| FORWARD | 经本机转发、目标不是本机的数据包 | filter、mangle |
| OUTPUT | 本机主动发出的数据包 | raw、mangle、nat、filter |
| POSTROUTING | 路由判断后、离开网卡前 | mangle、nat |
数据包流转路径(两种核心场景)
访问本机:外网 → 网卡 → PREROUTING → INPUT → 本机进程
本机做路由转发:外网 → 网卡 → PREROUTING → FORWARD → POSTROUTING → 内网主机
本机向外发包:本机进程 → 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 规则格式:
iptables [-t 表名] 链名 匹配条件 -j 动作-
表:不写默认
filter -
匹配条件:源 IP、目标 IP、端口、协议、网卡、状态等
-
动作(target):匹配后执行的操作
Terminal window # 详细规则格式iptables [-t 表名] [-A/I/D/R] <链名> [规则号] <-i/o 网卡名> -p 协议名 <-s 源IP/源子网> --sport 源端口 <-d 目标IP/目标子网> --dport 目标端口> -j 动作参数释义
-A/I/D/R:- `-A`:追加规则;`-I`:插入规则;`-D`:删除规则;`-R`:替换修改规则
<链名称>:INPUT 、OUTPUT 、FORWARD 、PREROUTING 、POSTROUTING,可选填写规则序号
-i 入网卡:匹配入站网卡;-o 出网卡:匹配出站网卡
-p:指定协议(tcp/udp/icmp/all)
-s:源地址(IP / 网段),! -s取反
--sport:源端口;--dport:目标端口
-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 查看规则
# 查看 filter 表所有规则(常用)iptables -L -n -v
# 查看 nat 表规则iptables -t nat -L -n
参数说明:-L 列出规则-n 不解析域名/端口(加速,必加)-v 详细信息--line-numbers 显示规则行号(删除规则用)1.1.3.2 增 / 删 / 改规则
# 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 规则持久化(重启不失效)
不同系统保存方式不同:
# CentOS 6/7service iptables save# 导出规则iptables-save > /opt/rule.txt
# 导入规则iptables-restore < /opt/rule.txt1.2 基础练习
前置说明:
- 使用docker创建一个模拟环境进行练习
- 拉取镜像:
docker pull ubuntu:latest- iptables 需要操作网络内核模块,必须加
--privileged
docker run -d -it --privileged --name iptables-linux ubuntu:latest /bin/bash- 进入容器,
docker exec -it iptables-linux /bin/bash- 进入容器安装iptables,
apt update && apt install -y iptables- 查看版本,
iptables --version- 先执行
iptables -F && iptables -t nat -F清空原有规则,避免冲突- 练习顺序:基础过滤 → 状态规则 → 端口 / IP 限制 → NAT 转发
1.2.1 filter表练习
# 追加规则:所有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
# 放行sshiptables -A INPUT -p tcp --dport 22 -j ACCEPT需求:放行已建立 / 关联连接,只拦截新非法连接,本机对外访问的回应包属于 ESTABLISHED,需要放行。
# 放行所有已建立、关联的入站连接iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
# 仅放行本机主动向外发起的连接回应(OUTPUT 链)iptables -A OUTPUT -m state --state ESTABLISHED,RELATED -j ACCEPT组合完整安全基线规则:
# 清空规则iptables -Fiptables -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、HTTPSiptables -A INPUT -p tcp --dport 22 -j ACCEPTiptables -A INPUT -p tcp --dport 80 -j ACCEPTiptables -A INPUT -p tcp --dport 443 -j ACCEPT
# 4. 允许 ICMP pingiptables -A INPUT -p icmp --icmp-type echo-request -j ACCEPT
# 5. 默认拒绝所有入站iptables -P INPUT DROPiptables -P FORWARD DROPiptables -P OUTPUT ACCEPT# 仅允许 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 DROP1.2.2 FORWARD 链(路由转发基础)
场景:当前 Linux 作为网关,转发内网流量。
- 开启内核转发(必须,否则 FORWARD 和NAT不生效)
# 临时开启echo 1 > /proc/sys/net/ipv4/ip_forward
# 永久开启(CentOS7)vi /etc/sysctl.conf# 添加/修改net.ipv4.ip_forward = 1sysctl -p # 生效- 放行转发流量
允许内网 192.168.2.0/24 网段转发流量:
iptables -A FORWARD -s 192.168.2.0/24 -j ACCEPTiptables -A FORWARD -d 192.168.2.0/24 -j ACCEPT1.2.3 NAT表练习
场景 1:SNAT 内网主机共享公网 IP 上网
网卡:eth0(公网 IP:203.0.113.10),eth1(内网 192.168.2.0/24)
# 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:
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
# PREROUTING 链:目标端口转发iptables -t nat -A PREROUTING -d 203.0.113.10 -p tcp --dport 8080 -j DNAT --to-destination 192.168.2.10:801.2.4 recent 模块练习(防御暴力破解)
限制同一 IP 在 60 秒内最多新建 4 次 SSH 连接。
# 标记新连接的 SSH 请求iptables -A INPUT -p tcp --dport 22 -m state --state NEW -m recent --name SSH_BRUTE --set
# 如果 60秒内超过4次,则 DROPiptables -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 ACCEPT1.2.5 日志审计练习
记录被 DROP 的数据包以便排查问题
# 在所有 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 取反符号
!:取反匹配,放在匹配参数前面,含义:不满足后面条件的报文才匹配本条规则
语法格式:! + 匹配项,空格必须隔开 ! 和参数
# 除了 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 全部拒绝访问 80iptables -A INPUT ! -s 10.0.0.0/24 -p tcp --dport 80 -j DROP1.2.7 规则管理与持久化
# 保存规则(Debian/Ubuntu)sudo apt install iptables-persistentsudo 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文章分享
如果这篇文章对你有帮助,欢迎分享给更多人!
赣公网安备36072602000131号