hyperf 无法控制 mysql 客户端 ip 白名单,该白名单由携程 mysql 服务端通过 create user 指定 host、grant 权限匹配及网络层(安全组/防火墙/bind-address)放行三者共同决定;hyperf 仅负责按服务端账号的 host 要求配置连接参数。

Hyperf 应用连接携程 MySQL 服务时,**客户端 IP 白名单不由 Hyperf 控制,也不在 PHP 或应用层配置**。白名单生效的前提是:MySQL 服务端已按标准 MySQL 规则创建了带 Host 限制的账号,且网络链路(云安全组、宿主机防火墙、MySQL bind-address)已放行该客户端 IP。Hyperf 只负责发起符合该账号要求的连接请求。
Hyperf 配置中不能设置 MySQL IP 白名单
Hyperf 的 mysql 组件(如 hyperf/database 或 hyperf/db)只处理连接参数:host、port、username、password、database 等。它不提供、也不支持任何类似 whitelist_ips、allowed_hosts 的配置项。试图在 config/autoload/databases.php 中添加白名单字段,MySQL 服务端完全无视。
常见错误现象:
- 在 Hyperf 配置里写了
'whitelist' => ['10.20.30.40']→ 启动报错或静默忽略,连接仍失败 - Hyperf 能连通但报
Access denied for user 'app'@'10.20.30.41'→ 实际是服务端账号建成了'app'@'10.20.30.40',而当前机器 IP 是10.20.30.41
必须由携程 MySQL 服务端完成的三件事
你无法绕过这三层,仅靠改 Hyperf 就让白名单生效:
-
CREATE USER必须显式指定 IP 或网段:例如CREATE USER 'hyperf_app'@'10.20.30.40' IDENTIFIED BY 'xxx';。携程若提供的是 RDS 类托管实例,Host字段通常被忽略,白名单必须在携程云控制台「安全组」或「网络访问控制」里配 -
GRANT的user@host必须与CREATE USER完全一致:执行GRANT SELECT ON mydb.* TO 'hyperf_app'@'10.20.30.40';,写成@'%'或@'10.20.30.%'都会失败 -
bind-address和防火墙必须允许该连接抵达:如果携程 MySQL 实例绑定了bind-address = 127.0.0.1,或安全组未放行10.20.30.40:3306,Hyperf 即使填对所有参数也会卡在Connection refused
Hyperf 连接配置需严格匹配服务端账号 Host
假设携程侧已为你开通账号 'hyperf_app'@'10.20.30.40',那么你的 config/autoload/databases.php 中对应配置必须满足:
-
'host'值应为该 IP 所在网络可达的 MySQL 服务地址(如内网 VIP10.20.30.10),不是客户端本机 IP -
'username'必须为'hyperf_app',不能多空格、大小写错误 - 不要在
'host'字段填'10.20.30.40'—— 那是客户端来源 IP,不是服务端地址 - 测试连接前,先在 Hyperf 服务器上手动执行:
mysql -u hyperf_app -p -h 10.20.30.10,确认底层可通
示例正确片段:
'default' => [
'driver' => 'mysql',
'host' => '10.20.30.10',
'port' => 3306,
'database' => 'mydb',
'username' => 'hyperf_app',
'password' => 'xxx',
// 其他字段...
],
最容易被忽略的验证点:客户端真实出口 IP
Hyperf 应用跑在容器或云主机里,其对外暴露的 IP 不一定是配置文件里写的那个。尤其在以下场景:
- Docker 桥接模式下,容器默认使用宿主机 IP 出口;若宿主机有多个网卡,得确认走的是哪个 IP
- K8s Pod 经 NodePort 或 Ingress 访问外部 MySQL,实际源 IP 是 Node 节点 IP,不是 Pod IP
- 携程 MySQL 白名单只认 TCP 层的
REMOTE_ADDR,不认 HTTP Header 里的X-Forwarded-For
务必登录到运行 Hyperf 的机器,执行 curl ifconfig.me 或 ip route get 8.8.8.8 | awk '{print $7}' 查出真实出口 IP,再拿这个 IP 去携程侧申请白名单。填错一个数字,整个连接就断在认证前。











