自动摘要
正在生成中……
为什么if是邪恶的?
if
指令在location里使用经常会出现不符合期望的情形,有时甚至会出现段错误(segfaults),这是因为if指令是重写模块的一部分,该模块命令式地计算指令。另一方面,NGINX配置是声明性的语言。但某些情况,由于用户的需要,会尝试在if中使用一些非重写指令
。
这就导致了现在的情况。它总体上是有效的,不过有一些情况可能并不如你所愿,比如:
# Here is collection of unexpectedly buggy configurations to show that
# if inside location is evil.
# only second header will be present in response
# not really bug, just how it works
location /only-one-if {
set $true 1;
if ($true) {
add_header X-First 1;
}
if ($true) {
add_header X-Second 2;
}
return 204;
}
# request will be sent to backend without uri changed
# to '/' due to if
location /proxy-pass-uri {
proxy_pass http://127.0.0.1:8080/;
set $true 1;
if ($true) {
# nothing
}
}
# try_files wont work due to if
location /if-try-files {
try_files /file @fallback;
set $true 1;
if ($true) {
# nothing
}
}
# nginx will SIGSEGV
location /crash {
set $true 1;
if ($true) {
# fastcgi_pass here
fastcgi_pass 127.0.0.1:9000;
}
if ($true) {
# no handler here
}
}
# alias with captures isn't correcly inherited into implicit nested
# location created by if
location ~* ^/if-and-alias/(?<file>.*) {
alias /tmp/$file;
set $true 1;
if ($true) {
# nothing
}
}
只有两种情况是100%安全的。
if ($request_method = POST ) { return 405; }
if ($args ~ post=140){ rewrite ^ http://example.com/ permanent; }
如何避免?
除了使用 try_files 和上面提到的 return ...;
和 rewrite ... last;
外,还可以把if
移到server
块,因为只有其他重写模块指令被允许在里面,这是安全的。
参考:https://www.nginx.com/resources/wiki/start/topics/depth/ifisevil/