首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 綜合知識

PHP 精準獲取伺服器真實 IP 地址(解決反向代理問題)

     編輯:PHP 綜合知識

問題場景

使用 $_SERVER['HTTP_HOST'] 或 $_SERVER['SERVER_ADDR'] 獲取伺服器 IP 時,若架構包含反向代理(Nginx、CDN、負載均衡器),取得的往往是內網 IP 或代理 IP,而非真實對外 IP。

常見伺服器變數對照

變數說明代理環境下表現
HTTP_HOST客戶端請求的 Host 標頭可能是代理轉發的內網域名/IP
SERVER_ADDR伺服器網卡綁定 IP通常是內網 IP(如 10.x.x.x, 192.168.x.x)
HTTP_X_FORWARDED_FOR客戶端真實 IP 鏈(代理附加)格式:client, proxy1, proxy2
HTTP_X_FORWARDED_HOST原始請求的 Host保留原始域名,繞過代理修改
HTTP_X_REAL_IPNginx 常用單一真實 IP需代理配置 proxy_set_header X-Real-IP $remote_addr;

最佳實作:多層級回退策略

function getServerRealIP() {
    // 1. 優先檢查代理轉發的原始 Host(適用於虛擬主機場景)
    if (!empty($_SERVER['HTTP_X_FORWARDED_HOST'])) {
        return $_SERVER['HTTP_X_FORWARDED_HOST'];
    }
    
    // 2. 其次使用標準 Host(無代理或代理透傳時)
    if (!empty($_SERVER['HTTP_HOST'])) {
        return $_SERVER['HTTP_HOST'];
    }
    
    // 3. 最後回退 SERVER_ADDR(僅能獲取伺服器綁定 IP)
    return $_SERVER['SERVER_ADDR'] ?? 'unknown';
}

// 獲取客戶端真實 IP(非伺服器 IP)
function getClientRealIP() {
    $headers = [
        'HTTP_X_FORWARDED_FOR',  // 標準代理鏈
        'HTTP_X_REAL_IP',        // Nginx 常用
        'HTTP_CLIENT_IP',        // 部分代理使用
        'HTTP_CF_CONNECTING_IP', // Cloudflare
        'REMOTE_ADDR'            // 直連或最後回退
    ];
    
    foreach ($headers as $header) {
        if (!empty($_SERVER[$header])) {
            // X-Forwarded-For 可能包含多個 IP,取第一個非私有 IP
            $ips = array_map('trim', explode(',', $_SERVER[$header]));
            foreach ($ips as $ip) {
                if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE)) {
                    return $ip;
                }
            }
            // 都為私有 IP 時返回第一個
            return $ips[0];
        }
    }
    return 'unknown';
}

Nginx 反向代理必要配置

location / {
    proxy_pass https://backend;
    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-Host $host;
    proxy_set_header X-Forwarded-Proto $scheme;
}

安全性提醒

  • 不可信任客戶端傳遞的 Header:僅信任已知代理層(如公司內部 Nginx、Cloudflare)附加的 Header
  • 配置 trusted_proxies:框架(Laravel、Symfony)提供受信任代理 IP 範圍設定,自動解析真實 IP
  • 避免直接暴露 $_SERVER:封裝為服務類別,集中管理解析邏輯

框架整合範例

// Laravel: config/app.php
'trusted_proxies' => ['10.0.0.0/8', '192.168.0.0/16'], // 內網代理範圍
// 控制器中直接使用
$request->ip(); // 自動解析真實客戶端 IP
$request->getHost(); // 自動解析真實 Host

// Symfony: Request::setTrustedProxies()
Request::setTrustedProxies(['10.0.0.0/8'], Request::HEADER_X_FORWARDED_FOR | Request::HEADER_X_FORWARDED_HOST);
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved