server {
listen 80;
server_name img.your-domain.com; # 替换为你的图片服务器域名
# 图片文件存放的根目录
root /path/to/your/images; # 替换为你的图片目录路径
# 关闭目录索引
autoindex off;
# 预定义跨域头(会被继承到子location)
add_header 'Access-Control-Allow-Methods' 'GET, OPTIONS' always;
add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range' always;
# 设置图片文件的 MIME 类型
location ~* \.(jpg|jpeg|png|gif|ico|svg|webp)$ {
# 设置缓存头
expires 30d;
add_header Cache-Control "public, no-transform" always;
# 防盗链设置 - 只允许 baidu.com 和 www.baidu.com 引用
valid_referers none blocked server_names
*.baidu.com baidu.com www.baidu.com;
if ($invalid_referer) {
return 403;
}
# 动态设置跨域头(根据请求来源)
if ($http_origin ~* (https?://(www\.)?baidu\.com)) {
add_header 'Access-Control-Allow-Origin' "$http_origin" always;
}
# 处理 OPTIONS 预检请求
if ($request_method = 'OPTIONS') {
add_header 'Access-Control-Max-Age' 1728000 always;
add_header 'Content-Type' 'text/plain; charset=utf-8' always;
add_header 'Content-Length' 0 always;
return 204;
}
# 尝试直接访问文件,如果不存在则返回404
try_files $uri =404;
}
# 禁止访问隐藏文件
location ~ /\. {
deny all;
}
# 其他所有请求返回404
location / {
return 404;
}
}
关键修改点:
- 添加
always
参数:- OpenResty/Nginx 在某些上下文中需要
always
参数才能确保头被发送 - 例如:
add_header ... always;
- OpenResty/Nginx 在某些上下文中需要
- 调整跨域头设置逻辑:
- 将固定的跨域头移到 server 层级
- 使用动态匹配设置
Access-Control-Allow-Origin
- OPTIONS 处理:
- 保持预检请求处理,但确保所有
add_header
都有always
- 保持预检请求处理,但确保所有
- 防盗链逻辑不变:
- 仍然保持原有的
valid_referers
检查
- 仍然保持原有的
注意事项:
- 如果你使用 HTTPS,请确保:
add_header 'Access-Control-Allow-Origin' "https://$http_origin" always;
这样能防止协议降级(HTTP网站引用HTTPS图片)
进阶配置,直接访问图片服务器域名不返回任何图片,只有指定的域名访问的时候才返回数据。
- 禁止直接访问(返回 403 或 404)
- 仅允许
baidu.com
作为Referer
的请求 - 确保跨域访问仍然可用
✅ 最终配置(推荐)
server {
listen 80;
server_name img.your-domain.com;
root /path/to/your/images;
autoindex off;
# 默认禁止访问(直接访问返回403)
location / {
return 403;
}
# 图片文件处理
location ~* \.(jpg|jpeg|png|gif|ico|svg|webp)$ {
# 防盗链:仅允许 baidu.com 引用
valid_referers none blocked server_names
*.baidu.com baidu.com www.baidu.com;
if ($invalid_referer) {
return 403;
}
# 允许跨域(仅限 zmt.wiki)
if ($http_origin ~* (https?://(www\.)?baidu\.com)) {
add_header 'Access-Control-Allow-Origin' "$http_origin" always;
add_header 'Access-Control-Allow-Methods' 'GET, OPTIONS' always;
add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range' always;
}
# 处理 OPTIONS 预检请求
if ($request_method = 'OPTIONS') {
add_header 'Access-Control-Max-Age' 1728000 always;
add_header 'Content-Type' 'text/plain; charset=utf-8' always;
add_header 'Content-Length' 0 always;
return 204;
}
# 返回图片
try_files $uri =404;
expires 30d;
add_header Cache-Control "public, no-transform" always;
}
# 禁止访问隐藏文件
location ~ /\. {
deny all;
}
}
关键点解析
location / { return 403; }
- 直接访问
img.your-domain.com
会返回 403(禁止访问) - 只有通过
baidu.com
引用的请求才能加载图片
- 直接访问
valid_referers
防盗链- 仅允许
baidu.com
和www.baidu.com
作为Referer
- 其他来源返回 403
- 仅允许
- 跨域支持(CORS)
- 仅对
baidu.com
开放跨域访问 - 支持
OPTIONS
预检请求
- 仅对
- 缓存优化
- 图片缓存 30天
- 减少服务器负载
测试方法
- 合法访问(应该能加载)
<!-- 在 baidu.com 的网页上 --> <img src="http://
img.your-domain.com
/test.jpg">
- ✅ 正常显示
- 非法访问(应该被拒绝)
- 直接浏览器访问
http://
→ 403
/test.jpgimg.your-domain.com
- 在其他网站引用该图片 → 403
- 直接浏览器访问
隐藏 Nginx 版本信息(安全加固)
server {
server_tokens off; # 隐藏 Nginx 版本
# 其他配置...
}
✅ 直接访问
→ 403(看不到图片)img.your-domain.com
✅ baidu.com
引用图片 → 正常加载
✅ 防盗链 + 跨域支持
✅ 缓存优化 + 安全加固
这样配置后,你的图片服务器既安全又高效! 🚀
- All rights reserved.
- No part of this website, including text and images, may be reproduced, modified, distributed, or transmitted in any form or by any means, without the prior written permission of the author.
- Unauthorized commercial use is strictly prohibited.
- Unauthorized personal use is strictly prohibited.