我的开发人员只允许将一些文件下载到局域网用户。 我说好吧,这很简单,我写了像这样的nginxconfiguration的变化:
location /restricteddir/download/file { allow 192.168.0.0/16; allow 10.0.0.0/8; deny all; }
好,从外面我得到403这样好,但从内部(LAN)给我404。为什么?
我已经检查过,磁盘上不存在文件的位置。 开发人员告诉我,这个位置是由phpdynamic生成的,所以文件在tmp目录中,但是当你点击如下链接之后:
https://example.com/report/download/file/id/somefile.txt它应该开始下载,但它给404错误。
最后一个物理位置是/restricteddir/download所以file/id/somefile.txt是由php生成的。
为了testing,我将位置更改为/restricteddir/download ,之后https://example.com/restricteddir/download给了我404。
禁用限制后,我很困惑,所有目录工作正常,我可以从https://example.com/report/download/file/id/somefile.txt下载文件,然后按https://example.com/report/download/无404.那么错误在哪里? 我应该添加到我的nginxconfiguration,使其工作?
EDIT1这是这个虚拟主机的完整configuration:
#example.com:443 server { listen 443 default; ssl on; ssl_certificate example.crt; ssl_certificate_key example.key; ssl_session_timeout 15m; ssl_protocols SSLv2 SSLv3 TLSv1; ssl_ciphers ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP; ssl_prefer_server_ciphers on; server_name example.com; access_log /var/log/nginx/example.com.access.log; error_log /var/log/nginx/example.com.error.log; location / { root /sites/public; index index.php; if (!-f $request_filename) { rewrite ^.*$ /index.php last; break; } } location /restricteddir/download/file { allow 192.168.0.0/16; allow 10.0.0.0/8; deny all; } #PHP location ~ \.php$ { fastcgi_pass 127.0.0.1:9000; fastcgi_index index.php; include /fastcgi_params; fastcgi_param SCRIPT_FILENAME /sites/public$fastcgi_script_name; } } server { listen 80 default; server_name example.com; access_log off; rewrite ^(.*)$ https://example.com$1 permanent; }
我在我的日志中创build了这个:
2012/08/07 11:55:43 [error] 11121#0: *90 open() "/usr/share/nginx/html/restricteddir/download/file/id/somefile.txt" failed (2: No such file or directory), client: 10.200.2.70, server: example.com, request: "GET /restricteddir/download/file/id/somefile.txt HTTP/1.1", host: "example.com"
所以现在我知道nginx在/usr/share/nginx/html/ /sites/public
所以也许我应该这样写:
location /sites/public/restricteddir/download/file { allow 192.168.0.0/16; allow 10.0.0.0/8; deny all; }
EDIT2
我把根指令移动到服务器块,现在在启用限制位置/ restricteddir /下载/文件中的日志我有:
2012/08/09 10:43:12 [error] 32120#0: *71 open() "/site/public/restricteddir/download/file/id/somefile.txt" failed (2: No such file or directory), client: 10.2.1.120, server: example.com, request: "GET /restricteddir/download/file/id/somefile.txt HTTP/1.1", host: "example.com"
所以现在nginx正在寻找正确的地方,但没有find任何东西。 像这个文件不是由PHP生成的? 我正在与它斗争,不知道什么是战争…这是一个简单的任务restrcit位置,为什么这是行不通的?
EDIT3
这是如何看起来我的虚拟主机configuration现在:
#example.com:443 server { listen 443 default; ssl on; ssl_certificate example.crt; ssl_certificate_key example.key; ssl_session_timeout 15m; ssl_protocols SSLv2 SSLv3 TLSv1; ssl_ciphers ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP; ssl_prefer_server_ciphers on; server_name example.com; access_log /var/log/nginx/example.com.access.log; error_log /var/log/nginx/example.com.error.log; root /sites/public; location / { index index.php; if (!-f $request_filename) { rewrite ^.*$ /index.php last; break; } } location /restricteddir/download/file { allow 192.168.0.0/16; allow 10.0.0.0/8; deny all; } #PHP location ~ \.php$ { fastcgi_pass 127.0.0.1:9000; fastcgi_index index.php; include /fastcgi_params; fastcgi_param SCRIPT_FILENAME /sites/public$fastcgi_script_name; } } server { listen 80 default; server_name example.com; access_log off; rewrite ^(.*)$ https://example.com$1 permanent; }
所以我只把root指令移动到服务器块,之后,nginx正在寻找好的地方,但仍然geting 404。我很困惑,因为我注释掉location / restricteddir /下载/文件块一切正常,我可以下载文件。
对我来说,它是非常奇怪的,因为它只是一个简单的限制…为什么它启用后,Nginx无法find该文件…
两点build议:
root指令移动到server块中,以便将其应用于其后的所有location块。 这似乎是你的意图。 location /sites/public的想法是没有意义的。 还有一些其他的反馈:
文件是否物理存在的问题在处理location指令时没有什么区别,它们将会匹配。
我看到的另一个不匹配是你的日志条目是指“restricteddir”,但你的“完整configuration”的职位并没有提到这一点。 它提到了一个“报告”目录。
首先,如果可能的话 ,我会避免以下情况,因为如果是邪恶的话 。 使用try_files代替:
location / { root /sites/public; index index.php; if (!-f $request_filename) { rewrite ^.*$ /index.php last; break; } }
这个更好:
location / { try_files $uri $uri/ index.php?$args; }
为了清楚起见,我将root和index移出location /并进入server块:
server { … server_name example.com; access_log /var/log/nginx/example.com.access.log; error_log /var/log/nginx/example.com.error.log; root /sites/public; index index.php;
这些文件是否完全由PHPdynamic生成,因此不直接存在于文件系统中,因此如果不将请求传递给PHP,就不能由nginx提供服务。 如果是这样,你需要将fastcgi_pass传递给fastcgi,以便PHP可以创build并提供文件,而不是nginx试图提供不存在的东西。 所以:
location /report/download/ { allow 192.168.0.0/16; allow 10.0.0.0/8; deny all; fastcgi_pass 127.0.0.1:9000; fastcgi_index index.php; include /fastcgi_params; fastcgi_param SCRIPT_FILENAME /sites/public$fastcgi_script_name; }
如果这些文件实际存在于磁盘上,但位于不同的位置,即请求以https://example.com/report/download/file/id/somefile.txt文件实际指向磁盘上的位置/sites/public/restricteddir/download/file/id/somefile.txt ,你希望nginx直接服务它,而不用交给fastcgi,那么你想要别名指令 。
location /report/download/ { allow 192.168.0.0/16; allow 10.0.0.0/8; deny all; # The actual physical path on disk - alias /sites/public/restricteddir/download/; # or should this be the following? - # alias /restricteddir/download/; }
最后要检查的事情是:如果nginx和fastcgi作为不同的用户运行,请确保两者都具有正确的操作系统文件权限来读取有问题的文件。 如果nginx正在查找正确的位置,但仍然无法find该文件,可能它的所有者和组是fastcgi:具有660个权限的fastcgi? 无论是或者有某种caching,比如nginx.conf中的open_file_cache