7.5.6 防盗链与访问控制
防盗链与访问控制是保护静态资源、限制访问来源和降低盗用带宽成本的关键手段。本节以 Nginx 为核心,介绍常见的防盗链策略与访问控制模型,提供可执行示例、排错方法与练习。
防盗链原理与场景#
- 原理:通过校验请求头中的
Referer或 URL 签名参数,判断请求是否来自允许的站点或客户端。 - 常见场景:图片/视频/下载包、静态文件 CDN 回源、热链带宽盗用。
- 限制:
Referer可被伪造或缺失,需配合签名、Token、IP 白名单等增强。
原理草图(请求链路与校验点):
基于 Referer 的防盗链#
使用 valid_referers 判断来源,并对非法请求进行拒绝或重定向。
配置示例(完整可运行片段)
文件路径:/etc/nginx/conf.d/static.conf
server {
listen 80;
server_name static.example.com;
# 静态资源目录
root /data/static;
location ~* \.(jpg|jpeg|png|gif|webp|mp4|zip|tar\.gz)$ {
# 允许空 Referer、被代理屏蔽的 Referer、以及指定域名
valid_referers none blocked server_names
*.example.com example.com;
# 变量说明:
# $invalid_referer=1 表示不合法
if ($invalid_referer) {
return 403;
}
access_log /var/log/nginx/static_access.log;
}
}
测试命令与预期效果
# 1) 合法来源(应返回 200)
curl -I -e "https://www.example.com/page.html" http://static.example.com/img/a.jpg
# 2) 非法来源(应返回 403)
curl -I -e "https://evil.com" http://static.example.com/img/a.jpg
# 3) 无 Referer(none 被允许,返回 200)
curl -I http://static.example.com/img/a.jpg
命令解释
- curl -I:只获取响应头,便于快速验证状态码。
- -e:设置请求头 Referer,模拟来源页面。
- valid_referers:定义合法来源,none/blocked/server_names 为常用内置类型。
基于签名/Token 的防盗链#
通过 URL 加签,避免 Referer 伪造。常见方案:secure_link。
配置示例
server {
listen 80;
server_name download.example.com;
root /data/download;
# 需要模块:ngx_http_secure_link_module(官方内置)
location /files/ {
# URL 形式: /files/package.tar.gz?md5=签名&expires=时间戳
secure_link $arg_md5,$arg_expires;
secure_link_md5 "$secure_link_expires$uri secret_key";
if ($secure_link = "") { return 403; } # 缺少参数
if ($secure_link = "0") { return 410; } # 过期
try_files $uri =404;
}
}
生成签名示例(本地)
# 变量说明
# expires: 过期时间戳(秒)
# uri: 资源路径
# secret: 与 Nginx 配置一致
expires=$(($(date +%s)+600))
uri="/files/package.tar.gz"
secret="secret_key"
# 生成 md5(base64 再替换字符,避免 URL 非法字符)
md5=$(printf "%s%s%s" "$expires" "$uri" "$secret" | \
openssl md5 -binary | openssl base64 | tr +/ -_ | tr -d =)
echo "URL: http://download.example.com${uri}?md5=${md5}&expires=${expires}"
测试
# 1) 使用正确签名(应返回 200)
curl -I "http://download.example.com/files/package.tar.gz?md5=xxx&expires=yyy"
# 2) 过期签名(应返回 410)
curl -I "http://download.example.com/files/package.tar.gz?md5=xxx&expires=1"
访问控制:IP 白名单/黑名单与路径限制#
适用于接口、管理后台或敏感下载路径。
配置示例
server {
listen 80;
server_name admin.example.com;
location /admin/ {
allow 10.0.0.0/8;
allow 192.168.0.0/16;
deny all;
# 基本认证(可选)
auth_basic "Restricted";
auth_basic_user_file /etc/nginx/.htpasswd;
}
}
生成认证文件
# 安装工具(以 Debian/Ubuntu 为例)
sudo apt-get install -y apache2-utils
# 创建用户
sudo htpasswd -c /etc/nginx/.htpasswd admin
命令解释
- allow/deny:基于源 IP 控制访问。
- auth_basic:基于 HTTP Basic Auth,适合后台保护。
常见排错与运维要点#
- 排错 1:合法来源被拒绝
- 检查
valid_referers是否包含实际域名或子域名。 - 用
curl -I -e模拟真实 Referer。 - 排错 2:签名校验失败
- 确认签名生成顺序与 Nginx 配置一致(
expires + uri + secret)。 - 时间戳是否已过期,服务器时间是否同步(NTP)。
- 排错 3:缓存与 CDN
- CDN 可能不传 Referer,需要在 CDN 配置透传或使用签名策略。
- 日志定位
# 实时查看防盗链命中
tail -f /var/log/nginx/static_access.log
# 过滤 403/410
awk '$9 ~ /403|410/' /var/log/nginx/static_access.log | tail -n 20
练习#
- 为图片资源开启 Referer 防盗链,要求
example.com与*.example.com允许,非法返回 403。 - 使用
secure_link为/files/路径配置签名,生成 10 分钟有效的下载链接并验证过期行为。 - 为
/admin/增加 IP 白名单与 Basic Auth,验证未授权返回 401。