nginx防盜鏈設置的一些細節

本文首發於我的個人網站: https://hewanyue.com/
本文作者: Hechao
本文鏈接: https://hewanyue.com/blog/e4415633.html

  防盜鏈的必要性,我這裏就不再贅述了,這是網站設計的最基本要求。而在nginx中,一般比較容易實現的防盜鏈手段就是通過ungx_http_referer_module模塊(官方文檔鏈接) 檢查訪問請求的referer信息是否有效來實現防盜鏈功能。
  所謂referer檢查,舉個例子來說,在正常情況下當用戶在瀏覽 http://example.com/abc.html 時點擊一個鏈接去到 http://example.com/123.mp3 文件時,瀏覽器在發出請求123.mp3 資源時還會附帶當刻瀏覽器所處的頁面地址(即http://example.com/abc.html),所以當你的網站程序接收到下載 jacky.mp3 資源請求的時候,先判斷http的referer字段的值,如果是從 自己的域名(example.com)過來的,則可以認爲是合法的連接請求,否則就返回一個錯誤的提示信息。
  這種方法通常用於圖片、mp3這種容易被人用html“嵌入”到其他網站的資源,使用這種方法可以防止你的圖片直接出現在別人的網頁裏(或者防止mp3直接被其他網站嵌入到flash播放器裏),不過訪客使用下載工具還是可以輕鬆下載,因爲現在的下載工具一般會自動用你的域名構造一個引用地址,所以如果想再進一步防範的話,可以使用一個對應表限制每個資源的引用地址,例如將 123.mp3 的引用地址限制爲 http://example.com/abc.htmlid=123456,這樣下載工具就不太可能構造一個“正確”的引用地址了。

referer

  要過濾掉盜鏈訪問的referer信息,首先要明確知道,正常訪問的referer有哪些。一般來說,正常的referer信息有以下四種:

  • none:請求報文首部沒有referer首部,比如用戶直接在瀏覽器輸入域名訪問web網站,就沒有referer信息。
  • blocked:請求報文有referer首部,但無有效值,比如爲空。
  • 本站鏈接:referer首部中包含本站域名。
  • 搜索引擎跳轉:referer中爲 * .baidu. * 、 * .google. * 、及其他搜索引擎(如360、必應)(具體圖片或mp3媒體文件,不希望被搜索引擎引用,可單獨設置,主頁等html頁面建議允許搜索引擎跳轉)
      所以根據官方文檔,我們只需制定合適的匹配規則,將正常的訪問放過,對那些“非正常的”盜鏈訪問,返回403錯誤代碼,即可實現防盜鏈。
valid_referers none blocked server_names
              *.example.com example.* www.example.org/galleries/
              ~\.google\.;

if ($invalid_referer) {
   return 403;
}

過濾規則設置

  打開nginx配置文件,找到想要定義的location下,加入下面設置

        location  /blog/ {
            root /apps/nginx/html/;    #定義路徑
            valid_referers none blocked server_names *.example.com  ~\.google\. ~\.baidu\.;  
            #設置允許訪問的匹配規則,匹配規則可以寫在一行,也可以分行寫。
            if ($invalid_referer) {     #設置條件判斷,不符合上述規則的,返回403狀態碼
                return 403;
            }
        }
        location ^~ /mp3/ {
            alias /apps/nginx/html/blog/mp3/;    #定義路徑,也可用root
            valid_referers none blocked server_names *.example.com ;   
            if ($invalid_referer) {     #設置條件判斷,不符合上述規則的,返回403狀態碼
                return 403;
            }
        }

  也可在全局配置server中做設置,不過還是建議每個location單獨設置,因爲對於圖片和或者音頻視頻文件本身,還是不希望直接被搜索引擎所引用,造成網站資源的無意義的消耗。

