数据库账号只允许业务服务器IP访问
当数据库和业务服务器分离部署时,把 MySQL 账号的访问来源限制为固定 IP,是降低数据泄露风险最有效的做法之一。
即使账号密码意外泄露,攻击者也没办法直接从其他机器连接数据库。
下面我按零基础可照做的顺序,讲清楚 MySQL 白名单限制来源 IP 的配置方法、验证方式和常见坑。
为什么用 MySQL 账号白名单限制来源 IP
很多数据泄露事件并不是因为密码太弱,而是数据库端口直接暴露在公网,且账号没有限制来源。
MySQL 本身在账号体系里内置了来源地址校验:一个用户是由 用户名@主机 共同定义的。
这里的主机就是白名单,MySQL 官方叫 Host,日常运维中常直接叫“账号白名单”。
限制来源 IP 之后,即使业务服务器上的配置被别人拿到,也无法从家里、办公室或其他云主机上直接连接数据库;
同时还能减少暴力破解、SQL 注入利用等自动化攻击的暴露面。
配置前需要确认的三件事
在动手修改之前,先确认下面几个信息,避免中途出错:
- 业务服务器真正的出口 IP,不是内网 IP。可以登录业务服务器执行
curl ifconfig.me或curl cip.cc查看公网出口;如果是云服务器,也可以去云控制台看公网 IP。 - 要限制的数据库账号名,以及当前允许登录的主机范围。
- 数据库账号是否有权限执行
CREATE USER、ALTER USER、DROP USER等操作,通常建议使用 root 或拥有全局 USER 管理权限的账号执行。
确认这些信息后,用数据库管理工具(命令行、phpMyAdmin、Navicat 都可以)连接 MySQL,开始正式操作。
查看现有账号的 Host 允许范围
先用一条 SQL 检查当前账号的主机限制情况:
SELECT user, host, plugin FROM mysql.user;
host 字段显示的是该账号允许从哪些 IP 或网段登录。
常见的几种取值含义如下:
%:不限制来源,任何 IP 都能登录localhost:仅限本机登录192.168.1.100:仅限这个 IP 登录192.168.1.%:仅限该网段登录
如果你的账号 host 显示为 %,就说明当前没有白名单限制,需要重点修改。
修改已有账号,只放行业务服务器 IP
假设业务服务器出口 IP 为 203.0.113.10,账号名为 app_user,需要把这个账号限制成只能从该 IP 连接,执行下面这条命令:
ALTER USER 'app_user'@'%' IDENTIFIED BY 'your_strong_password';
RENAME USER 'app_user'@'%' TO 'app_user'@'203.0.113.10';
FLUSH PRIVILEGES;
实际操作中,更推荐先创建一个严格限定 host 的新账号,再迁移权限,避免误改原有账号导致应用瞬断。
创建新的白名单专用账号(推荐做法)
如果你的业务允许短暂切换账号,或者是新部署环境,更稳妥的方式是直接新建一个仅限指定 IP 访问的账号:
CREATE USER 'app_user'@'203.0.113.10' IDENTIFIED BY 'your_strong_password';
GRANT ALL PRIVILEGES ON your_db.* TO 'app_user'@'203.0.113.10';
FLUSH PRIVILEGES;
把 your_db 替换成实际数据库名,权限范围按业务最小化原则给,能用 SELECT、INSERT、UPDATE、DELETE 就不要直接给 ALL PRIVILEGES。
如果你确认业务不再使用旧的开放账号,再删除:
DROP USER 'old_user'@'%';
删除前务必确认另一台服务器或本机没有在用这个旧账号连接,否则会直接影响线上业务。
如何验证白名单是否生效
改完配置后,不要只看配置结果,一定要实际测试连接效果。
在业务服务器上执行:
mysql -h 数据库IP -u app_user -p
能正常登录说明放行成功。
然后回到你本地电脑或另一台不属于白名单的服务器,执行同样的连接命令,预期会收到类似下面的报错:
ERROR 1130 (HY000): Host '你的IP' is not allowed to connect to this MySQL server
出现这个报错,就说明白名单已经生效了。
注意,MySQL 一旦无法匹配 host,会直接拒绝 TCP 连接握手,不会进入密码校验阶段,因此日志里不会留下密码错误记录。
避坑:改完白名单后应用连不上数据库
最常见的问题是 Host 'x.x.x.x' is not allowed to connect。
排查时按这个顺序检查:
- 确认业务服务器出口 IP 是否发生变化。有些云服务器的公网 IP 是动态的,重新关机开机后可能变了;NAT 出口和多线机房也需要以实际出口 IP 为准。
- 检查 MySQL 服务器防火墙和安全组是否放行了 3306 端口,白名单放行的是账号层,安全组和 iptables 如果没放通同样连不上。
- 确认
FLUSH PRIVILEGES已经执行,或者通过service mysql restart重启过数据库,避免权限缓存影响判断。 - 业务服务器如果用内网 IP 连接 RDS 或云数据库,白名单里要填内网 IP 或对应网段,而不是填公网 IP。
如果你不确定当前账号到底匹配了哪个 host,可以再次执行:
SELECT user, host FROM mysql.user WHERE user = 'app_user';
确认记录里同时存在 @'%' 和 @'203.0.113.10' 时,
MySQL 会优先选择更精确匹配的 host,
旧账号建议及时删除,
避免误连。
另外一个容易忽略的点:RENAME USER 之后,原账号的密码和权限会原样保留,但如果有程序仍然按旧账号名连接,连接会被拒绝。
生产环境改配置前一定先看业务代码里的数据库连接串。
补充:允许一个网段的账号写法
如果业务服务器出口 IP 不固定但都在同一网段,可以按网段限制:
CREATE USER 'app_user'@'203.0.113.%' IDENTIFIED BY 'your_strong_password';
网段写法只推荐在确实无法固定 IP 时使用,开放范围越大,白名单的意义越小。
MySQL 账号白名单的配置核心就是理解 host 字段的匹配逻辑。
你只需记住两条:第一,@'%' 等于没限制,生产环境一定要改成具体 IP;
第二,任何白名单改动后都要从放行和拒绝两个角度分别验证,确认线上应用和外部访问都符合预期。
按本文步骤操作完成后,你的业务服务器就能正常连接数据库,其他来源会被 MySQL 直接拒绝,数据库账号的暴露风险会明显下降。
如果后续遇到安全组、防火墙或数据库连接串相关问题,也可以继续在本站搜索对应教程。