防盜鏈通常通過檢查 HTTP 請求頭中的 Referer 字段實現:只有來自授權域名的請求才返回資源(圖片、視頻、下載鏈接等)。惡意網站通過 `
` 盜用流量,服務器端判斷 Referer 非授權域名則返回 403 或跳轉。
創建代理文件 file.php,接收目標 URL 參數,偽造 Referer 轉發請求:
<?php
// file.php?url=https://example.com/video.mp4
$targetUrl = isset($_GET['url']) ? $_GET['url'] : '';
if (empty($targetUrl)) die('缺少 url 參數');
// 解析 URL
$parsed = parse_url($targetUrl);
$host = $parsed['host'];
$path = isset($parsed['path']) ? $parsed['path'] : '/';
if (isset($parsed['query'])) $path .= '?' . $parsed['query'];
$port = isset($parsed['port']) ? $parsed['port'] : 80;
// 建立 Socket 連接
$fp = @fsockopen($host, $port, $errno, $errstr, 10);
if (!$fp) die("連接失敗: $errstr ($errno)");
// 構造 HTTP 請求頭(關鍵:偽造 Referer)
$out = "GET $path HTTP/1.1\r\n";
$out .= "Host: $host\r\n";
$out .= "Referer: https://$host/\r\n"; // 偽造為目標站內部引用
$out .= "User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36\r\n";
$out .= "Connection: Close\r\n\r\n";
fwrite($fp, $out);
// 讀取響應
$response = '';
while (!feof($fp)) {
$response .= fgets($fp, 1024);
}
fclose($fp);
// 簡單分離頭部與體
list($header, $body) = explode("\r\n\r\n", $response, 2);
// 檢查狀態碼
if (stripos($header, '200 OK') !== false) {
// 直接輸出內容(可根據 Content-Type 設置 Header)
echo $body;
} elseif (preg_match('/Location:\s*(\S+)/i', $header, $matches)) {
// 302 重定向:獲取真實地址並跳轉
header('Location: ' . trim($matches[1]));
} else {
echo "請求失敗,響應頭:
$header
";
}
?>
<?php
function fetchWithFakeReferer($url, $fakeReferer = '') {
$ch = curl_init();
curl_setopt_array($ch, [
CURLOPT_URL => $url,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_MAXREDIRS => 5,
CURLOPT_TIMEOUT => 15,
CURLOPT_SSL_VERIFYPEER => false, // 僅測試環境,生產請配置 CA
CURLOPT_HTTPHEADER => [
'Referer: ' . ($fakeReferer ?: $url), // 默認偽造為自身
'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'
],
]);
$content = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$err = curl_error($ch);
curl_close($ch);
if ($err) return ['error' => $err];
return ['code' => $httpCode, 'content' => $content];
}
// 使用示例
$result = fetchWithFakeReferer('https://target.com/protected.jpg', 'https://target.com/page.html');
if (isset($result['error'])) {
echo "錯誤: {$result['error']}";
} else {
// 直接輸出圖片(需設置正確 Content-Type)
header('Content-Type: image/jpeg');
echo $result['content'];
}
?>
<?php
$url = 'https://target.com/video.mp4';
$opts = [
'http' => [
'method' => 'GET',
'header' => "Referer: https://target.com/\r\n" .
"User-Agent: Mozilla/5.0\r\n",
'timeout' => 10,
'ignore_errors' => true, // 獲取非 2xx 響應體
]
];
$context = stream_context_create($opts);
$content = file_get_contents($url, false, $context);
// 從 $http_response_header 獲取狀態碼
// 直接輸出或轉存
?>
結合上述技術,可構建資源代理下載系統:
/download.php?id=123<?php
// download.php 簡化邏輯
$id = (int)($_GET['id'] ?? 0);
$resource = getResourceById($id); // 從 DB 獲取 {url, filename, mime}
if (!$resource) die('資源不存在');
$ch = curl_init($resource['url']);
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => false, // 直接輸出
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_HTTPHEADER => ['Referer: ' . parse_url($resource['url'], PHP_URL_HOST)],
CURLOPT_WRITEFUNCTION => function($ch, $data) {
echo $data; // 流式輸出到瀏覽器
return strlen($data);
},
]);
// 設置下載 Header
header('Content-Type: ' . $resource['mime']);
header('Content-Disposition: attachment; filename="' . $resource['filename'] . '"');
curl_exec($ch);
curl_close($ch);
?>
/video.mp4?sign=xxx&t=123456,服務端驗證簽名有效性valid_referers + if ($invalid_referer) { return 403; }PHP 通過 Socket、cURL、Stream Context 均可實現 Referer 偽造。cURL 方案功能最全、錯誤處理最佳,推薦生產環境使用。技術本身中性,關鍵在於使用場景合法合規。作為開發者,更應掌握防禦體系,保護自身資源不被濫用。