Построение настраиваемого сервера IIS 7.0

Введение

В IIS 6.0 и предыдущих версиях была реализована большая часть функций сервера, используемых внутри самого сервера. Напротив, механизм веб-сервера IIS 7.0 обеспечивает модульную архитектуру, на которой практически все функции сервера представлены в виде сменных компонентов. Благодаря этому появляется возможность использовать большое количество нововведений, включая:

  • Возможность точно определять, какой набор функций загружен/используется на сервере, удаляя ненужные функции для уменьшения поверхности атаки и уменьшая объем используемой сервером памяти.
  • Возможность заменять каждую функцию сторонними или настраиваемыми реализациями.
  • Возможность специализировать сервер на основе его роли в серверной топологии.
  • Расширенный контроль над набором функций сервера, как с помощью хорошей разделяемости функций, так и на уровне делегируемых приложений.

Эта компоненты сервера, также известные как модули, загружаются во время инициализации рабочего процесса пула приложений и обеспечивают услуги обработки запросов на сервере. Каждое приложение IIS 7.0 – это комбинация сервисов, обеспеченных включенными для приложения модулями, и связанного контента, используемого этими сервисами. Сервер предоставляет две основные роли, выполняемые модулями:

  • Предоставление обслуживания запросов, например, аутентификация или выходное кэширование (подобно ISAPI-фильтрам в IIS 6.0)
  • Предоставление обработки запросов, например, обработка статических файлов, CGI, или обработка страниц ASP.NET (подобно расширениям ISAPI в IIS 6.0)

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

Задачи, описанные в этой статье, включают:

  • Обзор конфигурации сервера, параметров, заданных по умолчанию, и набора модулей, загружаемых сервером по умолчанию.
  • Удаление всех модулей, для приведения сервера к его минимальной конфигурации, и исследование занимаемого места
  • Построение настраиваемого сервера через добавление модулей для поддержки определенных сценариев

Обзор конфигурации модулей, заданной по умолчанию

Главная конфигурация сервера содержится в файле applicationHost.config, расположенном в директории конфигурации IIS 7.0 (%windir%\system32\inetsrv\config). Рассмотрим следующую конфигурацию, содержащуюся в группе раздела <system.webServer>:

  • Раздел <globalModules>. Этот раздел уровня сервера содержит список модулей, загруженных рабочим процессом сервера и связан с родными DLL-библиотеками, в которых реализованы их функции.
  • Раздел <modules>. Этот раздел уровня приложения содержит список модулей, включенных для определенного приложения. Этот раздел служит для  выбора подмножества загруженных модулей, которые должны быть активны в приложении, а также для загрузки дополнительных модулей уровня приложения.
  • Раздел <handlers>. Этот раздел уровня URL содержит сопоставления обработчиков, которые использует сервер для отображения входящих запросов на определенные модули, которые их обрабатывают. Это похоже на карты сценариев в IIS 6.0 или ASP.NET, и служит для объединенного отображения запросов как на родные, так и на управляемые обработчики типов контента.

Полное описание модулей всех IIS 7.0 доступно в статье «IIS 7.0 Modules Overview».

Создание резервной копии конфигурации

Для начала мы делаем резервную копию конфигурации сервера, чтобы мы могли восстановить ее в случае необходимости. Запустите командную строку с правами администратора:

%windir%\system32\inetsrv\appcmd add backup initial

После этого мы можем восстановить конфигурацию сервера в ее начальном состоянии, выполнив:

%windir%\system32\inetsrv\appcmd restore backup initial 

Исследование стандартного списка модулей

Перейдите к разделу <system.webServer>/<globalModules>. Этот раздел, который можно сконфигурировать только на уровне сервера, содержит модули, загружаемые для каждого рабочего процесса сервера. Каждая запись конфигурирует модуль с определенным именем и DLL, в которой реализованы функции этого модуля:

<globalModules>


    <!--several modules omitted -->


    <add name="BasicAuthenticationModule" image="…\authbas.dll" />


    <add name="WindowsAuthenticationModule" image="…\authsspi.dll" />


</globalModules>

Посмотрите имена различных модулей в конфигурации сервера, заданной по умолчанию – мы видим знакомые службы, предоставляемые как часть сервера в IIS 6.0:

Windows Authentication module, NTLM request authentication

<add name="WindowsAuthenticationModule" image="…\authsspi.dll" />

Static File Handler module, serving static files

<add name="StaticFileModule" image="…\static.dll" />

Dynamic Compression module, compression of responses

<add name="DynamicCompressionModule" image="…\compdyn.dll" />

Перейдите к разделу <system.webServer>/<modules>. Этот раздел, который может быть сконфигурирован на уровне сервера или уровне приложений, определяет, какие модули, загруженные в разделе <globalModules>, включены для определенного приложения. По большей части мы видим, что в этом разделе перечислены имена модулей, которые мы видели вышеупомянутом разделе, благодаря чему по умолчанию они включены для всех приложений.

Примечание: В конце списка есть несколько дополнительных элементов – это управляемые модули, разработанные с помощью модели расширяемости ASP.NET. Узнать больше о построении управляемых режимов можно в пошаговом руководстве Develop a Module Using .NET.

Перейдите к разделу <system.webServer>/<handlers>. Этот раздел, который может быть сконфигурирован на уровне сервера, приложений или URL, определяет, как обрабатываются запросы. Модули обычно участвуют в каждом запросе, тогда как обработчики получают только запросы для определенных URL.

Хороший пример модуля – модуль сжатия. Модуль сжатия просматривает каждый ответ и если надо сжимает его. Обработчик страниц ASP.NET – хороший пример. Он получает только запросы, которые ему соответствуют, например, запросы, которые имеют расширение .aspx. Список <handlers> определяет соответствия между запросом, основанным на URL или команде, и модулем обработки, который будет использоваться для обработки данного запроса. Существует дополнительная информация, используемая для конфигурирования каждого соответствия, но она здесь не представлена.

<handlers>


    <!-- certain details omitted -->


    <add name="CGI-exe" path="*.exe" verb="*" modules="CgiModule" ... />


    <add name="ISAPI-dll" path="*.dll" verb="*" modules="IsapiModule" ... />


    <add name="ASPClassic" path="*.asp" verb="GET,HEAD,POST"  modules="IsapiModule" ... />


</handlers>

Изучение занимаемого сервером объема памяти

1. Откройте Internet Explorer и сделайте запрос к серверу, указав следующий URLи нажав Enter:

https://localhost/iisstart.htm

Запуститься пул приложений сервера и будет обслужен документ iisstart.htm.

2. Запустите Task Manager и перейдите на вкладку Processes . Поскольку рабочий процесс IIS 7.0 выполняется под другой учетной запись пользователя, вы должны выбрать флажок «Show processes for all users». Обратите внимание на размер рабочего процесса сервера w3wp.exe.

Рисунок 1: Task Manager отображает рабочий процесс IIS

3. Теперь выполните следующую команду:

TASKLIST /fi "imagename eq w3wp.exe" /m

Мы видим, что данным рабочим процессом загружено более 90 DLL-библиотек. Большинство из них расположено в директории …\intersrv\ - многие из них являются DLL модулей, которые мы видели в первой задаче, просматривая раздел <globalModules>, а оставшиеся поддерживают .NET framework и среду выполнения сервера.

Разборка сервера

В предыдущей задаче мы исследовали заданный по умолчанию список компонентов, загруженных сервером, который содержал более 35 модулей, обеспечивающих различные сервисы от аутентификации до обработки статических файлов. Каждый из компонентов, загруженных на сервере, влияет на занимаемый сервером объем памяти, его поверхность атаки, производительность среды выполнения и, конечно же, на набор включенных функций.

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

Если мы изменяли  файл applicationHost.config во время предыдущей задачи, мы можем восстановить его к предыдущему состоянию, выполнив %windir%\system32\inetsrv\appcmd restore backup initial в командной строке:

Теперь, чтобы разобрать сервер:

1. С помощью текстового редактора откройте %windir%\system32\inetsrv\config\applicationHost.config.

2. Перейдите к разделу <system.webServer>/<globalModules>.

3. Удалите все записи в коллекции, чтобы осталось только пустое определение раздела:

<globalModules> 
    <!—Remove Everything --> 
</globalModules>

4. Вставьте записи в окно блокнота, чтобы использовать их позднее. Проделайте то же самое с разделом <system.webServer>/<modules>. Удалите все записи в этом разделе и вставьте их в  окно блокнота для последующего использования. Это гарантирует, что мы отключаем все модули, которые более не будут загружаться. Вставьте эти вырезанные записи в окно блокнота для последующего использования.

