Nginx如何防止圖片被盜連HotlinkProtection

做你害怕做的事情。

「Hotlink Protection」(直接連結保護)是經營網站經常需要去注意的一塊,但為什麼我們會需要「Hotlink Protection」呢?身為圖文並茂的網路文章作家,最擔心得就是自己的文章被別人整篇連文帶圖地複製貼上到其它地方了。此時如果圖片有套用「Hotlink Protection」的話,就可以讓被盜用的圖片在其它網站上「不被正常顯示」出來,如此一來,就能使其它誤入盜文頁面的訪客可以知道該篇文章是篇被盜用的文章。不同的網站架構有不同的「Hotlink Protection」的設定方式,如果您的網站是使用Nginx伺服器來架設的話,可以參考這篇文章,來實現「Hotlink Protection」的功能。

Nginx的ngx_http_referer_module模組

「ngx_http_referer_module」是Nginx預設啟用的模組,可以用來阻擋使用無效HTTP標頭的Referer欄位的請求。使用「ngx_http_referer_module」模組時,通常會在Nginx設定檔中的特定location區塊內撰寫「valid_referers」命令,來針對特定連結做檢查HTTP標頭中Referer欄位的動作。

例如:

1
2
3
4
5
6
location ~ \.(jpg|jpeg|png|gif)$ {
valid_referers none server_names blocked *.magiclen.org *.facebook.com;
if ($invalid_referer) {
return 403;
}
}

先從location ~ \.(jpg|jpeg|png|gif)$開始介紹起。撰寫於server區塊內的location區塊,可以使Nginx伺服器能針對特定格式的網址來做不同的動作。至於這個「特定格式的網址」的網址規則,則是直接接在location這個命令之後。此處的~,表示要使用正規表示式,且必須判斷大小寫(case-sensitive)。而\.(jpg|jpeg|png|gif)$這串正規表示式,則代表所有以.jpg、.jpeg、.png或.gif結尾的網址。您可以將需要加上「Hotlink Protection」的圖片副檔名都放進這個正規表示式內。

再來看一下valid_referers命令,valid_referers命令可以用來設定$invalid_referer變數的值。若請求中的HTTP標頭的Referer欄位有符合valid_referers命令所指定的條件,此時$invalid_referer變數的值為空字串,所以之後的if判斷式就不會成立;若Referer欄位不符合valid_referers命令所指定的條件,則此時$invalid_referer變數的值為1,所以之後的if判斷式就會成立,而使得該連結會直接回傳HTTP的403狀態(Forbidden)。

至於valid_referers命令所接受的參數,有以下幾個:

  • none:這個參數可以允許那些HTTP標頭中沒有Referer欄位的請求。
  • server_names:這個參數可以允許那些HTTP標頭中的Referer欄位值符合server_name命令所設定的名稱的請求。
  • blocked:這個參數可以允許那些HTTP標頭中的Referer欄位值是空字串的請求。之所以遇到Referer欄位值是空字串的情況,通常是因為防火牆或是Proxy伺服器把原先HTTP標頭中的Referer欄位值給擋下來了。
  • 伺服器名稱:可以直接填入多個伺服器名稱(同樣以空格分隔),來作為判斷Referer欄位值是否有效的依據,名稱支援星號(*),表示任意數量的任意字元。
  • 正規表示式:可以以~字元為開頭再接上正規表示式,來判斷請求HTTP標頭中的Referer欄位值是否符合指定的正規表示式。

如果想要將無效的請求轉到其它網址,需要修改return命令,可以參考以下連結:

https://magiclen.org/nginx-rewrite

如果網站有使用CDN的話,本篇文章的作法就不怎麼合適了。若是Cloudflare CDN的話,可以參考以下連結來設定:

https://magiclen.org/cloudflare-hotlink-protection/

https://magiclen.org/nginx-hotlink-protection/