Nginx 常用安全头
Web 应用中配置 HTTP 安全响应头是提升网站安全性的重要一步。合理配置 Nginx 的安全头,可以抵御常见的安全威胁(如 XSS、点击劫持、MIME 类型嗅探等),增强用户隐私保护和传输安全性。
常见的 HTTP 安全头及其作用
1. Content-Security-Policy (CSP)
作用:限制资源(如脚本、样式、图片等)的加载来源,防止 XSS 和数据注入攻击。
add_header Content-Security-Policy "default-src 'self'; script-src 'self'; style-src 'self'; img-src 'self' data:; object-src 'none'; frame-ancestors 'none';worker-src blob:;";
配置说明:
- `default-src ‘self’:限制所有资源的默认加载来源为当前域。
script-src 'self'
:仅允许加载来自当前域的脚本。style-src 'self
:限制样式来源为当前域。img-src 'self' data:
:允许图片来自当前域和data:
URI。object-src 'none'
:禁止加载<object>
、<embed>
,防止插件攻击。frame-ancestors 'none'
:禁止页面被嵌套到其他站点的iframe
中。worker-src blob:
:允许 Web Worker 资源来源为blob:
。
注意事项:
- 如果需要加载第三方资源(如 CDN),需显式添加来源。
script-src 'self' https://cdn.jsdelivr.net;
- 避免使用
'unsafe-inline'
和'unsafe-eval'
,减少 XSS 风险。 - 使用
nonce
或hash
机制允许特定的内联脚本:
add_header Content-Security-Policy "script-src 'self' 'nonce-random123';";
2. Strict-Transport-Security (HSTS)
作用:强制浏览器通过 HTTPS 访问网站,防止中间人攻击。
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always;
配置说明:
max-age=63072000
:HSTS 有效期(以秒为单位),这里是 2 年。includeSubDomains
:对子域名启用 HSTS。preload
:允许网站加入 HSTS 预加载列表。
3. X-Frame-Options
作用:防止页面被嵌套到其他站点的 iframe
中,防止点击劫持攻击。
add_header X-Frame-Options SAMEORIGIN always;
配置说明:
SAMEORIGIN
:仅允许页面被嵌套到自身域的iframe
中。DENY
:彻底禁止页面被嵌套。ALLOW-FROM uri
:仅允许特定来源嵌套页面(需注意已被部分浏览器废弃)。
4. X-XSS-Protection
作用:启用浏览器的 XSS 过滤功能,防止跨站脚本攻击。
add_header X-XSS-Protection "1; mode=block" always;
配置说明:
1; mode=block
:启用 XSS 过滤器并阻止加载恶意脚本的页面。
5. X-Content-Type-Options
作用:防止浏览器对资源类型进行 MIME 嗅探,避免脚本注入攻击。
add_header X-Content-Type-Options "nosniff" always;
配置说明:
nosniff
:强制浏览器使用Content-Type
指定的 MIME 类型。
6. Referrer-Policy
作用:控制 Referer
头信息的发送,保护用户隐私。
add_header Referrer-Policy "origin" always;
配置说明:
origin
:跨域请求时仅发送来源站点信息,不包括完整的 URL。
7. Permissions-Policy (原 Feature-Policy)
作用:限制浏览器功能的使用,防止滥用。
add_header Permissions-Policy "geolocation=(), microphone=(), camera=(), fullscreen=(self);";
配置说明:
- 禁用了地理定位、麦克风、摄像头功能。
- 仅允许自身域使用全屏功能。
8. Cache-Control 和 Pragma
作用:控制缓存行为,防止敏感数据被缓存。
add_header Cache-Control "no-store" always;
add_header Pragma "no-cache" always;
配置说明:
Cache-Control: no-store
:禁止缓存页面内容。Pragma: no-cache
:兼容旧版 HTTP 协议的缓存控制头。
9. Set-Cookie
作用:为 Cookie 添加安全属性,防止 XSS 和中间人攻击。
add_header Set-Cookie "Path=/; HttpOnly; Secure";
配置说明:
HttpOnly
:防止客户端脚本访问 Cookie,避免 XSS。Secure
:仅通过 HTTPS 发送 Cookie。
10. Cross-Origin-Embedder-Policy (COEP)
作用: 限制跨域资源的加载,用于启用跨域隔离。
add_header Cross-Origin-Embedder-Policy "require-corp" always;
配置说明:
require-corp
:仅允许跨域加载具有 CORS 或Cross-Origin-Resource-Policy
标头的资源。
11. Cross-Origin-Opener-Policy (COOP)
作用: 隔离文档上下文,防止跨窗口攻击。
add_header Cross-Origin-Opener-Policy "same-origin" always;
配置说明:
same-origin
:仅允许相同源的页面与当前页面共享浏览上下文。
12. Cross-Origin-Resource-Policy (CORP)
作用: 限制资源的跨域加载。
add_header Cross-Origin-Resource-Policy "same-origin" always;
配置说明:
same-origin
:仅允许资源从相同源加载。
为静态资源启用缓存
为静态资源(如图片、CSS、JS 文件)启用缓存可以显著提升性能,同时不会直接引发安全问题。以下是推荐的配置:
location ~* \.(css|js|png|jpg|jpeg|gif|ico|woff|woff2|ttf|svg|eot|otf)$ {
expires 1y;
add_header Cache-Control "public";
add_header Content-Security-Policy "default-src 'self';";
add_header X-Content-Type-Options nosniff;
add_header X-Frame-Options SAMEORIGIN;
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload";
access_log off;
}
配置说明:
expires 1y
:允许静态资源缓存 1 年。Cache-Control: public
:标记资源为公共可缓存。access_log off
:禁用访问日志,减少服务器存储压力。
完整示例配置
安全头配置文件:
add_header Content-Security-Policy "default-src 'self' http: https: blob: ;
script-src 'self' yourJsUrl; object-src 'self';
img-src 'self' data: blob: yourimgUrl; style-src 'unsafe-inline' http: ;
frame-ancestors 'self'; worker-src blob:;" always;
add_header X-Frame-Options SAMEORIGIN always;
add_header X-XSS-Protection "1; mode=block" always;
add_header X-Content-Type-Options: nosniff always;
add_header Strict-Transport-Security "max-age=63072000; includeSubdomains; preload" always;
add_header Referrer-Policy origin always;
add_header Cache-Control no-store always;
add_header Pragma no-cache always;
add_header X-Permitted-Cross-Domain-Policies none always;
add_header X-Download-Options noopen always;
add_header Set-Cookie "Path=/; HttpOnly; Secure" always;
add_header Cross-Origin-Embedder-Policy "require-corp" always;
add_header Cross-Origin-Opener-Policy "same-origin" always;
add_header Cross-Origin-Resource-Policy "same-origin" always;
如果js和img需要配置允许的域名,替换路径即可。
跨域头配置文件:
add_header 'Access-Control-Allow-Origin' "$cors_origin" always;
add_header 'Vary' 'Origin' always;
add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS' always;
add_header 'Access-Control-Allow-Headers' 'Content-Type, Authorization, X-Requested-With' always;
add_header 'Access-Control-Max-Age' "$cors_max_age" always;
Nginx 的default.conf配置示例:
# 动态设置允许的跨域来源
map $http_origin $cors_origin {
default "";
"~^https?://trusteddomain1.com$" $http_origin;
"~^https?://trusteddomain2.com$" $http_origin;
}
# 动态设置缓存时间
map $http_origin $cors_max_age {
default "0";
"~^https?://trusteddomain1.com$" "86400"; # 1 天
"~^https?://trusteddomain2.com$" "3600"; # 1 小时
}
server {
listen 8081;
listen [::]:8081;
server_name localhost;
root /usr/share/nginx/html/applet/dist/build/h5/;
server_tokens off;
include /etc/nginx/conf.d/safety_headers.conf;
location ~* \.(css|js|png|jpg|jpeg|gif|ico|woff|woff2|ttf|svg|eot|otf)$ {
expires 1y;
include /etc/nginx/conf.d/safety_headers.conf;
add_header Cache-Control "public";
access_log off;
}
# 禁止敏感路径访问
location = /auth/ {
deny all;
return 404;
}
error_page 403 =404 /404.html;
location = /404.html {
root /usr/share/nginx/html;
}
# redirect server error pages to the static page /50x.html
#
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
location ~* ^/(code|authFront|adminplus|external|auth|admin|marry){
include /etc/nginx/conf.d/safety_headers.conf;
# 设置 CORS 响应头
include /etc/nginx/conf.d/cors_headers.conf;
# 如果是预检请求 (OPTIONS),直接返回成功
if ($request_method = 'OPTIONS') {
# 设置 CORS 响应头
add_header 'Access-Control-Allow-Origin' "$cors_origin" always;
add_header 'Vary' 'Origin' always;
add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS' always;
add_header 'Access-Control-Allow-Headers' 'Content-Type, Authorization, X-Requested-With' always;
add_header 'Access-Control-Max-Age' "$cors_max_age" always;
add_header 'Content-Length' 0;
add_header 'Content-Type' 'text/plain';
return 204;
}
proxy_pass backendUrl;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
client_max_body_size 1024m;
proxy_buffer_size 1024k;
proxy_buffers 16 1024k;
proxy_busy_buffers_size 2048k;
proxy_temp_file_write_size 2048k;
}
#location /manage {
# alias /usr/share/nginx/html/manage/dist/;
#}
location ~^/oss/crossdomain.xml {return 403;}
location ~^/oss/(.*HOST.*){return 403;}
location ~^/oss/ {
proxy_buffering off;
proxy_set_header Host $http_host;
rewrite ^/oss/(.*)$ /$1 break;
proxy_pass http://172.17.0.1:9000;
}
#error_page 404 /404.html;
# redirect server error pages to the static page /50x.html
#
#error_page 500 502 503 504 /50x.html;
#location = /50x.html {
# root /usr/share/nginx/html;
#}
# proxy the PHP scripts to Apache listening on 127.0.0.1:80
#
#location ~ \.php$ {
# proxy_pass http://127.0.0.1;
#}
# pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
#
#location ~ \.php$ {
# root html;
# fastcgi_pass 127.0.0.1:9000;
# fastcgi_index index.php;
# fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name;
# include fastcgi_params;
#}
# deny access to .htaccess files, if Apache's document root
# concurs with nginx's one
#
#location ~ /\.ht {
# deny all;
#}
}
参考:http-headers-MDN