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

PHP 獲取 IP 地址完整方案:伺服器 IP、客戶端 IP 與地理定位

     編輯:PHP 相關知識

IP 獲取分類與應用場景

類型用途關鍵變數/指令
伺服器公網 IP對外服務識別、授權驗證、多 IP 輪換ifconfig, ip addr, curl ifconfig.me
客戶端真實 IP風控、日誌審計、地理定位、個性化內容$_SERVER['REMOTE_ADDR'], HTTP_X_FORWARDED_FOR, HTTP_CLIENT_IP

一、獲取伺服器公網 IP(Linux 環境)

方法 1:解析 ifconfig/ip 指令輸出

<?php
/**
 * 獲取伺服器所有非內網 IP
 * @return array IP 陣列
 */
function getServerIps() {
    // 使用 ip 指令(現代 Linux 推薦)或 ifconfig
    $cmd = "ip -4 addr show scope global 2>/dev/null | grep -oP '(?<=inet\\s)\\d+(\\.\\d+){3}'";
    // 兼容舊系統
    if (empty(trim(shell_exec($cmd)))) {
        $cmd = "/sbin/ifconfig | grep -oP '(?<=inet\\s)\\d+(\\.\\d+){3}' | grep -v '^127\\.'";
    }
    exec($cmd, $ips);

    // 過濾私有/保留 IP 範圍
    $filtered = array_filter($ips, function($ip) {
        $long = ip2long($ip);
        // 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16, 127.0.0.0/8
        return !(
            ($long & 0xFF000000) == 0x0A000000 || // 10.x.x.x
            ($long & 0xFFF00000) == 0xAC100000 || // 172.16-31.x.x
            ($long & 0xFFFF0000) == 0xC0A80000 || // 192.168.x.x
            ($long & 0xFF000000) == 0x7F000000    // 127.x.x.x
        );
    });

    shuffle($filtered); // 隨機排序,利於輪換
    return array_values($filtered);
}

$ips = getServerIps();
print_r($ips);
// Array ( [0] => 203.0.113.45 [1] => 198.51.100.23 )
?>

方法 2:呼叫外部 API(簡單但有依賴)

<?php
function getPublicIpApi() {
    $apis = array(
        'https://api.ipify.org',
        'https://ifconfig.me/ip',
        'https://ipinfo.io/ip',
        'https://icanhazip.com'
    );
    foreach ($apis as $api) {
        $ctx = stream_context_create(array('http' => array('timeout' => 3)));
        $ip = @file_get_contents($api, false, $ctx);
        if ($ip && filter_var(trim($ip), FILTER_VALIDATE_IP)) {
            return trim($ip);
        }
    }
    return false;
}
?>

二、獲取客戶端真實 IP(穿透代理/負載均衡)

標準獲取函數

<?php
/**
 * 獲取客戶端真實 IP
 * @return string IP 位址
 */
function getClientIp() {
    $headers = array(
        'HTTP_CLIENT_IP',       // 標準代理頭
        'HTTP_X_FORWARDED_FOR', // 標準代理鏈(可能多個 IP,逗號分隔)
        'HTTP_X_FORWARDED',     // 較少見
        'HTTP_X_CLUSTER_CLIENT_IP', // 某些負載均衡
        'HTTP_FORWARDED_FOR',   // RFC 7239
        'HTTP_FORWARDED',       // RFC 7239
        'REMOTE_ADDR'           // 直接連線/最後防線
    );

    foreach ($headers as $header) {
        if (!empty($_SERVER[$header])) {
            $ips = explode(',', $_SERVER[$header]);
            foreach ($ips as $ip) {
                $ip = trim($ip);
                // 驗證 IP 格式並排除私有 IP
                if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE)) {
                    return $ip;
                }
            }
        }
    }

    // 兜底:直接連線 IP(可能為私有 IP)
    return $_SERVER['REMOTE_ADDR'] ?? '0.0.0.0';
}

// 簡化版(常見場景足夠)
function getClientIpSimple() {
    if (!empty($_SERVER['HTTP_CLIENT_IP']) && filter_var($_SERVER['HTTP_CLIENT_IP'], FILTER_VALIDATE_IP)) {
        return $_SERVER['HTTP_CLIENT_IP'];
    }
    if (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
        $ips = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);
        foreach ($ips as $ip) {
            $ip = trim($ip);
            if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE)) {
                return $ip;
            }
        }
    }
    return $_SERVER['REMOTE_ADDR'] ?? '0.0.0.0';
}
?>

