Потребовалось несколько часов, чтобы узнать, как правильно настроить NginX
, но я все еще думаю, что мог что-то упустить. Главным образом потому, что эта отлично работающая установка вызывает больше вопросов, чем ответов. Возможно, это даже NginX
NginX или что-то, представленное Debian
в Version: 1.2.1-2.2+wheezy2
Package: nginx-extras
, я просто не знаю.
Обратите внимание, что мой пример уже урезан до минимума (поэтому примите это как отправную точку), но он все равно должен содержать все необходимые текущие исправления безопасности.
Обратите внимание, что мне не нравится эвристика, склонная к ошибкам. Для этого он работает с /etc/php/fpm/pool.d/www.conf
установленным таким образом, что php-fpm
берет скрипт непосредственно из PATH_TRANSLATED
вместо того, чтобы угадывать его:
php_admin_value[cgi.fix_pathinfo]=0
security.limit_extensions = .php
php_admin_flag[expose_php] = off
Вот php
/home/tino/www/index.php
который выводит переменные:
<?
header("content-type: text/plain");
$a = array("PATH_TRANSLATED", "SCRIPT_FILENAME", "DOCUMENT_URI", "PATH_INFO", "QUERY_STRING" );
foreach ($a as &$v)
printf("%-15s %s\n", $v, $_SERVER[$v]);
?>
Рабочая конфигурация NginX
Обратите внимание, что /home/tino/www
- это место, где живет мой тестовый скрипт. И вы, возможно, захотите заполнить все остальные параметры из /etc/nginx/fastcgi_params
. Например вам нужно
fastcgi_param SCRIPT_NAME $fastcgi_script_name;
заполнить PHP_SELF
.
server_tokens off;
server {
listen 80;
root /home/tino/www;
if ($request_uri ~ " ") { return 444; }
location ~ [^/]\.php(/|$) {
limit_except GET HEAD POST { deny all; }
fastcgi_split_path_info ^((?U).+\.php)(.*)$;
try_files $fastcgi_script_name =404;
set $wtf $fastcgi_path_info;
fastcgi_param PATH_INFO $wtf;
fastcgi_param REQUEST_METHOD $request_method;
fastcgi_param PATH_TRANSLATED $document_root$fastcgi_script_name;
fastcgi_param SCRIPT_FILENAME $request_filename;
fastcgi_param DOCUMENT_URI $document_uri;
fastcgi_pass unix:/var/run/php5-fpm.sock;
fastcgi_index index.php;
}
}
Это дает мне следующий вывод для http://example.com/index.php/a.php?b=b.php
PATH_TRANSLATED /home/tino/www/index.php
SCRIPT_FILENAME /home/tino/www/index.php
DOCUMENT_URI /index.php
PATH_INFO /a.php
QUERY_STRING b=b.php
Это именно то, что я хочу. Обратите внимание, что это работает и для менее проблемных URI, конечно.
Не работающий конфиг
Тем не менее, прямая конфигурация не работает, и я действительно озадачен, почему:
server_tokens off;
server {
listen 80;
root /home/tino/www;
if ($request_uri ~ " ") { return 444; }
location ~ [^/]\.php(/|$) {
limit_except GET HEAD POST { deny all; }
fastcgi_split_path_info ^((?U).+\.php)(.*)$;
try_files $fastcgi_script_name =404;
fastcgi_param PATH_INFO $fastcgi_path_info;
fastcgi_param REQUEST_METHOD $request_method;
fastcgi_param PATH_TRANSLATED $document_root$fastcgi_script_name;
fastcgi_param SCRIPT_FILENAME $request_filename;
fastcgi_param DOCUMENT_URI $document_uri;
fastcgi_pass unix:/var/run/php5-fpm.sock;
fastcgi_index index.php;
}
}
Это то же самое, что и выше, только обходной путь $wtf
отсутствует:
set $wtf $fastcgi_path_info;
fastcgi_param PATH_INFO $wtf;
стал
fastcgi_param PATH_INFO $fastcgi_path_info;
Но это не работает, вывод для http://example.com/index.php/a.php?b=b.php
теперь таков :
PATH_TRANSLATED /home/tino/www/index.php
SCRIPT_FILENAME /home/tino/www/index.php
DOCUMENT_URI /index.php
PATH_INFO
QUERY_STRING b=b.php
Как видите: PATH_INFO
исчез. Это не имеет ничего общего с php-fpm
, это чисто NginX
!
Небезопасный конфиг работает снова
Следующая конфигурация, которая открывает большую дыру в безопасности из-за проверки отсутствующего файла, работает снова:
server_tokens off;
server {
listen 80;
root /home/tino/www;
if ($request_uri ~ " ") { return 444; }
location ~ [^/]\.php(/|$) {
limit_except GET HEAD POST { deny all; }
fastcgi_split_path_info ^((?U).+\.php)(.*)$;
fastcgi_param PATH_INFO $fastcgi_path_info;
fastcgi_param REQUEST_METHOD $request_method;
fastcgi_param PATH_TRANSLATED $document_root$fastcgi_script_name;
fastcgi_param SCRIPT_FILENAME $request_filename;
fastcgi_param DOCUMENT_URI $document_uri;
fastcgi_pass unix:/var/run/php5-fpm.sock;
fastcgi_index index.php;
}
}
На http://example.com/index.php/a.php?b=b.php
результат немного отличается (SCRIPT_FILENAME
выглядит неправильно, DOCUMENT_URI
может быть правильным с другой точки зрения).
PATH_TRANSLATED /home/tino/www/index.php
SCRIPT_FILENAME /home/tino/www/index.php/a.php
DOCUMENT_URI /index.php/a.php
PATH_INFO /a.php
QUERY_STRING b=b.php
Так пожалуйста
Очевидно, что try_files
ломает способ $fastcgi_path_info
после установки регулярного выражения с fastcgi_split_path_info
.
Так, пожалуйста, кто-нибудь может сказать мне, если этот обходной путь $wtf
действительно является правильным решением, или мне все еще нужно беспокоиться о дополнительных плохих побочных try_files
?
Благодарю. (Если я пропустил важный бит безопасности, пожалуйста, прокомментируйте.)