通过 add_header 重定义响应头¶
Gixy Check ID: add_header_redefinition
很多人不了解指令继承机制,这常导致在嵌套级别试图新增响应头时误用 add_header。
Nginx 文档对此有说明(见 docs):
可以存在多个
add_header指令。仅当当前级别未定义任何add_header指令时,才会继承上一级别的这些指令。
逻辑很简单:如果你在某一层(例如 server 段)设置了响应头,而在下一级(例如 location)又设置了其他响应头,那么前者会被丢弃。
很容易验证: - 配置:
server {
listen 80;
add_header X-Frame-Options "DENY" always;
location / {
return 200 "index";
}
location /new-headers {
# 特殊缓存控制
add_header Cache-Control "no-cache, no-store, max-age=0, must-revalidate" always;
add_header Pragma "no-cache" always;
return 200 "new-headers";
}
}
/(响应中包含 X-Frame-Options):
GET / HTTP/1.0
HTTP/1.1 200 OK
Server: nginx/1.10.2
Date: Mon, 09 Jan 2017 19:28:33 GMT
Content-Type: application/octet-stream
Content-Length: 5
Connection: close
X-Frame-Options: DENY
index
/new-headers(出现了 Cache-Control 与 Pragma,但没有 X-Frame-Options):
GET /new-headers HTTP/1.0
HTTP/1.1 200 OK
Server: nginx/1.10.2
Date: Mon, 09 Jan 2017 19:29:46 GMT
Content-Type: application/octet-stream
Content-Length: 11
Connection: close
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Pragma: no-cache
new-headers
如何规避?¶
可以采用以下方法解决:
- 重复设置重要响应头;
- 将所有响应头放在同一层设置(server 段通常是个好选择);
- 使用 ngx_headers_more 模块。
加固 NGINX,使用维护的 RPM
使用 GetPageSpeed 提供的 NGINX Extras 在 RHEL/CentOS/Alma/Rocky 上获取持续更新的 NGINX 与模块。 了解更多.
命令行与配置选项¶
--add-header-redefinition-headers headers(默认:未设置):以逗号分隔的响应头白名单(不区分大小写)。设置后,仅当这些头在子级被“丢弃”时才会报告;未设置则报告所有被丢弃的头。示例:--add-header-redefinition-headers x-frame-options,content-security-policy。
配置示例:
[add_header_redefinition]
headers = x-frame-options, content-security-policy