启用FastCGI缓存的Nginx安全Headers无法正常返回问题求助
我最近在带FastCGI缓存的Nginx环境里给站点配置安全Headers,碰到个头疼的问题:明明在虚拟主机配置里加了add_header字段设置安全Headers,但只有把fastcgi_main.conf里的add_header X-FastCGI-Cache $upstream_cache_status禁用掉,这些安全Headers才能正常返回。
我的配置文件
虚拟主机配置
} include /etc/nginx/bots.d/blockbots.conf; include /etc/nginx/bots.d/ddos.conf; include /etc/nginx/skip_cache.conf ; include /etc/nginx/purge_location.conf ; include /etc/nginx/gzip_location.conf ; include /etc/nginx/security_wp.conf; add_header Referrer-Policy 'origin'; add_header "X-Frame-Options: sameorigin" always; location ~ \.php$ { include snippets/fastcgi-php.conf; fastcgi_pass unix:/var/run/php/php7.3-fpm.sock; include "/etc/nginx/customfastcgi" ; proxy_connect_timeout 300; proxy_send_timeout 300; proxy_read_timeout 300; send_timeout 300; # underscores_in_headers on; client_max_body_size 256M; include /etc/nginx/fastcgi_main.conf ; } }
fastcgi_main.conf配置
fastcgi_no_cache $skip_cache; fastcgi_cache phpcache; fastcgi_cache_valid 200 1m; fastcgi_cache_valid 301 1m; fastcgi_cache_valid 302 1m; fastcgi_cache_valid 307 1m; fastcgi_cache_valid 404 1m; fastcgi_cache_use_stale error timeout invalid_header http_500 http_503; fastcgi_cache_min_uses 1; fastcgi_cache_methods GET HEAD; fastcgi_ignore_headers Cache-Control Expires Set-Cookie; add_header X-FastCGI-Cache $upstream_cache_status;
测试结果
我用curl命令测试站点响应头:
curl -I https://dev-kuhicbury.$domain
返回的结果里只有缓存状态头,看不到我设置的安全Headers:
HTTP/1.1 200 OK
Server: nginx/1.10.3 (Ubuntu)
Date: Fri, 09 Oct 2020 11:39:35 GMT
Content-Type: text/html; charset=UTF-8
Connection: keep-alive
Vary: Accept-Encoding
rel="https://api.w.org/"
X-FastCGI-Cache: HIT
问题原因&解决办法
后来查了Nginx的规则才明白:当子块(比如这里的location ~ \.php$)里包含的配置文件中有add_header指令时,它会覆盖父块(虚拟主机)里所有的add_header设置。也就是说,fastcgi_main.conf里的add_header X-FastCGI-Cache ...把虚拟主机里的安全Headers给覆盖了,导致只有缓存状态头能返回。
解决这个问题有两种靠谱的方式:
方式一:在fastcgi配置中同步添加安全Headers
直接在fastcgi_main.conf里也加上需要的安全Headers,并且记得给所有add_header加上always参数(这个参数能保证即使返回错误状态码,Headers也会被发送)。另外注意原来的X-Frame-Options写法多了个冒号,要修正过来:
fastcgi_no_cache $skip_cache; fastcgi_cache phpcache; fastcgi_cache_valid 200 1m; fastcgi_cache_valid 301 1m; fastcgi_cache_valid 302 1m; fastcgi_cache_valid 307 1m; fastcgi_cache_valid 404 1m; fastcgi_cache_use_stale error timeout invalid_header http_500 http_503; fastcgi_cache_min_uses 1; fastcgi_cache_methods GET HEAD; fastcgi_ignore_headers Cache-Control Expires Set-Cookie; add_header X-FastCGI-Cache $upstream_cache_status always; add_header Referrer-Policy 'origin' always; add_header X-Frame-Options sameorigin always;
方式二:统一管理所有Headers配置
把所有需要添加的Headers放到一个单独的配置文件里,比如/etc/nginx/global_headers.conf,内容如下:
add_header Referrer-Policy 'origin' always; add_header X-Frame-Options sameorigin always; add_header X-FastCGI-Cache $upstream_cache_status always;
然后在虚拟主机配置和fastcgi_main.conf里都include这个文件,这样就能统一管理,避免子块覆盖的问题。
这样修改后,再用curl测试就能看到所有需要的安全Headers和缓存状态头都正常返回了。
内容的提问来源于stack exchange,提问作者wajahat021

