Сегодня у нас на повестке дня вопросы, касающиеся обеспечения безопасности Web-сервера на базе OpenBSD. Мы научим PHP, MySQL и Sendmail работать с Apache, который запускается в окружении chroot - измененном корневом каталоге /var/www с правами непривилегированного пользователя www. Таким образом, нам удастся обеспечить дополнительный уровень защиты и максимально снизить возможный ущерб в том случае, если злоумышленнику окажется под силу взломать нашу систему. Применив полученные знания на практике, в твоем арсенале будет настолько защищенная система, что ты сможешь совершенно спокойно взяться за разработку любого проекта, будь то личный блог, новостной сайт компании или даже интернет-магазин с мириадами клиентов.
предварительный ликбез
Последняя версия ультрасекьюрной OpenBSD (3.9 на момент написания статьи) как нельзя лучше подойдет для выполнения нашей миссии. Короткая история взломов, прекрасная реализация стека TCP/IP, отличный файервол Packet Filter (pf), залатанный Apache 1.3.29 с поддержкой SSL, наличие последних версий OpenSSH и OpenSSL, тысячи добротно протестированных прекомпилированных пакетов - все это говорит в пользу сделанного выбора. Хотя стоит отметить, что в качестве используемой операционной системы может выступать любая из Free/Net/DragonFlyBSD.
За основу нашей конструкции примем PHP и MySQL. Не секрет, что за последние годы эта связка стала стандартом де-факто для интернет-проектов различного масштаба. Поэтому давай не будем на этом останавливаться и перейдем непосредственно к настройке.
каждой службе - свой раздел
Прежде всего, необходимо грамотно подойти к разделению дискового пространства. Лично я предпочитаю для каждой критически важной сетевой службы выделять собственный раздел. Для наглядности приведу содержимое конфига fstab(5) полностью:
# vi /etc/fstab
Преимущества такой конфигурации видны даже невооруженным глазом:
MySQL: записная книжка с SQL-интерфейсом
Для проверки правильности сборки выполняем набор прилагаемых тестов:
# make do-regress
Если все тесты прошли успешно, переходим к установке прекомпилированного пакета клиентской части MySQL:
# pkg_add /usr/ports/packages/i386/all/mysql-client-5.0.22.tgz
Уделяем внимание зависимостям mysql-server'а:
И устанавливаем пакадж серверной части MySQL:
# pkg_add /usr/ports/packages/i386/all/mysql-server-5.0.22.tgz
При необходимости создаем директорию /var/mysql:
Настало время проверить работоспособность БД и запустить скрипт для создания типовых баз mysql и test:
# /usr/local/bin/mysql_install_db
Теперь в стартовом сценарии /etc/rc.local указываем опции для mysqld_safe - своего рода обертки, которая запускает mysqld с заданными параметрами, производит мониторинг состояния демона и при необходимости перезапускает главный процесс MySQL.
# vi /etc/rc.local
Прокомментирую опции, которые мы указали при старте MySQL:
Чтобы не изобретать велосипед, давай возьмем предлагаемый разработчиками пример конфига MySQL, назначим ему корректные права доступа и отредактируем применительно к нашим задачам:
Как ты мог заметить, главное отличие от дефолтного my-medium.cnf заключается в определении местоположения абсолютного пути до сокета клиента и сервера MySQL. Вместо /var/run/mysql/mysql.sock мы будем использовать /var/www/var/run/mysql/mysql.sock, поэтому своевременно подготавливаем соответствующую поддиректорию:
Для хранения временных файлов необходимо создать каталог /var/www/tmp с либеральными правами доступа:
# mkdir -p -m 777 /var/www/tmp
С установкой и конфигурированием разобрались, переходим к запуску демона на орбиту:
# fstat | grep mysql
И создаем (для надежности) символическую ссылку на стандартное расположение сокета:
# ln -sf /var/www/var/run/mysql/mysql.sock /var/run/mysql/mysql.sock
нardening MySQL в подробностях
Опциональный шаг: выполняем ряд несложных операций по увеличению безопасности MySQL:
# /usr/local/bin/mysql -u root
хардкорные разборки с PHP
Далее на очереди - PHP4 со своими расширениями. Следующими командами мы установим пакет с основным движком - так называемый core-пакадж, модуль для работы с базами данных и библиотеку pear (набор специальных компонентов и расширений для PHP).
Активируем модуль libphp4.so:
# /usr/local/sbin/phpxs -s
Воспользуемся рекомендованной разработчиками версией php.ini:
# cp /usr/local/share/examples/php4/php.ini-recommended /var/www/conf/php.ini
Выставляем корректные права доступа:
Указываем путь до сокета MySQL:
# vi /var/www/conf/php.ini
mysql.default_socket = /var/run/mysql/mysql.sock
И активируем MySQL-модуль:
# /usr/local/sbin/phpxs -a mysql
сам себе надежный почтальон
Для корректной работы электронной почты в Apache chroot необходимо установить статически слинкованную версию mini_sendmail. Этот фэйковый почтовик будет передавать из среды chroot всю исходящую почту полноценному транспортному агенту.
Теперь снова возвращаемся в php.ini и указываем абсолютный путь до mini_sendmail относительно /var/www (внимание: запись «-fwww@mydomain.ru» обязательно должна идти без пробела).
sendmail_path = "/bin/mini_sendmail -fwww@mydomain.ru -t"
не выпускай суккуба из песочницы
# vi /var/www/conf/httpd.conf
управляем MySQL с комфортом
PHPMyAdmin представляет собой набор PHP-скриптов для управления сервером MySQL. Прекрасно подходит для поклонников визуального администрирования и тех, у кого синтаксис SQL-запросов вызывает определенную сложность. Кроме того, с помощью PHPMyAdmin довольно удобно выполнять рутинные операции по бэкапу, созданию и модификации баз данных, таблиц, пользователей и т.д. Устанавливаем:
В конфиге config.inc.php указываем, что в качестве типа соединения у нас используется «сокет» (напомню, mysqld не подвешен даже на интерфейс обратной петли), а также имя и пароль администратора MySQL:
# vi config.inc.php
Описание поддомена phpmyadmin.mydomain.ru в httpd.conf будет выглядеть следующим образом:
Совершенно очевидно, что доступ к phpMyAdmin необходимо ограничить. Этого можно добиться разными способами. Для расширения кругозора предлагаю воспользоваться аутентификацией по паролю. Чтобы проконтролировать доступ к каталогу /var/www/virtual/phpmyadmin.mydomain.ru и запретить по сети передавать пароли в открытом виде (директива SSLRequireSSL), создаем еще один управляющий файл - .htaccess. Преимущество использования такого подхода состоит в том, что мы не захламляем httpd.conf дополнительными директивами для описания правил доступа, указания местонахождения Auth-конфигов и методов аутентификации. Плюс к этому, при изменении конфигурации в файле .htaccess не придется перезагружать Web-сервер.
# vi /var/www/virtual/phpmyadmin.mydomain.ru/.htaccess
Аутентификационную базу /var/www/conf/.htpasswd (ни в коем случае не размещай .htpasswd в каталоге /var/www/virtual/phpmyadmin.mydomain.ru) будем вести с помощью утилиты htpasswd(1). Ключ '-c' отвечает за создание базы, ключ '-m' задает использование алгоритма шифрования MD5, вместо применяемой по умолчанию DES'овской функции crypt(3):
# htpasswd -cm /var/www/conf/.htpasswd admin
Только суперпользователь и демон httpd имеют право обращаться к базе с паролями:
проводим безопасные транзакции по протоколу https
Чтобы получить возможность устанавливать защищенные сеансы по протоколу https, необходимо создать приватный ключ, ввести регистрационные данные и подписать сертификат собственным ключом. Начнем с генерации секретного RSA-ключа длиной 1024 бит:
# openssl genrsa -out /etc/ssl/private/server.key 1024
Создаем запрос на сертификат:
# openssl req -new -key /etc/ssl/private/server.key \
Подписываем сертификат, который будет действовать на протяжении 10 лет (аргумент '-days 3650'), своим ключом:
# openssl x509 -req -days 3650 -in /etc/ssl/private/server.csr \
-signkey /etc/ssl/private/server.key -out /etc/ssl/server.crt
Выполняем остановку и повторный запуск httpd(8), но уже с поддержкой https:
Проверяем, забиндился ли апач на соответствующие порты:
% netstat -na -f inet | egrep '80|443'
В /etc/pf.conf создаем правило, разрешающее прохождение запросов к портам 80 и 443:
# vi /etc/pf.conf
Чтобы внесенные изменения вступили в силу, не забудь перезагрузить набор рулесетов файервола:
# pfctl -f /etc/pf.conf
В конфиге /etc/rc.conf следующими записями разрешаем автоматическую загрузку Apache SSL и Packet Filter при старте системы:
# vi /etc/rc.conf
постскриптумы
На этом настройку можно считать завершенной. Протестировать работу модуля php4 и его взаимодействие с MySQL можно с помощью php-файла, исходный код которого приведен ниже. Если при запросе www.mydomain.ru/test.php ты получишь лаконичный ответ «ok», смело начинай заливать любимую CMS'ку в каталог /var/www/virtual/www.mydomain.ru. Удачи.
# vi /var/www/virtual/www.mydomain.ru/test.php