5. Повторите то же самое с разделом <system.webServer>/<handlers>. Удалите все записи в этом разделе, чтобы гарантировать, что мы удалили все соответствия обработчиков с модулями, которые мы отключили. Вставьте записи в окно блокнота, чтобы использовать их позднее. Сохраните файл applicationHost.config, чтобы изменения вступили в силу.

Изучение объема памяти, занимаемого разобранным сервером

Теперь мы готовы загрузить наш разобранный сервер – мы повторим описанные выше шаги, чтобы изучить новый размер занимаемого сервером пространства.

1. Откройте Internet Explorer и сделайте запрос к серверу, указав следующий URLи нажав Enter:

https://localhost/iisstart.htm

Запуститься пул приложений сервера и возвратит браузеру ошибку, поскольку для обслуживания запрошенных вами ресурсов не зарегистрировано ни одного обработчика.

2. Запустите Task Manager и перейдите на вкладку Processes . Обратите внимание на размер рабочего процесса сервера w3wp.exe.

3. Выполните следующую команду:

TASKLIST /fi "imagename eq w3wp.exe" /m

Заметьте, что объем занимаемой сервером памяти уменьшился примерно до 8 Мб. По ходы работы сервера занимаемое сервером пространство будет и дальше уменьшаться.

Загружено только 50 DLL, по сравнению с более чем 90 – это указывает на то, что сервер не загрузил ни одной DLL модулей, что непосредственно или косвенно объясняет разницу в количестве DLL. В процессе не были загружены не только отключенные на сервере службы, но и код для этих функций. После оптимизации количество DLL пустого сервера будет значительно меньше.

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

Построение настраиваемого сервера

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

  • Обслуживание статических файлов
  • Обслуживание перечислений директорий
  • Защита контента с базовой аутентификацией и правила авторизации, основанными на URL.

Включение функции обслуживания статических файлов сервером

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

1. С помощью текстового редактора откройте

%windir%\system32\inetsrv\config\applicationHost.config.

2. Перейдите к разделу<system.webServer>/<globalModules>. Добавьте две строки, приведенные ниже, в коллекцию – скопируйте их из временного документа, используемого ранее для сохранения стандартных элементов коллекции. Они загружают модуль обработки статических файлов, который служит для обработки запросов для статических файлов, и модуль анонимной аутентификации, который создает стандартный маркер аутентификации для запроса:

<globalModules>

    <add name="StaticFileModule" image="%windir%\System32\inetsrv\static.dll" />

    <add name="AnonymousAuthenticationModule" image="%windir%\System32\inetsrv\authanon.dll" />

</globalModules>

3. Перейдите к разделу <system.webServer>/<modules>. Включите обработчик статических файлов и режимы анонимной аутентификации, добавив следующие строки:

<modules>

    <add name="AnonymousAuthenticationModule" />

    <add name="StaticFileModule" />

</modules>

4. Перейдите к разделу <system.webServer>/<handlers>. Отобразите обработчик статических файлов на все запросы файлов, добавив следующую строчку:

<handlers>

    <add name="StaticFile" path="*" verb="GET,HEAD"  modules="StaticFileModule" resourceType="Either" requireAccess="Read"/>

</handlers>

5. Сохраните файл applicationHost.config.

6. Откройте Internet Explorer и сделайте запрос к следующему URL:

https://localhost/iisstart.htm

Будет обслужен запрошенный документ. Мы успешно включили функцию обработки статических файлов на сервере.

7. Далее запросите перечисление содержимого директории, сделав запрос к следующему URL:

https://localhost

Вы получим пустой ответ, поскольку в данный момент не загружен, не включен и не сопоставлен ни один обработчик, который могу бы обработать перечисление содержимого директории – будет отправлен пустой ответ (200 OK). В следующей задаче мы добавив данный обработчик.

Включение функции перечисления содержимого директории на сервере

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

1. С помощью текстового редактора откройте

%windir%\system32\inetsrv\config\applicationHost.config.

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

<globalModules>

    <add name="AnonymousAuthenticationModule" image="%windir%\system32\inetsrv\authanon.dll" />

    <add name="StaticFileModule" image="%windir%\system32\inetsrv\static.dll" />

    <add name="DirectoryListingModule" image="%windir%\System32\inetsrv\dirlist.dll" />

</globalModules>

<modules>

    <add name="AnonymousAuthenticationModule" />

    <add name="StaticFileModule" />

    <add name="DirectoryListingModule" />

</modules>

