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

PHP 獲取用戶真實 IP 深度解析:HTTP_X_FORWARDED_FOR、HTTP_VIA、REMOTE_ADDR 在各類代理場景下的行為差異

     編輯:PHP 相關知識

PHP 獲取用戶真實 IP 深度解析:HTTP_X_FORWARDED_FOR、HTTP_VIA、REMOTE_ADDR 在各類代理場景下的行為差異

在經過代理、CDN、負載均衡的複雜網絡拓撲中,$_SERVER['REMOTE_ADDR'] 往往不是用戶真實 IP。本文系統梳理三大關鍵變量在**五種代理匿名級別**下的具體表現,並提供生產級獲取策略。

三大變量定義

變量含義來源
REMOTE_ADDR直接連接 Web 服務器的客戶端 IP(最後一級代理或用戶)TCP 連接層,不可偽造
HTTP_X_FORWARDED_FOR (XFF)代理鏈路 IP 列表:client, proxy1, proxy2...代理服務器添加的 HTTP 頭,可偽造
HTTP_VIA代理服務器標識信息(軟件名/版本/主機名)代理服務器添加
HTTP_CLIENT_IP部分代理/CDN 設置的客戶端 IP 頭非標準,視具體設備而定

五種代理匿名級別下的變量表現

代理類型REMOTE_ADDRHTTP_VIAHTTP_X_FORWARDED_FOR隱匿效果
無代理用戶真實 IP無/不顯示無/不顯示完全透明
透明代理
(Transparent)
最後一級代理 IP代理 IP用戶真實 IP
(多級代理時逗號分隔)
暴露真實 IP,僅繞過訪問限制
匿名代理
(Anonymous)
最後一級代理 IP代理 IP代理 IP
(隱藏真實 IP,但暴露使用代理)
隱藏真實 IP,但可被識別為代理流量
欺騙代理
(Distorting)
代理 IP代理 IP隨機/偽造 IP隱藏真實 IP 並欺騙目標服務器
高匿代理
(Elite/High Anonymity)
代理 IP無/不顯示無/不顯示完全偽裝為普通用戶,最難檢測

關鍵洞察

  1. XFF 可偽造:客戶端可發送偽造 X-Forwarded-For: 1.2.3.4,**Web 應用層無法單憑 XFF 判斷真實 IP**。
  2. 入口層清洗是核心:必須在 **Nginx/CDN/WAF 入口層** 信任已知代理 IP 範圍,清洗/重寫 XFF,應用層只信任經清洗的值。
  3. 多級代理取首個非內網 IP:XFF 格式 client, proxy1, proxy2,真實客戶端通常在**最左側**,需跳過內網/保留地址段(10.x、172.16-31.x、192.168.x、127.x、169.254.x)。

生產級 Nginx 入口層配置(標準做法)

# nginx.conf http 段
# 定義受信代理 IP 範圍(SLB、CDN 回源 IP、內部網關)
set_real_ip_from 10.0.0.0/8;        # 內網/負載均衡
set_real_ip_from 172.16.0.0/12;     # 內網
set_real_ip_from 100.64.0.0/10;     # 運營商級 NAT (CGNAT)
set_real_ip_from 192.168.0.0/16;    # 內網
# 添加具體 CDN/SLB IP 段,如:
# set_real_ip_from 1.2.3.0/24;      # 阿里云 SLB
# set_real_ip_from 47.0.0.0/8;      # 騰訊云 CLB

real_ip_header X-Forwarded-For;     # 從此頭獲取真實 IP
real_ip_recursive on;               # 遞歸查找:跳過受信代理,取第一個非受信 IP

# 可選:記錄原始 XFF 供審計
log_format main '$remote_addr - $realip_remote_addr [$time_local] "$request" '
                '$status $body_bytes_sent "$http_referer" '
                '"$http_user_agent" "$http_x_forwarded_for"';

配置後,**PHP 直接使用 $_SERVER['REMOTE_ADDR'] 即為真實客戶端 IP**,無需複雜應用層邏輯。

PHP 兜底獲取函數(僅作二次校驗/無入口層控制權場景)

function getRealIp(): string {
    $trustedProxies = ['10.0.0.0/8', '172.16.0.0/12', '192.168.0.0/16']; // 需與 Nginx 一致
    
    $headers = ['HTTP_CLIENT_IP', 'HTTP_X_FORWARDED_FOR', 'HTTP_X_FORWARDED', 'HTTP_FORWARDED_FOR', 'HTTP_FORWARDED'];
    
    foreach ($headers as $header) {
        if (!empty($_SERVER[$header])) {
            $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;
                }
            }
        }
    }
    
    // 兜底:REMOTE_ADDR(可能為內網代理 IP)
    return $_SERVER['REMOTE_ADDR'] ?? '0.0.0.0';
}

IPv6 支持補充

  • filter_var($ip, FILTER_VALIDATE_IP) 自動支持 IPv4/IPv6
  • 內網段擴展:fc00::/7 (ULA)、fe80::/10 (Link-local)、::1/128 (Loopback)
  • Nginx set_real_ip_from 支持 IPv6 CIDR

黃金法則:**真實 IP 識別責任鏈:客戶端 → 邊緣代理 (CDN/SLB/WAF) → 應用負載均衡 → Web 服務器 (Nginx) → PHP**。**在 Nginx 層通過 real_ip_recursive 解決**,PHP 層只做兜底與審計。任何嘗試在 PHP 中單獨解析 XFF 的方案在安全性上都是不完備的。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved