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

PHP 偽造 HTTP Referer 繞過防盜鏈:fsockopen 與 Stream Context 實作

     編輯:PHP 綜合知識

防盜鏈常透過檢查 Referer 標頭限制資源存取。本文提供三種 PHP 實作方式偽造 Referer 進行資源代理下載,適用於圖片、音訊、文件等靜態資源中繼場景。

方案一:fsockopen 底層 Socket 實作(完整控制)

<?php
/**
 * file.php - 通用防盜鏈代理
 * 用法: file.php?url=https://target.com/path/to/resource.mp3
 */
$targetUrl = isset($_GET['url']) ? $_GET['url'] : '';
if (!$targetUrl) die('缺少 url 參數');

$parsed = parse_url($targetUrl);
$host = $parsed['host'];
$path = $parsed['path'] . (isset($parsed['query']) ? '?' . $parsed['query'] : '');
$port = isset($parsed['port']) ? $parsed['port'] : 80;

// 建立連線
$fp = @fsockopen($host, $port, $errno, $errstr, 10);
if (!$fp) die("連線失敗: $errstr ($errno)");

// 發送請求(偽造 Referer 為目標域名首頁)
$request = "GET $path HTTP/1.1\r\n";
$request .= "Host: $host\r\n";
$request .= "Referer: https://$host/\r\n";
$request .= "User-Agent: Mozilla/5.0 (compatible; PHP Proxy)\r\n";
$request .= "Connection: Close\r\n\r\n";
fwrite($fp, $request);

// 讀取回應
$response = '';
while (!feof($fp)) {
    $response .= fgets($fp, 4096);
}
fclose($fp);

// 分離 Header 與 Body
list($header, $body) = explode("\r\n\r\n", $response, 2);

// 檢查狀態碼
if (strpos($header, '200 OK') === false) {
    // 可能為 302 重導向,嘗試取得 Location
    if (preg_match('/Location:\s*(\S+)/i', $header, $m)) {
        header('Location: ' . $m[1]);
        exit;
    }
    die('資源存取失敗: ' . substr($header, 0, 200));
}

// 輸出資源
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename="' . basename($path) . '"');
echo $body;
?>

方案二:stream_context_create 簡潔版(PHP 5.0+)

<?php
$url = $_GET['url'] ?? '';
$referer = 'https://' . parse_url($url, PHP_URL_HOST) . '/';

$opts = [
    'http' => [
        'method' => 'GET',
        'header' => "Referer: $referer\r\nUser-Agent: Mozilla/5.0\r\n",
        'timeout' => 15,
        'follow_location' => 1, // 自動追蹤 302
        'max_redirects' => 3,
    ]
];
$ctx = stream_context_create($opts);
$content = @file_get_contents($url, false, $ctx);
if ($content === false) die('取得失敗');

// 直接輸出(適用圖片、小檔案)
header('Content-Type: application/octet-stream');
echo $content;
?>

方案三:cURL 版(生產環境推薦)

<?php
$url = $_GET['url'] ?? '';
$referer = 'https://' . parse_url($url, PHP_URL_HOST) . '/';

$ch = curl_init($url);
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_FOLLOWLOCATION => true,
    CURLOPT_MAXREDIRS => 5,
    CURLOPT_REFERER => $referer,
    CURLOPT_USERAGENT => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
    CURLOPT_TIMEOUT => 20,
    CURLOPT_SSL_VERIFYPEER => false, // 僅測試用,生產請驗證
    CURLOPT_HEADER => false,
]);
$content = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);

if ($httpCode !== 200) die("HTTP $httpCode");
header('Content-Type: application/octet-stream');
echo $content;
?>

安全性強化建議

  1. 白名單域名:僅允許代理特定受信任域名,防止 SSRF 攻擊內網服務。
  2. 限制協議:僅允許 http/https,封鎖 file://、gopher:// 等。
  3. 檔案大小限制:避免大檔案佔用記憶體,改用串流輸出:
<?php
// 串流輸出大檔案(cURL 範例)
$ch = curl_init($url);
// ... 設定選項 ...
$fp = fopen('php://output', 'w');
curl_setopt($ch, CURLOPT_FILE, $fp);
curl_exec($ch);
curl_close($ch);
fclose($fp);
?>

法律與道德提醒

繞過防盜鏈可能違反目標網站服務條款,甚至觸犯《電腦犯罪法》相關條款。僅供技術研究、自有資源跨域調用或經授權的合作場景使用,請勿濫用。


掌握 HTTP 標頭偽造與串流代理技術,能解決跨域資源整合、CDN 回源驗證、爬蟲反反爬等實際工程問題,是後端開發進階必備技能。

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