Linux iptables 防火墙原理与实操——从四表五链到 NAT 配置

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
相关推荐
不像程序员的程序媛34 分钟前
linux常见文本操作命令
linux·运维·服务器
wangbing11251 小时前
开发指南149-IotDB-常用命令
linux·运维·iotdb
Dovis(誓平步青云)1 小时前
常用命令藏得太深?怎么做一个快捷命令坞
运维·前端·自动化·音视频·prometheus
看着博客敲代码1 小时前
WorkBuddy 接上 Kali MCP 做自动化渗透:信息收集到初步验证的落地记录
linux·人工智能·安全·网络安全·自动化
志栋智能1 小时前
运维超自动化的知识管理与传承
运维·自动化
蜗牛互联网2 小时前
Python Agent工具调用的白名单、参数校验与审批门禁
java·服务器·前端·人工智能·后端·python
jack186892 小时前
OpenClaw 数据采集与自动化应用场景指南
运维·自动化
小HANN3 小时前
华为云企业网站上云实战|从零搭建高可用WordPress全站架构(ECS+RDS+ELB+弹性伸缩+云监控闭环)
linux·运维·服务器·经验分享
奈落243 小时前
规则引擎还是大模型?AI 工作流与传统自动化的分工边界:确定性流程照旧,‘每次都不太一样‘的知识型工作才交给 AI
运维·人工智能·自动化·大模型·工作流·ai 办公
星恒随风3 小时前
Linux库的底层原理:ELF文件格式、静态链接、程序加载、虚拟地址空间与GOT/PLT详解
linux·运维·笔记·学习·状态模式