在 API 測試、爬蟲開發、跨域請求模擬、安全測試等場景中,需要偽造客戶端 IP 地址與來源頁面。本文介紹 PHP cURL 實現偽造 HTTP 頭部的完整方案。
<?php
// 1.php - 發起偽造請求
$ch = curl_init();
// 目標 URL
curl_setopt($ch, CURLOPT_URL, "https://localhost/2.php");
// 關鍵:偽造 IP 相關頭部
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'X-FORWARDED-FOR: 8.8.8.8', // 標準代理頭
'CLIENT-IP: 8.8.8.8', // 非標準但常用頭
'X-REAL-IP: 8.8.8.8', // Nginx 真實 IP 傳遞頭
'X-FORWARDED: 8.8.8.8', // 另一種變體
'FORWARDED: for=8.8.8.8' // RFC 7239 標準
]);
// 偽造 Referer 來源頁面
curl_setopt($ch, CURLOPT_REFERER, "https://www.google.com/search?q=php+curl");
// 返回響應頭與體
curl_setopt($ch, CURLOPT_HEADER, true);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
// 執行請求
$response = curl_exec($ch);
if (curl_errno($ch)) {
echo "cURL Error: " . curl_error($ch);
} else {
echo $response;
}
curl_close($ch);
?>
<?php
// 2.php - 接收並解析
function getClientIp(): string {
$headers = [
'HTTP_CLIENT_IP', // CLIENT-IP
'HTTP_X_FORWARDED_FOR', // X-FORWARDED-FOR
'HTTP_X_FORWARDED', // X-FORWARDED
'HTTP_X_REAL_IP', // X-REAL-IP
'HTTP_FORWARDED', // FORWARDED (RFC 7239)
'REMOTE_ADDR' // 真實 TCP 連接 IP(無法偽造)
];
foreach ($headers as $header) {
if (!empty($_SERVER[$header])) {
// X-Forwarded-For 可能包含多個 IP,取第一個
$ips = explode(',', $_SERVER[$header]);
return trim($ips[0]);
}
}
return 'unknown';
}
function getReferer(): string {
return $_SERVER['HTTP_REFERER'] ?? 'direct';
}
// 輸出結果
echo "IP: " . getClientIp() . "\n";
echo "Referer: " . getReferer() . "\n";
// 顯示所有相關頭部用於調試
echo "\n--- 所有 IP 相關頭部 ---\n";
foreach ($_SERVER as $key => $value) {
if (stripos($key, 'IP') !== false || stripos($key, 'FORWARD') !== false || $key === 'REMOTE_ADDR') {
echo "$key: $value\n";
}
}
?>
| 頭部名稱 | 標準/常見度 | 用途 | 可偽造性 |
|---|---|---|---|
| X-Forwarded-For | 事實標準 | 代理鏈傳遞原始客戶端 IP | ✅ 完全可偽造 |
| X-Real-IP | Nginx 慣例 | 單層代理傳遞真實 IP | ✅ 完全可偽造 |
| Client-IP | 非標準 | 某些系統使用 | ✅ 完全可偽造 |
| Forwarded | RFC 7239 | 標準化代理信息 | ✅ 完全可偽造 |
| Referer | HTTP 標準 | 請求來源頁面 | ✅ 完全可偽造 |
| User-Agent | HTTP 標準 | 客戶端標識 | ✅ 完全可偽造 |
| X-Forwarded-Host | 常見 | 原始請求 Host | ✅ 完全可偽造 |
| X-Forwarded-Proto | 常見 | 原始協議 (http/https) | ✅ 完全可偽造 |
| REMOTE_ADDR | TCP 層 | 真實連接 IP | ❌ 無法偽造(需代理) |
<?php
function createBrowserLikeCurl(string $url, array $options = []): resource {
$ch = curl_init($url);
$defaultHeaders = [
'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8',
'Accept-Language: zh-CN,zh;q=0.9,en;q=0.8',
'Accept-Encoding: gzip, deflate, br',
'Connection: keep-alive',
'Upgrade-Insecure-Requests: 1',
'Sec-Fetch-Dest: document',
'Sec-Fetch-Mode: navigate',
'Sec-Fetch-Site: none',
'Sec-Fetch-User: ?1',
'Cache-Control: max-age=0',
];
$ua = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36';
curl_setopt_array($ch, [
CURLOPT_HTTPHEADER => array_merge($defaultHeaders, $options['headers'] ?? []),
CURLOPT_USERAGENT => $options['user_agent'] ?? $ua,
CURLOPT_REFERER => $options['referer'] ?? 'https://www.google.com/',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_MAXREDIRS => 5,
CURLOPT_SSL_VERIFYPEER => false,
CURLOPT_SSL_VERIFYHOST => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_COOKIEJAR => $options['cookie_jar'] ?? '',
CURLOPT_COOKIEFILE => $options['cookie_file'] ?? '',
]);
return $ch;
}
// 使用
$ch = createBrowserLikeCurl('https://httpbin.org/headers', [
'headers' => [
'X-Forwarded-For: 1.2.3.4',
'X-Real-IP: 1.2.3.4'
],
'referer' => 'https://github.com/'
]);
$response = curl_exec($ch);
curl_close($ch);
?>
<?php
class ProxyRotator {
private $proxies = [];
private $current = 0;
public function addProxy(string $host, int $port, string $user = '', string $pass = '') {
$this->proxies[] = compact('host', 'port', 'user', 'pass');
}
public function getNextProxy(): array {
if (empty($this->proxies)) return [];
$proxy = $this->proxies[$this->current];
$this->current = ($this->current + 1) % count($this->proxies);
return $proxy;
}
public function applyToCurl(resource $ch): void {
$proxy = $this->getNextProxy();
if ($proxy) {
curl_setopt($ch, CURLOPT_PROXY, "{$proxy['host']}:{$proxy['port']}");
if ($proxy['user']) {
curl_setopt($ch, CURLOPT_PROXYUSERPWD, "{$proxy['user']}:{$proxy['pass']}");
}
// 代理自動設置 X-Forwarded-For,通常無需手動偽造
}
}
}
?>
REMOTE_ADDR 或受信代理傳遞的頭部set_real_ip_from、PHP 框架中間件驗證# nginx.conf
http {
# 信任的代理服務器 IP 段
set_real_ip_from 10.0.0.0/8; # 內網
set_real_ip_from 172.16.0.0/12; # Docker/容器網絡
set_real_ip_from 192.168.0.0/16; # 內網
# 使用哪個頭部獲取真實 IP
real_ip_header X-Forwarded-For;
# 遞歸查找最後一個非受信代理 IP
real_ip_recursive on;
}
最佳實踐:僅在受控環境、授權範圍內使用偽造技術;生產系統請求務必使用真實身份。
PHP cURL 偽造 IP 与 Referer 技術本身中性,關鍵在於使用場景與授權範圍。開發者應掌握:CURLOPT_HTTPHEADER 設置偽造頭部、CURLOPT_REFERER 設置來源、CURLOPT_PROXY 使用真實代理 IP。同時理解服務端如何通過信任邊界、代理配置、多因子驗證來識別與防禦偽造請求。