防火墙&&IPTABLES

6128 字
31 分钟
防火墙&&IPTABLES

IPTABLES实操#

[TOC]


基础命令#

-nL查看#

Terminal window
[root@m01 ~]# iptables -nL
# 查看iptables的默认策略
==============================
-n:不要把端口或ip,反向解析为名字
# 不解析为域名或者是主机名,不然的话特别慢!
-L:显示表中的所有规则
'默认加的是 -t filter'
# 默认操作的就是这张表
[root@m01 ~]# iptables -Ln
iptables: No chain/target/match by that name.
# 顺序不能反过来!

image-20260316150740088
image-20260316150740088

Terminal window
这里查的默认是filter表
展现出来的也是三个链条的规则!
1.INPUT
2.FORWARD
3.OUTPUT
[root@db03 ~]#iptables -t filter -nL INPUT
'你也可以查看指定表的,某个链条规则!'

image-20260316164549363
image-20260316164549363

Terminal window
[root@m01 ~]# iptables -nL --line
'--line就行!'
# 查看带行号的规则列表
--line-numbers

image-20260316152734483
image-20260316152734483

-D 删除#

Terminal window
[root@m01 ~]# iptables -t filter -D INPUT 2
-D:对某个链的,多少编号删除
# 删除INPUT链中的第二条规则

image-20260316153302943
image-20260316153302943

-j 动作对比#

iptables 中,-j(jump)用于指定 当数据包匹配某条规则时应执行的动作(target)

✅ 三大核心动作对比

动作行为说明对客户端的影响
ACCEPT接受数据包,允许其继续通行正常通信
DROP静默丢弃数据包,不发送任何响应客户端会超时(如 telnet 卡住、ping 无响应)
REJECT拒绝数据包,并返回错误信息给发送方客户端立即收到拒绝(如 “Connection refused”)

DROP

  • 最“安静”的拒绝方式 ,内核直接丢包,不消耗额外资源
  • 攻击者无法判断目标主机是否存在(“黑洞”效果)
  • 合法用户排查问题困难(不知道是防火墙拦了还是服务没开)
  • ==隐藏未开放端口==

REJECT

  • 主动拒绝,并根据协议返回标准错误:

    消耗额外资源

  • ==便于快速定位问题==

-A&-I规则添加#

选项作用
-AAppend(追加到链的末尾)
-IInsert(插入到开头或指定位置)
-DDelete(删除)
-RReplace(替换某条规则)
-FFlush(清空整条链)

-R(Replace)是 iptables 中用于替换某条已有规则

Terminal window
⚠️ 必须知道要替换的规则在链中的行号(编号)
[root@db03 ~]#iptables -nL INPUT --line-numbers
# 查看带编号的规则列表
4 ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:22
[root@db03 ~]#iptables -R INPUT 4 -p tcp --dport 80 -j ACCEPT
# 把第 4 条规则从允许 SSH(端口 22)改为允许 HTTP(端口 80)
[root@db03 ~]#iptables -nL INPUT --line-numbers
4 ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:80

✅ 安全设计—>模型推荐:默认拒绝

  • 默认策略设为 DROP(或显式在 ==最后== 加一条 DROP)
  • 先写允许规则(ACCEPT),把需要的服务放行
  • 最后拒绝其他一切
