You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Laravel 12 Docker容器中获取真实客户端IP的问题

问题:Docker环境下Laravel无法获取客户端真实IP

尝试获取注册请求的客户端真实IP,但代码返回的是Docker容器相关地址(172.18.0.1),已做以下配置:

bootstrap/app.php

->withMiddleware(function (Middleware $middleware) {
    $middleware->prepend(TrustProxies::class);
})

.env

TRUST_PROXIES=*
TRUST_PROXIES_HEADERS=HEADER_X_FORWARDED_FOR

app.conf(Nginx)

server {
    listen 80;
    server_name localhost;

    root /var/www/public;
    index index.php index.html;

    location / {
        try_files $uri $uri/ /index.php?$query_string;

        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }

    location ~ \.php$ {
        fastcgi_pass app-AxsSEMEFO:9000;
        fastcgi_index index.php;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;

        # Asegúrate de pasar los headers como variables correctas
        fastcgi_param HTTP_X_FORWARDED_FOR $proxy_add_x_forwarded_for;
        fastcgi_param HTTP_X_REAL_IP $remote_addr;
        fastcgi_param HTTP_X_FORWARDED_PROTO $scheme;
    }
}

测试代码

Route::get('/debug-ip', function () {
    return response()->json([
        'Laravel IP' => request()->ip(),
        '_SERVER["HTTP_X_FORWARDED_FOR"]' => $_SERVER['HTTP_X_FORWARDED_FOR'] ?? 'not set',
        '_SERVER["X_FORWARDED_FOR"]' => $_SERVER['X_FORWARDED_FOR'] ?? 'not set',
        'headers' => request()->headers->all(),
    ]);
});

测试结果

{
  "Laravel IP": "172.18.0.1",
  "_SERVER[\"HTTP_X_FORWARDED_FOR\"]": "172.18.0.1",
  "_SERVER[\"X_FORWARDED_FOR\"]": "not set",
  "headers": {
    "cookie": [
      "XSRF-TOKEN=eyJpdiI6IjBQYzVoRlA2VEx2bkpsV0gyZ1hlK0E9PSIsInZhbHVlIjoicklMajJtSnJ6K3ZPdi9WMXpKRzMxK2xMajBRQjByeWk0WmUrK1BBRXpaTjVSUHpnS1FyQXRvVFJKRFNiUHA3Z3BOZDFqaE1Yd2ZoeVdwbHJTZzBibTlxdjk5Z3RoU1QxUmNVOTFNQWJMcWRwWXkrUWpUVFdXazdqWnpydkErREIiLCJtYWMiOiJlMzE3MWYxODRkZTdiYmRhNGE5MDEwZDkyNDQ1MjEzNDNlYjI1YTRjMWQ2MmRhMWQ4NDhmZTUwYmZmZTFhYTdkIiwidGFnIjoiIn0%3D; laravel_session=eyJpdiI6ImRVa0V5QzZIU21Ob0lRUktiMWVsU3c9PSIsInZhbHVlIjoiMEdLNjV6d3MvNmhZUnBXanpxWTJjQitXVkNJdjdLdlZVY0NOakRoa1N1UGM0eTJkL1lxcHFITFg3WU1KRXpJWXg2TEtEdWR3QVJzbE9CZVhuVDRpSFl2cUZINnplcUwyL1E2QmlXcnJGUTFyLy84RGx2eHN3TmdScGY0SnZNZW4iLCJtYWMiOiIyNDkxZjI5ZDg5ODM3ODhlYzFhYWMyOWYxYzFkODdlMDk1NjY3Y2M0MThiYjAxOTRjODUxMmZhZTU1ODVmMjlkIiwidGFnIjoiIn0%3D"
    ],
    "accept-encoding": [
      "gzip, deflate, br, zstd"
    ],
    "sec-fetch-dest": [
      "document"
    ],
    "sec-fetch-user": [
      "?1"
    ],
    "sec-fetch-mode": [
      "navigate"
    ],
    "sec-fetch-site": [
      "none"
    ],
    "accept-language": [
      "es-419,es;q=0.9"
    ],
    "sec-gpc": [
      "1"
    ],
    "accept": [
      "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8"
    ],
    "user-agent": [
      "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36"
    ],
    "upgrade-insecure-requests": [
      "1"
    ],
    "sec-ch-ua-platform": [
      "\"Windows\""
    ],
    "sec-ch-ua-mobile": [
      "?0"
    ],
    "sec-ch-ua": [
      "\"Brave\";v=\"137\", \"Chromium\";v=\"137\", \"Not/A)Brand\";v=\"24\""
    ],
    "cache-control": [
      "max-age=0"
    ],
    "connection": [
      "keep-alive"
    ],
    "host": [
      "localhost:3020"
    ],
    "x-forwarded-proto": [
      "http"
    ],
    "x-real-ip": [
      "172.18.0.1"
    ],
    "x-forwarded-for": [
      "172.18.0.1"
    ]
  }
}

解决方案

1. 修正Nginx配置错误

location / 块中的 proxy_set_header 指令仅适用于反向代理(proxy_pass)场景,当前Nginx是直接处理静态文件并通过FastCGI转发到PHP容器,这些指令无效且可能干扰IP传递,需删除:

location / {
    try_files $uri $uri/ /index.php?$query_string;
    # 移除所有proxy_set_header指令
}

2. 理解Docker端口映射的IP特性

你当前用 localhost:3020 访问容器,Docker端口映射会将请求源IP转换为Docker网桥网关地址(172.18.0.1),这是本地访问的正常现象:

  • 若要测试真实外部IP,需用宿主机的局域网IP(如192.168.x.x)访问,或从外部网络(公网)发起请求
  • 生产环境中,若Nginx部署在云服务器或有前置负载均衡,$remote_addr 会是真实客户端IP(或负载均衡的IP,需配置TrustProxies信任该IP)

3. 优化Laravel TrustProxies配置

将 TRUST_PROXIES 从通配符 * 改为具体的Docker网段(更安全),比如你的Docker网桥网段是172.18.0.0/16:

TRUST_PROXIES=172.18.0.0/16
# 保留默认头配置即可,无需单独设置TRUST_PROXIES_HEADERS

同时,确保 App\Http\Middleware\TrustProxies 类的 $headers 属性包含正确的转发头:

protected $headers = Request::HEADER_X_FORWARDED_FOR | Request::HEADER_X_FORWARDED_HOST | Request::HEADER_X_FORWARDED_PORT | Request::HEADER_X_FORWARDED_PROTO | Request::HEADER_X_FORWARDED_AWS_ELB;

4. 验证配置

修改配置后,重启Nginx和Laravel容器,用宿主机局域网IP访问 /debug-ip,即可看到真实客户端IP。


内容的提问来源于stack exchange,提问作者user30680575

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 00:17:04