YAZONG 我的开源

记博客被攻击导致宕机事件及攻击分析_202604

  , ,
0 评论0 浏览

起因

博客部署在阿里云ECS服务器中,4月底不能突然访问了,先查了一下控制台监控,内外网流量几乎干涸了:

image.png

image.png

另外,登录服务器,docker三个服务(nginx1.25.3、jdk8、mysql5.7)都是停止的。

先说结论:

安全组,我设置了3306的MySQL端口,这里3306是暴露到了公网,是在上一次导出数据备份后,忘记关闭,导致此端口被反复恶意攻击,另外服务器配置本身就很低,2VCPU,2GB内存,docker跑三个服务,服务器硬件资源吃紧后,应用全部宕机。

注:虽然是常识问题,不该犯的问题,但是影响范围很大以此问题来放大安全防控与预防设施

image.png

服务器排查

#很明显的,这里除了Java和NGINX后,主要查MySQL的日志即可。
# 基本硬件配置:40GB硬盘,2GB内存,2VCPU,2Mbps带宽。
[root@XX ]# cat /etc/redhat-release 
CentOS Linux release 7.9.2009 (Core)
[root@XX ]# uname -a
Linux XX 3.10.0-1160.105.1.el7.x86_64 #1 SMP Thu Dec 7 15:39:45 UTC 2023 x86_64 x86_64 x86_64 GNU/Linux
[root@XX~]# df -h
[root@XX~]# htop
[root@XX~]# free -mh

#查看系统重启记录(确认是否因OOM导致系统重启)
[root@XX]# last reboot | head -10

[root@XX ]# docker ps

#查看容器退出状态码(重点关注)
# 状态码137 = 被SIGKILL信号杀死(通常是OOM导致)
# 状态码143 = 被SIGTERM信号正常终止
[root@XX~]# docker inspect mysql | grep ExitCode
[root@XX~]# docker inspect nginx | grep ExitCode
[root@XX~]# docker inspect solo | grep ExitCode

#确认OOM事件。
#查看系统日志中的OOM记录(最直接证据)
[root@XX]# grep -i "out of memory\|killed process" /var/log/messages*
[root@XX]# grep -i "oom-killer" /var/log/messages*
#专门查 Linux OOM 内核日志,看 MySQL 容器有没有因为内存不够被系统杀掉。
[root@XX]# dmesg | grep -i "out of memory\|killed process\|oom"
#容器内看 OOM 更精准的命令
#出现 "OOMKilled": true → 就是内存超限被杀。
[root@XX~]# docker inspect mysql | grep -i oom
            "OOMKilled": false,
            "OomScoreAdj": 0,
            "OomKillDisable": false,


# 查看 Docker 守护进程日志(最后100行)
# 关注点:
# 容器退出码(Exit Code):
# 137 或 143 通常表示被 SIGKILL 或 SIGTERM 终止,很可能是 OOM Killer 或手动停止。
# 255 可能代表 Docker 守护进程本身的问题。
# Docker 守护进程日志中是否有 OOM、Cannot allocate memory 或 no space left on device 错误。
[root@XX]# journalctl -u docker -n 100 --no-pager
[root@XX]# journalctl -u docker --since "2026-04-15" --until "2026-04-25"

# 查看定时任务
[root@XX]# crontab -l
[root@XX]# cat /etc/crontab
[root@XX]# ls /etc/cron.daily/ /etc/cron.weekly/

# 查看最近的系统更新日志
[root@XX]# grep " installed " /var/log/yum.log | tail -20

#重启docker服务。

#MySQL很明显的攻击日志,上千条持续4个月。
[root@XX ~]# docker logs MySQL的containerlog
...
2026-04-19T03:50:17.475620Z 228134 [Note] Access denied for user 'cron'@'89.190.156.25' (using password: YES)
2026-04-19T15:03:54.522453Z 228275 [Note] Access denied for user 'root'@'46.151.182.157' (using password: NO)
...

攻击分析

攻击日志

