Мои разработчики хотят разрешить загрузку некоторых файлов только пользователям в локальной сети. Я сказал хорошо, что это довольно просто, и написал следующие изменения в конфигурации nginx:
location /restricteddir/download/file {
allow 192.168.0.0/16;
allow 10.0.0.0/8;
deny all;
}
Хорошо, снаружи я получаю 403, так что это хорошо, но изнутри (LAN) дает мне 404. Почему?
Я проверил, расположение файла на диске не существует. Разработчик сказал мне, что местоположение динамически генерируется php, поэтому файлы находятся в каталоге tmp, но после того, как вы нажмете ссылку, например:
https://example.com/report/download/file/id/somefile.txt
он должен начать загрузку, но выдает ошибку 404.
Последнее физическое действие - /restricteddir/download
так file/id/somefile.txt
генерируется php.
Для тестирования я изменил локацию на /restricteddir/download
и после этого удара https://example.com/restricteddir/download
дал мне 404 к.
Я запутался после отключения ограничения на этот каталог, все работает нормально, я могу загрузить файл из https://example.com/report/download/file/id/somefile.txt
и ударил https://example.com/report/download/
без 404. Так где же ошибка? Что я должен добавить в конфигурацию nginx, чтобы он заработал?
РЕДАКТИРОВАТЬ1 Это полная конфигурация для этого виртуального хоста:
#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;
}
И я нашел это в своих журналах:
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;
}
РЕДАКТИРОВАТЬ2
Я переместил корневую директиву в блок сервера и теперь в журналах после включения ограничения для location / limiteddir / download / file у меня есть:
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 ? РЕДАКТИРОВАТЬ3
Вот как теперь выглядит моя конфигурация виртуального хоста:
#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;
}
Поэтому я только переместил корневую директиву в серверный блок, после этого nginx выглядит в хорошем месте, но все еще получает 404. Я запутался, потому что после того, как я закомментировал блок location / limiteddir / download / file, все работает нормально, и я могу загрузить файл .
Для меня это не очень странно, потому что это единственное простое ограничение ... почему после включения nginx не смог найти этот файл ...
Два предложения:
root
директива в server
блок, поэтому он будет применяться ко всем location
блоки, которые следуют за ним. Похоже, это ваше намерение.location /sites/public
не имеет смысла.И еще несколько отзывов:
Вопрос о том, существуют ли файлы физически или нет, не имеет значения при обработке. location
директивы, они будут совпадать независимо.
Еще одно несоответствие, которое я вижу, заключается в том, что ваша запись в журнале относится к "ограниченному каталогу", но в вашем сообщении "полная конфигурация" об этом не упоминается. Вместо этого он упоминает каталог "report".
Во-первых, я бы избегал следующих if
заблокировать, если возможно, потому что если зло. Использовать 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;
Полностью ли файлы генерируются PHP динамически, поэтому не существуют напрямую в файловой системе и, следовательно, не могут обслуживаться nginx без передачи запроса в PHP? Если это так, вам нужно передать вещи с помощью fastcgi_pass
в fastcgi, чтобы PHP мог создавать и обслуживать файл, а не 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 ищет в нужном месте, но все равно не может найти файл, возможно, его владелец и группа - fastcgi: fastcgi с разрешениями 660? Либо это, либо происходит какое-то кеширование, например open_file_cache
в nginx.conf