0

Nginx安全响应头配置详解:8个关键Header让你的网站固若金汤

2026.05.22 | youres | 19次围观

为什么要配置安全响应头

很多站长花大量精力搞SSL证书、防火墙、限流,却忽略了最简单有效的一层防护——HTTP安全响应头。浏览器收到这些头之后,会主动拦截很多攻击行为,比如点击劫持、XSS注入、混合内容加载。配置成本极低,防护效果显著,属于性价比最高的安全措施之一。

本文逐个讲解8个核心安全响应头,每个都给出Nginx配置代码和使用注意事项,读完直接上手。

一、X-Frame-Options:防止点击劫持

点击劫持(Clickjacking)的原理:攻击者用iframe把你的网页嵌入他的页面,覆盖一层透明按钮,用户以为点的是自己的页面,实际点的是攻击者安排的操作。

X-Frame-Options告诉浏览器:这个页面允不允被iframe嵌入。

三个可选值:

  • DENY——完全禁止嵌入,任何页面都不行
  • SAMEORIGIN——只允许同源页面嵌入
  • ALLOW-FROM uri——允许指定来源(已被主流浏览器弃用,不推荐)

Nginx配置:

add_header X-Frame-Options "SAMEORIGIN" always;

大多数网站用SAMEORIGIN就够了。如果你的页面完全不需要被iframe嵌入(比如API服务),直接上DENY。

二、X-Content-Type-Options:阻止MIME嗅探

浏览器有时候会"自作聪明":服务器说这是个text/plain文件,但浏览器发现内容像JS,就按JS执行了。这就是MIME嗅探,攻击者可以上传一个伪装文件来执行恶意脚本。

加上这个头,浏览器就老老实实按服务器声明的Content-Type来处理:

add_header X-Content-Type-Options "nosniff" always;

就一个值nosniff,没有选择困难症。这条建议所有站点都加。

三、X-XSS-Protection:浏览器XSS过滤器

老版浏览器(主要是Chrome和Safari)内置了反射型XSS检测功能。这个头用来控制它的行为:

add_header X-XSS-Protection "1; mode=block" always;

含义:开启XSS过滤,检测到攻击时直接阻止页面渲染而不是做"修复"(修复有时反而被利用)。

注意:现代浏览器已经逐步弃用这个头,改用CSP来替代。但为了兼容旧浏览器,加上也没坏处。

四、Content-Security-Policy(CSP):终极防护

CSP是安全响应头里最强大的一个,也是最复杂的一个。它用白名单机制告诉浏览器:只允许从哪些来源加载脚本、样式、图片、字体等资源。

基础配置示例:

add_header Content-Security-Policy "default-src 'self'; script-src 'self' https://cdn.example.com; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; font-src 'self' https://fonts.googleapis.com; connect-src 'self'; frame-ancestors 'self'; base-uri 'self'; form-action 'self'" always;

各指令含义:

  • default-src 'self'——默认只允许同源资源
  • script-src——JS只允许同源和指定CDN
  • style-src 'unsafe-inline'——允许内联样式(很多CMS需要)
  • img-src——图片允许同源、data URI和任意HTTPS
  • frame-ancestors 'self'——替代X-Frame-Options的现代写法

建议先用Content-Security-Policy-Report-Only模式观察,确认没有误拦再正式启用:

add_header Content-Security-Policy-Report-Only "default-src 'self'; report-uri /csp-report" always;

CSP配置不当会导致页面功能异常,务必先观察再上线。

五、Strict-Transport-Security(HSTS):强制HTTPS

即使用户手动输入http://,浏览器也会自动跳转到https://。防止降级攻击和SSL剥离:

add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;

参数说明:

  • max-age=31536000——缓存一年(秒)
  • includeSubDomains——子域名也强制HTTPS
  • preload——允许加入浏览器内置的HSTS预加载列表

重要提醒:开启HSTS前确保全站已经支持HTTPS且证书没有问题。一旦浏览器记住了HSTS,在max-age期间内http请求会直接被拦截,无法降级。建议先用短时间(比如max-age=300)测试,确认没问题再调到一年。

六、Referrer-Policy:控制来源信息泄露

用户从你的网站点链接跳到别的网站,浏览器默认会在Referer头里带上你的页面URL。这可能泄露敏感信息(比如URL里带token或用户ID)。

add_header Referrer-Policy "strict-origin-when-cross-origin" always;

含义:同源请求发送完整Referer,跨域请求只发送来源域名(不含路径和参数)。这是目前最推荐的策略。

其他常用值:

  • no-referrer——完全不发送Referer(隐私最强,但会影响统计)
  • same-origin——只在同源时发送

七、Permissions-Policy:限制浏览器功能

以前叫Feature-Policy,用来控制页面能用哪些浏览器API,防止被恶意脚本滥用:

add_header Permissions-Policy "camera=(), microphone=(), geolocation=(), payment=()" always;

这个配置禁止了摄像头、麦克风、定位和支付API的调用。如果你的网站不需要这些功能,直接禁掉。某些功能可以按需开放,比如视频会议网站开放camera和microphone:

add_header Permissions-Policy "camera=(self), microphone=(self), geolocation=(), payment=()" always;

八、Cross-Origin-Opener-Policy / Cross-Origin-Embedder-Policy

这两个是较新的安全头,主要防止Spectre类的侧信道攻击:

add_header Cross-Origin-Opener-Policy "same-origin" always;
add_header Cross-Origin-Embedder-Policy "require-corp" always;

启用后页面可以获得跨域隔离(cross-origin isolation),从而使用SharedArrayBuffer等高精度计时器。适合需要高安全级别的应用。普通网站暂时可以不配,但未来会是标配。

完整Nginx配置示例

把所有安全头汇总到一个server块里:

server {
    listen 443 ssl http2;
    server_name example.com;

    # SSL配置(略)

    # === 安全响应头 ===
    add_header X-Frame-Options "SAMEORIGIN" always;
    add_header X-Content-Type-Options "nosniff" always;
    add_header X-XSS-Protection "1; mode=block" always;
    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
    add_header Referrer-Policy "strict-origin-when-cross-origin" always;
    add_header Content-Security-Policy "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; font-src 'self'; connect-src 'self'; frame-ancestors 'self'; base-uri 'self'; form-action 'self'" always;
    add_header Permissions-Policy "camera=(), microphone=(), geolocation=(), payment=()" always;

    # 其他配置...
}

注意always参数很重要——确保即使响应是404/500也带上这些头。

add_header的继承陷阱

Nginx的add_header有个容易踩的坑:如果location块里定义了任何add_header,server块的add_header就不会被继承

比如你的location块加了CORS头:

location /api/ {
    add_header Access-Control-Allow-Origin "https://example.com";
    # 这会导致server块的8个安全头全部丢失!
}

解决办法:在每个location块里重复写安全头,或者用ngx_headers_more模块的more_set_headers指令(不受继承规则限制)。

安装方法:

# Ubuntu/Debian
apt install libnginx-mod-http-headers-more-filter

# 然后在nginx.conf顶部加载
load_module modules/ngx_http_headers_more_filter_module.so;

# 用more_set_headers替代add_header
more_set_headers "X-Frame-Options: SAMEORIGIN";
more_set_headers "X-Content-Type-Options: nosniff";

验证配置是否生效

发布后用curl检查:

curl -I https://example.com

或者用浏览器开发者工具(F12 → Network → 点击请求 → Headers),逐个确认每个安全头都存在且值正确。

也可以用在线检测工具比如securityheaders.com,输入域名就能看到评分和缺失的头。

相关文章

版权声明

本文仅代表个人观点。
本文系AI辅助作者原创,未经许可,转载请保留原文链接。

发表评论
883文章数 0评论数
作者其它文章