2026-01-02T10:04:24.490669Z 182386 [Note] Access denied for user 'root'@'180.149.32.98' (using password: YES)
2026-01-02T12:55:52.908990Z 182438 [Note] Access denied for user 'root'@'34.52.219.24' (using password: NO)
2026-01-02T14:13:19.489637Z 182457 [Note] Access denied for user 'root'@'34.79.212.205' (using password: NO)
2026-01-06T20:52:01.397817Z 183972 [Note] Access denied for user 'app_user'@'217.160.136.172' (using password: YES)
2026-01-06T20:52:02.016333Z 183973 [Note] Access denied for user 'app_user'@'217.160.136.172' (using password: YES)
2026-01-06T20:52:02.658274Z 183974 [Note] Access denied for user 'app_user'@'217.160.136.172' (using password: YES)
2026-01-06T20:52:03.266008Z 183975 [Note] Access denied for user 'app_user'@'217.160.136.172' (using password: YES)
...省略
2026-04-16T10:00:52.401125Z 227222 [Note] Access denied for user 'root'@'34.38.195.167' (using password: NO)
2026-04-16T22:38:53.713590Z 227397 [Note] Access denied for user 'root'@'64.89.163.178' (using password: NO)
2026-04-17T04:36:24.459315Z 227481 [Note] Access denied for user 'root'@'64.89.163.158' (using password: NO)
2026-04-17T04:36:24.989563Z 227482 [Note] Access denied for user 'root'@'64.89.163.158' (using password: YES)
2026-04-17T04:36:25.568749Z 227483 [Note] Access denied for user 'root'@'64.89.163.158' (using password: YES)
2026-04-17T04:36:26.245090Z 227484 [Note] Access denied for user 'root'@'64.89.163.158' (using password: YES)

2026-04-19T03:50:17.475620Z 228134 [Note] Access denied for user 'cron'@'89.190.156.25' (using password: YES)
2026-04-19T15:03:54.522453Z 228275 [Note] Access denied for user 'root'@'46.151.182.157' (using password: NO)

攻击日志概要

日志明确说明: MySQL 服务器正遭受高强度的暴力破解攻击。

这是导致服务器崩溃的直接导火索,结合之前的监控数据,完整的事件链条已经清晰:

攻击强度极高:每秒约 15-20 次登录尝试,持续不断

攻击目标明确:专门针对 MySQL 的root超级用户

攻击方式:使用密码字典进行自动化暴力破解

攻击如何导致服务全面崩溃

资源耗尽:每次 MySQL 登录验证都会消耗 CPU 和内存资源

连接数爆炸:大量失败连接导致 MySQL 连接池耗尽

连锁反应:MySQL 占用资源过高 → 系统内存耗尽 → 触发 OOM Killer → 杀死 MySQL 进程 → Docker 守护进程异常 → 所有容器停止运行。

攻击目标:他们想偷什么?

攻击者只有一个目的:猜出你数据库的用户名和密码。一旦成功,他们就可以:

1)窃取你数据库里的所有数据(用户信息、订单、商业机密等)。

2)加密你的数据,然后勒索你付钱解密(勒索病毒)。

3)删库跑路,破坏你的业务。

4)植入后门,把你的服务器变成他们发动下一次攻击的“跳板”。

从日志的时间跨度和条目数量来看,攻击强度相当高:

攻击强度:有多猛烈?

1)持续时间长:从2026-01-02一直到2026-04-19,前后持续三个多月,几乎没有中断。说明攻击者很有耐心,可能是自动化脚本在长期扫描。

2)频率极高:

例如 196.251.100.206 这个IP,在 2026-01-06 01:39:44 到 01:40:01 这短短17秒内,连续发起了 38次 登录尝试!

77.90.40.139 在 2026-01-06 09:41:44 到 09:42:54 这一分钟内,尝试了超过 70次。

还有像 81.17.16.178 这个IP,在 2026-01-15 10:43:33 到 10:47:23 连续尝试了几千次(日志里这个IP的记录有几百行,每一行代表一次尝试)。

3)并发来源多:攻击不是来自单一IP,而是来自成百上千个不同的IP地址(日志里去重后至少有几百个不同的IP)。这是典型的僵尸网络(肉鸡)攻击,攻击者控制了大量被感染的电脑、路由器、云服务器同时对你发起进攻,让你难以通过封一个IP来阻止。

结论:攻击强度非常大,属于分布式暴力破解,不是某个小毛贼手动敲键盘,而是专业的黑客工具在自动扫描。

攻击方式:他们是怎么尝试的?

1)用户名枚举:攻击者不仅尝试了最常见的 root,还尝试了一大批其他用户名:

2)常见管理名:admin, administrator, dbadmin, mysqladmin, sysadmin

应用名:app, app_user, appuser, wallet, exchange, production

通用名:test, user, guest, web, dev

甚至还有 root_dev, app_user_dev 这种带 _dev 的变体,说明攻击者知道很多公司会用开发环境的用户名。

这叫做用户名枚举,目的是先猜出你有哪个用户名存在,然后再重点爆破密码。

3)密码猜测:日志中绝大多数尝试都标注了 using password: YES,说明攻击者提供了密码(即使是错误的)。他们用的是字典攻击——预先准备了一个常用密码列表(比如 123456, password, root, admin123 等),逐个去试。

4)高频重试:同一个IP在极短时间内尝试几十上百次,这是典型的自动化工具行为(如 hydra, medusa, 或定制脚本)。

5)多线程/分布式:不同IP同时尝试,每个IP只尝试少量次数,这样不容易触发传统的“单IP失败次数过多”的告警。

攻击来源:他们从哪里来?

1)按国家 / 地区总览

美国:83 条(绝对主力黑客来源)

中国(含香港):31 条(业务 / 测试 / 少量国内扫描)

荷兰:24 条(批量暴力破解大户)

俄罗斯:17 条(同一 IP 段批量扫库)

法国:7 条

德国:4 条

英国:4 条

其他零散国家(尼日利亚、乌克兰、保加利亚、印度、新加坡、波兰、哥伦比亚、巴西):各 1 条,合计 8 条

2)美国内部细分(云厂商,黑客主力集群)

谷歌云 Google Cloud(34/35 开头):52 条

DigitalOcean(38/64.89 开头):24 条

Vultr:4 条

其他美国运营商 / 机房:3 条

3)中国内部细分

中国大陆(阿里云、腾讯云、电信、移动):24 条

中国香港:7 条

4)关键安全结论与发现

95% 以上攻击来自海外,美国谷歌云、DigitalOcean 是头号攻击源;

俄罗斯 81.17.16.178 单个 IP 发起17 次全账号暴力破解,属于重点恶意 IP;

荷兰、法国、德国、英国为欧洲黑客主要跳板;

高危入侵 IP:大量美国谷歌云、DigitalOcean、Vultr、荷兰 / 德国 / 俄罗斯 / 法国海外服务器,全是暴力破解 MySQL 的黑客扫描 IP;

重点拉黑 IP:81.17.16.178(俄罗斯批量扫库)、64.89.*.*(美国批量扫描段)、34/35.*(谷歌云黑客集群);

国内 IP:多为阿里云 / 腾讯云 / 电信,多为合法业务或内部测试,可放行。

5)结论:

IP分布全球各地,说明攻击者使用了大量的跳板机或被控制的设备(肉鸡)。

很多IP属于云服务商(Google Cloud、UCloud),黑客会注册低价云主机来发动攻击,用完就销毁。

还有一部分IP来自住宅宽带(如中国电信、BSNL印度等),可能是普通用户的电脑被植入木马,成为攻击你的帮凶。

你无法通过简单封禁某个国家或某个IP来彻底解决问题,因为来源太多了。

攻击方式-IP(黑名单)(直接用)

#重点拉黑 IP:81.17.16.178(俄罗斯批量扫库)、64.89.*.*(美国批量扫描段)、34/35.*(谷歌云黑客集群);

