php偽造Referer請求反盜鏈資源

趙帥強發表於2019-01-23

有些產品為了防止自己的產品被盜鏈訪問,會採用反盜鏈措施,如封閉型生態的音樂網站和影片網站,他們已經為了版權付費,自然不希望你免費使用他們的資源。但因為很多人專門研究盜鏈,因此我們也需要了解下盜鏈、反盜鏈和逃避反盜鏈的原理。

盜鏈

引用百度百科對盜鏈的定義:

盜鏈是指服務提供商自己不提供服務的內容,透過技術手段繞過其它有利益的終端使用者介面(如廣告),直接在自己的網站上向終端使用者提供其它服務提供商的服務內容,騙取終端使用者的瀏覽和點選率。受益者不提供資源或提供很少的資源,而真正的服務提供商卻得不到任何的收益。

常規盜鏈

我們知道,網站提供服務是向服務端請求一個html檔案,這個檔案中包含有css/js檔案,也包含img/video標籤,這些靜態資源會在html檔案載入時,依次的發起請求並填充在指定位置上,從而完成整個頁面的載入。

圖片描述

因此只要拿到這個圖片的URL並嵌入我們自己的html檔案中,就能在我們的網站上訪問,由於資源是不同的HTTP請求獨立訪問的,因此我們也能過濾源站的html檔案。這就是最簡單的盜鏈。

危害:在使用者訪問時,並沒有在訪問被盜鏈網站,但是依然會佔用該網站的頻寬資源,而頻寬是要給運營商付費的。同時,該網站的廣告、周邊、宣傳等資源並不會被使用者訪問到。

分散式盜鏈

分散式盜鏈比較複雜,需要在服務端部署專門的程式,並不針對單個網站或單個url,而是對全網的所有有用的資源進行盜取,並儲存在自己的資料庫中,並在使用者實際訪問時,完全轉換為自己的流量。

危害:自己透過勞動、金錢、版權付費得到的資源,被盜鏈網站免費使用,如網店攝影圖、期刊、電視劇等。並因此導致自己的會員、服務無法實現盈利。

反盜鏈分類

我們瞭解了盜鏈對源站的危害後,自然要透過一些手段來阻止這種行為維護自己的利益。

加水印

這是最簡單的方法,透過後端程式批次對圖片等資源加上水印,這樣在盜鏈的同時,也在為自己的網站做宣傳,有時甚至會主動尋求這種盜鏈。

資源重新命名

因為盜鏈是透過指定的url,這個url中一定包含該資源的路徑和名稱,因此透過不定期的更改檔案或目錄的名稱,能夠快速避免盜鏈,但也會導致正在下載的資源被中斷。

限制引用頁

http請求的頭部資訊中,有一個欄位:referer,它代表這個請求是從哪個頁面發起的,如果是單獨在頁面中開啟或者服務端請求的,則這個欄位為空。因此我們可以透過referer這個欄位的值做限制,如果是自己認可的頁面,則返回資源,否則,禁止該請求。但是由於每次都要開啟一個白名單的檔案做url匹配,因此會降低效能。

加密認證

在客戶端透過將使用者認證的資訊和資源的名稱進行組合後加密,將加密的字串作為url的引數發起請求,在服務端進行解密並認證透過後,才會返回請求的資源。這個方式主要用於防範分散式盜鏈。

反盜鏈程式

上面的3種反盜鏈方式,我們常用的是第三種,透過referer屬性來完成反盜鏈,今天也主要分享這一種方法的反盜鏈與防反盜鏈。

後端程式限制

這種限制需要消耗服務端計算資源,因此不如Nginx限制常用。

$from = parse_url($_SERVER['HTTP_REFERER']);
if ($from['host']!='xxx.com' && $from['host']!='www.xxx.com') {
    die('你丫在盜鏈');
}

Nginx限制

透過修改nginx配置檔案可以做到,修改完成後記得重啟nginx

// 這裡指定需要防盜鏈的資源,如gif/jpg等
location ~* \.(gif|jpg|png|jpeg)$ {
    // 設定資源的過期時間
    expires 30d;
    // 設定合法的引用頁,也就是防盜鏈的白名單;
    // none blocked保證使用者在新頁面開啟時依然能夠開啟,如果不希望使用者能夠儲存刪掉這兩項
    valid_referers none blocked *.hugao8.com *.baidu.com *.google.com;
    // 對於非法的引用頁,可以重寫圖片,也可以直接返回403或404頁面
    if ($invalid_referer) {
        rewrite ^/http://www.it300.com/static/images/404.jpg;
        #return 404;
    }
}

