Конфигурирование Web-сервера FreeBSD

Предположим, что при настройке сервера с FreeBSD требуется установить Web-сервер, а также обеспечить пересылку электронной почты и доступ пользователей к командному интерпретатору. В конфигурацию FreeBSD по умолчанию включена Sendmail - система, предоставляющая почтовые службы и не требующая никакой дополнительной конфигурации. С другой стороны, никакой эквивалент Web-сервера по умолчанию не устанавливается. Поэтому его необходимо инсталлировать самостоятельно из портов или пакетов. В 90% случаев в качестве Web-сервера используется Apache. Существует и несколько альтернативных серверов (например, Roxen или AOLserver), но Apache занял значительную долю рынка среди серверов Internet, поскольку был первой альтернативой серверу NCSA httpd.

В наши дни Apache пользуется гораздо большей популярностью, чем, допустим, Sendmail, и при этом практически не испытывает давления со стороны конкурентов. Проект Apache - один из лучших примеров философии программного обеспечения с открытым кодом в действии. Этот проект дал миру программное обеспечение, которое работает надежней, чем другие альтернативные серверы. Кроме того, оно лучше совместимо с утвержденными стандартами. Apache приспособлен к любым типам сред - начиная от небольших информационных Web-сайтов с низким трафиком и заканчивая полномасштабными серверами электронной коммерции с сотнями параллельных соединений. Плюс ко всему он поддерживает набор подключаемых модулей, обеспечивающих такие дополнительные возможности, как связь с базами данных и встроенная обработка сценариев на языке Perl.

В этой главе обсуждается, как настроить Apache для инсталляций разного типа.

Общие сведения о протоколе HTTP

HyperText Transfer Protocol (HTTP, протокол передачи гипертекста) - основа World Wide Web. Разработанный в 1993 году для поддержки обмена информацией в центре CERN (Швейцария), он представляет собой простейший протокол, не требующий аутентификации и включающий лишь несколько команд с клиентской стороны. Пер-воначально он был оптимизирован для пересылки небольших текстовых файлов. HTTP обеспечивает распространение связанных между собой информационных страниц, язык форматирования которых (понятный HTTP-браузерам) был разработан относительно недавно. Он называется HyperText Markup Language (HTML, язык разметки гипертекста).

В настоящее время использование HTTP вышло далеко за пределы его первона-чальной спецификации. Сейчас этот протокол используется для пересылки больших двоичных файлов, изображений, анимации и других элементов HTML-страниц. На заре WWW это было редкостью (поддержка форматов изображений GIF и JPEG начала распространяться на различных платформах лишь в 1994 году). Отвечая велениям времени, спецификации HTTP были несколько изменены. Наиболее важным является стандарт HTTP/1.1, поддерживающий такие свойства, как конвейеры (объединение гнескольких одновременных запросов в один ответный поток). Большинство браузеров следует этому стандарту лишь частично.

В отличие от SMTP, FTP и других популярных протоколов, HTTP не поддержи-вает "сеансы". Когда клиент соединяется с сервером, HTTP производит несколько операций, а потом закрывает соединение. HTTP при соединении позволяет выпол-нить только один запрос. Кроме того, это означает, что данный протокол не поддер-живает топологические свойства, ассоциированные с таким протоколом, как, напри-мер. SMTP: переключение (relaying), записи MX, очереди и т.д. Поэтому по мере увеличения числа одновременных соединений администратору HTTP-сервера при-ходится больше думать о полосе пропускания, ресурсах процессора и памяти, забо-титься об их наиболее эффективном использовании.

Структура запроса в протоколе HTTP/1.0 чрезвычайно проста. Эмулировать операцию HTTP можно, подключившись к порту 80 на HTTP-сервере и выполнив запрос GET. который может содержать несколько строк следующего вида:

f telnet www.somewhere.com 80 Connected to www.somewhere.com. Escape character is 1A]'. GET / HTTP/1.0

HTTP/1.1 200 OK

Date: Sun, 20 May 2001 22:45:55 GMT

Server: Apache/1.3.20 (Unix)

Content-Location: index.html

Vary: negotiate,accept-language,accept-charset

TCN: choice

Last-Modified: Fri, 31 Mar 2000 01:45:46 GMT

ETag: "6531f-54e-38e4034a;3a977613"

Accept-Ranges: bytes

Content-Length: 1358

Connection: close

Content-Type: text/html

Content-Language: en

Expires: Sun, 20 May 2001 22:45:55 GMT

<HTML>

<TITLE>test page</TITLE>

<BODY>

test

</BODY>

</HTML>

Чтобы получить только заголовки (а не полное сообщение), следует выполнить запрос HEAD. Ввод пустой строки (двойное нажатие на клавишу Enter) указывает на окончание многострочного запроса.

Первый блок строк в ответе представляет собой заголовок. По его содержимому легко определить, какой HTTP-сервер возвратил его, поскольку каждый сервер име-ют уникальную сигнатуру в строке Server:. Остальные строки, особенно строки Content-*:, содержат информацию, которая помогает Web-браузеру правильно от-форматировать страницу. Например, Content-Length: указывает браузеру, сколько данных осталось загрузить, a Content-Type: - как представить запрошенный файл (HTML, обычный текст, изображение GIF или JPEG и т.д.).

НТТР/1.0 позволяет включать в запрос дополнительные строки, например, наборы cookies, допустимые кодировки, предпочтительные языки и т.д. Кроме строки запроса (которая должна быть первой), порядок строк не имеет значения. Они являются дополнительными, обязательна лишь сама строка запроса. Запрос НТТР/1.1 практически совпадает с НТТР/1.0, за исключением того, что вторая строка (Host:) также является обязательной. Это дополнение к протоколу предназначено для под-держки виртуального хостинга (когда один Web-сервер может отзываться на несколько разных хостовых имен). Это значит, что клиент должен указать имя хоста, Web-содержимое которого он хочет получить. Поскольку Web-браузер определяет IP-ад-рес по имени хоста, указанного пользователем, и затем устанавливает HTTP-соеди-нение с этим IP-адресом (о работе TCP/IP рассказано в главе 22), сервер ничего не знает об имени хоста, к которому пытается обратиться пользователь. Поэтому кли-енту и необходимо указать заголовок

Host:.

# telnet www.somewhere.com 80 Connected to www.somewhere.com. Escape character is 1A J '. GET / HTTP/1.1 Host: www.somewhere.com

Все современные браузеры, включая и текстовые (типа Lynx), поддерживают стан-дартный для HTTP/I.I заголовок Host:. (Однако они не обязательно формируют свои запросы так, как HTTP/1.1. Например, Netscape Navigator поддерживает множество свойств HTTP/1.1, но посылает запросы НТТР/1.0.) Таким образом, виртуальный хостинг, основанный на информации из заголовка Host: (а не на IP-адресе и псев-донимах сетевого уровня), значительно упрощает настройку серверов. О виртуальном хостинге рассказано далее в этой главе.

Коды ответа и перенаправление

Хотя существует лишь несколько методов запроса (GET, HEAD и POST, а также несколько дополнительных методов в стандарте HTTP/1.1), имеется множество ва-риантов ответа, которые может возвратить сервер. Они являются трехзначными кодами и сгруппированы по значению первой цифры. В табл. 26.1 показан полный набор кодов HTTP-ответа и объяснены их значения (в основном в контексте сервера Apache и его свойств).

Таблица 26.1 Коды HTTP-ответа

Числовой Название Значение

Код 2хх - Успешное выполнение

200 ОК Стандартный код успешного выполнения

201 C r e a t e d ( Создано)

202 Accepted (Принято)

203 Partial Information (Частичная информация)

204 No Content (Нет содержимого)

Глава 26. Конфигурирование Web-сервера 493

Числовой Название Значение

код

Зхх - Перенаправление

300 Multiple Choices Запросы MultiViews или CheckSpelling

нашли несколько соответствий

3 0 2 M o v e d P e r m a n e n t l y Последний символ косой черты опущен

303 Moved Temporaril y Найдено перенаправление

304 Not Modified Можно использовать кешированную копию

4хх - Ошибка клиента

402 Bad Request (Плохой запрос)

4 0 3 U n a u t h o r i z e d Для продолжения необходима

аутентификация

403 Forbidden Права доступа или конфигурация сервера

запрещают доступ

404 Not Found Файла не существует

5хх - Ошибка сервера

501 I nter nal Serve r Er ro r Ошибка CGI-программы

502 N o t I m p le m e n t e d ( H e реализовано)

503 Bad Ga te w ay (Плохой шлюз)

