Одна из «фич» PHP-FPM — возможность запуска дочерних процессов в chroot окружении. В теории, это должно значительно увеличить безопасность системы засчет изоляции процесса исполняющего скрипт, т. е. если злоумышленник получит контроль над системой используя уязвимость PHP, то он выше той папки, в которой запущен процесс PHP-FPM, он не уйдет.
На практике, к сожалению, все далеко не столь радужно.
Связано это с тем, большинство веб-приложений (например, CMS Drupal 8) написаны с расчетом на доступ на чтение системных файлов и папок. Например, если в вашем скрипте или используемых им библиотеках как-либо используется генератор случайных чисел, то он работать не будет, т. к. ему нужен доступ к /dev/urandom
В процессе длительного хождения по граблям, я все же сумел запустить Drupal в PHP-FPM в chroot и NGINX, скажу сразу, оно не стоит затраченных усилий. Далее приведены конфиги для желающих повторить.
1. Сперва создадим песочницу. Это папка, в которой будет работать PHP-FPM.
В ней папка tmp будет использоваться для хранения сессий, logs для логов PHP-FPM (необязательно), папка htdocs — для файлов сайта. В etc, usr и dev будут примонтированы необходимые файлы и папки с самой машины.
mkdir -p /path/to/chrooted/folder/{tmp,etc,dev,usr/share/zoneinfo,logs,htdocs} touch /path/to/chrooted/folder/dev/random /path/to/chrooted/folder/dev/urandom \ /path/to/chrooted/folder/etc/localtime /path/to/chrooted/folder/etc/hosts \ /path/to/chrooted/folder/etc/resolv.conf mount -o bind,ro,noexec /dev/random /path/to/chrooted/folder/dev/random mount -o bind,ro,noexec /dev/urandom /path/to/chrooted/folder/dev/urandom mount -o bind,ro,noexec /etc/localtime /path/to/chrooted/folder/etc/localtime mount -o bind,ro,noexec /etc/hosts /path/to/chrooted/folder/etc/resolv.conf mount -o bind,ro,noexec /usr/share/zoneinfo /path/to/chrooted/folder/usr/share/zoneinfo chown -R www-data:www-data /path/to/chrooted/folder/htdocs chmod 1777 /path/to/chrooted/folder/tmp
2. Настроим пул PHP-FPM. Для Debian-based дистрибутивов создайте файл со следующим содержимым в /etc/php5/fpm/pool.d
:
[myawesomesite.ru] user = www-data group = www-data prefix = /path/to/chrooted/folder chroot = $prefix chdir = /htdocs listen = php5-fpm.sock listen.owner = www-data listen.group = www-data listen.mode = 0660 access.log = logs/$pool.access.log pm = static pm.max_children = 1
Обратите внимание на то, что процессы в данном пуле запускаются от имени пользователя, под которым работает nginx. Возможно, вам придется изменить права доступа на ряд файлов в песочнице.
3. Настроим nginx.
Конфиг виртуального сервера:
server { listen 11.22.33.44:80; server_name myawesomesite.ru; root /path/to/chrooted/folder/htdocs; location ~* (\.php(\?.(.)*)?|/)$ { fastcgi_index index.php; include /etc/nginx/conf.d/http_fastcgi.conf; fastcgi_pass unix:/path/to/chrooted/folder/php5-fpm.sock; } location / { index index.php; try_files $uri =404; } }
/etc/nginx/conf.d/http_fastcgi.conf:
fastcgi_param SCRIPT_FILENAME /htdocs$fastcgi_script_name; fastcgi_param QUERY_STRING $query_string; fastcgi_param REQUEST_METHOD $request_method; fastcgi_param CONTENT_TYPE $content_type; fastcgi_param CONTENT_LENGTH $content_length; fastcgi_param SCRIPT_NAME $fastcgi_script_name; fastcgi_param REQUEST_URI $request_uri; fastcgi_param DOCUMENT_URI $document_uri; fastcgi_param DOCUMENT_ROOT /htdocs; fastcgi_param SERVER_PROTOCOL $server_protocol; fastcgi_param HTTPS $https if_not_empty; fastcgi_param GATEWAY_INTERFACE CGI/1.1; fastcgi_param SERVER_SOFTWARE nginx/$nginx_version; fastcgi_param REMOTE_ADDR $remote_addr; fastcgi_param REMOTE_PORT $remote_port; fastcgi_param SERVER_ADDR $server_addr; fastcgi_param SERVER_PORT $server_port; fastcgi_param SERVER_NAME $server_name;
4. Проверяем конфиги и запускаем:
php5-fpm -t nginx -t service nginx start service php-fpm start
И пытаемся открыть сайт в браузере.