在 Web 開發中,準確獲取客戶端真實 IP 是實現訪問控制、防刷機制、日誌審計等功能的基礎。然而由於負載均衡、反向代理、CDN 等網路架構的普及,單純使用 $_SERVER['REMOTE_ADDR'] 往往無法獲取真實客戶 IP。本文深入解析三大核心 HTTP 頭部字段的差異、適用場景與安全風險,並提供生產環境的最佳實踐方案。
格式:client, proxy1, proxy2, ...(以逗號分隔的 IP 鏈)
產生原因:
安全風險:完全可偽造。客戶端可任意發送此頭部,第一個 IP(最左側)可能為攻擊者構造的虛假 IP。
最佳處理:僅信任「直接連接你的伺服器的上一跳 IP」(即鏈中最後一個可信代理的 IP),需配合伺服器配置(如 Nginx real_ip_header 與 set_real_ip_from)使用。
特點:部分代理伺服器用於記錄原始客戶端 IP 的非標準頭部。
現狀:極少數代理使用,不可靠,不建議作為主要依據。
含義:TCP 連接的直接來源 IP(即直接與你的 PHP 進程建立連接的那一方)。
適用場景:無任何代理、負載均衡的單點架構。
代理環境下表現:若前端有 Nginx 反向代理,此值將固定為 Nginx 伺服器 IP(如 127.0.0.1 或內網 IP)。
# Nginx 配置
set_real_ip_from 10.0.0.0/8; # 信任的代理 IP 段
real_ip_header X-Forwarded-For; # 使用哪個頭部
real_ip_recursive on; # 遞歸查找最後一個可信 IP
PHP 端直接讀取 $_SERVER['REMOTE_ADDR'] 即為真實客戶 IP。
function getRealIp(): string {
$trustedProxies = ['10.0.0.1', '192.168.1.100']; // 你的已知代理 IP
$remoteAddr = $_SERVER['REMOTE_ADDR'] ?? '';
// 只有當直接連接者是受信代理時,才解析 XFF
if (in_array($remoteAddr, $trustedProxies)) {
$xff = $_SERVER['HTTP_X_FORWARDED_FOR'] ?? '';
$ips = array_map('trim', explode(',', $xff));
// 取最後一個非受信代理 IP(即真實客戶 IP)
foreach (array_reverse($ips) as $ip) {
if (!in_array($ip, $trustedProxies) && filter_var($ip, FILTER_VALIDATE_IP)) {
return $ip;
}
}
}
return $remoteAddr; // 直連或不可信代理環境
}
HTTP_X_FORWARDED_FOR 的第一個 IP → 極易被偽造繞過 IP 限制HTTP_CLIENT_IP → 非標準、極易偽造real_ip 模組、雲廠商提供的真實 IP 頭部如 CF-Connecting-IP、True-Client-IP 等)文章作者曾通過偽造 X-Forwarded-For 繞過投票網站的 IP 限制,後該網站修補漏洞改用代理池檢測。這說明:
總結:獲取真實 IP 的核心在於信任鏈的建立——在基礎設施層(Nginx/Cloudflare/ALB)完成真實 IP 的識別與注入,應用層直接使用經過驗證的 REMOTE_ADDR,才是穩健、安全的架構選擇。