Posted in: Virtualization, Web

PHP-FPM в chroot окружении.

Одна из «фич» 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

И пытаемся открыть сайт в браузере.

Добавить комментарий

Back to Top