上一篇文章講了 Nginx 中的變量和運行原理,下面就來講一個主要提供變量並修改變量的值的模塊,也就是咱們要講的防盜鏈模塊:referer 模塊。html
若是作過我的站點的同窗,可能會遇到別人盜用本身站點資源連接的狀況,這就是盜鏈。說到盜鏈就要說一個 HTTP 協議的 頭部,referer 頭部。當其餘網站經過 URL 引用了你的頁面,用戶在瀏覽器上點擊 URL 時,HTTP 請求的頭部會經過 referer 頭部將該網站當前頁面的 URL 帶上,告訴服務器本次請求是由誰發起的。nginx
例如,在谷歌中搜索 Nginx 而後點擊連接:git
在打開的新頁面中查看請求頭會發現,請求頭中包含了 referer 頭部且值是 www.google.com/。github
像谷歌這種咱們是容許的,可是有一些其餘的網站想要引用咱們本身網站的資源時,就須要作一些管控了,否則豈不是誰均可以拿到連接。正則表達式
這裏目的其實已經很明確了,就是要拒絕非正常的網站訪問咱們站點的資源。算法
要實現上面的目的,referer 模塊可得算頭一號,一塊兒看下 referer 模塊怎麼用的。shell
--without-http_referer_module
禁用referer 模塊有三個指令,下面看一下。express
Syntax: valid_referers none | blocked | server_names | string ...;
Default: —
Context: server, location
Syntax: referer_hash_bucket_size size;
Default: referer_hash_bucket_size 64;
Context: server, location
Syntax: referer_hash_max_size size;
Default: referer_hash_max_size 2048;
Context: server, location複製代碼
valid_referers
指令,配置是否容許 referer 頭部以及容許哪些 referer 訪問。referer_hash_bucket_size
表示這些配置的值是放在哈希表中的,指定哈希表的大小。referer_hash_max_size
則表示哈希表的最大大小是多大。這裏面最重要的是 valid_referers
指令,須要重點來講明一下。瀏覽器
能夠同時攜帶多個參數,表示多個 referer 頭部都生效。安全
參數值
invalid_referer 變量
下面來看一個配置文件。
server {
server_name referer.ziyang.com;
listen 80;
error_log logs/myerror.log debug;
root html;
location /{
valid_referers none blocked server_names
*.ziyang.com www.ziyang.org.cn/nginx/
~\.google\.;
if ($invalid_referer) {
return 403;
}
return 200 'valid\n';
}
}
複製代碼
那麼對於這個配置文件而言,如下哪些請求會被拒絕呢?
curl -H 'referer: http://www.ziyang.org.cn/ttt' referer.ziyang.com/
curl -H 'referer: http://www.ziyang.com/ttt' referer.ziyang.com/
curl -H 'referer: ' referer.ziyang.com/
curl referer.ziyang.com/
curl -H 'referer: http://www.ziyang.com' referer.ziyang.com/
curl -H 'referer: http://referer.ziyang.com' referer.ziyang.com/
curl -H 'referer: http://image.baidu.com/search/detail' referer.ziyang.com/
curl -H 'referer: http://image.google.com/search/detail' referer.ziyang.com/複製代碼
咱們須要先來解析一下這個配置文件。valid_referers
指令配置了哪些值呢?
valid_referers none blocked server_names
*.ziyang.com www.ziyang.org.cn/nginx/
~\.google\.;複製代碼
下面就實際看下響應:
# 返回 403,沒有匹配到任何規則
➜ ~ curl -H 'referer: http://www.ziyang.org.cn/ttt' referer.ziyang.com/
<html>
<head><title>403 Forbidden</title></head>
<body>
<center><h1>403 Forbidden</h1></center>
<hr><center>nginx/1.17.8</center>
</body>
</html>
➜ ~ curl -H 'referer: http://image.baidu.com/search/detail' referer.ziyang.com/
<html>
<head><title>403 Forbidden</title></head>
<body>
<center><h1>403 Forbidden</h1></center>
<hr><center>nginx/1.17.8</center>
</body>
</html>
# 匹配到了 *.ziyang.com
➜ ~ curl -H 'referer: http://www.ziyang.com/ttt' referer.ziyang.com/
valid
➜ ~ curl -H 'referer: http://www.ziyang.com' referer.ziyang.com/
valid
# 匹配到了 server name
➜ ~ curl -H 'referer: http://referer.ziyang.com' referer.ziyang.com/
valid
# 匹配到了 blocked
➜ ~ curl -H 'referer: ' referer.ziyang.com/
valid
# 匹配到了 none
➜ ~ curl referer.ziyang.com/
valid
# 匹配到了 ~\.google\.
➜ ~ curl -H 'referer: http://image.google.com/search/detail' referer.ziyang.com/
valid複製代碼
referer 模塊是一種簡單的防盜鏈手段,必須依賴瀏覽器發起請求才會有效,若是攻擊者僞造 referer 頭部的話,這種方式就失效了。
secure_link 模塊是另一種解決的方案。
它的主要原理是,經過驗證 URL 中哈希值的方式防盜鏈。
基本過程是這個樣子的:
原理以下:
模塊:
Syntax: secure_link expression;
Default: —
Context: http, server, location
Syntax: secure_link_md5 expression;
Default: —
Context: http, server, location
Syntax: secure_link_secret word;
Default: —
Context: location複製代碼
命令行生成安全連接
echo -n '時間戳URL客戶端IP密鑰' | openssl md5 -binary | openssl base64 | tr +/ - | tr -d =複製代碼
/test1.txt?md5=md5生成值&expires=時間戳(如 2147483647)複製代碼
Nginx 配置
下面是一個實際的配置文件,我這裏就不作演示了,感興趣的能夠本身作下實驗。
server {
server_name securelink.ziyang.com;
listen 80;
error_log logs/myerror.log info;
default_type text/plain;
location /{
secure_link $arg_md5,$arg_expires;
secure_link_md5 "$secure_link_expires$uri$remote_addr secret";
if ($secure_link = "") {
return 403;
}
if ($secure_link = "0") {
return 410;
}
return 200 '$secure_link:$secure_link_expires\n';
}
location /p/ {
secure_link_secret mysecret2;
if ($secure_link = "") {
return 403;
}
rewrite ^ /secure/$secure_link;
}
location /secure/ {
alias html/;
internal;
}
}複製代碼
除了上面這種相對複雜的方式防盜鏈,還有一種相對簡單的防盜鏈方式,就是隻對 URI 進行哈希,這樣當 URI 傳
secure_link_secret secret;
配置密鑰命令行生成安全連接
echo -n 'linksecret' | openssl md5 –hex
Nginx 配置
secure_link_secret secret;
這個防盜鏈的方法比較簡單,那麼具體是怎麼用呢?你們都在網上下載過資源對吧,不論是電子書仍是軟件,不少網站你點擊下載的時候每每會彈出另一個頁面去下載,這個新的頁面其實就是請求的 Nginx 生成的安全 URL。若是這個 URL 被拿到的話,其實仍是能夠用的,因此須要常常的更新密鑰來確保 URL 不會被盜用。
今天這篇文章詳細講了防盜鏈的具體用法,最近的這兩篇文章都是說的已有的變量用法,下一篇文章講一下怎麼生成新的變量。
本文首發於個人我的博客:iziyang.github.io,全部配置文件我已經放在了 Nginx 配置文件,你們能夠自取。