<handlers>

    <add name="StaticFile" path="*" verb="GET,HEAD" modules="StaticFileModule,DirectoryListingModule"  resourceType="Either" requireAccess="Read" />

</handlers>

В этом пункте мы включили функцию перечисления содержимого директории на сервере. Однако, данная функция предоставляет дополнительную конфигурацию для обеспечения безопасности, которая определяет возможно ли перечисление содержимого директории. Эта конфигурация указана в разделе <system.webServer>/<directoryBrowse>.

3. Измените запись на:

<directoryBrowse enabled="true" />

4. Сохраните файл applicationHost.config.

5. Откройте Internet Explorer и повторите запрос к директории с помощью следующего URL:

https://localhost

Будет перечислено содержимое директории. Мы успешно включили функцию перечисления содержимого директории на сервере.

Далее мы добавим службы аутентификации и авторизации для защиты контента на сервере от неавторизованного доступа.

Защита ресурсов с помощью URL Authorization

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

1. С помощью текстового редактора откройте

%windir%\system32\inetsrv\config\applicationHost.config.

2. На этот раз мы добавим два модуля:

  • Модуль базовой аутентификации, который обеспечивает поддержку схемы базовой аутентификации по http1.1 вместо учетных данных Windows сервера.
  • Модуль авторизации URL, который поддерживает правила роли и пользователя на основании управления доступом.

3. Чтобы добавить эти модули, добавьте загрузочную запись модуля в раздел <system.webServer>/<globalModules>, и затем включите модуль в разделе <system.webServer>/<modules>, как мы делали ранее для обработчика статических файлов и просмотра директорий.

Примечание: На этот раз нам не надо ничего добавлять в раздел <system.webServer>/<handlers>, поскольку эти модули не предоставляют обработку запросов – они только предоставляют сервис для всех запросов. Ваша заключительная конфигурация, после добавления соответствующих записей, будет выглядеть вот так:

<globalModules>


    <add name="AnonymousAuthenticationModule" image="%windir%\system32\inetsrv\authanon.dll" /> 
    <add name="StaticFileModule" image="%windir%\system32\inetsrv\static.dll" /> 
    <add name="DirectoryListingModule" image="%windir%\system32\inetsrv\dirlist.dll" /> 
    <add name="UrlAuthorizationModule" image="%windir%\System32\inetsrv\urlauthz.dll" />      <add name="BasicAuthenticationModule"image="%windir%\System32\inetsrv\authbas.dll" /> 
</globalModules> 
 

<modules> 
    <add name="AnonymousAuthenticationModule" /> 
    <add name="StaticFileModule" /> 
    <add name="DirectoryListingModule" /> 
    <add name="BasicAuthenticationModule" /> 
    <add name="UrlAuthorizationModule" /> 
</modules>

Чтобы мы могли использовать добавленные функции, нам нужно их сконфигурировать.

4. Включите службу Basic Authentication. Перейдите к элементу <basicAuthentication> и установите атрибут enabled  в значение true:

<basicAuthentication enabled="true" />

5. Отключите анонимную аутентификацию. Перейдите к элементу <anonymousAuthentication> и установите атрибут enabled  в значение false:

<anonymousAuthentication enabled="false" userName="IUSR" />

Это отключает анонимную аутентификацию и требует, чтобы перед тем, как будет предоставлен доступ, была пройдена успешная аутентификация пользователя с помощью модуля базовой аутентификации.

6. Сохраните файл  applicationHost.config.

7. Откройте Internet Explorer и повторите запрос к директории с помощью следующего URL:

https://localhost

Данный запрос перечислит содержимое директории. Поскольку браузер не аутентифицировал нас, модуль авторизации URL отклонит запрос. Модуль базовой аутентификации перехватит отклонение и вернет браузеру требование базовой аутентификации, указав браузеру отобразить диалоговое окно входа базовой аутентификации.

8. Войдите с неправильным учетными данными. Запрос будет отклонен, и вас попросят снова ввести учетные данные.

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

Заключение

Эта статья раскрывает компонентную природу сервера, исследует предоставленные функции IIS и объясняет, как построить настраиваемый веб-сервер только с теми службами, которые могут понадобиться пользователю.

Перед тем как вернуться к использованию сервера, отмените изменения конфигурации сервера, внесенные в рамках данного пошагового руководства. Если вы ранее создали резервную копию, восстановите ее с помощью команды %windir%\system32\inetsrv\appcmd restore backup initial.