阻止Nginx解码URL

时间:2018-06-21 11:35:50

标签: nginx

我运行一个提供静态文件的Nginx服务器。一些文件名包含诸如%3a之类的字符串。

/var/www/testfile%3a

如果我尝试请求这些文件,则会出现 404 Not Found 错误。

这似乎是因为nginx decodes the URL并将%3a替换为:,然后找不到名为/var/www/testfile:的文件。我从nginx的以下调试输出中推断出这一点:

2018/06/21 10:03:21 [debug] 32523#0: *6 http process request line
2018/06/21 10:03:21 [debug] 32523#0: *6 http request line: "GET /testfile%3a HTTP/1.1"
2018/06/21 10:03:21 [debug] 32523#0: *6 s:0 in:'2F:/'
2018/06/21 10:03:21 [debug] 32523#0: *6 s:1 in:'74:t'
2018/06/21 10:03:21 [debug] 32523#0: *6 s:0 in:'65:e'
2018/06/21 10:03:21 [debug] 32523#0: *6 s:0 in:'73:s'
2018/06/21 10:03:21 [debug] 32523#0: *6 s:0 in:'74:t'
2018/06/21 10:03:21 [debug] 32523#0: *6 s:0 in:'66:f'
2018/06/21 10:03:21 [debug] 32523#0: *6 s:0 in:'69:i'
2018/06/21 10:03:21 [debug] 32523#0: *6 s:0 in:'6C:l'
2018/06/21 10:03:21 [debug] 32523#0: *6 s:0 in:'65:e'
2018/06/21 10:03:21 [debug] 32523#0: *6 s:0 in:'25:%'
2018/06/21 10:03:21 [debug] 32523#0: *6 s:4 in:'33:3'
2018/06/21 10:03:21 [debug] 32523#0: *6 s:5 in:'61:a'
2018/06/21 10:03:21 [debug] 32523#0: *6 s:0 in:'3A::'
2018/06/21 10:03:21 [debug] 32523#0: *6 http uri: "/testfile:"

到目前为止,我想出了两种可能的解决方案:

  • 重命名所有提供的文件,以使%3a成为文件名中的:,并教育每个在此处上传文件的人。
  • 写一个重写规则,使%符号转为%25。但是我相信重写阶段是在URL已经被解码之后进行的。当前,文件名中没有未转义的:字符,因此我可以将:重写为%253a,这可能会起作用。尽管这些文件名中可能存在其他字符,但这是不可能的,因为它们可能以编码和未编码形式出现在URL中。

我认为可能有一个我忽略的更简单的解决方案。有没有办法告诉nginx从字面上对待每个URL,例如没有解码转义字符?

2 个答案:

答案 0 :(得分:1)

目前,我已使用以下重写规则解决了该问题:

    rewrite ^(.*):(.*)$ $1%3a$2 last;

重写URL后,似乎没有更多解码步骤了,因此:可以直接替换为%3a

答案 1 :(得分:1)

如果您的网址中有百分号,只需将您的请求中的百分号与%25交换,如下所示:

https://domain/testfile%253a

然后它变成文件https://domain/testfile%3a

问题不在于“ Nginx解码URI”-您试图避开根据RFC标准的普通URI的工作方式,其中百分号始终用于编码特殊字符。您可能会读懂article about percent encoding并避免使用URI中使用的所有特殊字符,因为使用这些特殊字符都会引起问题(诸如?,&,#等字符,以及更多的字符)。对于文件名,完全避免使用它们是有意义的,例如,将它们替换为另一个字符,例如_。