34.52.219.24
34.79.212.205
104.155.31.18
35.195.180.151
34.76.44.148
196.251.100.206
77.90.40.139
217.160.136.172
34.38.45.85
38.52.140.99
38.188.238.201
34.38.106.200
34.22.177.31
34.79.159.68
156.229.16.165
104.199.46.221
81.29.142.100
165.154.221.151
198.163.192.128
34.14.118.150
35.240.115.119
34.76.34.183
35.195.241.97
38.52.141.39
195.24.236.158
34.76.210.200
34.52.238.9
34.76.139.101
81.17.16.178
152.32.131.245
206.62.174.69
34.78.183.19
35.233.94.99
146.190.173.12
34.76.70.200
165.154.11.140
35.187.114.229
146.148.12.176
24.199.123.34
15.204.110.179
34.76.255.44
35.195.168.139
89.97.205.99
91.217.249.210
91.217.249.69
34.79.180.31
141.164.130.146
34.140.135.10
109.123.236.128
35.233.5.189
34.76.200.20
73.76.95.48
34.78.138.227
38.254.110.27
81.29.142.6
46.151.182.157
34.34.132.221
190.83.8.3
34.14.103.46
46.151.182.158
35.187.31.145
38.188.238.210
35.205.235.254
45.86.202.189
45.86.202.36
34.140.188.44
46.151.182.183
34.78.169.237
34.78.140.118
208.3.195.65
34.14.33.150
34.22.173.102
45.86.202.246
35.205.250.241
35.241.216.72
209.126.3.23
34.38.83.65
104.238.34.9
165.154.138.79
82.66.143.234
128.14.237.130
34.52.219.2
165.154.36.245
130.211.53.197
38.171.255.69
34.53.130.250
64.89.163.154
64.89.163.80
64.89.163.89
38.121.208.169
46.151.182.160
46.151.182.185
46.151.182.159
64.89.163.165
64.89.163.166
64.89.163.146
64.89.163.79
64.89.163.176
64.89.163.77
64.89.163.78
64.89.163.97
51.158.146.123
64.89.163.141
95.155.37.66
34.140.251.161
46.151.182.162
46.151.182.182
64.89.163.153
35.233.88.72
64.89.163.158
46.151.182.187
34.76.35.74
64.89.163.167
34.78.23.28
158.140.165.5
158.140.165.19
34.38.195.167
198.199.67.35
34.78.189.165
38.172.56.68
38.172.56.73
165.154.179.62
45.8.249.101
64.89.163.91
64.89.163.92
64.89.163.180
35.205.166.64
212.51.34.197
38.248.130.141
76.13.80.104
141.164.253.63
64.89.163.139
190.112.222.106
91.217.249.203
46.151.182.186
89.117.36.53
164.52.210.113
35.233.21.145
64.89.163.178
89.190.156.25

攻击方式-攻击用户名:地区使用次数统计


规则:按国家/地区汇总,同一 IP 多条相同用户名多次登录,每条都计数;按上面归属地地区统计频次。

1. root(最高频,总 112 次)
美国:74 次
中国(大陆 + 香港):20 次
荷兰:8 次
俄罗斯:1 次
法国:4 次
英国:3 次
德国:0
其他(尼日利亚、乌克兰、保加利亚、印度、新加坡、波兰、哥伦比亚、巴西):2 次
2. admin(总 6 次)
美国:3 次
中国:1 次
巴西:1 次
俄罗斯:1 次
3. dbadmin(总 4 次)
俄罗斯:1 次
美国:1 次
德国:1 次
荷兰:1 次
4. cron(总 3 次)
中国:2 次
法国:1 次
5. app_user /app_user_dev(各 1 次,共 2 次)
德国:2 次
6. appuser /appuser_dev(各 1 次,共 2 次)
中国香港:2 次
7. llyweb(总 3 次)(域名名称)
荷兰:3 次
8. erpjiaju(总 3 次)
荷兰:2 次
中国:1 次
9. exchange /exchange_dev(各 1 次,共 2 次)
美国:1 次
荷兰:1 次
10. openser /opensips(各 1 次,共 2 次)
美国:2 次
11. wallet /wallet_dev(各 1 次,共 2 次)
美国:2 次
12. production /production_dev(各 1 次,共 2 次)
英国:2 次
13. root_dev(1 次)
中国:1 次
14. manager(1 次)
中国:1 次
15. admin_dev(1 次)
美国:1 次
16. kamailio(1 次)
美国:1 次
17. erpjiaju.com(1 次)
荷兰:1 次
18. administrator(1 次)
美国:1 次
19. sys(1 次)
中国:1 次
20. roo(1 次)
中国香港:1 次
21. xmh(1 次)
中国:1 次
22. 俄罗斯 81.17.16.178 批量扫描专用账号(共 16 个,各 1 次)
mysql、www、sysadmin、app、mysqladmin、test、system、dbuser、sql、demo、dev、db、sqladmin、guest、web、dba、user
全部:俄罗斯(各 1 次)

攻击方式-攻击用户名(名单):频次排序

#去重后所有用户名(@前)完整列表,按出现频次从高到低排序,去重后共 44 个:

root
root_dev
app_user
app_user_dev
appuser
appuser_dev
dbadmin
mysql
www
sysadmin
app
mysqladmin
test
system
dbuser
sql
demo
dev
db
sqladmin
guest
web
dba
user
admin
cron
manager
admin_dev
openser
opensips
roo
llyweb
kamailio
wallet
wallet_dev
production
production_dev
erpjiaju.com
erpjiaju
administrator
sys
exchange
exchange_dev
xmh

核心攻击特征总结

root 是全球黑客万能爆破账号,美国谷歌云 / DigitalOcean 占绝对主力;

俄罗斯黑客最爱扫全量弱口令账号:mysql、admin、test、user、db、web、guest 等;

** 欧洲(荷兰 / 德国 / 法国)** 常用:llyweb(域名名称)、erpjiaju、app_user、production;

国内 IP主要扫:root、cron、manager、sys、xmh,多为业务 / 内部测试;

大量 dev/_dev 后缀账号(root_dev、app_user_dev、wallet_dev)被境外黑客精准爆破,属于高危。

这次攻击不是偶然:这是互联网上广泛存在的自动化扫描和暴力破解攻击,所有暴露在公网的 3306 端口都会被扫描。

绝对不要使用弱密码:弱密码会在几分钟内被破解。

绝对不要允许 root 用户远程登录:这是最危险的配置。

定期备份数据:防止攻击成功导致数据丢失。

image.png

链路崩溃基本设置

概要

Solo 博客(Java)+ MySQL 长期运行,内存缓慢泄漏、占用持续上涨。

结论:无OOM事件,攻击是导致内存不够的原因,但确实是内存不够导致的

物理内存 1.7G 被打满,且无 Swap 缓冲。

重启后 Docker 自动启动,容器恢复,就是你现在看到的状态。

同时印证前面监控:

4 月起 CPU 长期高占用、连接数峰值极高。

4 月 19 日也有一次重启,历史上就是周期性内存爆了重启。

SWAP设置(最关键,防止硬重启)


[root@XX ]# free -mh
              total        used        free      shared  buff/cache   available
Mem:           1.7G        151M         68M        508K        1.5G        1.4G
Swap:            0B          0B          0B
 
# 用 dd 创建一个 2GB 的交换文件,生成2GB空文件,用作swap
# dd 是 Linux/Unix 系统里的一个底层文件操作工具,全称是 Data Duplicator(数据复制器),它的核心作用就是:启动数据复制工具,按指定规则复制、转换数据,可以操作普通文件,也能直接操作磁盘、分区、内存等设备。
# dd 就是一个精准控制大小、逐字节复制数据的工具,常用来:创建交换文件 /swap;备份磁盘 / 分区;生成指定大小的测试文件;底层数据拷贝。
# if=,input file,输入源(从哪里读数据)
# of=,output file,输出目标(写到哪里去),/swapfile
# /dev/zero,Linux 特殊设备,无限输出 0 字节的数据流
# bs=1M,block size,每次读写的块大小(1MB)
# count=2048,复制的块数量,一共复制 2048 个块,count=2048块 → 2G
# 最终效果:1M × 2048 = 2048MB = 2GB → 生成一个全是 0、大小为 2GB 的 /swapfile 文件。
[root@XX ]# dd if=/dev/zero of=/swapfile bs=1M count=2048
2048+0 records in
2048+0 records out
2147483648 bytes (2.1 GB) copied, 15.8997 s, 135 MB/s