504 Service Unavailable Ресурсы, необходимые для обработки

запроса, недоступны

Вы наверняка сталкивались с ошибками 404 и 403, и даже 500, если вам приходилось заниматься CGI-программированием. Не слишком понятным является код 304. Он никогда не выводится пользователю и предназначен для браузера. Тем не менее это один из самых распространенных кодов ответа корпоративного сервера, в чем можно убедиться, просмотрев log-файлы доступа (/var/log/httpd-access.log).

Когда клиент запрашивает файл, уже имеющийся в кэше (например, изображение GIF или HTML-страницу), он выполняет запрос GET, в поле If-Modified-Since которого установлена дата последней загрузки изображения. Это позволяет серверу проверить, изменился ли файл с этого момента. Если да, сервер пересылает файл (с кодом успешного выполнения 200), если нет, он возвращает код 304 (Not Modified), сообщающий браузеру, что можно использовать квитированный файл.

Другой код, часто используемый браузерами, но не известный пользователям, - это 301 (Moved Permanently). Чаще всего эта ошибка происходит в случае, когда запрашивается URL типа http://some.host.com/Subdirectery, где Subdirectory - имя каталога на сервере. Корректная форма указания URL содержит замыкающий символ косой черты http://some.host.com/Subdirectory/. Обратите внимание, что, если URL введен без последнего символа косой черты, браузер добавляет его автоматически. Это происходит, потому что при первом запросе он получает код 301, перенаправляющий его на тот же URL, но уже заданный в правильном формате. URL в строке браузера обновляется, браузер посылает второй запрос и получает в ответ требуемую страницу. Чтобы процесс выполнялся правильно, серверу необходимо знать имя хоста. Этой цели служит директива ServerName сервера Apache, назначение которой обсуждается далее в этой главе.

Более подробную информацию можно найти на Web-сайте Консорциума W3 (WWW Consortium) по адресу www.w3.org/Protocols. Исходный протокол НТТР/1.0 опреде-ляется спецификацией RFC 1945, a HTTP/1.1 - RFC 2068.

Получение и инсталляция сервера Apache

Название сервера Apache, как принято считать, происходит от "A Patchy Server" (Сервер исправлений), поскольку он "вырос" из набора исправлений, которыми до-полнялся стандартный, но в начале 1995 года имеющий весьма ограниченные воз-можности NCSA httpd-сервер. Apache - яркий пример самого широко портируемого на сегодня программного обеспечения. Он работает на платформах под управлением самых разных операционных систем - от AIX до Windows, от BeOS до Mac OS X, и, конечно же, FreeBSD. Этот сервер представляет собой не просто одну из наиболее полных реализаций HTTP-сервера, но и рассматривается многими как приближение к идеалу программного обеспечения с открытым кодом. Еще бы! Свободно разрабатываемый и распространяемый продукт стал стандартом де-факто в той области рынка, где существуют большие коммерческие пакеты от ведущих компаний отрасли. Apache занимает 60% рынка (на момент написания этой книги) и эта доля растет.

Apache устанавливается из портов (/usr/ports/www/apache13) или пакетов. На сегодняшний день Apache 1.3 законченная версия кода, чьи былые ошибки и проблемы с защитой давно решены. Именно эта версия - основа популярности и высокой репутации Apache. Она способна удовлетворить самым разным запросам пользователей. Тем не менее в этой версии имеется несколько структурных "причуд" (например, модель порождения дочерних процессов, когда для обработки каждого нового запроса создается новый процесс Apache). Поэтому код версии Apache 2.0 переписан заново, он включает управление цепочками ядра, а также высокомодульную архитектуру, предназначенную для повышения производительности. Сейчас Apache 2.0 находится в стадии альфа-разработки, поэтому в этой главе рассказано об Apache 1.3, а не о новой версии, которая включена в порты в каталоге /usr/ports/www/apache2 (может, вы захотите опробовать ее).

Достоинством сервера Apache для пользователей FreeBSD является то, что многие его компоненты были разработаны именно в среде FreeBSD, в частности, это модуль URL Rewrite (mod_rewrite), написанный Ральфом Энгельшалем (Ralf Engelschall), a также несколько опций настройки производительности. Из этого также следует, что Apache хорошо сочетается с файловой структурой FreeBSD.

Дистрибутив с исходным кодом Apache можно найти на многих зеркальных серверах по всему миру, если набор портов не позволяет обновить его с центрального сервера. Список серверов, а также набор документации по Apache имеется на сайте http://httpd.apache.org.

Схема расположения файлов сервера Apache

После инсталляции Apache корневой каталог сервера размещается в каталоге /usr/local. Этот новый каталог, /usr/local/www, содержит несколько подкаталогов, часть из которых является символическими ссылками. Схема расположения файлов Apache показана на рис. 26.1. Все компоненты Apache устанавливаются внутри иерархии /usr/local (в точном соответствии с идеологией FreeBSD), за исключением log-файлов (которые находятся в каталоге /var/log вместе с остальными log-файлами системы).

Фактически, несколько каталогов присутствуют лишь во временной структуре файловой системы, существующей на этапе инсталляции. Это предотвращает случайную замену сценарием установки существующих файлов на работающем сервере. Например, /usr/local/www/data.default представляет собой символическую ссылку на /usr/local/share/doc/apache, a /usr/local/www/data (где в конфигурации по умолчанию находится корневой каталог документов, т.е. каталог, где хранятся основные HTML-страницы сервера) - отдельную символическую ссылку на тот же каталог. При необходимости ее можно заменить. Аналогично, /usr/local/www/cgi-bin это сим-волическая ссылка на /usr/Iocal/www/cgi-bin.default (обычный каталог). Файлы, раз-мещаемые в cgi-bin, в действительности попадают в cgi-bin.default, однако при необ-ходимости cgi-bin можно также превратить в отдельный каталог.

/usr/local/etc/apache также имеют

.default-эквиваленты.Таким образом, вы всегда можете обратиться к файлам конфигурации по умолчанию, если требуется изменить что-то в конфигурации работающего сервера.

Как и в случае с Sendmail, схема расположения файлов значительно отличается от тех, которые применяются при инсталляции Apache на других платформах. Поэтому знание схемы FreeBSD вряд ли поможет вам при поддержке Apache на серверах, работающих под Linux, Solaris или Windows.

Один совет, который может оказаться полезным: обычно в любой конфигурации существует "корневой каталог сервера", как, например, /usr/local/www во FreeBSD, где находятся все компоненты, связанные с Apache. В Linux это, как правило, /var/ lib/apache. В инсталляции подобного вида почти все, связанное с Apache, включая конфигурационные, двоичные и log-файлы, исходный код и сценарии сборки, находится в пределах одного каталога. Хотя такая схема не обладает достоинствами четкой и последовательной структуризации, присущей FreeBSD, по крайней мере, все, что связано с инсталляцией, хранится в одном месте.

Конфигурирование сервера Apache

Как и каталог /etc/mail (с которым мы познакомились в главе 25), /usr/local/etc/ apache (конфигурационный каталог Apache) содержит несколько файлов, часть из них мы сейчас рассмотрим:

o httpd.conf. Это главный файл конфигурации Apache. Сегодня все настройки собраны в одном файле, а не в трех отдельных файлах, как было раньше.

o mime.types. В этом файле содержится таблица, указывающая соответствия меж-ду расширением файла и типом MIME (заголовки Content-Type) в файлах, посылаемых Apache. Благодаря ей браузеры узнают, как обрабатывать загру-жаемые ими файлы.

o magic. Альтернативным типам MIME методом является magic - "магическая последовательность", когда тип файла определяется по шаблону, содержаще-муся в самом файле, что делает обработку расширений необязательной. Этот же метод используется и командой file.

o access.conf и srm.conf. В этих файлах ранее содержались определенные на-стройки, которые теперь включены в httpd.conf. Если в этих файлах заданы какие-либо опции, сервер прочтет их, поэтому они и включены в конфигура-ционный каталог (для поддержки совместимости с прошлыми инсталляциями), тем не менее эти файлы не являются обязательными и их можно смело опус-тить.

Отметьте, что все эти файлы имеют .default-эквиваленты. Сразу после инсталляции они идентичны. После внесения изменений в основные файлы, которые необходимы для работы сервера, у вас всегда будут под рукой файлы с настройками по умолчанию. При обновлении версии Apache будут затронуты только файлы .default. Это позволяет обновить систему и добавить новые опции конфигурации, используя diff или какой-либо другой метод.

Использование httpd.conf

Файл httpd.conf достаточно длинный и подробный, но (в отличие от /etc/mail/ sendmail.cf) он имеет понятный текстовый формат и массу комментариев. Каждая директива предполагает значение по умолчанию. Любую из них можно изменить, а содержащаяся в файле документация четко объясняет назначение каждой опции. Если что-либо будет сконфигурировано некорректно, то при попытке запуска Apache точно сообщит, в чем проблема.

Сразу же после инсталляции Apache готов к запуску и правильной обработке запросов. Однако в целях безопасности несколько директив потребуется установить. Найдите их в файле httpd.conf и измените соответствующим образом:

#

o Адрес, на который высылаются сообщения о проблемах с сервером. Он

o отображается на некоторых страницах, генерируемых сервером, например, в

o сообщении об ошибке.

#

ServerAdmin уou@your.address

#

# Опция ServerName позволяет установить имя хоста, которое пересылается

# клиентам, если оно отличается от того, которое программа получила бы

# по умолчанию (например, использовать имя с приставкой www вместо

# реального имени хоста). # #ServerName new.host.name

Вторая из приведенных опций, ServerName используется при перенаправлениях с кодом 301 (о них было рассказано ранее). Если замыкающий символ косой черты опущен при запросе индекса или листинга каталога, Apache возвращает код 301 (Moved Permanently) и URL, по которому должен обратиться браузер. Apache воссоздает URL перенаправления по информации, содержащейся в запросе клиента, который содержит только часть URL. Например, нужный URL http://some.host.com/images/foo, а в запросе указано /images/foe. Если происходит запрос по протоколу НТТР/1.1, то в нем содержится заголовок Host:, которым Apache может воспользоваться для построения полного URL. Именно для этого и применяется директива ServerName.

Версия протокола HTTP/1.1 влечет за собой несколько последствий, связанных с директивой ServerName. Если применяется виртуальный хостинг по именам (к его рассмотрению мы вскоре перейдем), Apache использует значение директивы ServerName для сравнения имени виртуального хоста с заголовком Host: запроса. Для каждого виртуального хоста следует указать значение ServerName. Даже если виртуальный хостинг не используется, желательно установить опцию ServerName. Это поможет Apache правильно конструировать URL-перенаправления.

Подробную документацию можно найти на Web-сайте Apache Group - http:// httpd.apache.org/docs/.

Использование файлов .htaccess и заменяющих опций

Глобальные опции конфигурации содержатся в файле httpd.conf. Однако действие многих из них можно отменить, пользуясь настройками внутри контент-каталога. Перезапускать сервер при этом не нужно. Для этого в каталоге, к которому требуется применить другие настройки, размещается файл .htaccess, содержащий новые значения директив. При поступлении каждого запроса сервер вначале обращается к глобальной конфигурации, загруженной в память из файла httpd.conf, а затем к кон-фигурационному файлу из каждого каталога (.htaccess), проходя последовательно по иерархии каталогов к местонахождению запрашиваемого файла. Каждый последую-щий файл .htaccess может отменить предыдущие директивы, поскольку этот файл задает конфигурацию для своего каталога и подкаталогов в нем.

Можно ли использоваться файлы .htaccess, зависит от директивы AllowOverride. В файле httpd.conf опция AllowOverride установлена в значение None на уровне корневого каталога операционной системы и на уровне каталога /usr/local/www/data. Таким образом, по умолчанию файлы .htaccess игнорируются. Чтобы разрешить их использование, следует заменить значение None директивы AllowOverride (в блоке /usr/ local/www/data) любым значением из табл. 26.2 или их комбинацией (например, AllowOverride AuthConfig Limit).

Таблица 26.2 Опции конфигурации Allow/Override

Директива Разрешает использование файлов .htaccess для отмены

директив

AllowOverride Options Директива Options

AllowOverride Filelnfo Директивы типов файлов, например, AddType и ErrorDocument

AllowOverride AuthConfig Директивы авторизации, например, Require и Auth*

AllowOverride Limit Директивы доступа к хосту, например, Allow, Deny и Order

AllowOverride All Все перечисленные директивы

ПРИМЕЧАНИЕ

Директива Options - наиболее объемный и гибкий элемент Apache. Она управляет наиболее важными свойствами сервера, такими как ExecCGI [возможность запуска CGI-сценариев), Includes (серверные расширения) и MultiViews (гибкая договоренность о содержимом]. Все эти свойства можно добавить или устранить из текущей конфигурации на любом уровне иерар-хической структуры каталогов. Полное описание директивы Options см. на http:// httpd. apache. org/docs/mod/core.html#options.

