在經過 Proxy、CDN 或 Load Balancer 時,$_SERVER['REMOTE_ADDR'] 可能只取得代理伺服器 IP。本函式依序檢查 HTTP_CLIENT_IP、HTTP_X_FORWARDED_FOR、REMOTE_ADDR,並以正規表示式擷取合法 IPv4 格式,若皆無則回傳 unknown。
<?php
/**
* 取得客戶端真實 IP
* @return string IPv4 位址或 'unknown'
*/
function getClientIP() {
$cip = '';
if (!empty($_SERVER['HTTP_CLIENT_IP'])) {
$cip = $_SERVER['HTTP_CLIENT_IP'];
} elseif (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
// 可能包含多個 IP,取第一個
$list = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);
$cip = trim($list[0]);
} elseif (!empty($_SERVER['REMOTE_ADDR'])) {
$cip = $_SERVER['REMOTE_ADDR'];
}
// 驗證 IPv4 格式
if (preg_match('/^[\d\.]{7,15}$/', $cip)) {
return $cip;
}
return 'unknown';
}
?>
HTTP_CLIENT_IP:部分代理會設定此標頭,優先度最高。HTTP_X_FORWARDED_FOR:標準代理標頭,格式為 client, proxy1, proxy2...,取第一個為客戶端 IP。REMOTE_ADDR:直接連線時的來源 IP,若經過代理則為代理 IP。/^[\d\.]{7,15}$/ 簡易過濾 IPv4 格式(如 1.2.3.4 至 123.123.123.123),不支援 IPv6。unknown 表示無法判斷,建議記錄日誌以利追蹤。標頭可被偽造,若用於存取控制、記帳等關鍵邏輯,請搭配可信任的 Proxy 設定(如 Nginx real_ip_header、set_real_ip_from)在 Web Server 層面解析真實 IP,PHP 僅讀取已驗證的變數。