跳轉設置

  對於盜鏈者,也可以予以反擊,允許他們請求我們的資源,不過,只給他們我們指定的資源,例如百度使用的防盜鏈圖:

  在這裏插入圖片描述
  配置上只需將return 403;改爲rewrite ^/ http://www.example/images/return.jpg; 例如:

        location  ~ return\.jpg$ {
            root /apps/nginx/html/blog/images/
        }
        location  ~ .*\.(gif|jpg|jpeg|png|bmp|swf)$ {
            access_log off;
            root /apps/nginx/html/blog/images/; 
            valid_referers none blocked server_names *.example.com  ~\.google\. ~\.baidu\.; 
            if ($invalid_referer) { 
                rewrite ^/ http://www.example/images/return.jpg;
                            }
        }

  PS:return.jpg要設置規則優先匹配到,這個圖片不能被防盜鏈,不然會無限重定向,導致顯示不正常。

規則細節

  設置匹配規則時,根據官方文檔,只有none、blocked、server_names、arbitrary string和regular expression五種規則。

Parameters can be as follows:

none
  the “Referer” field is missing in the request header;
blocked
  the “Referer” field is present in the request header, but its value has been deleted by a firewall or proxy server; such values are strings that do not start with “http://” or “https://”;
server_names
  the “Referer” request header field contains one of the server names;
arbitrary string
  defines a server name and an optional URI prefix. A server name can have an “*” at the beginning or end. During the checking, the server’s port in the “Referer” field is ignored;
regular expression
  the first symbol should be a “~”. It should be noted that an expression will be matched against the text starting after the “http://” or “https://”.

  這就要求我們在設置匹配規則的時候,要按照這個五種方式來,none、blocked直接寫上就可以了,沒有什麼可說的,我們重點理解下剩下三種。

server_names

  server names字面上理解很容易,就是匹配的域名。注意:這裏的域名,指本服務器上所有監聽的域名。而且這是一個包含的關係,只要referer頭部信息中包含有本服務器的監聽的任意域名,即可通過匹配。

arbitrary string

  翻譯過來是任意字符串,其實就是任意可以匹配到到字符串,這裏支持通配符。大致有2種寫法:

  • 直接寫域名
    例如可以寫*.example.com,也可寫爲www.example.*,可問題是爲什麼就偏偏不支持 * .example. * 呢。這我也很費解,不過確實不支持,有興趣的朋友可以去試一下,也希望能有大佬告知這其中的原理是什麼。
[root@CentOS8 ~]#/apps/nginx/sbin/nginx -t
nginx: [emerg] invalid hostname or wildcard "*.example.*" in /apps/nginx/conf/nginx.conf:95
nginx: configuration file /apps/nginx/conf/nginx.conf test failed
  • 定義匹配域名加路徑
      例如:www.example.com/blog;
      而博主試驗過很很多次,如果寫成例如www.example.com/*,在www.example.com/blog/頁面下去引用頁面下的/apps/nginx/html/mp3/123.mp3文件時就會報403錯誤,而寫域名加確切地址如www.example.com/blog時纔可以訪問。仔細查閱了官方文檔,才知道,有個很關鍵的細節就是,這個通配符的位置,只能在域名裏。可以再看一下官方文檔,

defines a server name and an optional URI prefix. A server name can have an “*” at the beginning or end. During the checking, the server’s port in the “Referer” field is ignored;

  我們可以得知,只可以在域名的開頭和結尾用 * 的通配符,而不是URI中,這也就是爲什麼我發現www.examlpe.com/* 無法匹配通過的原因。
  跟server_names一樣,只要包含自定義字符串就可以,例如匹配規則寫成www.example.com/mp3/,在www.example.com/mp3/頁面下就可以引用的/apps/nginx/html/mp3/123.mp3文件了,在www.example.com/mp3/abc/efg/頁面下是同樣可以跳轉訪問/apps/nginx/html/mp3/123.mp3文件的。

regular expression

  被指定的正則表達式模式匹配到的字符串,要使用 ~ 開頭,例如:~.*.google.com。這要嚴格按照正則表達式匹配到的referer寫,否則就會無法訪問。

總結

  設置匹配規則時,必須符合其中的某一種,而不能想當然的把幾種規則混合起來使用,想要放行的鏈接,一定要考慮好,到底確切適用於哪一種規則,纔不會出現”誤傷“、“漏網”的情況。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章