仅开放3306端口不够,需结合最小ip段白名单、bind-address严格配置(如10.0.1.10而非0.0.0.0)、mysql用户host精确授权(如'10.0.1.%')及rds与自建环境差异处理,三者形成漏斗式防护。

云服务器安全组只放行3306端口还不够
仅开放3306端口是基础操作,但生产环境里这等于把门虚掩着。真实风险来自:允许0.0.0.0/0访问、没限制源IP段、没区分内网/公网流量。AWS、阿里云、腾讯云的安全组规则本质是无状态防火墙,它不识别MySQL协议内容,只按IP+端口+协议放行。
- 必须用最小IP段,比如应用服务器所在VPC子网的CIDR(如
10.0.1.0/24),而不是单个IP——后者运维成本高且易失效 - 禁止
0.0.0.0/0或::/0(IPv6全放行),哪怕临时调试也不该写进安全组 - 若数据库与应用同VPC,优先用内网域名(如
rds.mysql.internal)连接,此时安全组规则应只允许内网IP段,彻底屏蔽公网路径 - 跨区域或混合云场景下,别走公网,改用云厂商私有链路(如AWS Direct Connect、阿里云CEN),此时安全组只需放行对端私网IP,而非互联网出口IP
MySQL服务本身bind-address配置常被忽略
安全组只是第一道过滤,MySQL进程自己是否监听公网才是第二关。默认bind-address在多数Linux发行版中是127.0.0.1,意味着即使安全组开了3306,外部也连不上——这是保护机制,不是bug。
- 要支持远程连接,必须显式修改
my.cnf里的bind-address为0.0.0.0或具体内网IP(如10.0.1.10),不能只改安全组 -
bind-address = 0.0.0.0后,务必配合安全组做IP白名单,否则等于主动暴露端口 - Windows环境下MySQL 8.0+默认可能启用
skip-networking,需确认该配置项已被注释或删除 - 重启MySQL服务后,用
netstat -tlnp | grep :3306验证监听地址是否生效(Linux)或Get-NetTCPConnection -LocalPort 3306(PowerShell)
远程用户授权必须限定host,不能用'%'通配
安全组放行IP、MySQL监听了外网端口,接下来就是权限控制。很多故障源于GRANT ... TO 'user'@'%'这种写法——它允许该用户从任意IP登录,一旦密码泄露或弱口令被爆破,数据库就裸奔了。
- 授权时host部分必须和安全组白名单严格对应,例如安全组只放
10.0.1.0/24,那就用'user'@'10.0.1.%'或更精确的'user'@'10.0.1.5' - 避免
'root'@'%',root账号应仅限'localhost'或跳板机IP - 执行
GRANT后必须跟FLUSH PRIVILEGES,否则权限不生效;但注意该命令不刷新当前已建立的连接权限 - 检查现有用户:运行
SELECT user, host FROM mysql.user;,删掉所有host列为%且非业务必需的账号
云数据库RDS和自建MySQL的安全组逻辑不同
如果你用的是云厂商托管的RDS(如AWS RDS、阿里云RDS),安全组配置对象不是EC2/CVM实例,而是RDS实例本身。这意味着:规则作用范围更窄、无需关心OS层firewalld/ufw、且RDS默认禁用root远程登录。
- RDS安全组规则目标是RDS实例的ENI(弹性网卡),源IP填应用服务器的私网IP段即可,不用管RDS自己的IP(它是动态分配的)
- RDS不支持
bind-address配置,它的网络入口完全由安全组和VPC路由表控制 - 自建MySQL跑在ECS上时,既要配ECS的安全组,也要配ECS操作系统自带的防火墙(如
ufw或firewalld),而RDS省去了后者 - RDS强制要求TLS连接时,安全组仍只管3306端口通断,加密协商由MySQL协议层完成,不依赖安全组
netstat输出,又或者授权用了%却以为安全组已经兜底。这些细节不验证,配置就只是纸面功夫。











