My developers want to allow download some files only to users in lan. I said ok it's quite simple and I wrote changes to nginx config like this :
location /restricteddir/download/file {
allow 192.168.0.0/16;
allow 10.0.0.0/8;
deny all;
}
Ok from outside I'm getting 403 so thats good but from inside (LAN) gives me 404. Why?
I have checked, the location of file doesn't exist on disk. The developer told me that the location is dynamically generated by php so files are in tmp directory but after you click link like:
https://example.com/report/download/file/id/somefile.txt
it should started download but it gives 404 error.
The last physical loaction is /restricteddir/download
so file/id/somefile.txt
is generated by php.
For testing I changed the location to /restricteddir/download
and after that hiting https://example.com/restricteddir/download
gave me 404 to.
I'm confused after disabling restriction to that dir everythings works fine, I can download file from https://example.com/report/download/file/id/somefile.txt
and hit https://example.com/report/download/
without 404. So where is the bug ? What should I add to my nginx configuration to make it work?
EDIT1
This is full config for this virtualhost:
#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;
}
And I founded this in my logs:
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"
So now I know that nginx is looking this location in wrong root /usr/share/nginx/html/
instead in /sites/public
So maybe i should write this like :
location /sites/public/restricteddir/download/file {
allow 192.168.0.0/16;
allow 10.0.0.0/8;
deny all;
}
EDIT2
I moved root directive to server block and now in logs after enabling restriction for location /restricteddir/download/file I have:
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"
So now nginx is looking in right place but doesn't find enything. Like this file was not generated by php? I'm strugling with it and have no idea what is wront… Thats a simple task restrcit location why this doesn't work ?
EDIT3
This is how looks my virtualhost config now:
#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;
}
So I only moved root directive into server block, after that nginx is looking in good place but still geting 404. I'm confused beacuse after I comment out location /restricteddir/download/file block everything is working fine and I can download the file.
For me it't very strange because its only simple restriction … why is it that after enabling it nginx could not find that file …
Best Answer
Two suggestions:
root
directive into theserver
block, so it will apply to alllocation
blocks that follow it. That appears to be your intent.location /sites/public
doesn't make sense.And some other feedback:
The question of whether the files physically exist or not does not make a difference when processing
location
directives, they will match regardless.Another mis-match I see is that your log entry refers to "restricteddir", but your "full config" post does not mention this. It mentions a "report" dir instead.