Referer-Policy

Referer 首部包含了當前請求頁面的來源頁面的地址,即表示當前頁面是透過此來源頁面裡的連結進入的。服務端一般使用 Referer 首部識別訪問來源,可能會以此進行統計分析、日誌記錄以及快取最佳化等。

Referer屬性出現在請求頭中,也在請求頭中被設定,但是在瀏覽器的安全策略裡,該值無法被js所指定:

$.ajax({
        url: 'http://www.baidu.com',
        beforeSend(xhr) {
            // 在傳送ajax請求前設定header頭部
            xhr.setRequestHeader("Referer", "http://translate.google.com/");
            xhr.setRequestHeader("User-Agent", "stagefright/1.2 (Linux;Android 5.0)");
        },
        success(data) {
            console.log(data);
        },
        error(err) {
            console.log(err);
        }
});

然而瀏覽器會報錯:
圖片描述

那麼Referer是怎麼被自動設定的呢?這個得看Referer-Policy屬性是怎麼定義的:

  • no-referrer: 整個 Referer 首部會被移除。訪問來源資訊不隨著請求一起傳送。
  • no-referrer-when-downgrade(預設值): 在沒有指定任何策略的情況下使用者代理的預設行為。在同等安全級別的情況下,引用頁面的地址會被髮送(HTTPS->HTTPS),但是在降級的情況下不會被髮送 (HTTPS->HTTP)。
  • origin: 在任何情況下,僅傳送檔案的源作為引用地址。例如 https://example.com/page.html 會將 https://example.com/ 作為引用地址。
  • origin-when-cross-origin: 對於同源的請求,會傳送完整的URL作為引用地址,但是對於非同源請求僅傳送檔案的源。
  • same-origin: 對於同源的請求會傳送引用地址,但是對於非同源請求則不傳送引用地址資訊。
  • strict-origin: 在同等安全級別的情況下,傳送檔案的源作為引用地址(HTTPS->HTTPS),但是在降級的情況下不會傳送 (HTTPS->HTTP)。
  • strict-origin-when-cross-origin: 對於同源的請求,會傳送完整的URL作為引用地址;在同等安全級別的情況下,傳送檔案的源作為引用地址(HTTPS->HTTPS);在降級的情況下不傳送此首部 (HTTPS->HTTP)。
  • unsafe-url: 無論是同源請求還是非同源請求,都傳送完整的 URL(移除引數資訊之後)作為引用地址。

這個值可以透過三種方式來設定:

<meta name="referrer" content="origin">
<a href="http://example.com" referrerpolicy="origin">
<a href="http://example.com" rel="noreferrer">

防反盜鏈

前端JS不能在頭部設定Referer欄位,和跨域一樣是因為瀏覽器的安全策略,那麼同樣的在服務端進行請求就不會有這些限制,我們在服務端請求時就可以自由的修改Referer欄位。

我們透過簡單的PHP例子來完成這個功能:

<?php
$url = 'http://t11.baidu.com/it/u=3008889497,862090385&fm=77';
$refer = 'https://www.baidu.com';
$ch = curl_init();
//以url的形式 進行請求
curl_setopt($ch, CURLOPT_URL, $url);
//以檔案流的形式 進行返回  不直接輸出到瀏覽器
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
//瀏覽器發起請求 超時設定
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 30);
//偽造來源地址 
curl_setopt ($ch, CURLOPT_REFERER, $refer);
$file = curl_exec($ch);
curl_close($ch);
header('Content-Type: text/html');
// 對圖片進行base64編碼,然後返回給前端展示
$file = base64_encode($file);
echo "<img src='data:image/jpeg;base64,{$file}' />";
?>

我們第一次請求註釋了偽造來源地址這一行,第二次請求不註釋這一行,這樣可以驗證執行結果:
圖片描述
圖片描述

總結

盜鏈和反盜鏈是一個對立面,技術不斷升級,最終的目標也是為了開放資源和保護智慧財產權。在網際網路生態裡,我們透過反盜鏈保護我們的利益,也使用防反盜鏈的這種方式來擴大我們的內容,無論站在哪一方,都需要做到知己知彼。

參考文章

  1. 百科-盜鏈:https://baike.baidu.com/item/...
  2. php防盜鏈:https://segmentfault.com/q/10...
  3. Referer偽造:https://zhuanlan.zhihu.com/p/...
  4. nginx防盜鏈:https://www.jianshu.com/p/979...

相關文章