Linux学习之旅之防火墙与WEB加固
一 、IPtables防火墙
1.1、什么是Netfilter
bash
Netfilter 是 Linux 内核里的网络数据包处理框架(内核子系统),是 Linux 防火墙、NAT 的底层核心,从 Linux 2.4 内核正式引入。简单一句话:Netfilter 在内核网络栈埋了 5 个检查站(Hook 钩子),数据包路过时,可以被拦截、放行、修改、打日志;iptables/nftables 只是用户态工具,用来给 Netfilter 写规则。
从 Linux 2.4.x 版本的内核开始,netfilter 就正式成为了新一代的 Linux 防火墙机制,是Linux内核的一个子系统。Netfilter采用模块化设计,具有良好的可扩充性,提供扩展网络服务的结构化底层框架。Netfilter与IP协议栈是无缝契合,并允许对数据包进行过滤、地址转换、处理等操作。
1.2、5 个检查站

| 钩子名称 | 触发时机 | 适用流量 | 核心作用 | iptables 对应内置链 |
|---|---|---|---|---|
| PREROUTING | 数据包进入内核,路由查找之前 | 所有从网卡进入主机的数据包 | DNAT 端口映射、修改入报文头部、给入包打 mark 标记 | PREROUTING |
| INPUT | 路由判断完成,包目标为本机,交给本地应用之前 | 目的 IP 是本机的入站流量 | 入站防火墙过滤,控制外部访问本机的端口 / IP | INPUT |
| FORWARD | 路由判断完成,包不是本机,需要转发 | 经过本机网关转发的跨网段流量 | 转发流量防火墙过滤,控制内网和外网之间转发包 | FORWARD |
| OUTPUT | 本机应用生成数据包,路由查找之前向外发送 | 本机进程向外发出的数据包 | 本机出站流量过滤、修改本机发出报文 | OUTPUT |
| POSTROUTING | 路由完成,数据包即将离开网卡之前 | 所有要从本机网卡出去的包(本机发包 + 转发包) | SNAT/MASQUERADE 源地址转换,共享公网 IP 上网 | POSTROUTING |
PREROUTING 路由前,INPUT 本机收;FORWARD 做转发,OUTPUT 本机发;POSTROUTING 出网卡。
1.3、IPtables组成
| 表名 | 核心作用 | 可用的链(Netfilter 钩子) |
|---|---|---|
| filter | 默认表,数据包过滤防火墙,控制包放行 / 丢弃,最常用 | INPUT、FORWARD、OUTPUT |
| nat | 网络地址转换,SNAT/DNAT/MASQUERADE、端口映射 | PREROUTING、POSTROUTING、OUTPUT |
| mangle | 修改数据包报文头部信息,打 mark 标记,调整 TTL/TOS,用于 QoS、策略路由 | PREROUTING、INPUT、FORWARD、OUTPUT、POSTROUTING(5 条链全都支持) |
| raw | 最高优先级,用于关闭连接跟踪(nf_conntrack),绕过状态检测 | PREROUTING、OUTPUT |
| security | 安全访问控制,配合 SELinux,对数据包设置安全上下文 | INPUT、FORWARD、OUTPUT |
二、IPtables命令配置
2.1、命令格式
2.1.1、命令格式
bashiptables [-t 表名] 命令选项 [链名] [匹配条件] [-j 动作]
2.1.2、命令选项
| 参数 | 含义 |
|---|---|
-A |
Append,追加规则,加到链末尾 |
-I |
Insert,插入规则 ,默认插在第 1 行;-I INPUT 3插到第 3 行 |
-D |
Delete,删除一条规则 |
-F |
Flush,清空链所有规则 |
-L |
List,列出规则 |
-n |
数字格式,不解析域名(加速,推荐搭配 - L) |
-v |
verbose,详细信息(数据包、字节计数) |
-P |
Policy,设置链默认策略 |
-Z |
Zero,清空数据包计数器 |
-N |
新建自定义链 |
-X |
删除自定义空链 |
2.1.3、匹配条件
| 参数 | 含义 |
|---|---|
-s 源IP |
源地址,-s 192.168.1.0/24 |
-d 目的IP |
目的地址 |
-p 协议 |
协议:tcp/udp/icmp/all |
--sport |
源端口(配合 - p tcp/udp) |
--dport |
目的端口 |
-i 网卡 |
入网卡(PREROUTING/INPUT/FORWARD) |
-o 网卡 |
出网卡(FORWARD/OUTPUT/POSTROUTING) |
-m state --state |
状态匹配:NEW,ESTABLISHED,RELATED,INVALID |
2.1.4、最终动作
| target | 说明 |
|---|---|
| ACCEPT | 放行数据包 |
| DROP | 丢弃,无任何回应 |
| REJECT | 拒绝,返回 ICMP 报错 |
| LOG | 记录内核日志,不改变数据包 |
| SNAT | 静态源地址转换 |
| MASQUERADE | 源地址伪装(动态公网 IP) |
| DNAT | 目的地址转换 / 端口映射 |
| MARK | 给数据包打内核 mark 标记 |
2.2、命令基础配置
2.2.1、命令简单操作
拒绝数据
bash
# 准备两台主机
# ping 10.0.0.7主机
[root@rocky9-6 ~]# ping 10.0.0.7
PING 10.0.0.7 (10.0.0.7) 56(84) bytes of data.
64 bytes from 10.0.0.7: icmp_seq=1 ttl=64 time=0.580 ms
# 将来自10.0.0.6 的数据包丢弃
[root@ubuntu2404ser:~#] iptables -t filter -A INPUT -s 10.0.0.6 -j DROP
[root@ubuntu2404ser:~#]
# 会到主机6 可以观察到ping没有反应了,因为主机6不知道数据被丢弃了还在一直发生
# 查看规则
[root@ubuntu2404ser:~#] iptables -vnL
Chain INPUT (policy ACCEPT 281 packets, 19658 bytes)
pkts bytes target prot opt in out source destination
158 13272 DROP 0 -- * * 10.0.0.6 0.0.0.0/0
Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
[root@ubuntu2404ser:~#]
清除规则
bash
[root@ubuntu2404ser:~#] iptables -F
[root@ubuntu2404ser:~#] iptables -vnL
Chain INPUT (policy ACCEPT 367 packets, 25119 bytes)
pkts bytes target prot opt in out source destination
Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
[root@ubuntu2404ser:~#]
2.2.2、规则保存与还原
bash
[root@ubuntu2404ser:~#] iptables -t filter -A INPUT -s 10.0.0.6 -j DROP
[root@ubuntu2404ser:~#] iptables -nvL
Chain INPUT (policy ACCEPT 513 packets, 34809 bytes)
pkts bytes target prot opt in out source destination
0 0 DROP 0 -- * * 10.0.0.6 0.0.0.0/0
Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
# 保存规则
[root@ubuntu2404ser:~#] iptables-save > iptables.rules
[root@ubuntu2404ser:~#] iptables -F
[root@ubuntu2404ser:~#] iptables -nvL
Chain INPUT (policy ACCEPT 610 packets, 40994 bytes)
pkts bytes target prot opt in out source destination
Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
# 还原规则
[root@ubuntu2404ser:~#] iptables-restore < iptables.rules
[root@ubuntu2404ser:~#] iptables -nvL
Chain INPUT (policy ACCEPT 6 packets, 384 bytes)
pkts bytes target prot opt in out source destination
0 0 DROP 0 -- * * 10.0.0.6 0.0.0.0/0
Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
Chain OUTPUT (policy ACCEPT 4 packets, 384 bytes)
pkts bytes target prot opt in out source destination
2.2.3、规则清除
bash
# 床架几个规则
[root@ubuntu2404ser:~#] iptables -t filter -A INPUT -s 10.0.0.6 -j DROP
[root@ubuntu2404ser:~#] iptables -t filter -A INPUT -s 10.0.0.7 -j DROP
[root@ubuntu2404ser:~#] iptables -t filter -A INPUT -s 10.0.0.8 -j DROP
[root@ubuntu2404ser:~#] iptables -t filter -A INPUT -s 10.0.0.9 -j DROP
[root@ubuntu2404ser:~#] iptables -t filter -A INPUT -s 10.0.0.10 -j DROP
[root@ubuntu2404ser:~#] iptables -t filter -A INPUT -s 10.0.0.11 -j DROP
# 查看规则,--line-numbers显示行号
[root@ubuntu2404ser:~#] iptables -nL INPUT --line-numbers
Chain INPUT (policy ACCEPT)
num target prot opt source destination
1 DROP 0 -- 10.0.0.6 0.0.0.0/0
2 DROP 0 -- 10.0.0.6 0.0.0.0/0
3 DROP 0 -- 10.0.0.7 0.0.0.0/0
4 DROP 0 -- 10.0.0.8 0.0.0.0/0
5 DROP 0 -- 10.0.0.9 0.0.0.0/0
6 DROP 0 -- 10.0.0.10 0.0.0.0/0
7 DROP 0 -- 10.0.0.11 0.0.0.0/0
# 1. 删除指定行规则
[root@ubuntu2404ser:~#] iptables -D INPUT 3
[root@ubuntu2404ser:~#] iptables -nL INPUT --line-numbers
Chain INPUT (policy ACCEPT)
num target prot opt source destination
1 DROP 0 -- 10.0.0.6 0.0.0.0/0
2 DROP 0 -- 10.0.0.6 0.0.0.0/0
3 DROP 0 -- 10.0.0.8 0.0.0.0/0
4 DROP 0 -- 10.0.0.9 0.0.0.0/0
5 DROP 0 -- 10.0.0.10 0.0.0.0/0
6 DROP 0 -- 10.0.0.11 0.0.0.0/0
# 指定规则名字删除规则
[root@ubuntu2404ser:~#] iptables -D INPUT -s 10.0.0.11 -j DROP
[root@ubuntu2404ser:~#] iptables -nL INPUT --line-numbers
Chain INPUT (policy ACCEPT)
num target prot opt source destination
1 DROP 0 -- 10.0.0.6 0.0.0.0/0
2 DROP 0 -- 10.0.0.6 0.0.0.0/0
3 DROP 0 -- 10.0.0.8 0.0.0.0/0
4 DROP 0 -- 10.0.0.9 0.0.0.0/0
5 DROP 0 -- 10.0.0.10 0.0.0.0/0
# 先让主机6 ping几个包
[root@rocky9-6 ~]# ping 10.0.0.7
PING 10.0.0.7 (10.0.0.7) 56(84) bytes of data.
# pkts列是接收几个数据包
[root@ubuntu2404ser:~#] iptables -nvL INPUT
Chain INPUT (policy ACCEPT 475 packets, 30877 bytes)
pkts bytes target prot opt in out source destination
7 588 DROP 0 -- * * 10.0.0.6 0.0.0.0/0
0 0 DROP 0 -- * * 10.0.0.6 0.0.0.0/0
0 0 DROP 0 -- * * 10.0.0.8 0.0.0.0/0
0 0 DROP 0 -- * * 10.0.0.9 0.0.0.0/0
0 0 DROP 0 -- * * 10.0.0.10 0.0.0.0/0
[root@ubuntu2404ser:~#]
# 2. 清除数据包条目
[root@ubuntu2404ser:~#] iptables -Z
[root@ubuntu2404ser:~#] iptables -nvL INPUT
Chain INPUT (policy ACCEPT 24 packets, 1886 bytes)
pkts bytes target prot opt in out source destination
0 0 DROP 0 -- * * 10.0.0.6 0.0.0.0/0
0 0 DROP 0 -- * * 10.0.0.6 0.0.0.0/0
0 0 DROP 0 -- * * 10.0.0.8 0.0.0.0/0
0 0 DROP 0 -- * * 10.0.0.9 0.0.0.0/0
0 0 DROP 0 -- * * 10.0.0.10 0.0.0.0/0
# 3. 全部删除
[root@ubuntu2404ser:~#] iptables -X #自定义规则删除
[root@ubuntu2404ser:~#] iptables -F
[root@ubuntu2404ser:~#] iptables -nvL INPUT
Chain INPUT (policy ACCEPT 75 packets, 5081 bytes)
pkts bytes target prot opt in out source destination
2.2.4、最终动作
2.2.4.1、丢弃规则
bash
# 创建丢弃规则
[root@ubuntu2404ser:~#] iptables -t filter -A INPUT -s 10.0.0.6 -j DROP
[root@ubuntu2404ser:~#] iptables -nvL
Chain INPUT (policy ACCEPT 26930 packets, 38M bytes)
pkts bytes target prot opt in out source destination
0 0 DROP 0 -- * * 10.0.0.6 0.0.0.0/0
Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
# 对网卡抓包
[root@ubuntu2404ser:~#] tcpdump -i ens33 -nn icmp
[root@rocky9-6 ~]# ping 10.0.0.7
PING 10.0.0.7 (10.0.0.7) 56(84) bytes of data.
# 观察tcpdump抓包 :可以观察到只有
[root@ubuntu2404ser:~#] tcpdump -i ens33 -nn icmp
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on ens33, link-type EN10MB (Ethernet), snapshot length 262144 bytes
02:42:38.965494 IP 10.0.0.6 > 10.0.0.7: ICMP echo request, id 6, seq 158, length 64
02:42:39.989736 IP 10.0.0.6 > 10.0.0.7: ICMP echo request, id 6, seq 159, length 64
02:42:41.014494 IP 10.0.0.6 > 10.0.0.7: ICMP echo request, id 6, seq 160, length 64
02:42:42.037691 IP 10.0.0.6 > 10.0.0.7: ICMP echo request, id 6, seq 161, length 64
02:42:43.062203 IP 10.0.0.6 > 10.0.0.7: ICMP echo request, id 6, seq 162, length 64
02:42:44.085509 IP 10.0.0.6 > 10.0.0.7: ICMP echo request, id 6, seq 163, length 64
2.2.4.2、拒绝规则
bash
[root@ubuntu2404ser:~#] iptables -F
[root@ubuntu2404ser:~#] iptables -t filter -A INPUT -s 10.0.0.6 -j REJECT
[root@ubuntu2404ser:~#] iptables -nvL INPUT
Chain INPUT (policy ACCEPT 27426 packets, 38M bytes)
pkts bytes target prot opt in out source destination
3 252 REJECT 0 -- * * 10.0.0.6 0.0.0.0/0 reject-with icmp-port-unreachable
# 主机6显示目标不可达
From 10.0.0.7 icmp_seq=376 Destination Port Unreachable
From 10.0.0.7 icmp_seq=377 Destination Port Unreachable
From 10.0.0.7 icmp_seq=378 Destination Port Unreachable
From 10.0.0.7 icmp_seq=379 Destination Port Unreachable
From 10.0.0.7 icmp_seq=380 Destination Port Unreachable
From 10.0.0.7 icmp_seq=381 Destination Port Unreachable
From 10.0.0.7 icmp_seq=382 Destination Port Unreachable
From 10.0.0.7 icmp_seq=383 Destination Port Unreachable
From 10.0.0.7 icmp_seq=384 Destination Port Unreachable
From 10.0.0.7 icmp_seq=385 Destination Port Unreachable
From 10.0.0.7 icmp_seq=386 Destination Port Unreachable
# 抓包看看
[root@ubuntu2404ser:~#] tcpdump -i ens33 -nn icmp
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on ens33, link-type EN10MB (Ethernet), snapshot length 262144 bytes
02:47:15.877527 IP 10.0.0.6 > 10.0.0.7: ICMP echo request, id 6, seq 429, length 64
02:47:15.877574 IP 10.0.0.7 > 10.0.0.6: ICMP 10.0.0.7 protocol 1 port 33799 unreachable, length 92
02:47:16.923639 IP 10.0.0.6 > 10.0.0.7: ICMP echo request, id 6, seq 430, length 64
02:47:16.923685 IP 10.0.0.7 > 10.0.0.6: ICMP 10.0.0.7 protocol 1 port 40596 unreachable, length 92
02:47:17.948277 IP 10.0.0.6 > 10.0.0.7: ICMP echo request, id 6, seq 431, length 64
02:47:17.948327 IP 10.0.0.7 > 10.0.0.6: ICMP 10.0.0.7 protocol 1 port 36403 unreachable, length 92
02:47:18.972590 IP 10.0.0.6 > 10.0.0.7: ICMP echo request, id 6, seq 432, length 64
# 0.7主机返回的都是icmp端口不可达的报文
2.2.4.3、允许规则
bash
# 创建三个规则
[root@ubuntu2404ser:~#] iptables -F
[root@ubuntu2404ser:~#] iptables -t filter -A INPUT -s 10.0.0.1 -j ACCEPT #允许0.1主机访问,windows本机
[root@ubuntu2404ser:~#] iptables -t filter -A INPUT -s 10.0.0.0/24 -j REJECT #拒绝10.0.0网段拒绝访问
[root@ubuntu2404ser:~#] iptables -t filter -A INPUT -s 10.0.0.6 -j ACCEPT #0.6主机允许访问呢
[root@ubuntu2404ser:~#] iptables -nvL INPUT
Chain INPUT (policy ACCEPT 27737 packets, 38M bytes)
pkts bytes target prot opt in out source destination
194 13041 ACCEPT 0 -- * * 10.0.0.1 0.0.0.0/0
23 1932 REJECT 0 -- * * 10.0.0.0/24 0.0.0.0/0 reject-with icmp-port-unreachable
0 0 ACCEPT 0 -- * * 10.0.0.6 0.0.0.0/0
# 无奖竞猜:10.0.0.6可以ping通10.0.0.7吗
C:\Users\XUEYUN>ping 10.0.0.7 # windows主机测试 可以访问
正在 Ping 10.0.0.7 具有 32 字节的数据:
来自 10.0.0.7 的回复: 字节=32 时间=1ms TTL=64
来自 10.0.0.7 的回复: 字节=32 时间=1ms TTL=64
10.0.0.7 的 Ping 统计信息:
数据包: 已发送 = 2,已接收 = 2,丢失 = 0 (0% 丢失),
往返行程的估计时间(以毫秒为单位):
最短 = 1ms,最长 = 1ms,平均 = 1ms
[root@rocky9-6 ~]# ping 10.0.0.7
PING 10.0.0.7 (10.0.0.7) 56(84) bytes of data.
From 10.0.0.7 icmp_seq=1 Destination Port Unreachable
From 10.0.0.7 icmp_seq=2 Destination Port Unreachable
# 为什么0.6主机访问失败呢,规则里有可以访问
答:规则匹配是从上而下的匹配,当0.6访问时匹配第二条,发现是10.0.0全段拒绝就不会向下匹配了,所有在创建规则是详细规则在最前面,模糊规则在后面
2.2.4.4、规则插入
bash
[root@ubuntu2404ser:~#] iptables -nvL INPUT --line-numbers
Chain INPUT (policy ACCEPT 27737 packets, 38M bytes)
num pkts bytes target prot opt in out source destination
1 240 15770 ACCEPT 0 -- * * 10.0.0.1 0.0.0.0/0
2 220 18480 REJECT 0 -- * * 10.0.0.0/24 0.0.0.0/0 reject-with icmp-port-unreachable
3 0 0 ACCEPT 0 -- * * 10.0.0.6 0.0.0.0/0
[root@ubuntu2404ser:~#] iptables -nvL INPUT --line-numbers
Chain INPUT (policy ACCEPT 27743 packets, 38M bytes)
num pkts bytes target prot opt in out source destination
1 383 24687 ACCEPT 0 -- * * 10.0.0.1 0.0.0.0/0
2 0 0 DROP 0 -- * * 10.0.0.11 0.0.0.0/0
3 220 18480 REJECT 0 -- * * 10.0.0.0/24 0.0.0.0/0 reject-with icmp-port-unreachable
4 0 0 ACCEPT 0 -- * * 10.0.0.6 0.0.0.0/0
2.2.4.5、黑白名单
bash
[root@ubuntu2404ser:~#] iptables -D INPUT 2
[root@ubuntu2404ser:~#] iptables -D INPUT 2
[root@ubuntu2404ser:~#] iptables -D INPUT 2
[root@ubuntu2404ser:~#] iptables -nvL INPUT --line-numbers
Chain INPUT (policy ACCEPT 27743 packets, 38M bytes)
num pkts bytes target prot opt in out source destination
1 493 31588 ACCEPT 0 -- * * 10.0.0.1 0.0.0.0/0
# 添加拒绝所有规则
[root@ubuntu2404ser:~#] iptables -t filter -A INPUT -j REJECT
[root@ubuntu2404ser:~#] iptables -nvL INPUT --line-numbers
Chain INPUT (policy ACCEPT 27743 packets, 38M bytes)
num pkts bytes target prot opt in out source destination
1 797 50650 ACCEPT 0 -- * * 10.0.0.1 0.0.0.0/0
2 0 0 REJECT 0 -- * * 0.0.0.0/0 0.0.0.0/0 reject-with icmp-port-unreachable
[root@ubuntu2404ser:~#]
# 访问本机失败
[root@ubuntu2404ser:~#] ping -c 1 127.0.0.1
PING 127.0.0.1 (127.0.0.1) 56(84) bytes of data.
^C
--- 127.0.0.1 ping statistics ---
1 packets transmitted, 0 received, 100% packet loss, time 2087ms
[root@ubuntu2404ser:~#] iptables -t filter -I INPUT -s 127.0.0.1 -j ACCEPT
[root@ubuntu2404ser:~#] iptables -nvL INPUT --line-numbers
Chain INPUT (policy ACCEPT 27743 packets, 38M bytes)
num pkts bytes target prot opt in out source destination
1 4 336 ACCEPT 0 -- * * 127.0.0.1 0.0.0.0/0
2 1170 74569 ACCEPT 0 -- * * 10.0.0.1 0.0.0.0/0
3 16 1512 REJECT 0 -- * * 0.0.0.0/0 0.0.0.0/0 reject-with icmp-port-unreachable
[root@ubuntu2404ser:~#] ping 127.0.0.1 -c 1
PING 127.0.0.1 (127.0.0.1) 56(84) bytes of data.
64 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=0.028 ms
--- 127.0.0.1 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.028/0.028/0.028/0.000 ms
# 精确匹配在前,模糊匹配在后
2.2.5、基础匹配
2.2.5.1、规则取反
bash
# 将不是10.0.0.1的源地址拒绝
[root@ubuntu2404ser:~#] iptables -t filter -A INPUT ! -s 10.0.0.1 -j REJECT
[root@ubuntu2404ser:~#] iptables -nvL INPUT --line-numbers
Chain INPUT (policy ACCEPT 27855 packets, 38M bytes)
num pkts bytes target prot opt in out source destination
1 0 0 REJECT 0 -- * * !10.0.0.1 0.0.0.0/0 reject-with icmp-port-unreachable
[root@rocky9-6 ~]# ping 10.0.0.7 -c 1
PING 10.0.0.7 (10.0.0.7) 56(84) bytes of data.
From 10.0.0.7 icmp_seq=1 Destination Port Unreachable
--- 10.0.0.7 ping statistics ---
1 packets transmitted, 0 received, +1 errors, 100% packet loss, time 0ms
2.2.5.2、目的地址匹配
bash
# 插入目的地址是0.7的允许访问,-I INPUT后面不加行号默认最前面插入
[root@ubuntu2404ser:~#] iptables -t filter -I INPUT -d 10.0.0.7 -j ACCEPT
[root@ubuntu2404ser:~#] iptables -nvL INPUT --line-numbers
Chain INPUT (policy ACCEPT 28581 packets, 38M bytes)
num pkts bytes target prot opt in out source destination
1 8 512 ACCEPT 0 -- * * 0.0.0.0/0 10.0.0.7
2 80 6768 REJECT 0 -- * * !10.0.0.1 0.0.0.0/0 reject-with icmp-port-unreachable
[root@rocky9-6 ~]# ping 10.0.0.7 -c 1
PING 10.0.0.7 (10.0.0.7) 56(84) bytes of data.
64 bytes from 10.0.0.7: icmp_seq=1 ttl=64 time=0.525 ms
--- 10.0.0.7 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.525/0.525/0.525/0.000 ms
2.2.5.3、协议匹配
bash
[root@ubuntu2404ser:~#] iptables -F
[root@ubuntu2404ser:~#] iptables -nvL INPUT --line-numbers
Chain INPUT (policy ACCEPT 28587 packets, 38M bytes)
num pkts bytes target prot opt in out source destination
# 拒绝源地址0.6的主机icmp协议
[root@ubuntu2404ser:~#] iptables -t filter -A INPUT -s 10.0.0.6 -p icmp -j REJECT
[root@ubuntu2404ser:~#] iptables -nvL INPUT --line-numbers
Chain INPUT (policy ACCEPT 39031 packets, 53M bytes)
num pkts bytes target prot opt in out source destination
1 0 0 REJECT 1 -- * * 10.0.0.6 0.0.0.0/0 reject-with icmp-port-unreachable
[root@rocky9-6 ~]# ping 10.0.0.7 -c 1
PING 10.0.0.7 (10.0.0.7) 56(84) bytes of data.
From 10.0.0.7 icmp_seq=1 Destination Port Unreachable
--- 10.0.0.7 ping statistics ---
1 packets transmitted, 0 received, +1 errors, 100% packet loss, time 0ms
# 其他协议不会与问题,如ssh
[root@rocky9-6 ~]# ssh root@10.0.0.7
The authenticity of host '10.0.0.7 (10.0.0.7)' can't be established.
ED25519 key fingerprint is SHA256:qfxGIdAzjwhotvmLYQbmSuHI11uN+3FXYzu/UNvbqUo.
This key is not known by any other names.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added '10.0.0.7' (ED25519) to the list of known hosts.
root@10.0.0.7's password:
2.2.6、扩展匹配
2.2.6.1、扩展基础
bash
# 查看扩展条目总数
[root@ubuntu2404ser:~#] dpkg -L iptables | grep libxt_.*.so | wc -l
79
[root@ubuntu2404ser:~#] dpkg -L iptables | grep libxt_.*.so | head
/usr/lib/x86_64-linux-gnu/xtables/libxt_AUDIT.so
/usr/lib/x86_64-linux-gnu/xtables/libxt_CHECKSUM.so
/usr/lib/x86_64-linux-gnu/xtables/libxt_CLASSIFY.so
/usr/lib/x86_64-linux-gnu/xtables/libxt_CONNMARK.so
/usr/lib/x86_64-linux-gnu/xtables/libxt_CONNSECMARK.so
/usr/lib/x86_64-linux-gnu/xtables/libxt_CT.so
/usr/lib/x86_64-linux-gnu/xtables/libxt_DSCP.so
/usr/lib/x86_64-linux-gnu/xtables/libxt_HMARK.so
/usr/lib/x86_64-linux-gnu/xtables/libxt_IDLETIMER.so
/usr/lib/x86_64-linux-gnu/xtables/libxt_LED.so
2.2.6.2、显示扩展和隐示扩展
概念说明
- 隐式扩展(implicit match) :指定
-p 协议自动加载对应模块,不用写-m xxx- 显式扩展(explicit match) :必须手动写
-m 模块名才加载
| 类型 | 模块名称 | 触发方式 | 核心参数 | 简要说明 |
|---|---|---|---|---|
| 隐式扩展 | tcp | -p tcp |
--dport、--sport、--tcp-flags、--syn |
TCP 协议专用匹配 |
| 隐式扩展 | udp | -p udp |
--dport、--sport |
UDP 协议专用匹配 |
| 隐式扩展 | icmp | -p icmp |
--icmp-type |
ICMP 类型匹配(ping) |
| 隐式扩展 | icmpv6 | -p icmpv6 |
--icmpv6-type |
IPv6 ICMP,ipv6tables |
| 隐式扩展 | sctp | -p sctp |
--dport、--sport |
SCTP 协议端口 |
| 隐式扩展 | dccp | -p dccp |
--dport、--sport |
DCCP 协议端口 |
| 隐式扩展 | ah | -p ah |
--spi |
IPsec AH 安全参数索引 |
| 隐式扩展 | esp | -p esp |
--spi |
IPsec ESP 安全参数索引 |
| 显式扩展 | conntrack | -m conntrack |
--ctstate |
连接状态 NEW/ESTABLISHED/RELATED/INVALID,推荐替代 state |
| 显式扩展 | state | -m state |
--state |
旧版连接状态模块,conntrack 子集,不推荐新部署 |
| 显式扩展 | multiport | -m multiport |
--dports / --sports |
多离散端口一次性匹配 |
| 显式扩展 | iprange | -m iprange |
--src-range / --dst-range |
连续 IP 区间(非 CIDR 网段) |
| 显式扩展 | mac | -m mac |
--mac-source |
源 MAC 地址匹配,仅限同二层 |
| 显式扩展 | recent | -m recent |
--set/--update/--hitcount |
IP 访问计数、防暴力破解 |
| 显式扩展 | limit | -m limit |
--limit、--limit-burst |
令牌桶速率匹配 |
| 显式扩展 | time | -m time |
--timestart、--weekdays |
按时间匹配包 |
| 显式扩展 | string | -m string |
--algo、--string |
报文载荷字符串匹配 |
| 显式扩展 | mark | -m mark |
--mark |
匹配 fwmark 标记 |
| 显式扩展 | owner | -m owner |
--uid-owner、--gid-owner |
本机进程 UID/GID,仅 OUTPUT 链 |
| 显式扩展 | length | -m length |
--length |
IP 报文长度匹配 |
| 显式扩展 | ttl | -m ttl |
--ttl-eq/gt/lt |
IP 头部 TTL 值匹配 |
| 显式扩展 | pkttype | -m pkttype |
--pkt-type |
广播 / 组播 / 单播报文类型 |
2.2.6.3、tcp 议扩展解读
| 参数 | 别名 | 含义 | 写法示例 |
|---|---|---|---|
--dport |
--destination-port |
匹配 TCP目的端口 | --dport 22 --dport 1000:2000 --dport 1000:(1000~65535) |
--sport |
--source-port |
匹配 TCP源端口 | --sport :1024(0~1024) |
--tcp-flags mask comp |
- | TCP 标志位匹配mask:要检查哪些标志comp:必须置 1的标志 | --tcp-flags SYN,ACK,FIN,RST SYN |
--syn |
- | 简写,等价:--tcp-flags SYN,RST,ACK SYN |
匹配TCP 新建连接的 SYN 包(第一次握手包) |
--tcp-option |
- | 匹配 TCP 选项字段编号 | --tcp-option 8 匹配 MSS 选项 |
bash
[root@ubuntu2404ser:~#] iptables -t filter -A INPUT -s 10.0.0.8 -p tcp --dport 21:23 -j REJECT
[root@ubuntu2404ser:~#] iptables -nvL INPUT --line-numbers
Chain INPUT (policy ACCEPT 610K packets, 869M bytes)
num pkts bytes target prot opt in out source destination
1 1 84 REJECT 1 -- * * 10.0.0.6 0.0.0.0/0 reject-with icmp-port-unreachable
2 0 0 REJECT 6 -- * * 10.0.0.8 0.0.0.0/0 tcp dpts:21:23 reject-with icmp-port-unreachable
[root@rocky10-8 ~]# hostname -i
10.0.0.8
[root@rocky10-8 ~]# ssh root@10.0.0.7
ssh: connect to host 10.0.0.7 port 22: Connection refused
2.2.6.4、多端口与多IP匹配
| 参数 | 简写 | 含义 |
|---|---|---|
--destination-ports |
--dports |
匹配目的端口(最常用) |
--source-ports |
--sports |
匹配源端口 |
--ports |
- | 源端口 或 目的端口匹配列表端口(很少用) |
bash
# 1. 多端口
[root@ubuntu2404ser:~#] iptables -F
[root@ubuntu2404ser:~#] iptables -t filter -A INPUT -s 10.0.0.6 -p tcp -m multiport --dports 22,80,443 -j REJECT
[root@ubuntu2404ser:~#] iptables -nvL INPUT
Chain INPUT (policy ACCEPT 737K packets, 1050M bytes)
pkts bytes target prot opt in out source destination
0 0 REJECT 6 -- * * 10.0.0.6 0.0.0.0/0 multiport dports 22,80,443 reject-with icmp-port-unreachable
| 参数 | 含义 |
|---|---|
--src-range |
匹配源 IP范围 |
--dst-range |
匹配目的 IP范围 |
bash
# 2. 多IP
[root@ubuntu2404ser:~#] apt install nginx
[root@ubuntu2404ser:~#] iptables -A INPUT -m iprange --src-range 10.0.0.6-10.0.0.8 -p tcp --dport 80 -j REJECT
[root@ubuntu2404ser:~#] iptables -nvL INPUT
Chain INPUT (policy ACCEPT 737K packets, 1050M bytes)
pkts bytes target prot opt in out source destination
0 0 REJECT 6 -- * * 10.0.0.6 0.0.0.0/0 multiport dports 22,80,443 reject-with icmp-port-unreachable
0 0 REJECT 6 -- * * 0.0.0.0/0 0.0.0.0/0 source IP range 10.0.0.6-10.0.0.8 tcp dpt:80 reject-with icmp-port-unreachable
[root@rocky10-8 ~]# curl 10.0.0.7
curl: (7) Failed to connect to 10.0.0.7 port 80 after 0 ms: Could not connect to server
2.3、SNAT转换
2.3.1、前提准备

给0.7新增一个仅主机网卡

bash
# --0.8主机准备
[root@rocky10-8 ~]# dnf install nginx
[root@rocky10-8 ~]# systemctl restart nginx.service
[root@rocky10-8 ~]# systemctl status nginx.service
[root@rocky10-8 ~]# cd /usr/share/nginx/html
[root@rocky10-8 html]# ls
icons index.html nginx-logo.png poweredby.png system_noindex_logo.png
[root@rocky10-8 ~]# echo "rocky10 192.168.8.8" > /usr/share/nginx/html/index.html
[root@rocky10-8 html]# nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
[root@rocky10-8 html]# systemctl reload nginx.service
[root@rocky10-8 html]# curl localhost
rocky10 192.168.8.8
# 网卡改为仅主机

bash
# --0.7主机准备
[root@ubuntu24-7:~#] 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 noprefixroute
valid_lft forever preferred_lft forever
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UNKNOWN group default qlen 1000
link/ether 00:0c:29:70:b8:54 brd ff:ff:ff:ff:ff:ff
altname enp2s1
inet 10.0.0.7/24 brd 10.0.0.255 scope global ens33
valid_lft forever preferred_lft forever
inet6 fe80::20c:29ff:fe70:b854/64 scope link
valid_lft forever preferred_lft forever
3: ens37: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN group default qlen 1000
link/ether 00:0c:29:70:b8:5e brd ff:ff:ff:ff:ff:ff
altname enp2s5
[root@ubuntu24-7:~#] cd /etc/netplan/
[root@ubuntu24-7:/etc/netplan#] ls
50-cloud-init.yaml
[root@ubuntu24-7:/etc/netplan#] vim 50-cloud-init.yaml
[root@ubuntu24-7:/etc/netplan#] cat 50-cloud-init.yaml
network:
version: 2
ethernets:
ens33:
addresses:
- "10.0.0.7/24"
nameservers:
addresses:
- 223.5.5.5
- 223.6.6.6
search: []
routes:
- to: "default"
via: "10.0.0.2"
ens37:
addresses:
- "192.168.8.7/24"
[root@ubuntu24-7:/etc/netplan#] netplan apply
[root@ubuntu24-7:/etc/netplan#] 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 noprefixroute
valid_lft forever preferred_lft forever
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UNKNOWN group default qlen 1000
link/ether 00:0c:29:70:b8:54 brd ff:ff:ff:ff:ff:ff
altname enp2s1
inet 10.0.0.7/24 brd 10.0.0.255 scope global ens33
valid_lft forever preferred_lft forever
inet6 fe80::20c:29ff:fe70:b854/64 scope link
valid_lft forever preferred_lft forever
3: ens37: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UNKNOWN group default qlen 1000
link/ether 00:0c:29:70:b8:5e brd ff:ff:ff:ff:ff:ff
altname enp2s5
inet 192.168.8.7/24 brd 192.168.8.255 scope global ens37
valid_lft forever preferred_lft forever
inet6 fe80::20c:29ff:fe70:b85e/64 scope link
valid_lft forever preferred_lft forever
[root@ubuntu24-7:~#] sysctl -w "net.ipv4.ip_forward=1"
net.ipv4.ip_forward = 1
bash
# --0.6主机准备
[root@rocky9-6 ~]# hostname -i
10.0.0.6
[root@rocky9-6 ~]# ip route del default
[root@rocky9-6 ~]# ip route add default via 10.0.0.7
[root@rocky9-6 ~]# ip route list
default via 10.0.0.7 dev ens160
10.0.0.0/24 dev ens160 proto kernel scope link src 10.0.0.6 metric 100

2.3.2、SNAT原理与配置
bash
SNAT:Source Network Address Translation 源地址转换
链:nat 表 → POSTROUTING(重点!)
作用:修改数据包的源 IP,用于内网主机访问外网,把内网私网 IP 替换成网关公网 IP。
属于 target 动作,不是匹配扩展模块。
iptables -t nat -A POSTROUTING -s 源网段 -o 出口网卡 -j SNAT --to-source 转换后的IP
2.3.3、SNAT基础配置
bash
# 创建源地址是10.0.0网段的,目的地址不是10.0.0网段的,SNAT转换为192.168.8.7
[root@ubuntu24-7:~#] iptables -t nat -A POSTROUTING -s 10.0.0.0/24 ! -d 10.0.0.0/24 -j SNAT --to-source 192.168.8.7
[root@ubuntu24-7:~#] iptables -t nat -nvL POSTROUTING --line-numbers
Chain POSTROUTING (policy ACCEPT 1 packets, 76 bytes)
num pkts bytes target prot opt in out source destination
1 0 0 SNAT 0 -- * * 10.0.0.0/24 !10.0.0.0/24 to:192.168.8.7
----------
# 测试
[root@rocky10-8 ~]# tcpdump -nn icmp
dropped privs to tcpdump
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on ens160, link-type EN10MB (Ethernet), snapshot length 262144 bytes
[root@rocky9-6 ~]# ping 192.168.8.8 -c 1
PING 192.168.8.8 (192.168.8.8) 56(84) bytes of data.
64 bytes from 192.168.8.8: icmp_seq=1 ttl=63 time=1.25 ms
--- 192.168.8.8 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 1.245/1.245/1.245/0.000 ms
[root@rocky10-8 ~]# tcpdump -nn icmp
dropped privs to tcpdump
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on ens160, link-type EN10MB (Ethernet), snapshot length 262144 bytes
15:15:47.822094 IP 192.168.8.7 > 192.168.8.8: ICMP echo request, id 18, seq 1, length 64
15:15:47.822135 IP 192.168.8.8 > 192.168.8.7: ICMP echo reply, id 18, seq 1, length 64
# 关于观察到是8.7和8.8在互相访问
[root@rocky9-6 ~]# curl 192.168.8.8
rocky10 192.168.8.8
2.3.4、多地址转换
bash
# 修改
[root@ubuntu24-7:~#] iptables -t nat -R POSTROUTING 1 -s 10.0.0.0/24 ! -d 10.0.0.0/24 -o ens37 -j SNAT --to-source 192.168.8.123-192.168.8.244
[root@ubuntu24-7:~#] iptables -t nat -vnL POSTROUTING
Chain POSTROUTING (policy ACCEPT 3 packets, 217 bytes)
pkts bytes target prot opt in out source destination
0 0 SNAT 0 -- * ens37 10.0.0.0/24 !10.0.0.0/24 to:192.168.8.123-192.168.8.244
[root@rocky9-6 ~]# curl 192.168.8.8
#没有返回信息阻塞中
[root@rocky10-8 ~]# tcpdump -nn 'tcp port 80'
dropped privs to tcpdump
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on ens160, link-type EN10MB (Ethernet), snapshot length 262144 bytes
15:26:54.231344 IP 192.168.8.211.42756 > 192.168.8.8.80: Flags [S], seq 2781043554, win 64240, options [mss 1460,sackOK,TS val 1971705369 ecr 0,nop,wscale 7], length 0
15:26:55.278381 IP 192.168.8.211.42756 > 192.168.8.8.80: Flags [S], seq 2781043554, win 64240, options [mss 1460,sackOK,TS val 1971706416 ecr 0,nop,wscale 7], length 0
2.3.4、多端口转换
bash
[root@ubuntu24-7:~#] iptables -t nat -R POSTROUTING 1 -s 10.0.0.0/24 ! -d 10.0.0.0/24 -o ens37 -p tcp --dport 80 -j SNAT --to-source 192.168.8.7:12345
[root@ubuntu24-7:~#] iptables -t nat -vnL POSTROUTING
Chain POSTROUTING (policy ACCEPT 6 packets, 445 bytes)
pkts bytes target prot opt in out source destination
0 0 SNAT 6 -- * ens37 10.0.0.0/24 !10.0.0.0/24 tcp dpt:80 to:192.168.8.7:12345
[root@ubuntu24-7:~#]
[root@rocky9-6 ~]# curl 192.168.8.8
rocky10 192.168.8.8
[root@rocky10-8 ~]# tcpdump -nn 'tcp port 80'
dropped privs to tcpdump
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on ens160, link-type EN10MB (Ethernet), snapshot length 262144 bytes
15:32:18.658821 IP 192.168.8.7.12345 > 192.168.8.8.80: Flags [S], seq 1346938351, win 64240, options [mss 1460,sackOK,TS val 1972029797 ecr 0,nop,wscale 7], length 0
15:32:18.658869 IP 192.168.8.8.80 > 192.168.8.7.12345: Flags [S.], seq 1588357966, ack 1346938352, win 65160, options [mss 1460,sackOK,TS val 1333005092 ecr 1972029797,nop,wscale 7], length 0
15:32:18.660345 IP 192.168.8.7.12345 > 192.168.8.8.80: Flags [.], ack 1, win 502, options [nop,nop,TS val 1972029798 ecr 1333005092], length 0
# 可以观察到请求报文端口是12345
2.3.5、协议转换
bash
[root@ubuntu24-7:~#] iptables -t nat -R POSTROUTING 1 -s 10.0.0.0/24 ! -d 10.0.0.0/24 -o ens37 -p icmp -j SNAT --to-source 192.168.8.7:32768
[root@ubuntu24-7:~#] iptables -t nat -vnL POSTROUTING
Chain POSTROUTING (policy ACCEPT 6 packets, 445 bytes)
pkts bytes target prot opt in out source destination
0 0 SNAT 1 -- * ens37 10.0.0.0/24 !10.0.0.0/24 to:192.168.8.7:32768
[root@rocky9-6 ~]# ping 192.168.8.8 -c 1
PING 192.168.8.8 (192.168.8.8) 56(84) bytes of data.
64 bytes from 192.168.8.8: icmp_seq=1 ttl=63 time=1.25 ms
--- 192.168.8.8 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 1.246/1.246/1.246/0.000 ms
[root@rocky10-8 ~]# tcpdump -nn icmp
dropped privs to tcpdump
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on ens160, link-type EN10MB (Ethernet), snapshot length 262144 bytes
15:34:30.396849 IP 192.168.8.7 > 192.168.8.8: ICMP echo request, id 32768, seq 1, length 64
15:34:30.396887 IP 192.168.8.8 > 192.168.8.7: ICMP echo reply, id 32768, seq 1, length 64
2.3.6、MASQUERADE
MASQUERADE 属于 nat 表 POSTROUTING 的 Target,是动态版本的 SNAT,不需要指定IP地址
iptables -t nat -A POSTROUTING -s 内网网段 -o 出口网卡 -j MASQUERADE
bash
[root@ubuntu24-7:~#] iptables -t nat -R POSTROUTING 1 -s 10.0.0.0/24 ! -d 10.0.0.0/24 -j MASQUERADE
[root@ubuntu24-7:~#] iptables -t nat -vnL POSTROUTING
Chain POSTROUTING (policy ACCEPT 8 packets, 597 bytes)
pkts bytes target prot opt in out source destination
0 0 MASQUERADE 0 -- * * 10.0.0.0/24 !10.0.0.0/24
[root@rocky9-6 ~]# ping 192.168.8.8 -c 1
PING 192.168.8.8 (192.168.8.8) 56(84) bytes of data.
64 bytes from 192.168.8.8: icmp_seq=1 ttl=63 time=1.05 ms
[root@rocky10-8 ~]# tcpdump -nn icmp
dropped privs to tcpdump
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on ens160, link-type EN10MB (Ethernet), snapshot length 262144 bytes
15:40:23.797831 IP 192.168.8.7 > 192.168.8.8: ICMP echo request, id 20, seq 1, length 64
15:40:23.797867 IP 192.168.8.8 > 192.168.8.7: ICMP echo reply, id 20, seq 1, length 64
2.4、DNAT转换
2.4.1、前提准备
bash
[root@rocky9-6 ~]# ip route del default
[root@rocky9-6 ~]# ip route list
10.0.0.0/24 dev ens160 proto kernel scope link src 10.0.0.6 metric 100
[root@rocky10-8 ~]# ip route add default via 192.168.8.7
[root@rocky10-8 ~]# ip route list
default via 192.168.8.7 dev ens160
192.168.8.0/24 dev ens160 proto kernel scope link src 192.168.8.8 metric 100
[root@ubuntu24-7:~#] netstat -tnlp | grep 80
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 1340/nginx: master
tcp6 0 0 :::80 :::* LISTEN 1340/nginx: master
[root@ubuntu24-7:~#] systemctl disable --now nginx.service
Synchronizing state of nginx.service with SysV service script with /usr/lib/systemd/systemd-sysv-install.
Executing: /usr/lib/systemd/systemd-sysv-install disable nginx
Removed "/etc/systemd/system/multi-user.target.wants/nginx.service".
[root@ubuntu24-7:~#] netstat -tnlp | grep 80
2.4.1、DNAT配置
bash
[root@ubuntu24-7:~#] iptables -t nat -A PREROUTING -d 10.0.0.7 -p tcp --dport 80 -j DNAT --to-destination 192.168.8.8:80
[root@ubuntu24-7:~#] iptables -t nat -A PREROUTING -d 10.0.0.7 -p tcp --dport 8080 -j DNAT --to-destination 192.168.8.8:80
[root@ubuntu24-7:~#] iptables -t nat -nvL PREROUTING --line-numbers
Chain PREROUTING (policy ACCEPT 0 packets, 0 bytes)
num pkts bytes target prot opt in out source destination
1 0 0 DNAT 6 -- * * 0.0.0.0/0 10.0.0.7 tcp dpt:80 to:192.168.8.8:80
2 0 0 DNAT 6 -- * * 0.0.0.0/0 10.0.0.7 tcp dpt:8080 to:192.168.8.8:80
[root@rocky9-6 ~]# curl 10.0.0.7:8080
rocky10 192.168.8.8
[root@rocky9-6 ~]# curl 10.0.0.7:80
rocky10 192.168.8.8
[root@rocky10-8 ~]# tcpdump -nn 'tcp port 80'
dropped privs to tcpdump
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on ens160, link-type EN10MB (Ethernet), snapshot length 262144 bytes
15:52:49.156373 IP 192.168.8.7.40624 > 192.168.8.8.80: Flags [S], seq 1518178487, win 64240, options [mss 1460,sackOK,TS val 3835494592 ecr 0,nop,wscale 7], length 0
15:52:49.156413 IP 192.168.8.8.80 > 192.168.8.7.40624: Flags [S.], seq 1348421734, ack 1518178488, win 65160, options [mss 1460,sackOK,TS val 1334235590 ecr 3835494592,nop,wscale 7], length 0
15:52:49.157966 IP 192.168.8.7.40624 > 192.168.8.8.80: Flags [.], ack 1, win 502, options [nop,nop,TS val 3835494593 ecr 1334235590], length 0
2.4.3、多目标操作
bash
[root@rocky10-8 ~]# vim /etc/nginx/nginx.conf
[root@rocky10-8 ~]# grep -Ev '^$|#' /etc/nginx/nginx.conf | grep -A 6 'server {'
server {
listen 81;
listen [::]:80;
server_name _;
root /usr/share/nginx/html;
}
server {
listen 80;
listen [::]:80;
server_name _;
root /usr/share/nginx/html;
include /etc/nginx/default.d/*.conf;
}
[root@rocky10-8 ~]# nginx -t
nginx: [warn] conflicting server name "_" on [::]:80, ignored
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
[root@rocky10-8 ~]# systemctl reload nginx.service
[root@rocky10-8 ~]# netstat -tnlp | grep nginx
tcp 0 0 0.0.0.0:81 0.0.0.0:* LISTEN 3268/nginx: master
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 3268/nginx: master
[root@ubuntu24-7:~#] iptables -t nat -A PREROUTING -d 10.0.0.7 -p tcp --dport 81 -j DNAT --to-destination 192.168.8.8:81
[root@ubuntu24-7:~#] iptables -t nat -nvL PREROUTING --line-numbers Chain PREROUTING (policy ACCEPT 5 packets, 674 bytes)
num pkts bytes target prot opt in out source destination
1 1 60 DNAT 6 -- * * 0.0.0.0/0 10.0.0.7 tcp dpt:80 to:192.168.8.8:80
2 1 60 DNAT 6 -- * * 0.0.0.0/0 10.0.0.7 tcp dpt:8080 to:192.168.8.8:80
3 0 0 DNAT 6 -- * * 0.0.0.0/0 10.0.0.7 tcp dpt:81 to:192.168.8.8:81
[root@rocky9-6 ~]# curl 10.0.0.7:81
rocky10 192.168.8.8
2.5、nftables /nft 快速入门
nftables 是 iptables 的下一代,Linux 内核 3.13+ 引入;Ubuntu20.04+/Rocky8+ 默认支持,用来替代 iptables、ip6tables、arptables、ebtables 。 命令行工具:
nft
2.5.1、核心概念(和 iptables 对比理解)
iptables:表 → 链 → 规则,内置固定表 (filter/nat/mangle/raw),内置固定链
nftables:表 (table) → 链 (chain) → 规则 (rule)
链的 type + hook + priority(nft 最核心)
链必须指定:
type:filter/nat/routehook:挂载在内核网络栈哪个点(对应 iptables 的链)priority:优先级(数字,越小越早执行)
| nft hook | 等价 iptables 链 |
|---|---|
prerouting |
PREROUTING |
input |
INPUT |
forward |
FORWARD |
output |
OUTPUT |
postrouting |
POSTROUTING |
2.5.2、基础命令
bash
nft 动作 chain <家族> <表名> <链名> <{ 规则细节 }>
常见动作:
list 查看
add 创建
delete 删除
flush 清空
bash
# 1. 查看
[root@ubuntu24-7:~#] nft list ruleset
# Warning: table ip nat is managed by iptables-nft, do not touch!
table ip nat {
chain POSTROUTING {
type nat hook postrouting priority srcnat; policy accept;
ip saddr 10.0.0.0/24 ip daddr != 10.0.0.0/24 counter packets 12 bytes 862 masquerade
}
chain PREROUTING {
type nat hook prerouting priority dstnat; policy accept;
ip daddr 10.0.0.7 tcp dport 80 counter packets 1 bytes 60 dnat to 192.168.8.8:80
ip daddr 10.0.0.7 tcp dport 8080 counter packets 1 bytes 60 dnat to 192.168.8.8:80
ip daddr 10.0.0.7 tcp dport 81 counter packets 1 bytes 60 dnat to 192.168.8.8:81
}
}
# 2. 创建表
[root@ubuntu24-7:~#] nft list ruleset
[root@ubuntu24-7:~#] nft add table inet myfw
[root@ubuntu24-7:~#] nft list ruleset
table inet myfw {
}
[root@ubuntu24-7:~#] nft list table inet myfw
table inet myfw {
}
# 3. 删除表
[root@ubuntu24-7:~#] nft delete table inet myfw
[root@ubuntu24-7:~#] nft list ruleset
# 4. 创建链
[root@ubuntu24-7:~#] nft list ruleset
[root@ubuntu24-7:~#] nft add table inet myfw
# 创建链
[root@ubuntu24-7:~#] nft add chain inet myfw hehe { type filter hook input priority 0 \; policy accept \; }
[root@ubuntu24-7:~#] nft list ruleset
table inet myfw {
chain hehe {
type filter hook input priority filter; policy accept;
}
}
[root@ubuntu24-7:~#]
# 5. 清空与删除链
# 清空
[root@ubuntu24-7:~#] nft flush chain inet myfw hehe
[root@ubuntu24-7:~#] nft list chain inet myfw hehe
table inet myfw {
chain hehe {
type filter hook input priority filter; policy accept;
}
}
# 删除
[root@ubuntu24-7:~#] nft delete chain inet myfw hehe
[root@ubuntu24-7:~#] nft list ruleset
table inet myfw {
}
2.5.3、添加规则
bash
# 创建表
[root@ubuntu24-7:~#] nft add table inet myfw
# 创建链
[root@ubuntu24-7:~#] nft add chain inet myfw input '{ type filter hook input priority 0; policy accept; }'
# 创建规则
[root@ubuntu24-7:~#] nft add rule inet myfw input ip saddr 10.0.0.6 drop
# 查看规则
[root@ubuntu24-7:~#] nft list chain inet myfw input
table inet myfw {
chain input {
type filter hook input priority filter; policy accept;
ip saddr 10.0.0.6 drop
}
}
# 查看规则显示行号,行号是递增的
[root@ubuntu24-7:~#] nft -a list chain inet myfw input
table inet myfw {
chain input { # handle 2
type filter hook input priority filter; policy accept;
ip saddr 10.0.0.6 drop # handle 3
}
}
[root@ubuntu24-7:~#] nft add rule inet myfw input tcp dport 22 accept
[root@ubuntu24-7:~#] nft -a list chain inet myfw input
table inet myfw {
chain input { # handle 2
type filter hook input priority filter; policy accept;
ip saddr 10.0.0.6 drop # handle 3
tcp dport 22 accept # handle 4
}
}
2.5.4、删除规则
bash
# 不能像iptables一样删除
[root@ubuntu24-7:~#] nft delete rule inet myfw input '{ ip saddr 10.0.0.6 drop }'
Error: syntax error, unexpected '{', expecting handle
delete rule inet myfw input { ip saddr 10.0.0.6 drop }
# 需要按照行号删除
[root@ubuntu24-7:~#] nft delete rule inet myfw input handle 3
[root@ubuntu24-7:~#] nft -a list chain inet myfw input
table inet myfw {
chain input { # handle 2
type filter hook input priority filter; policy accept;
tcp dport 22 accept # handle 4
}
}
2.5.5、插入规则
bash
# insert插入 默认第一行,行号与位置有没有相关
[root@ubuntu24-7:~#] nft insert rule inet myfw input ip saddr 10.0.0.6 drop
[root@ubuntu24-7:~#] nft -a list chain inet myfw input
table inet myfw {
chain input { # handle 2
type filter hook input priority filter; policy accept;
ip saddr 10.0.0.6 drop # handle 5
tcp dport 22 accept # handle 4
}
}
# 指定行插入
[root@ubuntu24-7:~#] nft insert rule inet myfw input position 5 tcp dport 6633 accept
[root@ubuntu24-7:~#] nft -a list chain inet myfw input
table inet myfw {
chain input { # handle 2
type filter hook input priority filter; policy accept;
tcp dport 6633 accept # handle 6
ip saddr 10.0.0.6 drop # handle 5
tcp dport 22 accept # handle 4
}
}
[root@ubuntu24-7:~#]
2.5.6、替换规则
bash
[root@ubuntu24-7:~#] nft replace rule inet myfw input handle 6 ip saddr 10.0.0.100 drop
[root@ubuntu24-7:~#] nft -a list chain inet myfw input
table inet myfw {
chain input { # handle 2
type filter hook input priority filter; policy accept;
ip saddr 10.0.0.100 drop # handle 6
ip saddr 10.0.0.6 drop # handle 5
tcp dport 22 accept # handle 4
}
}
[root@ubuntu24-7:~#]
2.5.7、清空规则
bash
[root@ubuntu24-7:~#] nft flush chain inet myfw input
[root@ubuntu24-7:~#] nft -a list chain inet myfw input
table inet myfw {
chain input { # handle 2
type filter hook input priority filter; policy accept;
}
}
三、服务安全加固
3.1、常见服务端口
| 服务 | 默认端口 | 风险等级 | 风险简述 | 推荐访问策略 |
|---|---|---|---|---|
| SSH | 22/TCP | 🟥 高危 | 远程服务器管理入口;暴力密码爆破、密钥泄露、漏洞提权,拿下即服务器权限 | ✅ 禁止公网直接开放;公网访问走跳板机 / 堡垒机 / VPN;内网做 IP 白名单;禁用密码登录,仅密钥;改非默认端口只是防扫描,不是安全手段 |
| Telnet | 23/TCP | 🟥 极高危 | 明文传输!账号密码裸跑,中间人直接抓包拿密码;无加密,早已淘汰 | ❌ 生产环境禁止使用,全部替换 SSH;仅隔离内网调试临时用,绝对不能上公网 |
| Nginx | 80(TCP) / 443(TCP) | 🟧 中危 | 80:HTTP 明文;443:HTTPS 加密;风险不在端口本身,在于后端 Web 代码、路径穿越、注入、Web 漏洞、CC/DDoS | ✅ 80/443 是业务端口,可对公网;80 强制跳转 443;WAF 防护、限制速率、关闭不必要 HTTP 方法;及时更新 nginx 版本 |
| MySQL | 3306/TCP | 🟥 高危 | 数据库端口;弱口令爆破、未授权访问、注入、拖库、写入 shell;拿到库后业务数据全部泄露 | ✅ 禁止公网开放;仅内网 / 应用服务器访问,IP 白名单;禁止 root 远程;开启 SSL 加密连接;复杂密码 |
| Redis | 6379/TCP | 🟥 高危 | 经典高危端口!很多默认无密码;可写入 ssh 密钥、写 crontab 反弹 shell、写 webshell 直接拿下服务器 | ✅ 禁止公网开放;内网 IP 白名单;设置密码;禁止危险命令(CONFIG、FLUSHALL 等);尽量不绑定 0.0.0.0,绑定 127.0.0.1 |
3.2、环境准备
bash
[root@ubuntu24-19:~#] cat onekey_install_ruoyi_ubuntu24.sh
#!/bin/bash
# *************************************
# * 功能: Shell一键部署单机版Ruoyi-vue
# * 作者: 马哥教育王老师
# * 版本: xxxx-xx-xx
# *************************************
# set -euo pipefail
# ====================== 全局自定义变量 ======================
MYSQL_ROOT_PWD="Root@2026"
RUOYI_DB="ry_vue"
RUOYI_USER="ruoyi"
RUOYI_PWD="Ruoyi@123"
REDIS_PWD="Redis@2026"
APP_PORT=8080
WEB_DOMAIN="ruoyi.magedu.com"
BASE_DIR="/data/ruoyi"
SOURCE_DIR="/root/RuoYi-Vue"
RUOYI_SERVICE="/etc/systemd/system/ruoyi-admin.service"
# ===========================================================
# 日志打印函数
log_info() {
echo -e "\033[32m===== $1 =====\033[0m"
}
# 1. 系统更新 & 基础工具安装
func_sys_init() {
log_info "系统更新并安装基础工具 git curl"
apt update -y
apt install -y git curl
}
# 2. 安装 JDK17 并配置全局 JAVA_HOME
func_install_jdk() {
log_info "安装 JDK17"
apt install openjdk-17-jdk -y
echo "export JAVA_HOME=/usr/lib/jvm/java-17-openjdk-amd64" >> /etc/profile
echo "export PATH=\$JAVA_HOME/bin:\$PATH" >> /etc/profile
source /etc/profile
}
# 3. Maven 安装 + 阿里镜像加速
func_install_maven() {
log_info "安装 Maven 并配置阿里云镜像"
apt install maven -y
mkdir -p /root/.m2
cat > /root/.m2/settings.xml <<EOF
<?xml version="1.0" encoding="UTF-8"?>
<settings>
<mirrors>
<mirror>
<id>aliyun</id>
<mirrorOf>central</mirrorOf>
<url>https://maven.aliyun.com/repository/public</url>
</mirror>
</mirrors>
</settings>
EOF
}
# 4. Node20 + npm 淘宝源
func_install_node() {
log_info "安装 Node20 前端打包环境"
curl -fsSL https://deb.nodesource.com/setup_20.x | bash -
apt install nodejs -y
npm config set registry https://registry.npmmirror.com
}
# 5. Nginx 安装,清理默认站点
func_install_nginx() {
log_info "安装 Nginx"
apt install nginx -y
systemctl enable --now nginx
rm -f /etc/nginx/sites-enabled/default
mkdir -p /etc/nginx/conf.d
}
# 6. Redis 单机本地仅127.0.0.1访问
func_install_redis() {
log_info "安装并配置本地 Redis"
apt install redis-server -y
sed -i 's/^bind .*/bind 127.0.0.1/' /etc/redis/redis.conf
sed -i '/^requirepass /d' /etc/redis/redis.conf
sed -i '/# requirepass/a\requirepass "'${REDIS_PWD}'"' /etc/redis/redis.conf
sed -i 's/^protected-mode .*/protected-mode yes/' /etc/redis/redis.conf
systemctl restart redis-server
}
# 7. MySQL8 单机安装 + root初始化
func_install_mysql() {
log_info "安装 MySQL8 单机服务"
apt install mysql-server -y
systemctl enable --now mysql
mysql -e "ALTER USER 'root'@'localhost' IDENTIFIED BY '${MYSQL_ROOT_PWD}';FLUSH PRIVILEGES;"
}
# 8. 创建若依数据库、业务账号
func_init_mysql_db() {
log_info "初始化若依数据库与业务账号"
mysql -uroot -p${MYSQL_ROOT_PWD} -e "
CREATE DATABASE IF NOT EXISTS ${RUOYI_DB} DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER IF NOT EXISTS '${RUOYI_USER}'@'localhost' IDENTIFIED BY '${RUOYI_PWD}';
GRANT ALL ON ${RUOYI_DB}.* TO '${RUOYI_USER}'@'localhost';
FLUSH PRIVILEGES;" 2>/dev/null
}
# 9. 拉取源码 & 导入初始化SQL
func_get_source_and_import_sql() {
log_info "拉取 RuoYi-Vue 源码"
cd /root
[ ! -d "RuoYi-Vue" ] && git clone https://gitee.com/y_project/RuoYi-Vue.git
cd ${SOURCE_DIR}
log_info "导入系统初始化SQL"
mysql -uroot -p${MYSQL_ROOT_PWD} ${RUOYI_DB} < sql/ry_*.sql
}
# 10. 仅修改配置连接参数(sed替换,不覆盖完整yml)
func_modify_config() {
log_info "修改数据库、Redis连接配置(仅替换参数,保留原有全部配置)"
cd ${SOURCE_DIR}
# ========== application-druid.yml 修改本地MySQL ==========
DRUID_YML="ruoyi-admin/src/main/resources/application-druid.yml"
sed -i "s|url: jdbc:mysql://.*:3306/.*?|url: jdbc:mysql://127.0.0.1:3306/${RUOYI_DB}?|" ${DRUID_YML}
sed -i 's|useSSL=true|useSSL=false\&allowPublicKeyRetrieval=true|' ${DRUID_YML}
sed -i "/master:/,/password:/s| username: .*| username: ${RUOYI_USER}|" ${DRUID_YML}
sed -i "/master:/,/slave:/s| password: .*| password: ${RUOYI_PWD}|" ${DRUID_YML}
# ========== application.yml 修改Redis、上传路径、服务端口 ==========
APP_YML="ruoyi-admin/src/main/resources/application.yml"
sed -i "s|profile: .*|profile: ${BASE_DIR}/uploadPath|g" ${APP_YML}
sed -i "s/host: .*/host: 127.0.0.1/g" ${APP_YML}
sed -i '/redis:/,/timeout:/s/\s*password:.*/ password: '"${REDIS_PWD}"'/' ${APP_YML}
}
# 11. Maven打包后端,部署Jar包
func_build_backend() {
log_info "Maven打包后端项目"
cd ${SOURCE_DIR}
mvn clean package -Dmaven.test.skip=true
log_info "迁移Jar至部署目录"
mkdir -p ${BASE_DIR}/server ${BASE_DIR}/uploadPath
cp ruoyi-admin/target/ruoyi-admin.jar ${BASE_DIR}/server/
}
# 12. 前端打包,部署静态资源
func_build_frontend() {
log_info "前端打包生产静态资源"
cd ${SOURCE_DIR}
git checkout -b ruoyi-3.9.2 tags/v3.9.2
cd ${SOURCE_DIR}/ruoyi-ui
npm install
npm run build:prod
log_info "部署前端dist目录"
mkdir -p ${BASE_DIR}/web
cp -r dist ${BASE_DIR}/web/
}
# 13. 创建后端 systemd 托管服务
func_create_systemd() {
log_info "创建 ruoyi-admin systemd 服务"
cat > "${RUOYI_SERVICE}" <<EOF
[Unit]
Description=RuoYi-Vue Backend Admin Service
After=network.target mysql.service redis-server.service
[Service]
User=root
WorkingDirectory=${BASE_DIR}/server
ExecStart=/usr/lib/jvm/java-17-openjdk-amd64/bin/java -jar ruoyi-admin.jar
SuccessExitStatus=143
Restart=on-failure
RestartSec=5
[Install]
WantedBy=multi-user.target
EOF
systemctl daemon-reload
systemctl enable --now ruoyi-admin
}
# 14. Nginx站点反向代理配置
func_config_nginx() {
log_info "生成 Nginx 若依站点配置"
cat > /etc/nginx/conf.d/ruoyi.conf <<EOF
server {
listen 80;
server_name ${WEB_DOMAIN};
root ${BASE_DIR}/web/dist;
index index.html;
location / {
try_files \$uri \$uri/ /index.html;
}
location ^~ /prod-api/ {
proxy_pass http://127.0.0.1:${APP_PORT}/;
proxy_set_header Host \$host;
proxy_set_header X-Real-IP \$remote_addr;
proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
}
location /profile/ {
proxy_pass http://127.0.0.1:${APP_PORT}/profile/;
proxy_set_header Host \$host;
proxy_set_header X-Real-IP \$remote_addr;
}
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg)$ {
expires 1d;
add_header Cache-Control "public";
}
}
EOF
nginx -t
systemctl reload nginx
}
# 15. 部署完成提示
func_finish_tips() {
log_info "==================== RuoYi-Vue 单机部署全部完成 ===================="
echo "后端服务端口:${APP_PORT}"
echo "前端访问地址:http://${WEB_DOMAIN}"
echo "后端实时日志:journalctl -u ruoyi-admin -f"
echo "重启后端服务:systemctl restart ruoyi-admin"
echo "MySQL数据库:${RUOYI_DB} 账号:${RUOYI_USER} 密码:${RUOYI_PWD}"
echo "Redis本地连接密码:${REDIS_PWD}"
echo "清理环境的话,可以执行如下命令"
echo "apt purge nginx* redis-* mysql-* -y"
echo "rm -rf /data/ruoyi ${RUOYI_SERVICE} ${SOURCE_DIR}"
}
# ===================== 主执行流程 =====================
main() {
func_sys_init
func_install_jdk
func_install_maven
func_install_node
func_install_nginx
func_install_redis
func_install_mysql
func_init_mysql_db
func_get_source_and_import_sql
func_modify_config
func_build_backend
func_build_frontend
func_create_systemd
func_config_nginx
func_finish_tips
}
# 启动入口
main
[root@ubuntu24-19:~#]
main[root@ubuntu24-19:~#] cat update_actuator_ruoyi_ubuntu24.sh
#!/bin/bash
# *************************************
# * 功能: Shell脚本开放Actuator功能
# * 作者: 马哥教育王老师
# * 版本: 2026-09-06
# *************************************
# set -e
# 定义环境变量
POM_FILE="./RuoYi-Vue/ruoyi-admin/pom.xml"
YML_FILE="./RuoYi-Vue/ruoyi-admin/src/main/resources/application.yml"
SECURITY_JAVA="./RuoYi-Vue/ruoyi-framework/src/main/java/com/ruoyi/framework/config/SecurityConfig.java"
# 1 添加 spring‑boot‑starter‑actuator 依赖 "
actuator_status=$(grep -q "spring-boot-starter-actuator" "${POM_FILE}")
if [ "$actuator_status" == "" ] ;then
cat >> /tmp/actuator_dep.xml <<'EOF'
<!-- Spring Boot Actuator 监控依赖 -->
<!-- 提供生产级别的应用监控和管理功能,包括健康检查、指标收集、环境信息等端点 -->
<!-- 版本由 spring-boot-starter-parent 统一管理,无需显式指定 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
EOF
# 将依赖插入到dependencies闭合标签前
sed -i '/<\/dependencies>/e cat /tmp/actuator_dep.xml' "${POM_FILE}"
rm -f /tmp/actuator_dep.xml
fi
# 2 写入management独立端口配置 ====="
manager_status=$(grep -q "^management:" "${YML_FILE}")
if [ "$manager_status" == "" ] ;then
cat >> "${YML_FILE}" <<'EOF'
# ========= Actuator监控配置(独立端口8091,仅本机访问) =========
management:
endpoints:
web:
base-path: /actuator # 默认Actuator端点的访问路径前缀
exposure:
include: '*' # 暴露所有端点,推荐改为health,info,metrics
endpoint:
health:
show-details: always # 健康检查显示详情
server:
port: 8091 # actuator单独端口,不能和ruoyi的server.port重复
address: 127.0.0.1 # 只允许本机访问
EOF
fi
# 3 修改SecurityConfig.java放行 /actuator/**"
code_status=$(grep -q 'requestMatchers("/actuator/\*\*").permitAll()' "${SECURITY_JAVA}")
if [ "$code_status" == "" ] ;then
# 在现有requestMatchers放行块内部插入 .requestMatchers("/actuator/**").permitAll()
# 匹配已有匿名放行的行,在该行后面插入actuator放行规则
sed -i '/druid/a\ .requestMatchers("/actuator/**").permitAll()' "${SECURITY_JAVA}"
fi
echo -e "完成Ruoyi-vue开放actuator 监控功能 "
echo "后续操作:"
echo "重新打包 mvn clean package -DskipTests"
echo "启动测试 java -jar ruoyi-admin/target/ruoyi-admin.jar"
echo "启动后访问:curl -s http://127.0.0.1:8091/actuator/metrics"
[root@ubuntu24-19:~#] /bin/bash onekey_install_ruoyi_ubuntu24.sh
[root@ubuntu24-19:~#] /bin/bash update_actuator_ruoyi_ubuntu24.sh
3.3、MySQL安全加固
bash
[root@ubuntu24-19:~#] netstat -tnlp | grep -E 'mysql|redis|ssh|nginx|java'
tcp 0 0 127.0.0.1:6379 0.0.0.0:* LISTEN 1125/redis-server 1
tcp 0 0 127.0.0.1:33060 0.0.0.0:* LISTEN 1193/mysqld
tcp 0 0 127.0.0.1:6010 0.0.0.0:* LISTEN 1578/sshd: root@pts
tcp 0 0 127.0.0.1:3306 0.0.0.0:* LISTEN 1193/mysqld
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 1160/nginx: master
tcp6 0 0 :::8080 :::* LISTEN 1256/java
tcp6 0 0 ::1:6010 :::* LISTEN 1578/sshd: root@pts
# 配置监听端口
[root@ubuntu24-19:~#] vim /etc/mysql/mysql.conf.d/mysqld.cnf
[root@ubuntu24-19:~#] grep -E -A 1 "^bind-address" /etc/mysql/mysql.conf.d/mysqld.cnf
bind-address = 127.0.0.1,10.0.0.19
mysqlx-bind-address = 127.0.0.1,10.0.0.19
[root@ubuntu24-19:~#] systemctl restart mysql.service
[root@ubuntu24-19:~#] mysql
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 8
Server version: 8.0.46-0ubuntu0.24.04.4 (Ubuntu)
Copyright (c) 2000, 2026, Oracle and/or its affiliates.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql> select Host,User from mysql.user;
+-----------+------------------+
| Host | User |
+-----------+------------------+
| localhost | debian-sys-maint |
| localhost | mysql.infoschema |
| localhost | mysql.session |
| localhost | mysql.sys |
| localhost | root |
| localhost | ruoyi |
+-----------+------------------+
6 rows in set (0.00 sec)
# 修改密码
mysql> alter user root@localhost identified by 'Xyx@1234';
Query OK, 0 rows affected (0.01 sec)
# 只能本机登录
mysql> REVOKE ALL PRIVILEGES, GRANT OPTION FROM 'ruoyi'@'localhost';
Query OK, 0 rows affected (0.00 sec)
# 修改用户对指定库表权限
mysql> GRANT SELECT,INSERT,UPDATE,DELETE ON ry_vue.* TO 'ruoyi'@'localhost';
Query OK, 0 rows affected (0.01 sec)
# 创建用户指定网段可以连接
mysql> CREATE USER IF NOT EXISTS 'ruoyi_dev'@'10.0.0.%' IDENTIFIED BY 'Ruoyi@123';
Query OK, 0 rows affected (0.03 sec)
# 修改用户对指定库表权限
mysql> GRANT SELECT,INSERT,UPDATE,DELETE,CREATE,ALTER,INDEX ON ry_vue.* TO 'ruoyi_dev'@'10.0.0.%';
Query OK, 0 rows affected (0.01 sec)
# 刷新配置
mysql> FLUSH PRIVILEGES;
Query OK, 0 rows affected (0.00 sec)
mysql>exit;
3.4、Redis安全加固
bash
[root@ubuntu24-19:~#] vim /etc/redis/redis.conf
[root@ubuntu24-19:~#] grep -E '10.0.0.19|^protected-mode|Redis@2026|^rename-command' /etc/redis/redis.conf
bind 127.0.0.1 10.0.0.19 # 监听地址
protected-mode yes #开启保护模式
requirepass "Redis@2026" # 认证密码
# 禁用敏感词
rename-command FLUSHALL ""
rename-command FLUSHDB ""
rename-command DEBUG ""
rename-command KEYS "KEYS_123456"
rename-command CONFIG "CONFIG_123456"
[root@ubuntu24-19:~#] systemctl restart redis
# 密码认证登录,敏感命令取消
[root@ubuntu24-19:~#] redis-cli -a Redis@2026
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
127.0.0.1:6379> KEYS_123456 *
1) "sys_config:sys.account.registerUser"
2) "sys_dict:sys_job_group"
3) "sys_dict:sys_oper_type"
4) "sys_dict:sys_yes_no"
5) "sys_config:sys.user.initPassword"
6) "sys_dict:sys_notice_type"
7) "sys_dict:sys_notice_status"
8) "sys_dict:sys_show_hide"
9) "sys_config:sys.account.initPasswordModify"
10) "sys_config:sys.account.captchaEnabled"
11) "sys_dict:sys_normal_disable"
12) "sys_dict:sys_common_status"
13) "sys_config:sys.index.sideTheme"
14) "sys_config:sys.index.skinName"
15) "sys_dict:sys_user_sex"
16) "sys_dict:sys_job_status"
17) "sys_config:sys.account.chrtype"
18) "sys_config:sys.login.blackIPList"
19) "sys_config:sys.account.passwordValidateDays"
127.0.0.1:6379> KEYS *
(error) ERR unknown command 'KEYS', with args beginning with: '*'
3.5、Nginx加固
Nginx 默认开启版本号回显、开启目录浏览功能。攻击者可通过响应头获取 Nginx 具体版本,针对性搜索版本漏洞.
bash
[root@ubuntu24-19:~#] curl -I 10.0.0.19
HTTP/1.1 200 OK
Server: nginx/1.24.0 (Ubuntu)
Date: Wed, 21 Oct 2026 08:03:32 GMT
Content-Type: text/html
Content-Length: 12759
Last-Modified: Wed, 21 Oct 2026 03:47:11 GMT
Connection: keep-alive
ETag: "6ad835bf-31d7"
Accept-Ranges: bytes
----------------------
[root@ubuntu24-19:~#] cat > /etc/nginx/conf.d/security.conf <<'EOF'
server_tokens off;
autoindex off;
EOF
[root@ubuntu24-19:~#] chown -R www-data:www-data /data/ruoyi/web
[root@ubuntu24-19:~#] find /data/ruoyi/web -type d -exec chmod 755 {} \;
[root@ubuntu24-19:~#] find /data/ruoyi/web -type f -exec chmod 644 {} \;
[root@ubuntu24-19:~#] nginx -t && systemctl reload nginx.service
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
[root@ubuntu24-19:~#]
-----------------------
[root@ubuntu24-19:~#] curl -I 10.0.0.19
HTTP/1.1 200 OK
Server: nginx
Date: Wed, 21 Oct 2026 08:10:29 GMT
Content-Type: text/html
Content-Length: 12759
Last-Modified: Wed, 21 Oct 2026 03:47:11 GMT
Connection: keep-alive
ETag: "6ad835bf-31d7"
Accept-Ranges: bytes
3.6、Actuator安全加固
生产环境仅保留健康检查端点用于监控告警,关闭所有敏感信息端点。
bash
[root@ubuntu24-19:~#] cd RuoYi-Vue/
[root@ubuntu24-19:~/RuoYi-Vue#] vim ruoyi-admin/src/main/resources/application.yml
[root@ubuntu24-19:~/RuoYi-Vue#] grep -E -C 5 'base-path' ruoyi-admin/src/main/resources/application.yml
# ========= Actuator监控配置(独立端口8091,仅本机访问) =========
management:
endpoints:
web:
base-path: /actuator # 默认Actuator端点的访问路径前缀
exposure:
include: 'health,metrics' # 暴露所有端点,推荐改为health,info,metrics
endpoint:
health:
show-details: always # 健康检查显示详情
[root@ubuntu24-19:~/RuoYi-Vue#] mvn clean package -DskipTests
[root@ubuntu24-19:~/RuoYi-Vue#] cp ruoyi-admin/target/ruoyi-admin.jar /data/ruoyi/server/
[root@ubuntu24-19:~/RuoYi-Vue#] systemctl restart ruoyi-admin.service
[root@ubuntu24-19:~/RuoYi-Vue#] mvn clean package ^C
[root@ubuntu24-19:~/RuoYi-Vue#] systemctl status ruoyi-admin.service
● ruoyi-admin.service - RuoYi-Vue Backend Admin Service
Loaded: loaded (/etc/systemd/system/ruoyi-admin.service; enabled; preset: enabled)
Active: active (running) since Wed 2026-10-21 08:19:04 UTC; 2min 25s ago
Main PID: 3007 (java)
Tasks: 252 (limit: 4545)
Memory: 855.4M (peak: 860.2M)
CPU: 1min 57.797s
CGroup: /system.slice/ruoyi-admin.service
└─3007 /usr/lib/jvm/java-17-openjdk-amd64/bin/java -jar ruoyi-admin.jar
[root@ubuntu24-19:~/RuoYi-Vue#] cd
[root@ubuntu24-19:~#] curl -I 10.0.0.19
HTTP/1.1 200 OK
Server: nginx
Date: Wed, 21 Oct 2026 08:21:51 GMT
Content-Type: text/html
Content-Length: 12759
Last-Modified: Wed, 21 Oct 2026 03:47:11 GMT
Connection: keep-alive
ETag: "6ad835bf-31d7"
Accept-Ranges: bytes
3.6、Actuator安全加固
生产环境仅保留健康检查端点用于监控告警,关闭所有敏感信息端点。
bash
[root@ubuntu24-19:~#] cd RuoYi-Vue/
[root@ubuntu24-19:~/RuoYi-Vue#] vim ruoyi-admin/src/main/resources/application.yml
[root@ubuntu24-19:~/RuoYi-Vue#] grep -E -C 5 'base-path' ruoyi-admin/src/main/resources/application.yml
# ========= Actuator监控配置(独立端口8091,仅本机访问) =========
management:
endpoints:
web:
base-path: /actuator # 默认Actuator端点的访问路径前缀
exposure:
include: 'health,metrics' # 暴露所有端点,推荐改为health,info,metrics
endpoint:
health:
show-details: always # 健康检查显示详情
[root@ubuntu24-19:~/RuoYi-Vue#] mvn clean package -DskipTests
[root@ubuntu24-19:~/RuoYi-Vue#] cp ruoyi-admin/target/ruoyi-admin.jar /data/ruoyi/server/
[root@ubuntu24-19:~/RuoYi-Vue#] systemctl restart ruoyi-admin.service
[root@ubuntu24-19:~/RuoYi-Vue#] mvn clean package ^C
[root@ubuntu24-19:~/RuoYi-Vue#] systemctl status ruoyi-admin.service
● ruoyi-admin.service - RuoYi-Vue Backend Admin Service
Loaded: loaded (/etc/systemd/system/ruoyi-admin.service; enabled; preset: enabled)
Active: active (running) since Wed 2026-10-21 08:19:04 UTC; 2min 25s ago
Main PID: 3007 (java)
Tasks: 252 (limit: 4545)
Memory: 855.4M (peak: 860.2M)
CPU: 1min 57.797s
CGroup: /system.slice/ruoyi-admin.service
└─3007 /usr/lib/jvm/java-17-openjdk-amd64/bin/java -jar ruoyi-admin.jar
[root@ubuntu24-19:~/RuoYi-Vue#] cd
[root@ubuntu24-19:~#] curl -I 10.0.0.19
HTTP/1.1 200 OK
Server: nginx
Date: Wed, 21 Oct 2026 08:21:51 GMT
Content-Type: text/html
Content-Length: 12759
Last-Modified: Wed, 21 Oct 2026 03:47:11 GMT
Connection: keep-alive
ETag: "6ad835bf-31d7"
Accept-Ranges: bytes