Nginx 代理配置關鍵(確保 Header 傳遞正確)

# nginx.conf / site.conf
location / {
    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;
    # ...
}

三、IP 地理定位(調用第三方 API)

新浪 IP 查詢介面(免費、支援 JSONP)

<?php
/**
 * 獲取 IP 所在地理位置
 * @param string $ip
 * @return string 位置描述
 */
function getIpLocation($ip) {
    $url = "https://int.dpool.sina.com.cn/iplookup/iplookup.php?format=json&ip={$ip}";
    $ctx = stream_context_create(array('http' => array('timeout' => 5)));
    $json = @file_get_contents($url, false, $ctx);
    if (!$json) return '查詢失敗';

    $data = json_decode($json, true);
    if (empty($data) || $data['ret'] != 1) return '未知位置';

    // 組合地址:國家 省份 城市 區 ISP
    $parts = array();
    foreach (array('country', 'province', 'city', 'district', 'isp') as $field) {
        if (!empty($data[$field]) && $data[$field] != 'XX') {
            $parts[] = $data[$field];
        }
    }
    return implode(' ', $parts) ?: '未知位置';
}

// 使用範例
$ip = getClientIp();
echo "您的 IP: {$ip} 位置: " . getIpLocation($ip);
// 輸出:您的 IP: 203.0.113.45 位置: 台灣 台北市 中正區 中華電信
?>

其他免費 IP 定位 API 推薦

服務API 端點限制特色
ipapi.cohttps://ipapi.co/{ip}/json/1000/天欄位豐富、支援 HTTPS
ipinfo.iohttps://ipinfo.io/{ip}/json50k/月速度快、含 ASN、公司資訊
ip-api.comhttps://ip-api.com/json/{ip}45/分鐘批次查詢支援
MaxMind GeoLite2本地資料庫無限制離線查詢、準確度高、需定期更新

四、IP 處理工具函數庫

<?php
class IpUtils {
    // IP 轉長整數(IPv4)
    public static function toLong($ip) {
        return sprintf('%u', ip2long($ip));
    }

    // 長整數轉 IP
    public static function fromLong($long) {
        return long2ip($long);
    }

    // CIDR 範圍檢查
    public static function inCidr($ip, $cidr) {
        list($net, $mask) = explode('/', $cidr);
        $netLong = ip2long($net);
        $ipLong = ip2long($ip);
        $maskLong = ~((1 << (32 - $mask)) - 1);
        return ($ipLong & $maskLong) == ($netLong & $maskLong);
    }

    // 取得 CIDR 範圍起始/結束 IP
    public static function cidrRange($cidr) {
        list($net, $mask) = explode('/', $cidr);
        $netLong = ip2long($net);
        $hosts = 1 << (32 - $mask);
        return array(
            'start' => long2ip($netLong),
            'end' => long2ip($netLong + $hosts - 1),
            'count' => $hosts
        );
    }

    // IPv6 簡易支援(需 PHP 支援)
    public static function isValidV6($ip) {
        return filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6) !== false;
    }
}

// 使用範例
var_dump(IpUtils::inCidr('192.168.1.50', '192.168.1.0/24')); // true
var_dump(IpUtils::cidrRange('10.0.0.0/8')); // 16777216 個 IP
?>

安全性與隱私合規提醒

  1. GDPR/個資法:IP 視為個人資料,蒐集需告知同意,保留期限需限制
  2. 代理偽裝:X-Forwarded-For 可被偽造,關鍵風控決策需結合裝置指紋、行為分析
  3. 內網洩露:錯誤訊息、日誌避免輸出內網 IP(10.x, 172.16-31.x, 192.168.x)
  4. IPv6 部署:現代系統需支援 IPv6 格式(如 2001:db8::1),資料庫欄位建議 VARCHAR(45)

結語

IP 獲取看似簡單,實則涉及網路拓撲、代理穿透、隱私合規等多層面。建立可靠的 getClientIp() 函數庫、配合 Nginx 正確傳遞 Header、善用本地 GeoIP 資料庫離線查詢,是打造高可用、安全、合規系統的關鍵基礎設施。

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