Terminal window
[root@m01 ~]# iptables -F
============================
-F:清空整条链,清空整个规则
[root@m01 ~]# iptables -nL --line-numbers
Chain INPUT (policy ACCEPT)
num target prot opt source destination
'输入链'
Chain FORWARD (policy ACCEPT)
num target prot opt source destination
'转发链'
Chain OUTPUT (policy ACCEPT)
num target prot opt source destination
'输出链'
[root@m01 ~]# iptables -A INPUT -i lo -j ACCEPT
# 允许本地回环
============================
-i:input、输入的时候,从哪个网卡进来
-o:ouput、输出的时候 从哪个网卡出去
============================
[root@m01 ~]# ip a
1: lo:
2: eth0:
3: eth1:
# 回环网卡来
-j:执行的动作
[root@m01 ~]# iptables -t filter -nL INPUT --line-numbers
Chain INPUT (policy ACCEPT)
num target prot opt source destination
1 ACCEPT all -- 0.0.0.0/0 0.0.0.0/0
# 指定表的链条,并显示行号!
[root@m01 ~]# iptables -t filter -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
# '允许已建立的连接,和正在启动的新连接'
============================
-m state --state ESTABLISHED,RELATED
'固定搭配!'
-m 指定模块
# 用于识别已建立的连接或与已有连接相关的数据包
[root@m01 ~]# iptables -t filter -nL INPUT --line-numbers
Chain INPUT (policy ACCEPT)
num target prot opt source destination
1 ACCEPT all -- 0.0.0.0/0 0.0.0.0/0
2 ACCEPT all -- 0.0.0.0/0 0.0.0.0/0 state RELATED,ESTABLISHED
[root@m01 ~]# iptables -A INPUT -p tcp --dport 22 -j ACCEPT
# 允许SSH连接
============================
-p:protocal协议;tcp/udp/icmp/all
--dport:目标端口
--sport:源端口
-s:--source、源ip
-d:--destination、目标ip
============================
[root@m01 ~]# iptables -t filter -nL INPUT --line-numbers
Chain INPUT (policy ACCEPT)
num target prot opt source destination
1 ACCEPT all -- 0.0.0.0/0 0.0.0.0/0
2 ACCEPT all -- 0.0.0.0/0 0.0.0.0/0 state RELATED,ESTABLISHED
3 ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:22
[root@m01 ~]# iptables -A INPUT -p tcp --dport 80 -j ACCEPT
[root@m01 ~]# iptables -A INPUT -p tcp --dport 443 -j ACCEPT
# 允许 HTTP/HTTPS
[root@m01 ~]# iptables -t filter -nL INPUT --line-numbers
Chain INPUT (policy ACCEPT)
num target prot opt source destination
1 ACCEPT all -- 0.0.0.0/0 0.0.0.0/0
2 ACCEPT all -- 0.0.0.0/0 0.0.0.0/0 state RELATED,ESTABLISHED
3 ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:22
4 ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:80
5 ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:443
[root@m01 ~]# iptables -A INPUT -j DROP
# 最后:拒绝其他所有(显式拒绝)
============================
这里面用的都是-A,追加!
# 在后面追加着呢
[root@m01 ~]# iptables -t filter -nL INPUT --line-numbers
Chain INPUT (policy ACCEPT)
num target prot opt source destination
1 ACCEPT all -- 0.0.0.0/0 0.0.0.0/0
2 ACCEPT all -- 0.0.0.0/0 0.0.0.0/0 state RELATED,ESTABLISHED
3 ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:22
4 ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:80
5 ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:443
6 DROP all -- 0.0.0.0/0 0.0.0.0/0

🔐 这是最安全的做法: ==只放行明确需要的服务==

当我们要写 拒绝规则(如封 IP、封端口),用 -I 插入到最前面

Note
  • -A追加到末尾,适合按逻辑顺序构建规则

  • -I插入开头,适合紧急封禁

    像封禁 某个IP端口

参数作用是否影响默认链是否影响计数器
-F清除所有规则✅ 是(清除规则)❌ 不影响
-X删除自定义链❌ 不影响默认链❌ 不影响
-Z清零计数器❌ 不影响链结构✅ 是

💡配置filter表规则#

Terminal window
正式配置之前,先备份,再清空规则
===========================
'确保当前的 iptables 规则处于一个干净、可控的状态'
[root@m01 ~]# iptables -F
[root@m01 ~]# iptables -X
[root@m01 ~]# iptables -Z
[root@m01 ~]# iptables -nL
Chain INPUT (policy ACCEPT)
target prot opt source destination
Chain FORWARD (policy ACCEPT)
target prot opt source destination
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
'现在filter里面的3个链条规则都是空的!'
Terminal window
(1)禁止访问22端口
[root@m01 ~]# iptables -t filter -A INPUT -p tcp --dport 22 -j DROP
[root@m01 ~]#
Socket error Event: 32 Error: 10053.
Connection closing...Socket close.
'配置完之后,我说我这键盘咋失效了!Xshell连的就是22端口!'

image-20260316191718649
image-20260316191718649

