目录
Nginx 防盗链问题
两个网站 A 和 B, A网站引用了B网站上的图片,这种行为就叫做盗链。 防盗链,就是要防止A引用B的图片。
配置 Nginx 防盗链保护是一项重要的任务,它可以防止其他网站直接链接到你的资源(如图片、视频等),从而节省带宽和提高网站的安全性。
1. nginx 防止网站资源被盗用模块
ngx_http_referer_module
2. 如何区分哪些是不正常的用户?
HTTP Referer是Header的一部分,当浏览器向Web服务器发送请求的时候,一般会带上Referer,告诉服务器我是从哪个页面链接过来的,服务器借此可以获得一些信息用于处理,例如防止未经允许的网站盗链图片、文件等。因此HTTP Referer头信息是可以通过程序来伪装生成的,所以通过Referer信息防盗链并非100%可靠,但是,它能够限制大部分的盗链情况.
比如在www.google.com 里有一个www.baidu.com
链接,那么点击这个www.baidu.com
,它的header
信息里就有:Referer=http://www.google.com
3.防盗链配置
配置要点:
[root@nginx-server ~]# vim /etc/nginx/nginx.conf
# 日志格式添加"$http_referer"
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
# valid_referers 使用方式
Syntax: valid_referers none | blocked | server_names | string ...;
Default: —
Context: server, location
-
none : 允许没有http_refer的请求访问资源;
-
blocked : 允许不是http://开头的,不带协议的请求访问资源;
-
server_names : 只允许指定ip/域名来的请求访问资源(白名单);
1. 环境准备:
准备两台机器,关闭防火墙和selinux
localhost | Roucky_linux9.4 | 192.168.226.20 |
localhost | Roucky_linux9.4 | 192.168.226.21 |
两个都安装nginx
sudo tee /etc/yum.repos.d/nginx.repo << 'EOF'
[nginx-stable]
name=nginx stable repo
baseurl=https://nginx.org/packages/centos/$releasever/$basearch/
gpgcheck=1
enabled=1
gpgkey=https://nginx.org/keys/nginx_signing.key
[nginx-mainline]
name=nginx mainline repo
baseurl=https://nginx.org/packages/mainline/centos/$releasever/$basearch/
gpgcheck=1
enabled=0
gpgkey=https://nginx.org/keys/nginx_signing.key
EOF
2. 对192.168.226.20主机操作
上传一个两张图片到发布目录里
#进入发布目录
cd /usr/share/nginx/html/
上传两张图片
修改其默认发布页面
vim /usr/share/nginx/html/index.html
清空原文件内容,加入如下测试页面代码
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>防盗链测试页面</title>
<style>
body {
font-family: "Microsoft YaHei", "Arial", sans-serif;
text-align: center;
}
h1 {
color: #333;
}
p {
font-size: 16px;
}
img {
margin-top: 20px;
}
</style>
</head>
<body>
<h1>欢迎来到防盗链测试页面</h1>
<p>这是一个用于测试 Nginx 防盗链功能的简单网页。</p>
<img src="./tu.jpg" alt="测试图片" width="600" height="500" />
</body>
</html>
配置nginx配置文件
vim /etc/nginx/conf.d/default.conf
#修改内容为如下:
server {
listen 80; # 监听80端口
server_name localhost; # 设置服务器名称为localhost
location / {
root /usr/share/nginx/html; # 设置根目录为/usr/share/nginx/html
index index.html index.htm; # 设置默认索引文件为index.html或index.htm
# 有效的referer,包括:
# 1. none:无referer的请求
# 2. blocked:被防火墙或代理阻止referer的请求
# 3. *.qq.com:qq.com域及其子域名的请求
# 4. 192.168.226.20:指定IP地址的请求
valid_referers none blocked *.qq.com 192.168.226.20;
# 如果请求的referer无效,则返回502错误
if ($invalid_referer) {
return 502;
}
}
# 针对以.gif、.jpg、.png、.jpeg为扩展名的图片文件
location ~* \.(gif|jpg|png|jpeg)$ {
root /usr/share/nginx/html; # 设置图片文件的根目录为/usr/share/nginx/html
# 有效的referer,包括:
# 1. qq.com:来自qq.com域名的请求
# 2. 192.168.226.20:指定IP地址的请求
valid_referers qq.com 192.168.226.20;
# 如果请求的referer无效,则返回403错误
if ($invalid_referer) {
return 403;
}
}
}
启动Nginx
systemctl enable --now nginx
打开浏览器访问测试
3. 对192.168.226.21主机操作
编辑默认访问页面
vim /usr/share/nginx/html/index.html
修改为如下:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>ceshi.com</title>
</head>
<body style="background-color:red;">
<img src="http://192.168.226.20/tu.jpg"/>
</body>
</html>
启动nginx
systemctl enable --now nginx
测试:
来到两台虚拟主机随便一个上执行:
1. 测试不带 Referer
头
curl -v http://192.168.226.20/tu.jpg
输出中会有包括:< HTTP/1.1 200 OK
2. 测试带合法 Referer
头
curl -v -e http://qq.com http://192.168.226.20/tu.jpg
输出中会有包括:< HTTP/1.1 200 OK
3. 测试带非法 Referer
头
curl -v -e http://192.168.226.21 http://192.168.226.20/tu.jpg
输出中会有包括:< HTTP/1.1 403 Forbidden
对应的刷因192.168.226.21的网页,代码中应用的图片就是看不到的。
结果:
- 对于没有
Referer
头的请求,应返回 200。 - 对于带非法
Referer
头的请求,应返回 403。 - 对于带合法
Referer
头的请求,应返回 200。
HTTP Referer
头
HTTP Referer
头是一个请求头字段,它表示用户是从哪个页面导航到当前请求页面的。服务器可以通过这个头信息了解请求的来源页面。
Referer
头的功能和用途
-
来源追踪:服务器可以使用
Referer
头来了解用户是从哪个页面跳转到当前页面的。这在分析流量来源、跟踪用户行为和广告投放效果等方面非常有用。 -
防盗链:服务器可以通过检查
Referer
头,来防止其他网站直接链接其资源(如图片、视频等)。如果Referer
头不在允许的来源列表中,服务器可以拒绝提供资源,通常返回403 Forbidden或其他错误状态。 -
安全性检查:某些安全策略会基于
Referer
头来防止CSRF(跨站请求伪造)攻击。例如,只允许来自同一站点的请求。
Referer
头的格式
Referer
头包含了完整的 URL,例如:
Referer: http://example.com/previous-page.html
当用户从 http://example.com/previous-page.html
页面点击链接跳转到当前页面时,浏览器会在请求头中添加这一行。
没有Referer头的情况
没有 Referer
头的请求并不一定表示是从一个空页面跳转的。以下是一些常见的导致没有 Referer
头的情况:
-
直接输入 URL:用户在浏览器地址栏中直接输入 URL 并访问资源。这种情况下没有
Referer
头。 -
书签访问:用户通过书签访问资源。同样,这种情况下没有
Referer
头。 -
浏览器隐私设置:一些浏览器的隐私模式或者用户隐私设置可能会阻止
Referer
头的发送。 -
防火墙和代理服务器:某些防火墙或代理服务器可能会移除或阻止
Referer
头,以保护用户隐私。 -
某些 HTTP 请求:例如使用
curl
或其他 HTTP 客户端工具进行的请求,除非明确指定Referer
头,否则这些请求默认没有Referer
头。 -
某些形式的嵌入或加载:某些情况下,通过 JavaScript 动态创建的请求可能没有
Referer
头。
请求失败也返回一个图片的方法
如果别人引用你的图片,你并没有授权他,你不想返回一个错误,而是想返回一个自己指定的东西给他,可以是提示语,或者是图片等。
修改192.168.226.20这个被引用主机的配置文件
vim /etc/nginx/conf.d/default.conf
#修改成如下内容:
server {
listen 80; # 监听80端口
server_name localhost; # 设置服务器名称为localhost
# 根目录及默认文件设置
root /usr/share/nginx/html;
location / {
index index.html index.htm; # 默认文件
}
# 针对以 .gif、.jpg、.png、.jpeg 为扩展名的图片文件
location ~* \.(gif|jpg|png|jpeg)$ {
valid_referers 192.168.226.20 *.baidu.com *.google.com;
# 有效的 referer 包括:
# 1. 192.168.226.1:来自定位 IP 地址 192.168.226.1 的请求
# 2. 192.168.226.20:来自定位 IP 地址 192.168.226.20 的请求
# 3. *.baidu.com:来自 baidu.com 域及其子域的请求
# 4. *.google.com:来自 google.com 及其子域的请求
if ($invalid_referer) {
rewrite ^/ https://picsum.photos/200/300;
# 如果 referer 无效,重写请求路径,重定向到https://picsum.photos/200/300
}
}
}
重启nginx
nginx -s reload
测试:
1. 允许的 Referer 头测试:
curl -v -e http://192.168.226.20 http://192.168.226.20/tu.jpg
curl -v -e http://www.baidu.com http://192.168.226.20/tu.jpg
curl -v -e http://www.google.com http://192.168.226.20/tu.jpg
输出提示中包括: < HTTP/1.1 200 OK
2. 禁止的 Referer 头测试:
curl -v -e http://www.invalid.com http://192.168.226.20/tu.jpg
curl -v http://192.168.226.20/tu.jpg # 不带 -e 参数,模拟没有 Referer 头的请求
输出提示中包括: < HTTP/1.1 302 Moved Temporarily
然后浏览器刷新网页访问192.168.226.21
看这个主机引用的图片是否还是为tu.jpg
可以看到并不是192.168.226.20主机的tu.jpg图片,而是一个在其配置文件中指定让你看到的链接的图片。