iptables 简介
iptables 是 Linux 系统内核集成的包过滤防火墙工具,通过操作内核中的 Netfilter 框架实现网络流量控制。它基于规则链(如 INPUT、OUTPUT、FORWARD)和表(如 filter、nat、mangle)来管理数据包的过滤、转发和修改。
功能特性:
- 支持基于端口、IP、协议等条件的流量过滤。
- 提供 NAT(网络地址转换)和端口转发能力。
- 直接操作内核网络栈,性能高效。
firewall(如 firewalld、ufw)简介
firewall 是更上层的防火墙管理工具,通常作为 iptables/nftables 的前端,提供简化配置和动态规则管理。常见实现包括:
firewalld:默认用于 RHEL/CentOS/Fedora,支持动态更新和区域(zone)概念。
一.实验环境
| 主机名 | 网卡 | 用途 |
|---|---|---|
| node1 | nat-172.25.254.10 | 外网主机 |
| node2 | nat-172.25.254.100|hostonly-192.168.0.100 | 路由器 |
| node3 | hostonly-192.168.0.10 | 内网主机 |
二.iptables启用
bash
[root@node2 ~]# dnf install iptables-nft-services.noarch -y
[root@node2 ~]# systemctl start iptables.service
[root@node2 ~]# iptables -nL
Chain INPUT (policy ACCEPT)
target prot opt source destination
ACCEPT all -- 0.0.0.0/0 0.0.0.0/0 state RELATED,ESTABLISHED
ACCEPT icmp -- 0.0.0.0/0 0.0.0.0/0
ACCEPT all -- 0.0.0.0/0 0.0.0.0/0
ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 state NEW tcp dpt:22
REJECT all -- 0.0.0.0/0 0.0.0.0/0 reject-with icmp-host-prohibited
Chain FORWARD (policy ACCEPT)
target prot opt source destination
REJECT all -- 0.0.0.0/0 0.0.0.0/0 reject-with icmp-host-prohibited
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
.四张表五条链
1.四大表(优先级:raw > mangle > nat > filter)
1. filter 过滤表(默认表,最常用)
作用
:包过滤,放行 / 拒绝数据包,防火墙核心
内置链
:INPUT、OUTPUT、FORWARD
INPUT:发给本机的数据包OUTPUT:本机向外发出的数据包FORWARD:经过本机转发的数据包(网关 / 路由场景)
2. nat 网络地址转换表
作用
:修改数据包源 / 目的 IP、端口,实现共享上网、端口映射
内置链
:PREROUTING、POSTROUTING、OUTPUT
PREROUTING:数据包刚进网卡,改目的 IP(DNAT 端口映射)POSTROUTING:数据包离开网卡前,改源 IP(SNAT/ MASQUERADE 共享上网)OUTPUT:本机自身发出包的 DNAT 转换
3. mangle 修正表
作用
:修改数据包报文头特殊标记(TTL、TOS、MARK 标记),QoS 流量控制
内置链
:PREROUTING、INPUT、FORWARD、OUTPUT、POSTROUTING
唯一覆盖全部五条内置链的表
4. raw 原始表(优先级最高)
作用
:关闭连接追踪(conntrack),规避 nf_conntrack 性能开销
内置链
:PREROUTING、OUTPUT
数据包先经过 raw 表,再走其他表
五大链
| 链名 | raw | mangle | nat | filter |
|---|---|---|---|---|
| PREROUTING | ✅ | ✅ | ✅ | ❌ |
| INPUT | ❌ | ✅ | ❌ | ✅ |
| FORWARD | ❌ | ✅ | ❌ | ✅ |
| OUTPUT | ✅ | ✅ | ✅ | ✅ |
| POSTROUTING | ❌ | ✅ | ✅ | ❌ |
PREROUTING
数据包刚抵达网卡,还未路由判断
适用:DNAT、打流量标记、关闭连接追踪
INPUT
路由判断后,目标是本机进程的包进入此链
适用:防火墙拦截外部访问本机端口
FORWARD
路由判断后,源和目标都不是本机,需要本机转发
适用:路由器、二层防火墙过滤跨网段流量
OUTPUT
本机程序主动向外发送数据包
适用:限制本机对外访问、本地 DNAT
POSTROUTING
数据包路由完成,即将离开网卡
适用:SNAT/MASQUERADE 内网共享上网
数据包完整流转路径(两种场景)
场景 1:外部主机 → 本机服务(入站访问本机)
网卡 → raw:PREROUTING → mangle:PREROUTING → nat:PREROUTING → 路由判断 → mangle:INPUT → filter:INPUT → 本机应用
场景 2:本机程序向外发包(本机出站)
本机应用 → raw:OUTPUT → mangle:OUTPUT → nat:OUTPUT → 路由判断 → mangle:POSTROUTING → nat:POSTROUTING → 网卡发出
场景 3:外网 → 本机路由 → 内网(转发流量)
网卡入 → raw:PREROUTING → mangle:PREROUTING → nat:PREROUTING → 路由判断 → mangle:FORWARD → filter:FORWARD → mangle:POSTROUTING → nat:POSTROUTING → 网卡出
四.filter表
在本机设定apache只能被192.168.0.0/24网段访问
bash
[root@node2 ~]# echo 172.25.254.100 > /var/www/html/index.html
[root@node2 ~]# systemctl enable --now httpd
Created symlink /etc/systemd/system/multi-user.target.wants/httpd.service → /usr/lib/systemd/system/httpd.service.
# 使用apache 辅助测试
[root@node2 ~]# iptables -t filter -I INPUT 5 -p tcp --dport 80 -s 192.168.0.0/24 -m state --state new -j ACCEPT
#-t 指定所修改的表,默认filter可选(nat mangle raw)
#-I INPUT 5 操作指令 + 链名 + 规则序号
# (可选操作指令) -A -D -F清空链所有规则 -N新建自定义链 -X删除自定义空链
#-p tcp 基础匹配:协议
#--dprot 80 协议专属扩展匹配:目标端口
#-s 基础匹配:源地址
#-m state --state new 加载扩展匹配模块 state 模块参数
# (连接状态 4 种)NEW 新建连接首包 ESTABLISHED 已建立的连接 RELATED 关联连接 INVALID 非法异常数据包
#-j jump 跳转处理动作ACCEPT DROP(丢包) REJECT
[root@node2 ~]# iptables -nL
Chain INPUT (policy ACCEPT)
target prot opt source destination
ACCEPT all -- 0.0.0.0/0 0.0.0.0/0 state RELATED,ESTABLISHED
ACCEPT icmp -- 0.0.0.0/0 0.0.0.0/0
ACCEPT all -- 0.0.0.0/0 0.0.0.0/0
ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 state NEW tcp dpt:22
ACCEPT tcp -- 192.168.0.0/24 0.0.0.0/0 tcp dpt:80 state NEW
REJECT all -- 0.0.0.0/0 0.0.0.0/0 reject-with icmp-host-prohibited
测试:
bash
[root@node1 ~]# curl 172.25.254.100
curl: (7) Failed to connect to 172.25.254.100 port 80: 没有到主机的路由
[root@node3 ~]# curl 192.168.0.100
172.25.254.100
五.nat表
1.内网访问外网
1.在node3 192.168.0.10主机中
bash
[root@node3 ~]# ping 172.25.254.10
ping: connect: 网络不可达
#设定网关
[root@node3 ~]# nmcli connection modify eth0 ipv4.gateway 192.168.0.100
[root@node3 ~]# route -n
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
192.168.0.0 0.0.0.0 255.255.255.0 U 100 0 0 eth0
[root@node3 ~]# nmcli connection reload
[root@node3 ~]# nmcli connection up eth0
连接已成功激活(D-Bus 活动路径:/org/freedesktop/NetworkManager/ActiveConnection/6)
[root@node3 ~]# route -n
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
0.0.0.0 192.168.0.100 0.0.0.0 UG 100 0 0 eth0
192.168.0.0 0.0.0.0 255.255.255.0 U 100 0 0 eth0
在双网卡主机中设置出站策略
把所有从此主机中出去的数据包来源都转换成eth0网卡的ip
bash
[root@node2 ~]# iptables -D FORWARD 1
[root@node2 ~]# iptables -t nat -A POSTROUTING -o eth0 -j SNAT --to-source 172.25.254.100
#-o eth0:匹配从 eth0 网卡发出的数据包 output
#-j SNAT:匹配成功执行目的地址转换动作
#--to-source 172.25.254.100:把数据包的源头 IP强制改成 172.25.254.100
[root@node2 ~]# iptables -t nat -nL
Chain PREROUTING (policy ACCEPT)
target prot opt source destination
Chain INPUT (policy ACCEPT)
target prot opt source destination
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
Chain POSTROUTING (policy ACCEPT)
target prot opt source destination
SNAT all -- 0.0.0.0/0 0.0.0.0/0 to:172.25.254.100
#打开内核路由功能
[root@node2 ~]# sysctl -a | grep ip_forward
net.ipv4.ip_forward = 0
[root@node2 ~]# vim /etc/sysctl.conf
net.ipv4.ip_forward=1
[root@node2 ~]# sysctl -p
net.ipv4.ip_forward = 1
[root@node2 ~]# sysctl -a | grep ip_forward
net.ipv4.ip_forward = 1
测试:
[root@node3 ~]# ping 192.168.0.100
PING 192.168.0.100 (192.168.0.100) 56(84) 比特的数据。
64 比特,来自 192.168.0.100: icmp_seq=1 ttl=64 时间=0.292 毫秒
[root@node1 ~]# w -i
11:37:55 up 1:36, 3 users, load average: 0.00, 0.00, 0.00
USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT
root tty1 - 10:02 1:35m 0.01s 0.01s -bash
root pts/0 172.25.254.1 10:32 2.00s 0.04s 0.00s w -i
root pts/1 172.25.254.100 11:37 6.00s 0.00s 0.00s -bash
2.外网访问内网
bash
[root@node2 ~]# iptables -t nat -A PREROUTING -i eth0 -j DNAT --to-dest 192.168.0.10
#-i eth0:匹配从 eth0 网卡收到的数据包 input
#-j DNAT:匹配成功执行目的地址转换动作
#--to-dest 192.168.0.10:把数据包的目标 IP强制改成 192.168.0.10
[root@node2 ~]# iptables -t nat -nL
Chain PREROUTING (policy ACCEPT)
target prot opt source destination
DNAT all -- 0.0.0.0/0 0.0.0.0/0 to:192.168.0.10
Chain INPUT (policy ACCEPT)
target prot opt source destination
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
Chain POSTROUTING (policy ACCEPT)
target prot opt source destination
SNAT all -- 0.0.0.0/0 0.0.0.0/0 to:172.25.254.100
测试:
bash
[root@node1 ~]# ssh -l root 172.25.254.100
Activate the web console with: systemctl enable --now cockpit.socket
Register this system with Red Hat Insights: rhc connect
Example:
# rhc connect --activation-key <key> --organization <org>
The rhc client and Red Hat Insights will enable analytics and additional
management capabilities on your system.
View your connected systems at https://console.redhat.com/insights
You can learn more about how to register your system
using rhc at https://red.ht/registration
Last login: Tue Jul 21 10:33:22 2026 from 192.168.0.1
[root@node3 ~]# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
link/ether 00:0c:29:1e:58:f3 brd ff:ff:ff:ff:ff:ff
altname enp3s0
altname ens160
inet 192.168.0.10/24 brd 192.168.0.255 scope global noprefixroute eth0
valid_lft forever preferred_lft forever
inet6 fe80::575a:d7ac:c15a:3503/64 scope link noprefixroute
valid_lft forever preferred_lft forever