Terminal window
[C:\~]$ telnet 10.0.0.81 22
Connecting to 10.0.0.81:22...
Could not connect to '10.0.0.81' (port 22): Connection failed.
# 就是telnet也是连不上的
'删除规则'
1)查看序号
[root@m01 ~]# iptables -nL --line
# --line就行!
Chain INPUT (policy ACCEPT)
1 DROP tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:80
2)根据序号删除规则
[root@m01 ~]# iptables -D INPUT 1
Terminal window
(2)屏蔽某个ip
[root@m01 ~]# iptables -I INPUT -s 10.0.0.53 -j DROP
-s:源IP地址
# 封禁某个恶意 IP(插入最前)
[root@m01 ~]# iptables -nL INPUT --line
Chain INPUT (policy ACCEPT)
num target prot opt source destination
1 DROP all -- 10.0.0.53 0.0.0.0/0
# 测试验证!
[root@m01 ~]# yum -y install nginx
[root@m01 ~]# systemctl start nginx
[root@m01 conf.d]# locate index.html
locate: can not stat () `/var/lib/mlocate/mlocate.db': No such file or directory'
[root@m01 conf.d]# updatedb
# 更新一下
[root@m01 conf.d]# locate index.html
...
/usr/share/nginx/html/index.html
# 就是这个
[root@m01 conf.d]# echo 'Hello world' > /usr/share/nginx/html/index.html
[root@m01 conf.d]# curl localhost
Hello world
[root@m01 ~]# iptables -nL INPUT --line
Chain INPUT (policy ACCEPT)
num target prot opt source destination
1 DROP all -- 10.0.0.53 0.0.0.0/0
[root@db03 ~]# hostname -I
10.0.0.53 172.16.1.53
# 另一台机器
[root@db03 ~]# curl 10.0.0.81
^C
# 卡住
[root@db03 ~]# curl 172.16.1.81
Hello world
# 内网可以访问
'因为我们没有把局域网的那个IP禁止掉'
[root@m01 ~]# iptables -I INPUT -s 172.16.1.53 -j DROP
[root@db03 ~]#curl 172.16.1.81
^C
# 再次访问就卡住了

image-20260316193211223
image-20260316193211223

因为我们这里禁止的是某个具体的IP地址,我们用宿主机的浏览器试着访问一下!

image-20260317081033499
image-20260317081033499

  • 如果我们把整个网段都禁止了的话,我们电脑浏览器也访问不到了(10.0.0.1)
Terminal window
(3)禁止网段连入(禁止10.0.0.0/24网段访问 80端口)
[root@m01 ~]# iptables -I INPUT -s 10.0.0.0/24 -j DROP
# 禁止完之后,我们Xshell也连不上了!

image-20260317081336369
image-20260317081336369

image-20260317081418526
image-20260317081418526

nc命令#

Terminal window
'创建一个端口'
-l:使用监听模式,管控传入的资料
-k:接受多个连接请求
-v:显示指令执行过程
[root@m01 ~]# yum -y install nc
....
Dependencies resolved.
Nothing to do.
Complete!
[root@m01 ~]# nc -lk 12306
# 这个窗口夯住,直接
'我们可以新开一个窗口!检测一下!'
[root@m01 ~]# ss -lntup | grep 12306
tcp LISTEN 0 10 0.0.0.0:12306 0.0.0.0:* users:(("nc",pid=1536,fd=4))
# 检查端口连接
Windows本地可用telnet尝试登录
[C:\~]$ telnet 10.0.0.81 12306
'ctrl+alt+]退出'
Connecting to 10.0.0.81:12306...
Connection established.
To escape to local shell, press 'Ctrl+Alt+]'.
# 现在是可以登录上去!!
[root@m01 ~]# iptables -I INPUT -s 10.0.0.0/24 -p tcp --dport 12306 -j DROP
# 禁止10网段访问12306端口!
[root@m01 ~]# iptables -nL INPUT
Chain INPUT (policy ACCEPT)
DROP tcp -- 10.0.0.0/24 0.0.0.0/0 tcp dpt:12306
[C:\~]$ telnet 10.0.0.81 12306
Connecting to 10.0.0.81:12306...
Could not connect to '10.0.0.81' (port 12306): Connection failed.
# 连接失败!

修改默认策略#

实现 阿里云白名单 功能:默认是拒绝

  • 开放 端口网段
Tip

上面的实验,INPUT的默认行为是接受accept

  • 上面是允许,下面决绝所有
  • 要是放行 -I 放在前面
Terminal window
[root@m01 ~]# iptables -t filter -nL INPUT --line-numbers
'ACCEPT'
Chain INPUT (policy ACCEPT)
num target prot opt source destination
1 ACCEPT all -- 0.0.0.0/0 0.0.0.0/0
2 ACCEPT all -- 0.0.0.0/0 0.0.0.0/0 state RELATED,ESTABLISHED
3 ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:22
4 ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:80
5 ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:443
6 DROP all -- 0.0.0.0/0 0.0.0.0/0
Terminal window
#方法2:
'修改链默认规则、修改为拒绝、再添加准许'
(1)修改默认规则
[root@m01 ~]# iptables -nL INPUT
Chain INPUT (policy ACCEPT)
target prot opt source destination
'ACCEPT'
[root@m01 ~]# iptables -P INPUT DROP
====================================
-P 选项表示 设置链(chain)的默认策略(Policy)
====================================

image-20260317090133134
image-20260317090133134

image-20260317090153661
image-20260317090153661

Terminal window
1.把源地址是10.0.0.1、目的端口是22的能远程连接我们
2.允许内网进行访问!
(2)放行必要的端口和IP
# 把我们必须的端口进行放行!!
'80、443...'
[root@m01 ~]# iptables -A INPUT -p tcp --dport 80 -j ACCEPT
[root@m01 ~]# iptables -A INPUT -p tcp --dport 443 -j ACCEPT
[root@m01 ~]# iptables -nL INPUT
Chain INPUT (policy DROP)
ACCEPT tcp -- 10.0.0.1 0.0.0.0/0 tcp dpt:22
ACCEPT all -- 172.16.1.0/24 0.0.0.0/0
ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:80
ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:443
'想要放行,就往下面追加就行了!'
# 还原环境!
先别急着给他-F清理所有规则,因为INPUT链默认是拒绝
你清理完规则后,又连不上了!!!
[root@m01 ~]# iptables -P INPUT ACCEPT
[root@m01 ~]# iptables -F
[root@m01 ~]# iptables -nL INPUT
Chain INPUT (policy ACCEPT)
target prot opt source destination

指定多个端口#

Terminal window
[root@m01 ~]# iptables -I INPUT -p tcp --dport 8888 -j ACCEPT
[root@m01 ~]# iptables -I INPUT -p tcp --dport 9999 -j ACCEPT
[root@m01 ~]# iptables -nL INPUT
Chain INPUT (policy ACCEPT)
ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:9999
ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:8888
'一个一个的放行太慢了!!!'
=============补充=============
[root@m01 ~]# iptables -I INPUT -p tcp -m multiport --dport 1111,2222,3333 -j ACCEPT
-m multiport
# 加载 multiport 扩展模块
'在一条规则中匹配多个端口'
[root@m01 ~]# iptables -nL INPUT
Chain INPUT (policy ACCEPT)
target prot opt source destination
ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 multiport dports 1111,2222,3333
'在这!!'
ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:9999
ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:8888
连续端口(端口范围)
# 如果是连续的端口、可以不加上-m multiport
这条规则允许目标端口在 1 1024(含) 之间的 TCP 流量
[root@m01 ~]# iptables -I INPUT -p tcp --dport 55:66 -j ACCEPT
[root@m01 ~]# iptables -nL INPUT
Chain INPUT (policy ACCEPT)
target prot opt source destination
ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpts:55:66
# 从55端口到66端口

禁止被ping#

  • ping 使用的就是icmp协议

  • 有效禁止被 ping

Terminal window
[root@m01 ~]# iptables -I INPUT -p icmp --icmp-type 8 -j DROP
[root@m01 ~]# iptables -nL INPUT
Chain INPUT (policy ACCEPT)
DROP icmp -- 0.0.0.0/0 0.0.0.0/0 icmptype 8
==========================
-p icmp:匹配 ICMP 协议(用于 ping、traceroute 等)
--icmp-type 8:匹配ICMP Echo Request(类型8),也就是别人发来的“ping 请求”
-j DROP:静默丢弃该数据包(不回复任何信息)
⚠️这条规则只影响别人 ping 你,不影响你 ping 别人
这条规则只作用于 IPv4、IPv6 不受影响
==========================
测试验证!
[root@db03 ~]# ping 10.0.0.81
PING 10.0.0.81 (10.0.0.81) 56(84) bytes of data.
# 直接卡住
# 还原环境!
[root@m01 ~]# iptables -D INPUT 1
  • ==通过内核参数,控制禁止被ping==
Terminal window
方法一:临时生效(重启失效)
[root@m01 ~]# echo 1 > /proc/sys/net/ipv4/icmp_echo_ignore_all
# 立即生效 & 系统重启后失效
值说明:
0:响应 ping(默认)
1:忽略所有 ICMP echo 请求(即禁止被 ping)
[root@m01 ~]# echo 0 >/proc/sys/net/ipv4/icmp_echo_ignore_all
# 还原环境!
方法二:永久生效(写入配置文件)
(1)编辑 /etc/sysctl.conf 文件
(2)添加或修改以下行:
net.ipv4.icmp_echo_ignore_all = 1
(3)使配置立即生效
sysctl -p
[root@m01 ~]# echo net.ipv4.icmp_echo_ignore_all = 1 >> /etc/sysctl.conf
[root@m01 ~]# sysctl -p
...
net.ipv4.icmp_echo_ignore_all = 1
[root@m01 ~]# sed -i 's#net.ipv4.icmp_echo_ignore_all = 1##g' /etc/sysctl.conf
# 把它替换成空
[root@m01 ~]# sysctl -p
....
# 没有了!
# 还原环境!
[root@m01 ~]# reboot
Connection closing...Socket close.
[root@db03 ~]# ping 10.0.0.81
PING 10.0.0.81 (10.0.0.81) 56(84) bytes of data.
64 bytes from 10.0.0.81: icmp_seq=1 ttl=64 time=0.694 ms
64 bytes from 10.0.0.81: icmp_seq=2 ttl=64 time=0.213 ms

匹配网络状态#

Terminal window
'(TCP/IP连接状态)'
-m state --state
# -m state:使用状态模块!
NEW:已经或将启动新的连接
ESTABLISHED:已建立的连接
RELATED:正在启动的新连接
INVALID:非法或无法识别的
==========================
ACCEPT all -- 0.0.0.0/0 0.0.0.0/0 state RELATED,ESTABLISHED
# 他默认就有这个状态!
所以ESTABLISHED、和RELATED还是挺重要的!
[root@m01 ~]# iptables -t filter -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
'允许已建立的连接,和正在启动的新连接'
[root@m01 ~]# netstat -an | grep 80
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN
tcp 0 0 10.0.0.81:80 10.0.0.1:10929 TIME_WAIT
tcp 0 0 10.0.0.81:80 10.0.0.1:8200 TIME_WAIT
tcp6 0 0 :::80 :::* LISTEN
# 现在这两个状态是LISTEN,监听状态!!
==========面试题==========
如何统计业务后台的接口状态!
这里用的是netstat -an,可以通过awk取最后一列,这就是所有连接的状态!!
还可以通过sort -rn...排序
==========================
[root@m01 ~]# iptables -I INPUT -p tcp --dport 80 -j ACCEPT
[root@m01 ~]# iptables -nL
Chain INPUT (policy ACCEPT)
ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:80
# 放行80端口!
'模拟客户端访问80网站'

image-20260317102613409
image-20260317102613409

image-20260317103117719
image-20260317103117719

限制并发及速率#

在实际生产中,应用层限速(如 Nginx)通常比 iptables 更合适,因为更灵活、可读性强

Terminal window
-m limit --limit N/单位 --limit-burst M
参数说明
--limit N/单位平均速率,后面的单位分别为:秒second、 分minute、 时hour
--limit-burst M令牌桶初始容量,即“突发允许的最大次数”(默认 5

🔹 工作原理(令牌桶模型)

  • 系统维护一个“令牌桶”,最多装 M 个令牌(由 --limit-burst 指定)

  • 每当有包匹配该规则:

    • 如果桶里有令牌 → 消耗 1 个令牌,规则匹配成功(继续执行 -j 动作)
    • 如果没令牌 → 规则不匹配
  • 令牌按 --limit 的速率自动补充(例如 --limit 2/minute → 每 30 秒补 1 个)

    一分钟给 2 个令牌,也就是每 30秒 补一个

✅ 所以:--limit-burst 决定了“一开始能连续通过多少个请求”

  • 如果不写,默认一开始就只有 5
Terminal window
'ping测试(icmp协议)'
iptables -F
iptables -I INPUT -p icmp --icmp-type 8 -m limit --limit 10/minute --limit-burst 2 -j ACCEPT
iptables -A INPUT -p icmp --icmp-type 8 -j DROP
[root@m01 ~]# iptables -F
# 先清空
[root@m01 ~]# iptables -I INPUT -p icmp --icmp-type 8 -m limit --limit 10/minute --limit-burst 2 -j ACCEPT
# 刚开始只能ping两次,然后每一分钟(60s)补10个,也就是6秒补一个!
'它们的动作是放行!'
[root@m01 ~]# iptables -A INPUT -p icmp --icmp-type 8 -j DROP
'这个是默认动作是丢弃!'
# 这个丢弃是-A,追加;不能-I放在开头!否则后面的放行动作无效!
[root@m01 ~]# iptables -nL INPUT
Chain INPUT (policy ACCEPT)
target prot opt source destination
ACCEPT icmp -- 0.0.0.0/0 0.0.0.0/0 icmptype 8 limit: avg 10/min burst 2
DROP icmp -- 0.0.0.0/0 0.0.0.0/0 icmptype 8
# 注意他们的顺序和规则!
'拒绝的在后面!'
Terminal window
'db03 进行ping测试'
# ping 10.0.0.81
[root@db03 ~]# ping 10.0.0.81
PING 10.0.0.81 (10.0.0.81) 56(84) bytes of data.
64 bytes from 10.0.0.81: icmp_seq=1 ttl=64 time=0.182 ms
64 bytes from 10.0.0.81: icmp_seq=2 ttl=64 time=0.251 ms
--limit-burst 2
# 默认只能ping两次!
64 bytes from 10.0.0.81: icmp_seq=7 ttl=64 time=0.189 ms
--limit 10/minute
# 后续每60秒给10个!也就是每6秒给1个!
64 bytes from 10.0.0.81: icmp_seq=13 ttl=64 time=0.233 ms
'后续每6秒允许ping一次'

保存与恢复#

🔹iptables-save

  • 作用:将当前内存中的 iptables 规则 导出为可读的文本格式

  • 默认行为:输出到 屏幕,不会自动保存到文件

  • 用法示例:

    Terminal window
    [root@db03 ~]# iptables-save
    '打印规则到屏幕'
    # Generated by iptables-save v1.8.5 on Tue Mar 17 11:12:56 2026
    *filter
    :INPUT ACCEPT [96:8699]
    :FORWARD ACCEPT [0:0]
    :OUTPUT ACCEPT [111:10540]
    -A INPUT -p icmp -m icmp --icmp-type 8 -m limit --limit 10/min --limit-burst 2 -j ACCEPT
    -A INPUT -p icmp -m icmp --icmp-type 8 -j DROP
    COMMIT
    # Completed on Tue Mar 17 11:12:56 2026
    '查看默认的配置!'
    [root@m01 ~]# cat /etc/sysconfig/iptables
    =====================
    1.在 RHEL、CentOS 6/7 等系统中,iptables 服务默认使用这个路径保存规则
    2.系统启动时,如果启用了 iptables 服务,会自动执行 iptables-restore < /etc/sysconfig/iptables 来恢复规则
    3.所以我们重启后,默认使用的就是如下规则!
    =====================
    # sample configuration for iptables service
    # you can edit this manually or use system-config-firewall
    # please do not ask us to add additional ports/services to this default configuration
    *filter
    :INPUT ACCEPT [0:0]
    :FORWARD ACCEPT [0:0]
    :OUTPUT ACCEPT [0:0]
    -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
    -A INPUT -p icmp -j ACCEPT
    -A INPUT -i lo -j ACCEPT
    -A INPUT -p tcp -m state --state NEW -m tcp --dport 22 -j ACCEPT
    -A INPUT -j REJECT --reject-with icmp-host-prohibited
    -A FORWARD -j REJECT --reject-with icmp-host-prohibited
    COMMIT
    =====================
    这是手动持久化 iptables 规则的标准方法之一
    iptables-save > /etc/sysconfig/iptables
    # 保存到文件(关键!)

Tip

补充:

  • 我们现在的修改全部都是 临时 的!

    ==重启后就会失效!==

  • systemctl restart iptables

  • 读取 /etc/sysconfig/iptables内容

Terminal window
[root@m01 ~]# iptables -nL
Chain INPUT (policy ACCEPT)
target prot opt source destination
Chain FORWARD (policy ACCEPT)
target prot opt source destination
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
'现在啥也没有'
[root@m01 ~]# systemctl restart iptables
'重启后,就又都复原了!'
[root@m01 ~]# 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

🔹 iptables-restore

  • 作用:从文件中 加载并应用 iptables 规则

  • **必须指定文件 **作为输入(不能交互式输入)

  • 用法示例:

    Terminal window
    iptables-restore < /etc/sysconfig/iptables
    ⚠️ 注意:它会替换当前所有规则,不是增量添加!
    iptables-restore /etc/sysconfig/iptables
    # 某些版本支持直接跟文件名
    =====================================
    [root@m01 ~]# iptables -nL
    Chain INPUT (policy ACCEPT)
    target prot opt source destination
    ACCEPT icmp -- 0.0.0.0/0 0.0.0.0/0 icmptype 8 limit: avg 10/min burst 2
    DROP icmp -- 0.0.0.0/0 0.0.0.0/0 icmptype 8
    Chain FORWARD (policy ACCEPT)
    target prot opt source destination
    Chain OUTPUT (policy ACCEPT)
    target prot opt source destination
    [root@m01 ~]# iptables-restore < /etc/sysconfig/iptables
    [root@m01 ~]# 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

实际生产用法#

  • iptables配置方式
    • 看电影模式: 默认规则是 DROP
  • 默认是拒绝
  1. ssh可以连接进来
Terminal window
iptables -F
iptables -X
iptables -Z
iptables -nL
[root@m01 ~]# iptables -nL
Chain INPUT (policy ACCEPT)
target prot opt source destination
Chain FORWARD (policy ACCEPT)
target prot opt source destination
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
# 现在是什么都没有!
(1)允许本地回环
[root@m01 ~]# iptables -A INPUT -i lo -j ACCEPT
[root@m01 ~]# iptables -A OUTPUT -o lo -j ACCEPT
# 允许本机回环lo接口数据流量流出与流入
(2)允许已建立的连接,和正在启动的新连接
[root@m01 ~]# iptables -t filter -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
(3)放行必要的端口
[root@m01 ~]# iptables -A INPUT -p tcp -s 10.0.0.1 --dport 22 -j ACCEPT
'只能本地10.0.0.1可以远程连接我们的22端口'
[root@m01 ~]# iptables -A INPUT -m multiport -p tcp --dport 80,443 -j ACCEPT
'中间逗号隔开'
# 放行连续的端口!
(4)放行必要的网段
[root@m01 ~]# iptables -A INPUT -s 10.0.0.0/24 -j ACCEPT
# 模拟公司的公网
[root@m01 ~]# iptables -A INPUT -s 172.16.1.0/24 -j ACCEPT
# 模拟公司的内网
(5)更改链表默认的规则
# (ACCEPT or DORP)
[root@m01 ~]# iptables -P INPUT DROP
# 进来的流量,默认都丢弃
[root@m01 ~]# iptables -P FORWARD DROP
# 默认不转发,就是丢弃
[root@m01 ~]# iptables -P OUTPUT ACCEPT
# 出去的流量,都不做限制
'查看规则!'
[root@m01 ~]# iptables -nL
Chain INPUT (policy DROP)
target prot opt source destination
ACCEPT all -- 0.0.0.0/0 0.0.0.0/0
ACCEPT all -- 0.0.0.0/0 0.0.0.0/0 state RELATED,ESTABLISHED
ACCEPT tcp -- 10.0.0.1 0.0.0.0/0 tcp dpt:22
ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 multiport dports 80,443
ACCEPT all -- 10.0.0.0/24 0.0.0.0/0
ACCEPT all -- 172.16.1.0/24 0.0.0.0/0
Chain FORWARD (policy DROP)
target prot opt source destination
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
ACCEPT all -- 0.0.0.0/0 0.0.0.0/0
'输出至屏幕上'
[root@m01 ~]# iptables-save
# Generated by iptables-save v1.8.5 on Tue Mar 17 12:06:36 2026
*filter
:INPUT DROP [0:0]
:FORWARD DROP [0:0]
:OUTPUT ACCEPT [17:2298]
-A INPUT -i lo -j ACCEPT
-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
-A INPUT -s 10.0.0.1/32 -p tcp -m tcp --dport 22 -j ACCEPT
-A INPUT -p tcp -m multiport --dports 80,443 -j ACCEPT
-A INPUT -s 10.0.0.0/24 -j ACCEPT
-A INPUT -s 172.16.1.0/24 -j ACCEPT
-A OUTPUT -o lo -j ACCEPT
COMMIT
# Completed on Tue Mar 17 12:06:36 2026

💡配置nat表规则#

  • 网络地址转换
    • 端口映射ip映射
    • 给数据包“换马甲”

👉 比如你家里的电脑用的是内网 IP(比如 192.168.1.100),想上网,但外面只能看到一个公网 IP;这时候 nat 表就出来帮忙,把你的内网 IP “伪装” 成公网 IP 发出去

🔍 它具体干啥?

==它主要做两件事:==

  1. 共享上网(内网多台机器共用一个公网IP上外网)
    • 举个例子:你家里有5台电脑,但只有一个公网IP 所有电脑上网时,路由器(或服务器)会用 nat 表把它们的内网IP都换成自己的公网IP发出去,回来时再分发回去
    • 这叫 SNAT(源地址转换),一般在 POSTROUTING 链处理
  2. 端口映射 / IP 映射(让外网能访问内网服务)
    • 比如你在家里有一台 Web 服务器,运行在内网 IP 192.168.1.100:9000 你想让外网用户通过 公网IP:80 访问它,就需要 nat 表把“外网来的80端口”映射到“内网的9000端口”
    • 这叫 DNAT(目的地址转换),一般在 PREROUTING 链处理

🔗 它有三个关键“链”(检查点):

链名大白话解释
PREROUTING数据包刚进来时,改“目标是谁” → 做 端口映射、IP映射(比如把公网80转成内网9000)
OUTPUT本机自己发包时,改“我是谁” → 用于本机做 NAT(较少见)
POSTROUTING数据包要出去时,改“我从哪来” → 做 共享上网(比如把内网IP换成公网IP)

共享上网#

image-20260317160542554
image-20260317160542554

  • ==POSTROUTING && SNAT==
Terminal window
[root@m01 ~]# iptables -F
[root@m01 ~]# iptables -X
[root@m01 ~]# iptables -Z
[root@m01 ~]# iptables -P INPUT ACCEPT
[root@m01 ~]# iptables -P FORWARD ACCEPT
'在filter表中,一定要确保INPUT,和FORWARD默认的规则是允许访问的!'
[root@m01 ~]# iptables -nL
Chain INPUT (policy ACCEPT)
target prot opt source destination
Chain FORWARD (policy ACCEPT)
target prot opt source destination
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
(1)防火墙配置
[root@m01 ~]# iptables -t nat -A POSTROUTING -s 172.16.1.53 -j SNAT --to-source 10.0.0.81
===========================
-t:指定nat表
-A:在POSTROUTING初做,也就是路由出口
-s:不能上网的IP,可以是网段
-j:动作,开启SNAT转发
--to-source:根能上网的IP地址
共享上网(SNAT):
[root@m01 ~]# iptables -t nat -A POSTROUTING -s 172.16.1.53 -j MASQUERADE
# 换成这个条命令也是可以的!
意思:所有来自内网 172.16.1.53 的包,在出去前,把源IP换成我的公网IP
'但是后台web的网关和dns别忘记配!'
(2)路由转发
[root@m01 ~]# echo 'net.ipv4.ip_forward = 1' >> /etc/sysctl.conf
[root@m01 ~]# sysctl -p | tail -1
net.ipv4.ip_forward = 1
# 开启路由转发!
(3)后台web配置,不能上网
[root@db03 ~]# tail -2 /etc/sysconfig/network-scripts/ifcfg-eth1
# 内网IP配置文件
GATEWAY=10.0.0.81
DNS1=223.6.6.6
'多网关和DNS即可,这个网关是能上网的IP地址'
[root@db03 ~]# grep ONBOOT /etc/sysconfig/network-scripts/ifcfg-eth0
ONBOOT=no
# 能上网的配置文件,关闭自连接
[root@db03 ~]# systemctl restart network
'重启网络后,Xshell连接断开!'
# db03的公网损坏,不能上网!

image-20260317145356136
image-20260317145356136

image-20260317150005196
image-20260317150005196

Terminal window
db03虽然10.0.0.53,不能访问,但是它的172.16.1.53是可以访问的!
[root@m01 ~]# ping 172.16.1.53
PING 172.16.1.53 (172.16.1.53) 56(84) bytes of data.
64 bytes from 172.16.1.53: icmp_seq=1 ttl=64 time=0.315 ms
64 bytes from 172.16.1.53: icmp_seq=2 ttl=64 time=0.271 ms
# 用m01和db03测试通信!
[root@m01 ~]# ssh 172.16.1.53
The authenticity of host '172.16.1.53 (172.16.1.53)' can't be established.'
....
root@172.16.1.53's password: '
Last login: Tue Mar 17 14:52:56 2026
[root@db03 ~]# hostname -I
172.16.1.53
# 我们可以通过m01登录上db03
# 很明显他只有一个IP地址
[root@m01 ~]# ping 10.0.0.53
PING 10.0.0.53 (10.0.0.53) 56(84) bytes of data.
From 10.0.0.81 icmp_seq=1 Destination Host Unreachable
From 10.0.0.81 icmp_seq=2 Destination Host Unreachable
'主机不可达!!!'

端口转发#

  • ==PREROUTING && DNAT==

image-20260317183519835
image-20260317183519835

Terminal window
'通过我们10.0.0.81的9000端口,访问到我们172.16.1.53的22端口'
=======================
如果我们真的要做端口转发,基本不会用IPtables去做的!!!
像这个例子,必须要满足3个条件:
1.m01也就是81的转发要开启
2.db03也就是53的10.xxx段要关闭
3.db03的172.xxx段的网关指向10.0.0.81
之后你再配置iptables -t nat -A PREROUTING -d 10.0.0.81 -p tcp --dport 9000 -j DNAT --to-destination 172.16.1.53:22 才行!!!
=======================
[C:\~]$ ssh 172.16.1.53
Connecting to 172.16.1.53:22...
Canceled.
# 连接失败
[C:\~]$ ssh 10.0.0.53
# 连接失败
Connecting to 10.0.0.53:22...
Could not connect to '10.0.0.53' (port 22): Connection failed.
[C:\~]$ ssh 10.0.0.81 9000
# 连接失败
Connecting to 10.0.0.81:9000...
Could not connect to '10.0.0.81' (port 9000): Connection failed.
=============PREROUTING && DNAT=============
[root@m01 ~]# iptables -t nat -A PREROUTING -d 10.0.0.81 -p tcp --dport 9000 -j DNAT --to-destination 172.16.1.53:22
-A:PREROUTING
-d:目标IP
--dport:目标IP端口
-j:DNAT
--to-destination:转发给目标IP:端口
[root@m01 ~]# iptables -nL PREROUTING -t nat
Chain PREROUTING (policy ACCEPT)
target prot opt source destination
DNAT tcp -- 0.0.0.0/0 10.0.0.81 tcp dpt:9000 to:172.16.1.53:22
'测试与检查'
# 本地shell中
[C:\~]$ ssh 10.0.0.81 9000
# 访问81的9000端口
Connecting to 10.0.0.81:9000...
Connection established.
...
Last login: Tue Mar 17 15:19:19 2026 from 172.16.1.81
[root@db03 ~]# hostname -I
172.16.1.53
# 实际连接的是db03

文章分享

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

防火墙&&IPTABLES
https://www.kpyun.fun/posts/basics/extension/extension14/
作者
久棹
发布于
2025-10-06
许可协议
CC BY-NC-SA 4.0
Profile Image of the Author
久棹
只要胆子大,天天寒暑假!
公告
欢迎来到久棹的技术小站!本站专注 Linux 运维学习笔记分享,如有问题欢迎交流探讨 🎉
分类
标签
站点统计
文章
98
分类
11
标签
203
总字数
244,453
运行时长
0
最后活动
0 天前
站点信息
构建平台
Local
博客版本
Firefly v6.13.5
文章许可
CC BY-NC-SA 4.0

文章目录