frankenphp默认$_server['remote_addr']即真实ip,但前置代理时需配置trusted_proxies和trusted_headers,并在caddyfile中正确设置header_up转发头,否则symfony无法解析真实ip。

FrankenPHP 本身不走传统反向代理链路(比如 Nginx → PHP-FPM),它把 HTTP 服务和 PHP 运行时合并在一个进程里,所以 $_SERVER['REMOTE_ADDR'] 默认就是客户端真实 IP —— 但前提是没在前面再套一层代理(比如 CDN、Nginx、Cloudflare)。一旦加了前置代理,$_SERVER['REMOTE_ADDR'] 就变成那个代理的内网 IP,真实 IP 被藏在 X-Forwarded-For 或 X-Real-IP 里。Symfony 默认不信任这些头,直接调用 $request->getClientIp() 会返回代理 IP。
FrankenPHP + Symfony 必须显式配置 trusted proxies
Symfony 的 Request 类默认只信任 127.0.0.1 和 ::1,其他所有 X-Forwarded-* 头都被忽略。哪怕 FrankenPHP 已经把 X-Forwarded-For 正确传进来了,不告诉 Symfony “哪些 IP 是可信代理”,它就永远不解析。
- 在
config/packages/framework.yaml中添加trusted_proxies配置,值必须是**前置代理的真实 IP 段**(不是0.0.0.0/0) - 如果前面只有 FrankenPHP 自身(即无额外 Nginx/CDN),可设为
127.0.0.1或localhost - 如果前面还有一层 Nginx(例如用 Caddy 做反向代理到 FrankenPHP),则填 Nginx 所在机器的内网 IP,如
172.20.0.2 - 支持 CIDR 表示法,例如
192.168.1.0/24;多个用逗号分隔 - 同时要确保
trusted_headers包含x-forwarded-for和x-real-ip
framework:
trusted_proxies: ['127.0.0.1', '172.20.0.2']
trusted_headers: ['x-forwarded-for', 'x-real-ip', 'x-forwarded-proto']
Caddyfile 中必须正确设置转发头
FrankenPHP 通常以 Caddy 为 Web 层启动,Caddyfile 是唯一入口配置。若这里没传对头,后面全白搭。
-
reverse_proxy指令必须显式用header_up注入真实 IP 相关头 - 不能只依赖默认行为:Caddy 默认不加
X-Forwarded-For -
header_up X-Forwarded-For {remote_host}是最简方案,但生产环境建议用{http.request.header.X-Forwarded-For}, {remote_host}实现链式追加 - 务必加
header_up X-Real-IP {remote_host},部分老逻辑或中间件仍依赖这个头 - 如果用了 HTTPS 终止,还要加
header_up X-Forwarded-Proto https
your-domain.com {
reverse_proxy localhost:8080 {
header_up X-Forwarded-For {http.request.header.X-Forwarded-For}, {remote_host}
header_up X-Real-IP {remote_host}
header_up X-Forwarded-Proto {scheme}
}
}
验证真实 IP 是否生效的三个检查点
别只信日志或 dump,要逐层确认数据流是否完整抵达 Symfony。
- 在控制器里写一行
dump($request->server->get('HTTP_X_FORWARDED_FOR'), $request->server->get('HTTP_X_REAL_IP'), $request->getClientIp());,看三者是否一致且为公网 IP - 检查 Symfony 日志中
request.INFO行的client_ip字段,它已走完getClientIp()逻辑 - 用
curl -H "X-Forwarded-For: 1.2.3.4" http://your-domain.com/test手动注入头,确认是否被识别 —— 若能识别,说明配置通;若不能,大概率是trusted_proxies没覆盖到请求来源 IP
最容易被忽略的是:FrankenPHP 容器内部的网络模式。如果你用 docker-compose 启动 Caddy 和 FrankenPHP 两个服务,默认是 user-defined bridge 网络,此时 Caddy 的 {remote_host} 是容器 IP(如 172.20.0.3),而 Symfony 的 trusted_proxies 如果只写了 127.0.0.1,就会失效。必须把 Caddy 容器的 IP 段加入信任列表,或者改用 host 网络模式让它们共享宿主机网络栈。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











