Проект по разработке HTTP-сервера фонда Apache Software Foundation, известный как Apache, в настоящее время является преобладающим Web-сервером в Интернете, согласно статистическим данным он занимает более 60 процентов рынка. Все больше и больше Apache используется как часть набора свободного программного обеспечения в конфигурации, известной как LAMP, Web-платформа, построенная на базе технологий с открытыми исходными кодами Linux®, Apache, MySQL и PHP. Из этой статьи вы узнаете о способе, позволяющем повысить безопасность установки LAMP путем использования модуля mod_proxy и нескольких внутренних серверов. Я расскажу вам о достоинствах и недостатках такого подхода, и вы увидите пример конфигурации работающей установки.
PHP и Apache: проблемы безопасности
Одна из проблем, с которой сталкиваются администраторы LAMP -- предоставление всех возможностей полной установки PHP и, в то же время, обеспечение безопасного окружения для всех пользователей системы. Использование безопасного режима PHP -- один из методов достижения этой цели, но это также может чрезмерно ограничить пользователей, и некоторые PHP-приложения просто не будут функционировать, когда включен этот режим.
Корень проблемы безопасности PHP лежит в том, как сконфигурировано большинство Apache-серверов. Поскольку большинство установок Apache работает под специальным пользовательским идентификатором www-data, весь пользовательский хостинг Web-сайта должен по умолчанию гарантировать, что файлы пользователей будут доступны для чтения этим пользователям. Следовательно есть вероятность, что все пользовательские файлы, доступные через Web, будут доступны всем другим пользователям системы и могут подвергнуться атаке со стороны других, не имеющих отношения к данной системе. Положение становится даже более сложным, когда файлы или каталоги должны быть доступны для записи для пользователя www-data.
Вы можете отчасти избежать этой проблемы при запуске программ CGI, например, написанных с использованием популярных языков Perl и Python, используя механизм suEXEC. Говоря коротко, suEXEC использует специальную промежуточную программу для выполнения программы CGI под пользовательским идентификатором, который является владельцем программы. (Ссылки на статьи с более подробным описанием см. в разделе Ресурсы.) Это очень эффективный механизм, традиционно использовавшийся в течение многих лет.
Однако хостинг страниц PHP с использованием модуля mod_php выполняется как часть основного процесса Apache. Собственно, страницы PHP наследуют все мандаты процесса Apache, и поэтому любые выполняемые на файловой системе действия должны выполняться от имени пользователя www-data.
Запуск Apache с использованием различных пользовательских идентификаторов
Очевидное решение описанной выше проблемы -- хостинг всех запросов для пользовательских доменов от копии Apache, которая имеет только этот пользовательский мандат. Вы можете сконфигурировать Apache так, чтобы при запуске принимать любые пользовательские мандаты. Это может решить проблему для несложных конфигураций, где каждому пользователю назначается индивидуальная комбинация IP адрес/порт, доступная через Интернет.
Для более сложных конфигураций, где IP-адреса пользуются большим спросом, этот метод не работает. Вы можете использовать только виртуальный хостинг -- метод, широко распространенный в установках Apache, где единственная копия Apache контролирует особую комбинацию IP адрес/порт. Это предотвращает возможность хостинга множества доменов, принадлежащих множеству пользователей с одной и той же комбинации IP адрес/порт.
В Apache 2.0 вводится понятие мультипроцессорных модулей (MPM). Среди модулей, предоставляемых с пакетом Apache 2.0, присутствует экспериментальный модуль perchild, позволяющий осуществлять виртуальный хостинг при множестве пользовательских идентификаторов путем назначения distributor-потока для комбинации IP адрес/порт и передачи запросов на satellite-потоки, выполняющиеся под индивидуальными пользовательскими мандатами. К сожалению, perchild оставался экспериментальным и функционировал только в случае удачи и в конце концов был удален из официального Apache, начиная с версии 2.2. Перед этим, понимая, что необходимость в наличии стабильного функционирующего perchild-подобного модуля сохраняется, сообщество Apache начало работу по созданию модулей MPM, способных заполнить образовавшийся пробел. Разработка MetuxMPM и его подпроцесса, созданного через fork, peruser, явилась продолжением работ по достижению этой цели. (Ссылки на статьи с описанием модулей MetuxMPM и peruser см. в разделе Ресурсы).
Несмотря на то, что нет официального Apache MPM, пригодного для непосредственного предоставления виртуального хостинга с использованием различных пользовательских идентификаторов, вы все же можете создать систему Apache, работающую таким образом, путем разумного конфигурирования и администрирования. Основное понятие метода -- использование модуля mod_proxy, который в числе других функций позволяет Apache перенаправлять запросы страниц на другие серверы и передавать ответ обратно клиенту, от которого поступил запрос.
Листинг 1. Пример конфигурации обратного прокси для переадресации основного запроса
ProxyRequests Off
ProxyPass /foo http://foo.example.com/bar
ProxyPassReverse /foo http://foo.example.com/bar
|
Код в Листинге 1 -- простой пример, в котором показано перенаправление запроса любой страницы хоста /foo на соответствующую страницу, размещаемую на http://foo.example.com/bar. Например, страница /foo/index.htm будет перенаправлена на http://foo.example.com/bar/index.htm. Вы можете использовать этот принцип для решения проблемы.
Рассмотрим сценарий, в котором администратор Apache должен предоставить хостинг для двух доменов, принадлежащих двум разным клиентам. Один клиент -- недавно созданная онлайн компания, которая беспокоится об онлайн безопасности. Другой является частным лицом. Он не заботится о безопасности сайта и известно, что он загружает на свой сайт небезопасный код. Учитывая эти моменты, администратор Apache должен предпринять действия для изоляции этих сайтов друг от друга.
Таким образом, у администратора имеется два домена: www.startup.tld, принадлежащий недавно созданной онлайн компании (идентификатор пользователя startup), и www.reckless.tld, принадлежащий частному лицу (идентификатор пользователя nimrod). Для решения проблемы администратор принял решение использовать mod_proxy. Администратор выдал каждому пользователю его собственную копию Apache, запущенную под его собственным ID на приватной комбинации IP-адрес/порт, и использовал решение mod_proxy для предоставления доступа к обоим доменам через наружный сервер, запущенный под ID www-data на публичной комбинации IP-адрес/порт. Законченный сценарий показан на Рисунке 1.
Рисунок 1. Образец сценария
Для каждого элемента конфигурации в нашем образце приложения администратор Apache должен использовать версии Apache, перечисленные в Таблице 1.
Таблица 1. Версии Apache, использованные в примере приложения
| Элемент | Версия Apache | Объяснение |
|---|---|---|
| Внешний сервер | Apache 2, выполняющий MPM worker или MPM event | Apache 2 добавляет важное расширение для модуля mod_proxy. MPM worker и MPM event выполняются в виде thread'ов и помогают уменьшить непроизводительный расход памяти на внешнем сервере. |
| Внутренние серверы | Apache 1.3, или Apache 2, выполняющие prefork MPM | Администратор Apache должен осознавать, что модуль PHP не должен запускаться под thread-окружением. Эти два варианта предлагают основанные на порождении процессов окружения для модуля PHP. |
Конфигурирование внутренних Apache instance
Фрагменты Листингов 2 и 3 иллюстрируют важные моменты конфигурирования, отличающиеся от стандартной конфигурации Apache. Их необходимо добавлять в случае необходимости. Так, в пример конфигурации не включена функциональность PHP.
Листинг 2. Конфигурация Apache для недавно созданной онлайн компании
# Stuff every Apache configuration needs
ServerType standalone
LockFile /var/lock/apache/accept.startup.lock
PidFile /var/run/apache.startup.pid
ServerName necessaryevil.startup.tld
DocumentRoot "/home/startup/web"
# Essential modules
LoadModule access_module /usr/lib/apache/1.3/mod_access.so
# Which user to run this Apache configuration as
User startup
Group startup
# This must be off else the host isn't passed correctly
UseCanonicalName Off
# The IP/port combination to listen on
Listen 127.0.0.2:10000
# Using name-based virtual hosting allows you to host multiple sites per IP/port combo
NameVirtualHost 127.0.0.2:10000
<VirtualHost 127.0.0.2:10000>
ServerName www.startup.tld
# You can add aliases so long as the facade server is aware of them!
ServerAlias startup.tld
DocumentRoot "/home/startup/web/www.startup.tld"
<Directory /home/startup/web/www.startup.tld/>
Options Indexes FollowSymLinks MultiViews ExecCGI Includes
AllowOverride All
Order allow,deny
Allow from all
</Directory>
</VirtualHost>
|
Листинг 3. Конфигурация Apache для частного клиента
# Stuff every Apache configuration needs
ServerType standalone
LockFile /var/lock/apache/accept.nimrod.lock
PidFile /var/run/apache.nimrod.pid
ServerName necessaryevil.nimrod.tld
DocumentRoot "/home/nimrod/web"
# Essential modules
LoadModule access_module /usr/lib/apache/1.3/mod_access.so
# Which user to run this Apache configuration as
User nimrod
Group nimrod
# This must be off else the host isn't passed correctly
UseCanonicalName Off
# The IP/port combination to listen on
Listen 127.0.0.2:10001
# Using name-based virtual hosting allows you to host multiple sites per IP/port combo
NameVirtualHost 127.0.0.2:10001
<VirtualHost 127.0.0.2:10001>
ServerName www.reckless.tld
# You can add aliases so long as the facade server is aware of them!
ServerAlias reckless.tld
DocumentRoot "/home/nimrod/web/www.reckless.tld"
<Directory /home/nimrod/web/www.reckless.tld/>
Options Indexes FollowSymLinks MultiViews ExecCGI Includes
AllowOverride All
Order allow,deny
Allow from all
</Directory>
</VirtualHost>
|
В Листинге 4 показана конфигурация для внешнего instance Apache.
Листинг 4. Конфигурация Apache для внешнего instance Apache
# Stuff every Apache configuration needs
LockFile /var/lock/apache/accept.www-data.lock
PidFile /var/run/apache.www-data.pid
ServerName necessaryevil.facade.server
DocumentRoot "/home/www-data"
# Essential modules
LoadModule proxy_module /usr/lib/apache2/modules/mod_proxy.so
LoadModule proxy_http_module /usr/lib/apache2/modules/mod_proxy_http.so
# Which user to run this Apache configuration as
User www-data
Group www-data
# These must be set else the host isn't passed correctly
UseCanonicalName Off
ProxyVia On
ProxyRequests Off
# This must also be set, though it's only an option in Apache2
ProxyPreserveHost On
# The IP/port combination to listen on
Listen 9.20.1.1:80
# Using name-based virtual hosting allows you to host multiple sites per IP/port combo
NameVirtualHost 9.20.1.1:80
# Configuration to forward requests for startup.tld
<VirtualHost 9.20.1.1:80>
ServerName www.startup.tld
ServerAlias startup.tld
ProxyPass / http://127.0.0.2:10000/
ProxyPassReverse / http://127.0.0.2:10000/
ProxyPassReverse / http://www.startup.tld:10000/
ProxyPassReverse / http://startup.tld:10000/
</VirtualHost>
# Configuration to forward requests for reckless.tld
<VirtualHost 9.20.1.1:80>
ServerName www.reckless.tld
ServerAlias reckless.tld
ProxyPass / http://127.0.0.2:10001/
ProxyPassReverse / http://127.0.0.2:10001/
ProxyPassReverse / http://www.reckless.tld:10001/
ProxyPassReverse / http://reckless.tld:10001/
</VirtualHost>
|
Здесь важно отметить директиву ProxyPreserveHost.
Эта директива появилась, начиная с версии Apache 2. Она решает некоторые проблемы перенаправления на внутренние серверы корректных заголовков HTTP. Настоятельно рекомендуется использовать Apache 2 instance в качестве внешнего сервера.
Все конфигурации выполняет пользователь root. Apache берет привилегии, требуемые конфигурационным файлом для всех связанных с хостингом процессов. В Листинге 5 показано, как это запустить.
Листинг 5. Запуск серверов примера
/usr/sbin/apache -f /etc/apache/startup.tld.conf
/usr/sbin/apache -f /etc/apache/nimrod.tld.conf
/usr/sbin/apache2 -f /etc/apache2/facade.tld.conf
|
Крайне важно заметить, что метод, описанный в этой статье, не будет работать с доменами, требующими SSL-соединений. Это происходит потому, что протокол SSL не позволяет виртуальный хостинг доменов. Вследствие этого ограничения любой SSL-хостинг должен осуществляться способом, когда каждый домен SSL имеет хостинг на своей собственной комбинации IP/порт. Это ограничение касается всех конфигураций Apache, не только тех, которые используют это решение. Тем не менее вы можете запускать домены SSL под идентификатором пользователя их владельца.
Из этой статьи вы узнали об использовании возможностей модуля Apache mod_proxy для построения окружения, состоящего из внешнего сервера, пересылающего запросы на два внутренних сервера. Такой подход позволяет системным администраторам исключить возможные риски, связанные с безопасностью, и в то же время сохранять гибкость, предоставляемую такими инструментами, как PHP.
Научиться
-
Оригинал этого учебного пособия на developerWorks.
-
suEXEC support: получите документацию непосредственно от Apache и узнайте, как уменьшить риски, связанные с безопасностью, когда ваши пользователи разрабатывают и запускают личные программы CGI или SSI.
-
Introduction to LAMP technology (Jono Bacon, developerWorks, май 2005): в этом учебном пособии, которое является хорошим введением в Linux-Apache-MySQL-PHP или LAMP, Web-среду разработки, поищите решения распространенных проблем.
-
developerWorks Web development zone.
-
Linux zone.
-
Technology bookstore: здесь вы найдете список книг на эти и другие технические темы.
-
Технические события developerWorks и интернет-конференции:
участвуйте в текущих технических сессиях, которые позволят сократить вашу кривую обучения и повысить качество и улучшить результаты ваших самых трудных проектов разработки программного обеспечения.
Получить продукты и технологии
-
peruser MPM: узнайте больше об этом MPM, базирующемся на metuxmpm модуле Apache 2, являющемся работающей реализацей perchild MPM.
-
IBM trial software: постройте ваш следующий проект разработки при помощи этих средств, доступных непосредственно с developerWorks.
-
Зона developerWorks Web Development Downloads and products: найдите продукты, доступные для свободного выкачивания.
Обсудить
- Примите участие в обсуждении материала на форуме.
- Читайте
блоги developerWorks и обсуждайте с сообществом developerWorks!
Ник Маинард (Nick Maynard) работал в лаборатории сценарного анализа IBM в Харсли (Hursley) с момента поступления в IBM UK Ltd. после окончания в 2003 году Имперского колледжа науки, технологии и медицины. Он специализируется в областях Linux, Web-сервисов и интеграционных бизнес-технологий. Связаться с Ником можно по адресу nick.maynard@uk.ibm.com