#设置权限:仅root可读可写,防止普通用户篡改
[root@XX ]# chmod 600 /swapfile
#格式化为swap文件系统
[root@XX ]# mkswap /swapfile
Setting up swapspace version 1, size = 2097148 KiB
no label, UUID=c999d457-2cb7-4eaa-87c8-3a90b97acd6c
#立即启用swap,当前会话生效
[root@XX ]# swapon /swapfile
#写入fstab,开机自动挂载(标准写法)
/swapfile
要挂载的设备 / 文件:你创建的交换文件路径。
swap(挂载点)
常规磁盘是挂载到 / /home 这类目录;swap 无实际挂载目录,这里填 swap 是旧习惯写法。
swap(文件系统类型)
指定这是交换分区 / 交换文件,Linux 识别为 Swap。
defaults(挂载参数)
等价于:rw,suid,dev,exec,auto,nouser,async
对 swap 来说,内核会自动叠加 sw 挂载标记。
0(dump)
0 = 不使用 dump 工具备份;swap 不需要备份,固定 0。
0(fsck)
0 = 开机不做磁盘自检;swap 禁止开机自检,固定 0。
[root@XX ]# echo '/swapfile none swap sw 0 0' >> /etc/fstab
# 调整内核swap倾向:内存剩余30%时开始使用swap,避免OOM硬重启,适合小内存服务器。而swappiness=0:尽量不用 swap(容易 OOM)
[root@XX ]# echo "vm.swappiness=30" >> /etc/sysctl.conf
#生效
[root@XX ]# sysctl -p
vm.swappiness = 0
kernel.sysrq = 1
net.ipv4.neigh.default.gc_stale_time = 120
net.ipv4.conf.all.rp_filter = 0
net.ipv4.conf.default.rp_filter = 0
net.ipv4.conf.default.arp_announce = 2
net.ipv4.conf.lo.arp_announce = 2
net.ipv4.conf.all.arp_announce = 2
net.ipv4.tcp_max_tw_buckets = 5000
net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_max_syn_backlog = 1024
net.ipv4.tcp_synack_retries = 2
net.ipv4.tcp_slow_start_after_idle = 0
vm.swappiness = 30
#查看swap是否启用
[root@XX ]# free -mh
              total        used        free      shared  buff/cache   available
Mem:           1.7G        152M         76M        508K        1.5G        1.4G
Swap:          2.0G          0B        2.0G
#查看fstab配置是否正确
[root@XX ]# cat /etc/fstab 

#
# /etc/fstab
# Created by anaconda on Wed Dec 20 08:18:11 2023
#
# Accessible filesystems, by reference, are maintained under '/dev/disk'
# See man pages fstab(5), findfs(8), mount(8) and/or blkid(8) for more info
#
UUID=74ee7f1f-178b-49d9-916a-1969563010c3 /                       ext4    defaults        1 1
/swapfile none swap sw 0 0
#测试开机挂载(不重启,模拟)
[root@XX ]# mount -a
# 无报错即代表配置完全正确

docker设置(待完善)


#Docker绑定本地未设置。

#docker限制进程内存
[root@XX ]# docker update mysql-container-id --memory 400m --memory-swap 600m
mysql-container-id
[root@XX ]# docker update java-container-id --memory 400m --memory-swap 600m
java-container-id


[root@XX ]# docker inspect mysql-container-id|grep -i memory
            "Memory": 419430400,
            "KernelMemory": 0,
            "MemoryReservation": 0,
            "MemorySwap": 629145600,
            "MemorySwappiness": -1,
[root@XX ]# docker inspect java-container-id|grep -i memory
            "Memory": 419430400,
            "KernelMemory": 0,
            "MemoryReservation": 0,
            "MemorySwap": 629145600,
            "MemorySwappiness": -1,
[root@XX ]# docker inspect nginx-container-id|grep -i memory
            "Memory": 0,
            "KernelMemory": 0,
            "MemoryReservation": 0,
            "MemorySwap": 0,
            "MemorySwappiness": -1,

#看实时内存限制
[root@XX ]# docker stats NGINX-container-id
CONTAINER           CPU %               MEM USAGE / LIMIT       MEM %               NET I/O             BLOCK I/O           PIDS
NGINX-container-id        0.00%               3.469 MiB / 1.715 GiB   0.20%               655 MB / 738 MB     30.4 MB / 4.1 kB    3

[root@XX ]# docker stats java-container-id
CONTAINER           CPU %               MEM USAGE / LIMIT     MEM %               NET I/O             BLOCK I/O           PIDS
Java-container-id        0.06%               210.2 MiB / 400 MiB   52.56%              1.13 MB / 5.31 MB   36.5 MB / 13.7 MB   33

[root@XX ]# docker stats java-container-id
CONTAINER           CPU %               MEM USAGE / LIMIT     MEM %               NET I/O             BLOCK I/O           PIDS
MySQL-container-id        0.08%               152.4 MiB / 400 MiB   38.10%              0 B / 0 B           85.3 MB / 102 kB    22

[root@mysql-container-id]# docker stats mysql --no-stream
CONTAINER           CPU %               MEM USAGE / LIMIT     MEM %               NET I/O             BLOCK I/O           PIDS
mysql               0.08%               210.6 MiB / 400 MiB   52.65%              2.68 MB / 11.3 MB   36.6 MB / 13.7 MB   33


