2026-03-09 11:53:58 +08:00
|
|
|
|
<?php
|
|
|
|
|
|
|
|
|
|
|
|
namespace App\Http\Middleware;
|
|
|
|
|
|
|
|
|
|
|
|
use Closure;
|
|
|
|
|
|
use Illuminate\Http\Request;
|
|
|
|
|
|
use Symfony\Component\HttpFoundation\Response;
|
|
|
|
|
|
|
|
|
|
|
|
class CloudflareProxies
|
|
|
|
|
|
{
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 文件功能:强制信任并解析 CDN 传导的真实客户端 IP。
|
|
|
|
|
|
* 解决 Herd 环境 / Nginx 本地反代时,丢失 X-Forwarded-For 导致全员 IP 变成 127.0.0.1 的问题。
|
|
|
|
|
|
*/
|
|
|
|
|
|
public function handle(Request $request, Closure $next): Response
|
|
|
|
|
|
{
|
|
|
|
|
|
// 优先采纳 Cloudflare 的 CF-Connecting-IP
|
|
|
|
|
|
if ($request->hasHeader('CF-Connecting-IP')) {
|
|
|
|
|
|
$realIp = $request->header('CF-Connecting-IP');
|
|
|
|
|
|
}
|
2026-03-12 07:16:32 +08:00
|
|
|
|
// 腾讯云 EdgeOne CDN 自定义回源头部(后台配置名:EO-Client-IP)
|
|
|
|
|
|
elseif ($request->hasHeader('EO-Client-IP')) {
|
|
|
|
|
|
$realIp = $request->header('EO-Client-IP');
|
|
|
|
|
|
}
|
|
|
|
|
|
// 其他国内 CDN 厂商(阿里云 DCDN 等)通用头部
|
2026-03-09 11:53:58 +08:00
|
|
|
|
elseif ($request->hasHeader('X-Real-IP')) {
|
|
|
|
|
|
$realIp = $request->header('X-Real-IP');
|
2026-03-12 07:16:32 +08:00
|
|
|
|
}
|
|
|
|
|
|
// 最后兜底:取 X-Forwarded-For 最左边第一个(真实客户端)IP
|
|
|
|
|
|
// 格式为 "真实客户端, CDN节点1, CDN节点2"
|
|
|
|
|
|
elseif ($request->hasHeader('X-Forwarded-For')) {
|
|
|
|
|
|
$realIp = trim(explode(',', $request->header('X-Forwarded-For'))[0]);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (! empty($realIp)) {
|
2026-03-09 11:53:58 +08:00
|
|
|
|
$request->server->set('REMOTE_ADDR', $realIp);
|
|
|
|
|
|
$request->headers->set('X-Forwarded-For', $realIp);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return $next($request);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|