После внесения соответствующих изменений в файл httpd.conf, необходимо пере-запустить сервер (об этом сейчас пойдет речь). Теперь файлы .htaccess можно разме-стить в требуемых Web-каталогах и включить в них необходимые директивы (за более подробными сведениями обратитесь к документации http://httpd.apache.org/docs/).

Файл httpd.conf содержит закомментированный блок для управления каталогами пользователей (внутри /home). Если вы планируете поддерживать сервер, на котором пользователи смогут размещать свои страницы, и хотите быть уверенным, что бра-узеры, поддерживающие различные методы изменения данных по стандарту HTTP/ 1.1 (DELETE, COPY и MOVE), не смогут изменить их, следует включить этот блок:

#

# Управление доступом к каталогам UserDir. Ниже приведен пример сервера,

# где доступ к ним возможен в режиме только для чтения. # #<Directory /home/*/public_html>

# AllowOverride Filelnfo AuthConfig Limit

# Options MultiViews Indexes SymLinksIfOwnerMatch IncludesNoExec

# <Limit GET POST OPTIONS PROPFIND>

# Order allow,deny

# Allow from all

# </Limit>

# <LimitExcept GET POST OPTIONS PROPFIND>

# Order deny,allow

# Deny from all

# </LimitExcept>

#</Directory>

Заметьте, что директива AllowOverride разрешает файлам .htaccess отменять оп-ции Filelnfo, AuthConfig и Limit, но директивы Options установлены на глобальном уровне.

ПРИМЕЧАНИЕ

В соответствии с историческим соглашением, каталоги с Web-документами пользователей называются public htm! Запрос типа http://some.host.com/~user/ покажет документы, находящиеся в /home/user/public_html. Также по традиции, если присутствует файл index.html, Apache возвратит этот файл, а не листинг каталога. (Серверы компании Microsoft используют для этого файл с именем Default.htm) Число индексных файлов может быть любым. Директива Directory!ndex позволяет указать все эти файлы. Apache попытается найти файлы с заданными именами в указанном порядке.

Запуск и останов демона HTTP

Процесс инсталляции Apache из набора портов запускает сервер автоматически. Для проверки следует найти httpd среди текущих процессов (с помощью утилит ps и grep):

# ps -waux I grep httpd

root 220 0.0 2.0 4436 2456 ?? Ss Sat02PM 0:02.79

/usr/local/sbin/httpd

nobody 303 0.0 2.0 4496 2548 ?? I Sat02PM 0:00.01

/usr/local/sbin/httpd

nobody 304 0.0 2.0 4460 2452 ?? I Sat02PM 0:00.00

/usr/local/sbin/httpd

nobody 305 0.0 2.0 4460 2452 ?? I Sat02PM 0:00.00

/usr/local/sbin/httpd

nobody 306 0.0 2.0 4460 2452 ?? I Sat02PM 0:00.00

/usr/local/sbin/httpd

nobody 307 0.0 2.0 4460 2452 ?? I Sat02PM 0:00.00

/usr/local/sbin/httpd

nobody 13963 0.0 2.0 4468 2468 ?? I SatlOPM 0:00.00

/usr/local/sbin/httpd

Обратите внимание на то, что Apache использует модель порождения новых про-цессов, в которой один главный (master) процесс (владельцем которого является root) прослушивает порт 80 и при поступлении запроса порождает свою копию (ее владель-цем является уже псевдопользователь nobody, не обладающий никакими правами доступа). Это дочерний процесс, обрабатывающий поступивший запрос. Таким образом, главный процесс никогда не обслуживает запросов, поскольку Web-сервер, обрабатывающий запросы от имени пользователя root, был бы очень опасным для безопасности системы, поскольку он обладал бы возможностью запускать программы с правами root. В такой ситуации малейшая "дыра" или ошибка в CGI-сценарии привела бы или к взлому системы, или просто к потере данных.

При такой модели порождения процессов, когда одновременно могут выполняться десятки процессов httpd, удаление и перезапуск каждого запущенного процесса, разумеется, нецелесообразен. Существует следующий способ: для останова сервера достаточно удалить главный процесс, если же сервер нужно перезапустить, главному процессу необходимо послать сигнал HUP. В последнем случае сервер завершит все дочерние процессы, перезапустит свой собственный процесс и заново запустит все порожденные процессы.

Хотя приведенная схема довольно проста, она требует использования таких утилит, как ps, grep и kill. К счастью, Apache поддерживает удобное средство, предназначенное для решения этой задачи: apachectl, которое установлено в каталоге /usr/ local/sbin (включенном по умолчанию в пути поиска). С помощью apachectl запустить или остановить сервер Apache достаточно просто:

# apachectl start /usr/local/sbin/apachectl start: httpd started

# apachectl stop /usr/local/sbin/apachectl stop: httpd stopped

После внесения изменений в файлы внутри каталога /usr/local/etc/apache сервер необходимо перезапустить. Программа apachectl позволяет выполнить и эту операцию:

# apachectl restart

/usr/local/sbin/apachectl restart: httpd restarted

Команда restart утилиты apachectl представляет собой эквивалент посылки сигнала kill -HUP главному процессу httpd: все порожденные процессы завершаются (даже если они обслуживают файлы клиентов); в этом случае клиенты получают сигнал о внезапном обрыве соединения. Если нужно перезапустить Apache менее варварским способом (например, на сильно загруженном сервере, где очень важна целостность данных), можно произвести более "изящный" перезапуск, когда вместо сигнала SIGHUP используется SIGUSR1. В этом случае главный процесс перезапускается без завершения порожденных процессов. Иначе говоря, пересылка файлов клиентам не прерывается.

# apachectl graceful

/usr/local/sbin/apachectl graceful: httpd gracefully restarted

Утилита apachectl часто применяется вместе с командой configtest. Она заставляет Apache (независимо от того, запущен он в данный момент или нет) прочесть конфи-гурационные файлы из каталога /usr/local/etc/apache и сообщить о найденных ошибках, как это сделала бы команда start. Единственное исключение: сервер не запускается, даже если ошибки отсутствуют. Это не просто замечательное средство диагностики, но и обязательная часть команд restart и graceful: утилита apachectl применяет configtest для определения корректности конфигурации до перезапуска сервера. Если установки непригодны к использованию, продолжает выполняться текущий процесс. Это предотвращает непреднамеренное завершение работы сервера командами restart или graceful:

# apachectl graceful

/usr/local/sbin/apachectl graceful: configuration broken, ignoring restart /usr/local/sbin/apachectl graceful: (run 'apachectl configtest' for details)

совет

Если в данный момент сервер Apache не запущен, команды apachectl restart или apachectl graceful запускают его.

Основы контроля доступа к серверу

Определенные части Web-сайта, разумеется, не должны быть общедоступными. Контроль доступа позволяет ограничить их просмотр лишь узким кругом пользователей на основе аутентификации по имени xoста/IP-адресу или паролю. Здесь рассматриваются оба метода.

Контроль доступа по адресу

Предположим, что доступ к определенному файлу, каталогу или набору файлов и каталогов должен быть ограничен списком фиксированных IP-адресов или имен хостов. Выполнить эту операцию можно на глобальном уровне (httpd.conf) или же (что гораздо эффективнее) воспользоваться файлом .htaccess в каталоге, содержащем элементы, которые требуется защитить (или на один уровень выше).

Прежде всего необходимо убедиться, что отмена глобальных опций настройками .htaccess разрешена для той части сайта, которую требуется защитить. Как было показано ранее, для разрешения директив контроля доступа (Allow, Deny и Order) на уровне /usr/local/www/data (или глубже в структуре каталогов, или в другом контейнере <Directory>), используется директива AllowOverride Limit. Поскольку все директивы Apache читаются одновременно, следует указать порядок чтения директив Allow и Deny, иначе они будут отменять друг друга самым неожиданным образом.

Чтобы закрыть каталог для всех, кроме пользователей с указанных адресов или имен хостов, в нем необходимо разместить файл .htaccess следующего содержания:

Order deny,allow

Deny from all

Allow from 64.41.131.102

Allow from stripes.somewhere.com

Allow from nowhere. com

Allow from 10.5.100

Allow from 10.67.22.211/255.255.255.0

Как легко видеть, допускается несколько различных форматов адреса. Это просто правила поиска совпадения: если хост соответствует шаблону имени или сети, ему открывается доступ. Аналогично, можно открыть каталог для всех, но закрыть его для определенных хостов:

Order allow,deny

Allow from all

Deny from 133t.hacker.com

Deny from 192.168

Если настройки происходят на глобальном уровне (в файле httpd.conf), их необ-ходимо разместить внутри блока <Directory> или <Location>. Чтобы правила контроля доступа применялись к определенным файлам (где бы в системе они ни находились), следует воспользоваться директивами <Files> или <FilesMatch>, задающими список таких файлов.

<Files "*.jpg">

Order deny,allow

Deny from all

Allow from 64.41.131.102 </Files>

FilesMatch позволяет указать имена файлов с помощью регулярных выражений. Ниже приведен пример фильтра, обрабатывающего файлы с расширением ,gif, .jpg, .jpeg и .png:

<FilesMatch " .(gif|jpe?g|png)$">

Order deny,allow

Deny from all

Allow from 64.41.131.102 </FilesMatch>

Отметьте, что применение спецификаций <Directory> и <Location> в файлах .htaccess не допускается.

Блок <Limit>, несмотря на свое название (limit - предел, ограничение), не является обязательным для приведенных выше примеров контроля доступа. Его назначение - перечислить методы доступа, подлежащие контролю. Например, можно контролировать доступ для методов GET и POST, оставив все остальные методы без ограничений. А блок <LimitExcept>, наоборот, позволяет указать только те методы, к которым не применяется контроль доступа. Пример этих директив был приведен ранее в закомментированном блоке, управляющем пользовательскими каталогами внутри иерархии /home.

Контроль доступа по паролю

Иногда непрактично или даже нежелательно ограничивать доступ по адресу. Оп-ределенная часть сайта может быть доступна зарегистрированным пользователям (например, заплатившим взнос), вместе с тем необходимо обеспечить доступ к другой части сайта с заранее непредсказуемых IP-адресов. В таком случае для контроля доступа лучше воспользоваться аутентификацией по паролю.

Apache хранит собственные базы данных имен и паролей пользователей, отличные от баз данных системного уровня /etc/master.passwd и связанных с ним файлов. Это абсолютно необходимо для защиты, поэтому не стоит даже пытаться объединить две эти базы данных. База данных паролей FreeBSD предназначена для аутентификации пользователей, обращающихся к командному интерпретатору и имеющих учетную запись в системе, а базы данных аутентификации Apache управляют доступом Web-пользователей к определенным областям Web-сайта. В некоторых случаях две функциональности накладываются друг на друга (например, при использовании сер-вера в локальной сети компании), тем не менее не стоит пытаться обойтись одной базой данных. Даже если вам это удастся, такая методика - хороший пример плохой защиты системы и неграмотного системного администрирования.

Для контроля доступа с помощью пароля необходимо воспользоваться файлом .htaccess (или эквивалентной конфигурацией в глобальном файле httpd.conf), включая использование блоков <Directory>, <Location> и <Files>, как это было сделано при контроле доступа по адресу. Однако содержимое файла или блока конфигурации будет существенно отличается от предыдущего, поскольку управление доступом осуществляется уже другим модулем Apache. Вот пример блока опций:

AuthType Basic AuthName "Restricted Area" AuthUserFile

/usr/local/www/.htpasswd Require valid-user

Это минимальное число директив, необходимых для аутентификации такого типа. Каждая из них (или альтернативная ей) является обязательной. Рассмотрим эти ди-рективы по отдельности:

o AuthType. Она может иметь значение Basic или Digest. Нас интересует только Basic.

o AuthName. Это название защищаемой области. Оно отображается в окне аутен-тификации пользовательского браузера (например, "Enter username for

'Restricted Area' at www.somewhere.com" - "Введите пароль для 'Защищенной области' на сайте www.somewhere.com"), помогая пользователю определить, какое имя пользователя и пароль требуется ввести. Название может быть лю-бым. Если оно содержит пробелы, его следует заключить в кавычки.

o AuthUserFile, AuthDBUserFile и AuthDBMUserFile. Одна из этих директива дол-жна быть обязательно указана, поскольку она задает местонахождение базы данных имен пользователей/паролей для защищенной области. Каждая область может иметь отдельную базу данных, если нужно. Если это обычный тексто-вый файл, указывается директива AuthUserFile, если он имеет формат db или dbm, ускоряющий поиск (весьма желательно при большом количестве запи-сей), - директива AuthDBUserFile или AuthDBMUserFile, соответственно. О том, как создать пользовательскую базу данных в формате текстового файла или db/dbm, рассказано далее.

o AuthGroupFile, AuthDBGroupFile и AuthDBMGroupFile. Эти директивы работают так же, как AuthUserFile. В них заданы группы пользователей из файла AuthUserFile, что позволяет ограничивать доступ не только отдельным пользо-вателям, а и целым группам. Эта директива не является обязательной, но если она используется, файл AuthUserFile также необходим, чтобы пользователи распознавались, как принадлежащие к перечисленным группам.

o Require. Эта директива указывает Apache, как аутентифицировать пользовате-ля. Аргументом может быть valid-user (имя пользователя из файла AuthUserFile; при этом требуется ввод корректного пароля), user <username> <username>... (список пользователей) или group <groupname> <groupname>... (список групп).

Добавление пользователей

Когда блок контроля доступа уже настроен и команда apachectl configtest сообща-ет о корректности конфигурации, в систему можно добавить учетные записи пользо-вателей Apache. Вначале рассмотрим, как создать базу данных в виде обычного тек-стового файла, указываемого как аргумент директивы AuthUserFile. Для этого применяется команда htpasswd, которая в FreeBSD расположена в каталоге /usr/ local/bin и поэтому автоматически включена в пути поиска:

o htpasswd -с /usr/local/www/.htpasswd frank

Ключ -с обязателен только при первом запуске. Он указывает команде htpasswd, что файл нужно создать, поскольку он еще не существует. Затем команда запраши-вает пароль пользователя, который требуется ввести, как обычно, дважды. Если ко-манда используется в сценарии, ключ -Ь позволяет указать пароль во втором аргу-менте:

o htpasswd -b /usr/local/www/.htpasswd joe Prld3L4ndz

Следующей полезной опцией является -т. Она указывает htpasswd использовать алгоритм шифрования MD5, а не системную процедуру crypt(), обеспечивая тем самым более серьезную защиту. О других опциях рассказано на странице справочного ру-ководства man apachectl.

ПРЕДУПРЕЖДЕНИЕ

Файл с пользовательской базой данных может находиться в любом месте системы, где его может прочесть пользователь Web-сервера [nobody], и иметь любое имя. Использование име-ни .htpasswd является традиционным и защищает файл от просмотра в конфигурации сервера по умолчанию. Естественно, не следует размещать файл там, где посетители сайта смогут прочесть его с помощью Web-бразуера, т.е. в каталоге /usr/local/www/data или в каком-либо из пользовательских каталогов publicjitml. Для него вполне подойдет такое недоступное по Web-протоколу место, как /usr/local/www. Разумеется, вам совсем не нужно, чтобы пользователи смогли загрузить базу данных паролей и попытались ее взломать!

Пользовательские базы данных в виде обычных текстовых файлов подходят для небольших списков пользователей. Когда число пользователей вырастает до десятков или сотен, время, необходимое для поиска пароля в базе, делает такой способ аутентификации неудобным или даже нефункциональным. Решение заключается в использовании настоящей базы данных в формате db или dbm и соответствующей директивы AuthDBUserFile или AuthDBMUserFile. Программа, предназначенная для работы с базами данных в-таком формате, называется /usr/local/bin/dbmmanage:

# dbmmanage /usr/local/www/.htpwddb adduser frank

New password:

Re-type new password:

User frank added with password encrypted to NtMDxy6jwyW7A using crypt

В этом примере создается db-файл /usr/local/www/.htpwddb, для доступа к которому применяется директива AuthDBUserFile. При необходимости можно воспользоваться и dbm-эквивалентом. Подробную информацию об управлении записями пользователей можно почерпнуть из справочного руководства man dbmmanage.

Добавление групп Перечислить группы в обычном текстовом файле (AuthGroupFile) очень просто. Каждая строка содержит имя группы, двоеточие и список пользователей в ней:

mygroup: frank joe alice

Файл группы должен находиться там же, где и пользовательский, и иметь сходное имя. Так как файл группы не содержит паролей, соображения безопасности здесь не столь существенны.

Файлами групп можно управлять и с помощью утилиты dbmmanage, но на практике к ней, как правило, прибегать не приходится (как в случае с /etc/group), поскольку групп, как правило, гораздо меньше, чем пользователей. Директиву AuthGroupFile допускается, использовать в сочетании с AuthDBUserFile, если нужно объединить форматы. Вероятно, это простейший способ поддержки большого списка пользователей с небольшим списком групп.

Контроль доступа по адресу и паролю

При предоставлении доступа к закрытой области можно пользоваться обоими типами защиты: ограничениями адреса и аутентификацией по паролю. Для этого применяется директива Satisfy:

Allow from 64.41.131.102 Require valid-user Satisfy all

Директива Satisfy all используется по умолчанию, если присутствуют обе директивы - Allow и Require. Это означает, что пользователь, во-первых, должен удовлетворять требованиям директивы Allow, во-вторых, он должен указать подходящие имя и пароль, и только после этого ему будет предоставлен доступ к закрытой области. Директива же Satisfy any говорит серверу, что пользователь должен либо указать корректный пароль, либо его адрес должен удовлетворять требованиям директивы Allow. Такая настройка применяется тогда, когда часть пользователей посещает Web-сайт с определенных адресов, а для всех остальных пользователей требуется аутентификация.

Виртуальный хостинг

Виртуальный хостинг представляет собой методику хранения содержимого Web-сайтов с разными именами доменов или хостов на одном сервере. Для обслуживания всех запросов достаточно одного Apache. Например, именам www.mystore.com и www.frankspage.com в DNS может соответствовать один и тот же IP-адрес, и Apache обслуживает оба этих сайтов (равно как и собственное имя хоста, которое задано директивой ServerName).

Как мы убедились, протокол HTTP/1.0 не указывает имя хоста. Поэтому ранее виртуальный хостинг был возможен лишь в том случае, когда каждому имени хоста был поставлен в соответствие отдельный IP-адрес (с последующим созданием IP-псевдонимов, указывающих на одну и ту же Ethernet-карту). Каждый виртуальный хост определялся по IP-адресу, и запрос, приходящий от Web-браузера, всегда получал в ответ страницу соответствующего Web-сайта. Недостатком такого подхода было то, что привязка больших блоков IP-адресов к одной и той же карте становилась громоздкой и приводила и к излишнему потреблению адресного IP-пространства.

С появлением версии протокола НТТР/1.1 данный процесс значительно упростился. Обязательный заголовок Host: указывает искомое имя хоста, поэтому виртуальные хосты, различаемые по имени, стали нормой в современном Internet. Клиенты, не поддерживающие заголовка Host: теперь чрезвычайно редки. Далее обсуждается исключительно такой вариант виртуального хостинга. Если вы заинтересованы в использовании виртуального хостинга на базе IP-адресов, обратитесь к документации, имеющейся на Web-сайте Apache.

Большая часть файла httpd.conf определяет сервер по умолчанию - глобальный набор определений, применяющихся ко всем запросам, получаемым сервером Apache. В сервере по умолчанию директива ServerName используется в первую очередь для конструирования URL-перенаправления с кодом 301. Можно также воспользоваться небольшим набором директив, отменяющим глобальные настройки в том случае, когда заголовок Host: совпадает с определенным именем хоста. Такие наборы правил и представляют собой виртуальные хосты.

Предположим, что сервер называется stripes.somewhere.com. Его имя задано в главной директиве ServerName. Для настройки виртуального хостинга по именам следует воспользоваться директивой NameVirtualHost с аргументом * (этот символ-заместитель означает "все хосты"), за которой следует необходимое число различных блоков <VirtualHost *>:

NameVirtualHost *

<VirtualHost *>

ServerName www.somewhere.com

DocumentRoot /usr/local/www/data

ServerAdmin webmaster3somewhere.com

ErrorLog logs/www.somewhere.com-error_log

CustomLog logs/www.somewhere.com-access_log common </VirtualHost>

<VirtualHost *>

ServerName www.frankspage.com

ServerAlias frankspage.com

DocumentRoot /home/frank/public_html

ServerAdmin frank@frankspage.com

ErrorLog logs/www.frankspage.com-error_log

CustomLog logs/www.frankspage.com-access_log common </VirtualHost>

Внутри контейнера <VirtualHost> директива ServerName определяет имя хоста. Директива DocumentRoot указывает, где находится корневой каталог файловой системы для приходящего запроса, a ErrorLog и CustomLog - альтернативные log-файлы для каждого виртуального хоста. ServerAlias позволяет перечислить псевдонимы виртуального хоста. В блоке <VirtualHost> можно включить и любые другие директивы.

Важно отметить, что при настройках, приведенных ранее, запрос к серверу по умолчанию (stripes.somewhere.com) или к любому другому имени хоста, соответству-ющему IP-адресу сервера, но не совпадающему ни с одним из блоков <VirtualHost>, обработан не будет.

Вот пример более корректной конфигурации:

NameVirtualHost *

<VirtualHost *>

ServerName stripes.somewhere.com </VirtualHost>

<VirtualHost *>

ServerName www.somewhere.com

ServerAlias *.somewhere.com

DocumentRoot /usr/local/www/data

ServerAdmin webmaster@somewhere.com

ErrorLog logs/www.somewhere.com-error_log

CustomLog logs/www.somewhere.com-access_log common </VirtualHost>

<VirtualHost *>

ServerName www.frankspage.com

ServerAlias frankspage.com

DocumentRoot /home/frank/public_html

ServerAdmin frank@frankspage.com

ErrorLog logs/www.frankspage.com-error_log

CustomLog logs/www.frankspage.com-access_log common </VirtualHost>

Виртуальные хосты можно создавать множеством способов: указывая различные IP-адреса и порты в блоках <VirtualHost>. Синтаксис таких методов можно уточнить по адресу http://httpd.apache.org/docs/vhosts/.

Модули сервера Apache

Одним из главных преимуществ сервера Apache является его модульная структура. Каждая конфигурационная директива является частью того или иного модуля. В ранних версиях Apache они включались или отключались на этапе компиляции, теперь же они доступны как динамические разделяемые объекты (dynamic shared objects, DSO), что позволяет загружать их во время исполнения.

Встроенные модули

Просмотреть модули, статически скомпилированные с Apache, позволяет команда httpd -1:

# httpd -I Compiled-in modules:

http_core.с

mod_so.с suexec: disabled; invalid wrapper /usr/local/sbin/suexec

Это значит, что с гарантией доступны лишь директивы модулей Core и mod_so. Модуль Core обеспечивает доступ к фундаментальным директивам Apache, без которых запустить его просто невозможно, a mod_so - за поддержку DSO, которая позволяет загрузить все остальные тридцать два модуля, поставляемые с Apache, и любые из дополнительно установленных модулей.

ПРИМЕЧАНИЕ Сообщение о suexec можно игнорировать. Эта утилита позволяет выполнять процесс Apache с setuid когда запросы запускаются от имени определенного пользователя (обычно для разных виртуальных хостов пользователи эти разные]. Оболочка suexec по умолчанию не устанавлива-ется. Ознакомиться с документацией можно по адресу http://httpd.apache.org/docs/ suexec.html. В главе 29 рассказано о CGIwrap - альтернативе suexec.

Динамически загружаемые модули

Динамически загружаемые модули позволяют уменьшить потребление ресурсов вы-полняемыми процессами httpd, выгрузив ненужные модули. Это легко сделать на этапе исполнения, просто закомментировав их в файле httpd.conf. Если функциональность каких-либо модулей вдруг понадобится, их можно включить заново и перезапустить Apache. Полный список всех модулей сервера Apache и соответствующих им директив имеется на http://httpd.apache.org/docs/mod/.

Для включения модуля требуются две директивы: LoadModuIe (динамически под-ключает модуль к процессу httpd) и AddModule (включает директивы модуля в пра-вильном порядке). Просмотрев файл httpd.conf, легко убедиться, что директивы LoadModuIe и AddModule указаны для всех поставляемых модулей Apache, которые установлены в каталоге /usr/local/libexec/apache. Порядок загрузки модулей важен. Если один модуль зависит от другого, последний должен быть подключен раньше. В конфигурации по умолчанию указан корректный порядок модулей.

Сторонние модули

Широкие возможности модульной структуры Apache проявляются, когда в игру вступают модули от сторонних поставщиков. Эти модули подключаются на этапе

исполнения, как и все остальные модули Apache, и обеспечивают дополнительную функциональность и директивы конфигурации. Обычно они позволяют Apache более эффективно обрабатывать определенные типы данных на сервере. Например, одним из очень популярных модулей является mod_perl, который встраивает в Apache интерпретатор языка Perl, что значительно ускоряет обработку CGI-сценариев на этом языке, поскольку отпадает необходимость запускать процесс командного интерпре-татора и исполнять CGI-программу в нем. Не менее популярен и модуль mod_php4, который позволяет Apache обрабатывать динамические PHP-страницы (более удач-ный UNIX-аналог технологии ASP). В разделе /usr/ports/www набора портов включены еще 34 сторонних модуля Apache. Их имена имеют префикс mod_.

Создание модулей с помощью apxs

Раньше, когда поддержка DSO была, в лучшем случае, экспериментальной, под-ключение такого модуля требовало изменения файлов конфигурации исходного кода Apache и исходного кода модуля, а затем компиляции одного "гибридного" двоичного файла. Хотя технически это был "модульный" подход (все-таки это лучше, чем внесение изменений непосредственно в исходный код Apache), им было сложно пользоваться. Он требовал сборки нового выполняемого файла при появлении новой версии Apache или модуля, а также немалых усилий при работе с кодом.

Затем появилось средство apxs, APache eXtenSion (расширение Apache). Эта про-грамма, находящаяся в /usr/local/sbin, предназначена для того, чтобы, используя поддержку DSO, уже скомпилированную в двоичном файле (статический модуль mod_so), обеспечить среду сборки, учитывающую все свойства двоичного файла httpd. Теперь для создания сторонних модулей исходный код Apache не нужен: apxs ком-пилирует и преобразует модули из исходного кода или из уже скомпилированных объектных файлов в файлы .so, которые можно загрузить с помощью директивы LoadModule, как и любые другие модули.

Скорее всего, вам не придется работать с утилитой apxs непосредственно. Она используется на этапе компиляции средствами сборки портов. Все, что требуется для сборки стороннего модуля (как и любого другого порта), это перейти в его каталог в иерархии /usr/ports/www и запустить команду make. Все остальное сделает apxs. Если появится новая версия Apache, ее можно будет собрать и инсталлировать независимо - сторонние модули будут продолжать работать. И наоборот, при обновлении модуля его достаточно заново собрать и установить. В этом проявляются преимущества модульной системы.

mod_perl

Один из самых популярных сторонних модулей - raodjerl. Поскольку язык Perl чаще всего используется при CGI-программировании, запуск сценариев Perl означает дополнительную работу для сервера Apache. Когда приходит HTTP-запрос на запуск CGI-программы на Perl, Apache требуется запустить процесс командного интерпретатора и выполнить сценарий в нем, возвращая затем результат клиенту.

С помощью модуля mod_perl интерпретатор языка Perl встраивается прямо в Apache. Специальные директивы определяют некоторые типы файлов как выполняемые сценарии на Perl, которые Apache может запускать самостоятельно. Более того, каждый сценарий, запускаемый Apache, сохраняется в памяти в скомпилированном виде для дальнейшего использования. Это значительно ускоряет запуск CGI-программ, а значит, и ответ сервера.

Более подробную информацию о mod_perl можно найти по адресу http:// perl.apache.org.

mod_python

С ростом популярности языка Python как наследника Perl в серверном програм-мировании появился модуль mod_python, обеспечивающий Apache ту же функцио-нальность по отношению к Python, какую mod_perl обеспечивает по отношению к Perl. Интерпретатор Python доступен Apache непосредственно, позволяя серверу самостоятельно запускать CGI-программы на этом языке.

Домашняя страница mod_python находится по адресу www.modpython.org.

mod_php

PHP, чрезвычайно популярное средство для создания динамических страниц в UNIX, также является частью Apache благодаря модулям mod_php3 и mod_php4. Директивы этих модулей позволяют Apache естественным образом обрабатывать php-файлы, запуская их для генерирования окончательной формы страницы перед пересылкой ее клиенту. После сборки и инсталляции модуля mod_php4 файл httpd.conf автоматически обновляется, чтобы обеспечить поддержку php- и phps-файлов.

Более детальная информация о РНР и mod_php4 имеется на Web-сайте www.php.net.

Существует множество других модулей, расширяющих функциональность Apache. Модульность Apache была окончательно закреплена лишь недавно, а широкое рас-пространение сторонних модулей в сочетании с набором портов FreeBSD послужили началом новой эры в администрировании HTTP-сервера.

Серверные расширения

Одно из самых популярных свойств Apache - это возможность обрабатывать сер-верные расширения, которые включены в HTML-файлы и обрабатываются сервером перед отправкой их браузеру. Серверные расширения (server-side includes) позволяют производить различные операции, начиная от вывода на страницу переменных среды до импорта HTML-фрагментов или запуска серверных-программ при каждом обращении к странице.

Серверные расширения встраиваются в так называемый анализируемый HTML (parsed HTML). Последний представляет собой обычный HTML-код, который сервер Apache анализирует при запросе страницы, находит серверные расширения и обрабатывает каждое из них перед отправкой документа клиенту. Каждое расширение имеет сле-дующий формат:

<!-#command attribute=value attribute=value ... -->

В общем случае, командой command может быть include, exec, config, echo и т.д. Пары attribute=value позволяют установить (используя расширения) или прочесть (используя переменные среды) значения переменных.

Чтобы разрешить использование серверных расширений, в Apache необходимо убрать комментарии со следующих двух строк в файле httpd.conf (или добавить их в соответствующий файл .htaccess):

AddType text/html .shtml AddHandler server-parsed .shtml

Затем опцию Includes нужно добавить в блок <Directory> или <Location> (или файл .htaccess), который управляет соответствующей областью Web-сайта:

Options +Includes

Директива AddType добавляет новый класс файлов к типу MIME, расширяя базо-вый набор, который хранится в файле /usr/local/etc/apache/mime.types, a AddHandler присваивает определенному расширению соответствующий обработчик (внутренний метод обработки файла, запрашиваемого пользователем). В данном случае используется расширение shtml (традиционное расширение HTML-файлов, которые перед обработкой подвергаются синтаксическому анализу).

ПРЕДУПРЕЖДЕНИЕ

Если не считать наличия серверных расширений, единственное различие между html- и shtml-файлами - это разные расширения. Оба типа являются обычными HTML-файлами. Если в html-файл были включены серверные операции, следует изменить его расширение на .shtml. Серверные расширения в html- или htm-файлах обрабатываться не будут.

Вот несколько полезных примеров:

o <!- "echo var="HTTP_USER_AGENT"--> - Выводит строку, идентифициру-ющую браузер пользователя на странице. Подробное обсуждение доступных переменных среды приведено далее в разделе, посвященном CGI-программи-рованию.

o <!--#set var="e-mail" value="me@somewhere.com""> -- Устанавливает пере-менную e-mail значением me@somewhere.com для оставшейся части страницы.

o <!~#include virtual="/toolbar.html"-> - Вставляет на страницу содержимое фай-ла /toolbar.html. Серверные расширения обрабатываются рекурсивно, поэтому файл, подключенный таким образом, может содержать и собственные расши-рения. (Будьте бдительны!)

o <!--#config timefmt="%A %B %d, %Y"-> - Устанавливает формат для всех серверных расширений, выводящих дату и время. Строка формата совпадает с той, что используется командой date. См. man date.

o <!--#flastmod file="index.shtml"--> - Выводит дату и время последней моди-фикации файла index.shtml. Допустимый формат приведен в предыдущем при-мере config timefmt.

o <!--#ехес cgi="/cgi-bin/counter"--> - Запускает CGI-сценарий counter и ото-бражает его вывод.

Если в shtml-файле размещены подобные директивы, но они почему-то не работают, просмотрите исходный код страницы. Эти директивы не должны содержаться в HTML-коде, отправляемом клиенту. Если они там присутствуют, следовательно, они не были обработаны сервером. Скорее всего, конфигурация Apache не настроена для поддержки серверных расширений. Убедитесь, что директивы AddType и AddHandler заданы корректно и относятся к используемой части Web-сайта.

СОВЕТ

Если имя файла не указано, то по умолчанию клиенту отображается файл index.html. Директива Directorylndex позволяет изменить или расширить список значений:

Directorylndex index.php index.php3 index.html index.shtml

Apache пытается найти любой из файлов в порядке перечисления и, если ни один из них не найден (а директива Options Indexes включена), отображает листинг файлов каталога.

Вместо этого можно воспользоваться следующими директивами:

Options +MultiViews Directorylndex index INDEX

Директива MultiViews сообщает Apache о поиске файла, имя которого (без расширения) со-впадает с указанным, a Directorylndex сообщает, что обслуживанию подлежит файл вида index.* (с любым расширением). Обычно поиск файлов происходит в алфавитном порядке. Таким образом, сервер будет обрабатывать файлы index.htm, index.HTM, INDEX.HTML и т.д.

Полное руководство по серверным расширениям, где изложено все: от условного управления потоком выполнения до запуска внешних CGI-программ, - можно найти на сайте http://httpd.apache.org/docs/howto/ssi.html.

Основы CGI

Обычные Web-сайты состоят из статических HTML-страниц. Расширить их фун-кциональность позволяют серверные расширения. Однако реальные Web-приложе-ния (коммерческие сайты, доски объявлений, базы данных и многие другие) требуют определенной программной среды для обработки пользовательского ввода и управ-ления запрашиваемым выводом. Стандартом этой среды служит CGI, Common Gateway Interface (Общий шлюзовый интерфейс).

CGI представляет собой протокол-посредник, своего рода слой Web-сервера, ко-торый позволяет получать данные от пользователя в виде HTML-форм и передавать их в стандартном формате любой программе на сервере - независимо от того, на каком языке она написана. CGI-программа может быть сценарием на языке коман-дного интерпретатора или Perl, скомпилированным двоичным файлом, написанным на С, или любым другим файлом, который может быть выполнен пользователем сервера Apache (nobody). Вывод программы Apache перенаправляет прямо Web-бра-узеру. Это значит, что можно написать CGI-программу, которая читает переменные из HTML-формы, обрабатывает их, открывает конвейер с программой Sendmail, высылает значения переменных вам (администратору) и выдает ответ пользователю в HTML-формате. Далее мы увидим, как решить подобную задачу с помощью сцена-рия на Perl.

Включение CGI в Apache

Существует два способа использования CGI-программ в Apache. Первый, наибо-лее корректный, состоит во включении в httpd.conf директивы ScriptAlias, определя-ющей некоторый каталог как содержащий только CGI-программы и отображающей виртуальный путь к нему (видимый Web-браузеру):

ScriptAlias /cgi-bin/ "/usr/local/www/cgi-bin/"

Эта строка, которая в файле httpd.conf включена по умолчанию, сообщает Apache, что cgi-bin - это каталог, предназначенный для CGI, и все файлы, находящиеся в нем, являются CGI-программами. Если в нем разместить что-либо другое и попробовать к нему обратиться, сервер возвратит ошибку с кодом 500 (Server Error), т.е. ошибку при запуске CGI. Количество директив ScriptAlias может быть любым. Путь к CGI-каталогу в файловой системе (например, /usr/local/www/cgi-bin/) совсем не должен быть доступным для Web-запросов. Псевдоним может указывать на любую точку файловой системы, доступную для чтения пользователю nobody. Это предотвращает возможность просмотра содержимого каталога посетителями Web-сайта. К тому же, они никогда не работают с CGI-программами напрямую. Последние вызываются как ссылки или для обработки форм.

ПРИМЕЧАНИЕ

Обратите внимание, что в пути /cgi-bin/ указан замыкающий символ косой черты. Это еще одна предосторожность, которая предотвращает неавторизованный доступ к листингу каталога. Имя CGI-программы в Apache образуется путем добавления непосредственно имени программы (например, script.cgi] к виртуальному пути директивы ScriptAlias (например, /cgi-bin/), по-этому символ косой черты необходим для правильного воссоздания пути (в данном случае, /cgi-bin/script.cgi] Перенаправления с кодом 301 здесь не поддерживаются.

Другой способ включения CGI-программ состоит в использовании директивы Options для добавления опции ExecCGI к области сервера, заданной в блоке <Directory> или <Location>. Это полезно для разрешения запуска CGI-программ в пользовательских каталогах public_html. При этом используется расширение файлов (например, .cgi) и бит права на выполнение. В следующем примере разрешен запуск всех выполняемых пользовательских cgi-файлов, независимо от их местоположения:

<Directory /home/*/public_html>

Options +ExecCGI

AddHandler cgi-script .cgi </Directory>

Если CGI-файл (находящийся в каталоге ScriptAlias или назначаемый обработчику по расширению) по каким-либо причинам не может быть запущен, пользователю пересылается сообщение с кодом 500 (Server Error). Более подробные диагностические сообщения содержатся в log-файле Apache. Вот пример записи об ошибке при неудачном запросе сценария blah на языке Perl в каталоге /usr/local/www/cgi-bin:

# tail /var/log/httpd-error.log

syntax error at /usr/local/www/cgi-bin/blah line 3, at EOF

Execution of /usr/local/www/cgi-bin/blah aborted due to compilation

errors.

[Tue May 22 22:06:26 2001] [error] [client 64.2.43.44] Premature end of

script headers: /usr/local/www/cgi-bin/blah

Две первых строки вывода принадлежат интерпретатору Perl. Они имеют тот же вид, как если бы сценарий был запущен из командной строки. В третьей строке сервер Apache сообщает о попытке запуска сценария, который завершил работу до того, как вывести какой-либо HTTP-заголовок, например, Content-type: (является обязательным для корректного CGI-сценария). Здесь следует убедиться, что программа, предназначенная для выполнения через CGI-интерфейс, написана корректно.

Написание CGI-программ

Формат, в котором CGI-переменные пересылаются серверной программе, пред-ставляет собой закодированную в URL текстовую строку, в которой переменные и значения разделяются знаком равенства (=), а сами переменные - символом ампер-санта (&). Строка поступает на стандартный ввод сценария (STDIN).

Самым распространенным языком CGI-программирования является Perl, поэтому два этих термина ошибочно используются как синонимы. Их не следует путать: язык Perl, кроме Web-программирования, предназначен для решения многих других задач, a CGI обеспечивает интерфейс ко всем языкам, в том числе и к не существующим на данный момент. В силу превалирования Perl в CGI-программировании, мы рассмотрим пример сценария на этом языке.

Основными достоинствами Perl (с которыми мы познакомились в главе 21) являются обработка текста и простота разработки кода. Поэтому он и является идеальным кандидатом для чтения переменных HTML-формы (имя пользователя, адрес электронной почты, почтовый адрес, комментарии и т.д.) и преобразования их в формат, пригодный для дальнейшего использования. Обычно CGI-программы на Perl вызываются в результате обработки HTML-форм:

<FORM NAME="myform" METHOD="POST" ACTION="/ogi-bin/post2me">

Когда пользователь отсылает форму, все переменные передаются с помощью CGI-интерфейса сценарию post2me. Последний представляет собой программу на языке Perl, чьей задачей является их обработка. Первое, что делает сценарий, - это чтение переменных из стандартного входного потока и запись в ассоциативный массив (для упрощения дальнейшей работы с ними):

read(STDIN, $buffer, $ENV{ ' CONTENT_LENGTH ' }) ; @pairs = split (/&/, $buf fer) ; foreach $pair (gpairs) {

($name, $value) = split(/=/, $pair) ;

$value =- tr/+/ /;

$value =~ s/%([a-fA-FO-9] [a-fA-FO-9] ) /pack("C" , hex($l) ) /eg;

$value =~ s/~!/ ~!/g;

$FORM{$name} = $value;

Вначале производится проверка запроса, на предмет безопасности. Она предотвращает пересылку программе злонамеренного ввода. В частности, если CGl-npoграмма выводит пользователю HTML-файл на основе данных, введенных в форму, пользователь может включить определенный HTML-код, который, вызывая сервер-ные расширения, сможет запустить определенную программу на сервере. Поскольку все программы по http-запросам запускаются от имени пользователя nobody (не об-ладающего необходимыми правами доступа), это не вызывает большой тревоги. Как бы там ни было, это в какой-то мере дыра в защите, забывать о которой нельзя. Поэтому блок кода запрещает потенциально опасные HTML-тэги, вставляя в соот-ветствующих местах пробелы и дефисы.

Когда сценарий прочитает весь ввод, каждая переменная формы становится доступна как ключ ассоциативного массива %FORM. Например, содержимое поля e-mail доступно теперь как значение $FORM{'e-maiI'}.

Теперь сценарий должен вывести корректный HTML-заголовок. Здесь существует две возможности: вывести HTML-код в стандартный выходной поток, создавая но-вую страницу прямо из сценария, или перенаправить пользователя на другой URL, пока сценарий выполняет свою работу. Первый способ осуществляется с помощью заголовка Content-type:, который может включать любой корректный тип MIME (браузер самостоятельно решает, как обрабатывать его), за которым следуют два символа новой строки, сигнализирующие об окончании блока заголовка:

print "Content-type: text/html ";

Все, что выведено сценарием после заголовка, браузер будет визуализовать как HTML-код. Чтобы отобразить обычный текст, можно воспользоваться типом text/ plain.

Второй метод (перенаправление) выполняется с помощью заголовка Location: и URL-перенаправления:

print "Location: http://www.somewhereelse.com/path/to/file.html ";

Все, что будет выведено после этого заголовка, браузер уже не воспримет, по-скольку к этому моменту он перейдет к новому URL.

CGI-программам доступны также и переменные среды, а HTTP-соединение не-сет немало интересной информации. Перечислим некоторые из них: HTTP_REFERER (URL ссылающегося документа), HTTP_USER_AGENT (браузер пользователя), REMOTE_HOST (имя хоста пользователя) и т.д. Просмотреть все значения позволяет сценарий printenv, включенный в инсталляцию Apache по умолчанию (он находится в каталоге /usr/local/www/cgi-bin). Для доступа к нему достаточно указать URL http://www.somewhere.com/cgi-bin/printenv, подставив, естественно, имя хоста или IP-адрес FreeBSD-машины. В Perl к переменным среды можно обратиться как к ключам ассоциативного массива %ENV, например, $ENV{ 'REMOTE_HOST'}.

Рассмотрим пример несложной CGI-программы на Perl, которая читает из HTML-формы три переменных (name, e-mail и comments), высылает их администратору по электронной почте и выдает сообщение пользователю. Этот сценарий, приведенный в листинге 26.1, содержится на прилагаемом компакт-диске под именем sendcomments.cgi.

Листинг 26.1 Пример CGI-программы на языке Perl #!/usr/bin/perl

read(STDIN, $buffer, $ENV{'CONTENT_LENGTH'}); Spairs = split(/S/, $buffer); foreach $pair (Spairs) {

($name, $value) = split(/=/, $pair);

$value =~ tr/+/ /;

$value =~ s/%([a-fA-FO-9][a-fA-FO-9])/pack("C", hex($l))/eg;

$value =~ a/~!/ ~!/g;

$ FORM {$ name} = $value; } print "Content-type: text/html ";

open (MAIL,"| /usr/sbin/sendmail -oi -t") ;

print MAIL "From: $FORM{'name'} <$FORM{'e-mail1}> ";

print MAIL "To: you@your.hostname.com ";

print MAIL "Subject: Form output ";

print MAIL "$FORM{ 'name' } , from $ENV{ ' REMOTE_HOST ' } ($ENV{ ' REMOTE_ADDR' }) ,

has sent you the following comment: ";

print MAIL "$FORM{'comment'} ";

close (MAIL) ;

print qqA<HTML> <HEAD> <TITLE>Thank you!</TITLEX/HEAD> A;

print qqA<BODYXH3>Thank you!</H3> Thanks for your comments! </H3> </

BODY> </HTML>A;

Чтобы настроить сценарий для своих нужд, следует заменить фиктивный заголо-вок То: реальным адресом электронной почты (символ @ необходимо обязательно экранировать символом обратной косой черты). Сам по себе сценарий не выполняет никаких особенных действий, но изучив саму методику, вы убедитесь, что принципы, изложенные здесь, применимы ко все серверным программам - от небольших об-работчиков форм до сложных баз данных и коммерческих систем.

CGI-программу можно вызывать не только из HTML или методом POST. Можно указать URL сценария CGI, если ему не требуется передавать переменные в ассоци-ативный массив (наподобие %FORM, показанного в примере). URL выглядит след-ющим образом:

http://www.somewhere.com/cgi-bin/sysinfo?frank+3

По этому URL вызывается программа sysinfo из каталога /cgi-bin/. Все, что нахо-дится после вопросительного знака, называется строкой запроса (query string). Ее со-держимое доступно сценарию как массив @ARGV. Аргументы разделяются знаком плюс (+). В программе sysinfo строка frank будет элементом $ARGV[0], а число 3 -$ARGV[1].

СОВЕТ

Обратиться ко всей строке запроса в Perl позволяет переменная среды QUERY STRING, или $EIMV{ QUERY STRING'}

Обновлено: 12.03.2015