[root@XX ]# docker exec -it  MySQL-containerd-id   free -h
             total       used       free     shared    buffers     cached
Mem:          1.7G       1.6G        83M       648K        23M       1.0G
-/+ buffers/cache:       610M       1.1G
Swap:         2.0G       2.0M       2.0G

阿里云ECS安全组设置

SSH22:禁掉,设置其他端口登录,并且这个端口要限制IP可访问,并且要经常换。

MySQL3306:禁掉,用完及关。需完善监控3306端口。

MySQL设置(待完善)

#bind-address等暂不设置。
#root没被破解,因为远程访问禁掉了,并且密码强度很强。

[root@XX ]# docker exec -it XX bash
root@XX:/# cat /etc/mysql/my.cnf

!includedir /etc/mysql/conf.d/
!includedir /etc/mysql/mysql.conf.d/
#修改my.cnf
# 降低InnoDB缓冲池
innodb_buffer_pool_size=128M
# 限制每个IP的最大连接数
max_connect_errors=10
# 服务器自动断开非活动连接的时间(秒)
wait_timeout=600
# 最大连接数
max_connections=100
#关掉MySQL 自带的性能监控、诊断工具:监控 MySQL 正在跑的 SQL,统计锁等待、IO、内存使用,帮 DBA 排查慢查询、性能瓶颈。默认开启会占用 几十 MB ~ 几百 MB 内存。一般生产环境都会打开,但小内存容器必须关。
performance_schema = OFF
root@XX:/# echo -e echo -e "[mysqld]\ninnodb_buffer_pool_size=128M\nmax_connect_errors=10\nwait_timeout=600\nperformance_schema = OFF" >> /etc/mysql/my.cnf
root@XX:/# exit
[root@XX ]# docker exec -it XX bash
root@XX:/# cat /etc/mysql/my.cnf

!includedir /etc/mysql/conf.d/
!includedir /etc/mysql/mysql.conf.d/
[mysqld]
innodb_buffer_pool_size=128M
max_connections=50
max_connect_errors=10
wait_timeout=600
performance_schema = OFF

root@XX:/# exit

#重启docker。


[root@XX]# free -mh
              total        used        free      shared  buff/cache   available
Mem:           1.7G        564M         91M        648K        1.1G        1.0G
Swap:          2.0G        2.0M        2.0G

Java进程

JDK8最大小堆内存、元数据区。

持续监控

持续观察内存,稳定后就不会再重启:
正常:可用内存稳定,Swap 少量使用
异常:可用内存持续下跌,需进一步优化 Java/SQL
[root@XX]# watch -n 2 free -mh

image.png

必须直面的短板

#个人服务监控要与公司生产环境对标。态度问题。

安全策略存在致命缺陷

"安全组3306是暴露到了公网,是在上一次导出数据备份后,忘记关闭"

点评:

"忘记关闭",而是没有建立“端口最小暴露”的基线规范。MySQL 3306 端口永远不应该直接暴露在公网,无论你是否需要导出数据。正确的做法是:

通过 VPN、跳板机或阿里云内网访问;

或者使用 mysqldump + scp 从内网导出,导出后无须打开端口。

教训:团队必须制定“公网端口白名单”制度,只允许 80、443、以及特定的管理端口(且管理端口必须限制来源IP)。任何临时开放都需双人确认并设自动回收。

监控与告警完全缺失

在3月份就观察到"并发连接数从950万骤降",却没有触发任何告警;4月份攻击持续三个多月,MySQL日志里每天上千条Access Denied,却直到服务宕机才发现。

点评:

这不是技术问题,是运维纪律问题。一个生产系统的监控应该包括:

安全监控:对Access denied、error日志进行实时告警(哪怕用 tail -f + 脚本也能做)。

资源监控:内存、CPU、磁盘、连接数,设置阈值告警(阿里云监控免费,你未启用)。

可用性监控:对外网站HTTP状态码监控(如 UptimeRobot)。

改进:立即配置阿里云云监控,对 MySQL 错误日志的关键词设置告警,对内存使用率 >80% 告警。

后续

其他安全措施后续输出文档。


标题:记博客被攻击导致宕机事件及攻击分析_202604
作者:yazong
地址:https://blog.llyweb.com/articles/2026/05/16/1778862465156.html