一、功能
防盗链;
ngx_http_secure_link_module模块用于检查所请求链接的真实性,保护资源免受未经授权的访问,并限制链接寿命。
该模块提供两种可选的操作模式。
-
第一种模式由 secure_link_secret 指令启用,用于检查所请求链接的真实性以及保护资源免遭未经授权的访问。
-
第二种模式由 secure_link 和secure_link_md5指令启用,也用于限制链接的生命周期。
默认情况下不构建此模块,应使用--with-http_secure_link_module配置参数启用它。
二、场景
用户在客户端点击下载按钮,服务器收到请求后生成一个下载地址返回给客户端。客户端在用这个生成的下载地址去请求资源,此时
nginx去做校验,校验链接地址真伪和链接地址是否过期。如果链接地址是真的并且链接地址没有过期,就给客户端返回下载资源。(
nginx验证和服务器生成密钥规则要一致,否则不会通过的)
三、配置语法
secure_link:
语法: secure_link expression; 或者 secure_link md5_hash[,expiration_time];
默认: none
配置段: http, server,location
variables: yes
功能:
定义一个带有变量的字符串,将从请求中提取链接的md5和生命周期。
从字符串中提取的md5值与secure_link_md5指令定义的表达式的 MD5 哈希值进行比较。如果校验和不同,则$secure_link变量设置为空字符串。如果校验和相同,则检查链路生存期。如果链接的生命周期有限并且时间已过,则$secure_link变量设置为“0”。否则,它被设置为“1”。
请求中传递的 MD5 哈希值以base64url编码。过期时间为 unix 时间,如果不加过期时间,那么这个连接永远都不会过期。请求中传递的过期时间可通过 $secure_link_expires 变量在 secure_link_md5 指令中使用。
secure_link_md5:
语法: secure_link_md5 secret_token_concatenated_with_protected_uri
默认: none
配置段: http, server,location
variables: yes
功能:
定义一个表达式,将为其计算 MD5 哈希值并将其与请求中传递的值进行比较。使用上面提供的 uri、密钥、过期时间生成 md5 哈希值。
四、示例
1、前提:安装 secure_link 模块
nginx -V
# 输出nginx所有已安装模块,检查是否有ngx_http_secure_link_module
root@node1:~# nginx -V
nginx version: nginx/1.14.0 (Ubuntu)
built with OpenSSL 1.1.1 11 Sep 2018
TLS SNI support enabled
configure arguments: --with-cc-opt='-g -O2 -fdebug-prefix-map=/build/nginx-YlUNvj/nginx-1.14.0=. -fstack-protector-strong -Wformat -Werror=format-security -fPIC -Wdate-time -D_FORTIFY_SOURCE=2' --with-ld-opt='-Wl,-Bsymbolic-functions -Wl,-z,relro -Wl,-z,now -fPIC' --prefix=/usr/share/nginx --conf-path=/etc/nginx/nginx.conf --http-log-path=/var/log/nginx/access.log --error-log-path=/var/log/nginx/error.log --lock-path=/var/lock/nginx.lock --pid-path=/run/nginx.pid --modules-path=/usr/lib/nginx/modules --http-client-body-temp-path=/var/lib/nginx/body --http-fastcgi-temp-path=/var/lib/nginx/fastcgi --http-proxy-temp-path=/var/lib/nginx/proxy --http-scgi-temp-path=/var/lib/nginx/scgi --http-uwsgi-temp-path=/var/lib/nginx/uwsgi --with-debug --with-pcre-jit --with-http_ssl_module --with-http_stub_status_module --with-http_realip_module --with-http_auth_request_module --with-http_v2_module --with-http_dav_module --with-http_slice_module --with-threads --with-http_addition_module --with-http_geoip_module=dynamic --with-http_gunzip_module --with-http_gzip_static_module --with-http_image_filter_module=dynamic --with-http_sub_module --with-http_xslt_module=dynamic --with-stream=dynamic --with-stream_ssl_module --with-mail=dynamic --with-mail_ssl_module
默认情况下 nginx 不会安装 secure_link 模块,需要手动指定添加(
别忘了现有的模块),步骤如下:
1、下载对应版本的nginx包:
$ wget http://nginx.org/download/nginx-1.14.0.tar.gz
$ tar -zxvf nginx-1.14.0.tar.gz
$ cd nginx-1.14.0
2、前往你的nginx安装目录,找到configure这个文件,添加--with-http_secure_link_module,执行命令
$ ./configure --with-cc-opt='-g -O2 -fdebug-prefix-map=/build/nginx-YlUNvj/nginx-1.14.0=. -fstack-protector-strong -Wformat -Werror=format-security -fPIC -Wdate-time -D_FORTIFY_SOURCE=2' --with-ld-opt='-Wl,-Bsymbolic-functions -Wl,-z,relro -Wl,-z,now -fPIC' --prefix=/usr/share/nginx --conf-path=/etc/nginx/nginx.conf --http-log-path=/var/log/nginx/access.log --error-log-path=/var/log/nginx/error.log --lock-path=/var/lock/nginx.lock --pid-path=/run/nginx.pid --modules-path=/usr/lib/nginx/modules --http-client-body-temp-path=/var/lib/nginx/body --http-fastcgi-temp-path=/var/lib/nginx/fastcgi --http-proxy-temp-path=/var/lib/nginx/proxy --http-scgi-temp-path=/var/lib/nginx/scgi --http-uwsgi-temp-path=/var/lib/nginx/uwsgi --with-debug --with-pcre-jit --with-http_ssl_module --with-http_stub_status_module --with-http_realip_module --with-http_auth_request_module --with-http_v2_module --with-http_dav_module --with-http_slice_module --with-threads --with-http_addition_module --with-http_geoip_module=dynamic --with-http_gunzip_module --with-http_gzip_static_module --with-http_image_filter_module=dynamic --with-http_sub_module --with-http_xslt_module=dynamic --with-stream=dynamic --with-stream_ssl_module --with-mail=dynamic --with-mail_ssl_module --with-http_secure_link_module # --prefix指定安装目录 可能需要apt-get install -y libgd-dev libgeoip-dev
3、执行mak编译nginx:
$ make
4、如果单纯添加模块,不需要install,而是执行以下操作,将打过补丁的nginx二进制文件(--prefix=/usr/share/nginx)覆盖 /usr/sbin/目录(which nginx查看得到)中的文件即可
$ mv /usr/share/nginx/sbin/nginx /usr/sbin/
5、重启nginx:
$ nginx -s reload
6、查看模块
2、配置nginx
server {
listen 80;
server_name localhost;
root /usr/share/nginx/html/;
location / {
secure_link $arg_md5,$arg_expires; # 客户端传递的md5和链接过期时间
secure_link_md5 "$secure_link_expires$uri secret_key"; # secret_key为自定义的加密串;验证参数md5,expires是否和服务端生成验证的一致
if ($secure_link = "") {
return 403; # 资源不存在或哈希比对失败
}
if ($secure_link = "0") {
return 410; # 时间戳过期
}
if ($request_filename ~* ^.*?\.(jpg)$){
add_header Content-Disposition attachment; # 不浏览,直接下载
}
}
}
准备带下载的文件test.jpg,
文件放在
/
usr
/
share
/
nginx
/
html
/目录下
3、使用shell脚本生成下载的链接
生产环境由开发在代码中实现
[root@img_server html]# cat md5url.sh
#!/bin/bash
servername="192.168.11.135" # 服务器的IP或域名
download_file="/test.jpg" # 测试下载文件的uri路径,该环境test.jpg放在/usr/share/nginx/html下面
time_num=$(date -d "+300 seconds" +%s) # 定义过期时间为300秒
secret_num="secret_key" # 自定义的加密串,和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}" # 打印下载链接
这个生成密钥的方式一般由后台生成,这里采用自己写的这个.sh文件来生成密钥, 命令: sh md5url.sh,
生成的密钥:
http://192.168.11.135/test.jpg?md5=8l4smyfik0l7lsGWNDJY-g&expires=1686302780
4、使用生成的下载链接进行访问
过五分钟(即脚本中300秒)再次访问,返回410:
注意:
-
密钥防止泄露、以及经常更新密钥
-
下载服务器和链接生成的服务器上的时间不能相差太大,否则容易出现文件一直都是过期状态.
五、参考
(4条消息) nginx添加模块_青霄的博客-CSDN博客
Module ngx_http_secure_link_module