天天看點

Nginx http_secure_link_module 實作下載下傳防盜鍊

 secure_link 子產品

下載下傳伺服器上有衆多的軟體資源, 可是很多來源不是本站,是迅雷、 flashget, 源源不斷的帶寬,防盜鍊絕對是當務之急. 使用來源判斷根本不靠譜,隻能防止一些小白站點的盜鍊,迅雷之類的下載下傳工具完全無效,如果你是nginx 的話,使用 secure link 完美解決這個問題,遠離迅雷.本文僅用于下載下傳伺服器,不适用于圖檔防盜鍊。

該子產品主要實作下面兩個功能:

(1)指定并允許檢查請求的連結的真實性以及保護資源免遭未經授權的通路

(2)限制連結生效周期

Nginx http_secure_link_module 實作下載下傳防盜鍊

預設情況下 nginx 不會安裝 secure_link 子產品,需要手動指定,配置參數如下:

# ./configure --with-http_secure_link_module \

--prefix=/usr/local/nginx-1.4.2 --with-http_stub_status_module

secure link 指令

secure_link
文法: secure_link md5_hash[,expiration_time]
預設: none
配置段: location
variables: yes
這個指令由 uri 中的 MD5 哈希值和過期時間組成. md5 哈希必須由 base64 加密的,過期時間為 unix 時間.如果不加過期時間,那麼這個連接配接永遠都不會過期.


secure_link_md5
文法: secure_link_md5 secret_token_concatenated_with_protected_uri
預設: none
配置段: location
variables: yes
md5 值對比結果,使用上面提供的 uri、密鑰、過期時間生成 md5 哈希值.如果它生成的 md5 哈希值與使用者送出過來的哈希值一緻,那麼這個變量的值為 1,否則為 0


secure_link_secret
文法: secure_link_secret word
預設:
配置段: location
Reference: secure_link_secret
nginx 0.8.50 之後的版本已經使用 secure_link_md5 取代,不再多說.      

驗證原理

Nginx http_secure_link_module 實作下載下傳防盜鍊

使用者在用戶端點選下載下傳按鈕,伺服器收到請求後生成一個​

​下載下傳位址​

​傳回給用戶端。用戶端在用這個生成的下載下傳位址去請求資源,此時nginx去做校驗,校驗連結位址真僞和連結位址是否過期。如果連結位址是真的并且連結位址沒有過期,就給用戶端傳回下載下傳資源。(nginx驗證和伺服器生成密鑰規則要一緻,否則不會通過的)

配置nginx

server {
        listen       80;
        server_name  www.test.com;
        charset utf-8;
        root /usr/local/nginx/html/;

       location /{
       secure_link $arg_md5,$arg_expires; 
       #secure_link:取參數md5,expires的值
       
       secure_link_md5 "$secure_link_expires$uri test"; #test為自定義的加密串
       #secure_link_md5驗證參數md5,expires是否和服務端生成驗證的一緻

       if ($secure_link = "") {   #資源不存在或哈希比對失敗
            return 403;
       }

       if ($secure_link = "0") {  #時間戳過期 
            return 410;
       }

    }

}      

使用shell腳本生成下載下傳的連結(生産環境由開發在代碼中實作)

[root@www]# cat md5url.sh 
#!/bin/bash
#生成一個測試連結腳本
servername="192.168.179.99"  #伺服器的IP或者域名
download_file="/nginx.png"  #測試下載下傳檔案的uri路徑,該環境nginx.png放在/usr/local/nginx/html下面
time_num=$(date -d "+300 seconds" +%s)  #定義過期時間為300秒
secret_num="test"   #自定義的加密串,和nginx的配置檔案中加密串相同

res=$(echo -n "${time_num}${download_file} ${secret_num}"|openssl md5 -binary | openssl base64 | tr +/ -_ | tr -d =)  #生成MD5值
echo "http://${servername}${download_file}?md5=${res}&expires=${time_num}"  #列印下載下傳連結


[root@www]# ./md5url.sh 
http://192.168.179.99/nginx.png?md5=rNISU5RF0H45cvo8Ym5dpA&expires=1588909599      

模拟Tomcat等後端産生一個下載下傳連結

使用Shell腳本生成,内容如下:

[root@www app]# ./md5url.sh   ----注意!!!每時每刻該shell腳本産生的expires值都在發生變化
http://192.168.179.99/nginx.png?md5=FsGJgGZ9gko7obkPZDEHRw&expires=1588911183
[root@www app]# ./md5url.sh 
http://192.168.179.99/nginx.png?md5=1fJiz1qHBM9m4kmf5y2Jnw&expires=1588911184
[root@www app]# ./md5url.sh 
http://192.168.179.99/nginx.png?md5=Sucvv1ddt8FOzwFskb5K8g&expires=1588911186

#此處是模拟背景生成的一個下載下傳連結,這些操作其實都是在伺服器背景執行的,隻有背景才知道加密串"test"和過期時間(expires)等。

      

測試

[root@www app]# wget `bash md5url.sh`   --測試下載下傳nginx.png圖檔
--2020-05-08 12:00:32--  http://192.168.179.99/nginx.png?md5=h7Mwc0S7sdglbuC8i5UsrQ&expires=1588910732
Connecting to 192.168.179.99:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 848 [image/png]
Saving to: ‘nginx.png?md5=h7Mwc0S7sdglbuC8i5UsrQ&expires=1588910732’

100%[===============================================================================================>] 848         --.-K/s   in 0s      

2020-05-08 12:00:32 (161 MB/s) - ‘nginx.png?md5=h7Mwc0S7sdglbuC8i5UsrQ&expires=1588910732’ saved [848/848]

[root@www app]# ls
md5url.sh  nginx.png?md5=h7Mwc0S7sdglbuC8i5UsrQ&expires=1588910732
[root@www sbin]# cmp /usr/local/nginx/html/nginx.png  /opt/app/nginx.png\?md5\=h7Mwc0S7sdglbuC8i5UsrQ\&expires\=1588910732  -l   
#可以看到下載下傳的和源圖檔内容是一樣的
[root@www app]#     #可以看到下載下傳成功




[root@www app]# wget http://192.168.179.99/nginx.png?md5=Hry5OCxz-thoBxGr5vz5tA&expires=1588911074
[1] 83766
[root@www app]# --2020-05-08 12:06:25--  http://192.168.179.99/nginx.png?md5=Hry5OCxz-thoBxGr5vz5tA
Connecting to 192.168.179.99:80... connected.
HTTP request sent, awaiting response... 403 Forbidden  ##資源不存在或哈希比對失敗,這裡是哈希對比失敗
2020-05-08 12:06:25 ERROR 403: Forbidden.


[1]+  Exit 8                  wget http://192.168.179.99/nginx.png?md5=Hry5OCxz-thoBxGr5vz5tA

将後面的時間戳随便改寫如expires=1588911074,回車,發現網頁變為403      

注意事項

1 密鑰防止洩露、以及經常更新密鑰
2 下載下傳伺服器和連結生成的伺服器上的時間不能相差太大,否則容易出現檔案一直都是過期狀态.      

繼續閱讀