Apache в OpenBSD chroot jail как PIE

THE HOLY BIBLE - King James Version - БИБЛИЯ в Синодальном переводе
"Нас Атакуют!" Изобличи козни лукавого, запрети диаволу

Установка новейшего вебсервера Apache в OpenBSD chroot jail как PIE

Вебсервер Апачи приобрёл заслуженную популярность, обусловленную его качеством разработки, обилием возможностей, масштабируемостью и производительностью. В течение долгого времени ОпенБСД включала в стандартную поставку морально устаревшую, но надёжную и прошедшую тщательный аудит версию вебсервера. Эта версия была более чем достаточна для нужд типового несложного интернет-сайта.

В последних версиях OpenBSD просматривается тенденция замены apache новым сервером nginx. Это наверняка означает что команда разработчиков ОпенБСД прекратит дальнейшую поддержку их собственной старой версии апачи. Меня, как любителя разработки модулей Апачи, такой вариант развития событий не устраивал - мне было необходимо оставить Апачи в составе системы ОпенБСД, сохранив все имеющиеся улучшения в области безопасности и при этом установив последнюю версию Apache 2.4.4, предоставляющую мне доступ к библиотеке APR и новейшим возможностям вебсервера.

В предлагаемой заметке я рассказываю о моём опыте внедрения вебсервера Apache 2.4.4 на OpenBSD 5.3. При этом я сохраняю уже имеющиеся в ОС принципы безопасности вебсервера - раскладку, режимы и владельцев файлов, chroot через system call и сборку в виде position independent executable. Такой подход требует 64-битной версии OpenBSD.

Прежде чем мы продолжим, я хотел бы привести строки из Евангелия:



.................. == От Иоанна святое благовествование == .....................
=== Глава 14, Стих 6 ===
5 Фома сказал Ему: Господи! не знаем, куда идешь; и как можем знать путь?
6 Иисус сказал ему: Я есмь путь и истина и жизнь; никто не приходит к Отцу,
 как только через Меня.
7 Если бы вы знали Меня, то знали бы и Отца Моего. И отныне знаете Его и
 видели Его.

Лично для вас благая весть - Единородный Сын Божий Иисус Христос любит вас, Он взошёл на крест за ваши грехи, был распят и на третий день воскрес, сел одесную Бога и открыл нам дорогу в Царствие Небесное.

Сегодня, в светлый праздник Вознесения Господнего, мы вспоминаем о Его заповедях к нам. И с горечью подводим итоги - как много людей создают себе истуканов и служат им - богатство, власть и гордыня так обуяли нас, что мы уже и готовы забыть всё и всех, продать друзей и родных - лишь бы набить карманы. Как написано в Библии, что в последние времена охладеет любовь - так мы это всё и наблюдаем в нашей ежедневной жизни. Но богатство и гордость не приносят облегчения их рабам - в чём же дело?

А ведь ответ на этот вопрос уже дан - бойся Господа, ненавидя зло и удаляясь греха, поступай по Его заповедям - и получишь гораздо больше того, о чём мечтаешь. Самый главный дар - милость Господня к нам, с которой приходят свобода духовная и добрая слава людская и достаток для жизни. Только не теряй ориентиров в жизни и твёрдо стой на христианских духовных принципах. Где же Он, наш ориентир? Прямо перед вами, дорогой читатель - только откройте Библию, отворите сердце своё, вчитайтесь - и вот Он перед вами, Спаситель Иисус Христос. Именно в этот день, почти 2 тысячи лет назад, Он вознёсся на небо - и с тех самых пор служит нам ориентиром в жизни и светом в ночи - но лишь для тех, кто согласен открыть очи свои и поднять голову вверх, оторвав её от кормушки мирской жадности и алчности ...

Покайтесь, примите Иисуса как вашего Спасителя, ибо наступают последние времена и время близко - стоит Судья у ворот.

Пожалуйста, в своих каждодневных трудах, какими бы занятыми вы себе ни казались - находите время для Бога, Его заповедей и Библии.

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


Вернёмся к нашим техническим деталям.

Итак, для получения работающего вебсервера Apache 2.4.4 на OpenBSD 5.3 мне понадобится:

  • скачать исходный код Apache
  • подготовить код к компиляции, установив нужные параметры
  • скомпилировать, собрать и установить вебсервер
  • отредактировать конфигурационный файл и запустить сервер
  • провести небольшое тестирование производительности
  • Исходный код

    Начнём - скачать код надо с вебсайта Apache. Нам понадобятся httpd, apr и apr-util. Также необходим пакет "pcre" - но его мы скачаем с одного из зеркал OpenBSD. Вот что получилось у меня:

    .......... == Первое соборное послание святого апостола Иоанна == ..............
    === Глава 3, Стих 24 ===
    24 И кто сохраняет заповеди Его, тот пребывает в Нем, и  Он  в  том.  А  что  Он
    пребывает в нас, узнаем по духу, который Он дал нам.
    
    (b+/b-, c+/c-, +/-, *) >
    
    reat $ ls -latrh *gz
    -rw-rw-r--. 1 u1 u1  38M May 13 13:56
    -rw-rw-r--. 1 u1 u1 6.2M Jun 11 17:38 httpd-2.4.4.tar.gz
    -rw-rw-r--. 1 u1 u1 960K Jun 11 17:39 apr-1.4.6.tar.gz
    -rw-rw-r--. 1 u1 u1 848K Jun 11 17:39 apr-util-1.5.2.tar.gz
    -rw-rw-r--. 1 u1 u1 1.1M Jun 11 18:16 pcre-8.31.tgz
    reat $
    ...
    нa OpenBSD сервере я начал с установки "pcre":
    ...
    root:5# pkg_info | grep pcre
    pcre-8.31           perl-compatible regular expression library
    root:6#
    

    Подготовка кода

    Современный Апачи использует скрипт "configure", подготовленный для нас программой Autoconf. Увидеть все доступные параметры конфигурации можно запустив "configure --help". Модули могут быть включены в вебсервер путём статической сборки или загружены динамически. Я предпочитаю статическую сборку, но в приведенном примере я "включаю" в сервер только один модуль - "mod_unixd". Именно этот модуль помогает нам "заключить" рабочие процессы нашего сервера в chroot jail и сменить пользователя после запуска.

    При компиляции и сборке сервера я буду использовать position-independent executable - этот подход усложняет "угадывание" раскладки памяти исполняемых файлов в формате ELF. Также я буду использовать самый старый (но и самый проверенный) MPM модуль "prefork" - для вебсайтов с малым числом посещений именно этот MPM, на мой взгляд, является оптимальным. Сие означает что все процессы вебсервера будут использовать механизм "fork" и не будут использовать "threads". Мне кажется, такой подход позволяет администратору более чётко понять на что расходуются ресурсы системы.

    Очень часто мне приходилось видеть, как люди пытаются задействовать самый "современный" MPM, оптимизируя системные вызовы, их очерёдность и способы получения сообщений - но при этом сам вебсайт использует CGI скрипт, написанный на Perl.

    Мой подход проще - я начинаю оптимизацию написанием своего кода в виде модуля Апачи, статически связанного и работающего непосредственно в адресном пространстве процесса (worker) Apache. А уже потом, после стресс тестирования под нагрузкой, если потребуется, начинаю выбирать более производительный MPM.

    Для конфигурирования я использую такие параметры:

    ......................... == Книга Иисуса Навина == ............................
    === Глава 24, Стих 16 ===
    16 И отвечал народ и сказал: нет, не будет того, чтобы  мы  оставили  Господа  и
    стали служить другим богам!
    17 Ибо Господь -- Бог наш, Он вывел нас  и  отцов  наших  из  земли  Египетской,
    из дома рабства, и делал пред глазами нашими великие знамения  и  хранил  нас
    на всем пути, по которому мы шли, и  среди  всех  народов,  чрез  которые  мы
    проходили.
    
    (b+/b-, c+/c-, +/-, *) >
    
    root:1# cd /usr/src/DC/httpd-2.4.4
    root:2# ./configure --enable-layout=OpenBSD --with-included-apr --enable-pie \
    > --enable-unixd=static --with-mpm=prefork
    ...
    

    Мне было интересно узнать как работает "chroot" процесс и я немного изменил код - если вам это тоже интересно, отредактируйте код модуля "mod_unixd" - в файле "httpd-2.4.4/modules/arch/unix/mod_unixd.c" начиная со строки #162 добавьте:

    if (chroot(ap_unixd_config.chroot_dir) != 0) {
    rv = errno;
    ap_log_error(APLOG_MARK, APLOG_ALERT, errno, NULL, APLOGNO(02160)
    "Can't chroot to %s", ap_unixd_config.chroot_dir);
    return rv;
    } // Начало дополнительного кода
    else {
    ap_log_error(APLOG_MARK, APLOG_ALERT, 0, NULL, APLOGNO(02160)
    "SUCCESS: chroot'ed to %s", ap_unixd_config.chroot_dir);
    } // Конец дополнительного кода
    
    
    if (chdir("/") != 0) {
    rv = errno;
    ap_log_error(APLOG_MARK, APLOG_ALERT, errno, NULL, APLOGNO(02161)
    "Can't chdir to new root");
    return rv;
    } // Начало дополнительного кода
    else {
    ap_log_error(APLOG_MARK, APLOG_ALERT, 0, NULL, APLOGNO(02161)
    "SUCCESS: chdir'd to new root");
    
    } // Конец дополнительного кода
    

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

    root:27# grep -i success /var/www/logs/error_log
    ...
    [... дата ...] [unixd:alert] [pid 11519] : AH02160: SUCCESS: chroot'ed to /var/www
    [... дата ...] [unixd:alert] [pid 11519] : AH02161: SUCCESS: chdir'd to new root
    ...
    root:28#
    

    Это означает что рабочие процессы вебсервера использовали системный вызов "chroot" для смены "корня" файловой системы непосредственно перед запуском каждого из них. При этом конфигурационные файлы были прочитаны основным процессом из обычного каталога "/var/www" и логфайлы были открыты на запись в их стандартном "/var/www/logs".

    Не забудьте убрать эти временные изменения и перекомпилировать вебсервер!

    Компиляция, сборка и установка вебсервера

    Здесь всё просто - "make" с последующим "make install". Обратите внимание на эти два параметра, использованные мной выше при конфигурации кода: --enable-layout=OpenBSD --with-included-apr. Их назначение - расположить конечные файлы в моей системе "по правилам" ОпенБСД и не пытаться найти предустановленную в системе библиотеку APR. Также заметьте, что я компилирую как пользователь "root" - я не хотел убирать ограничения, накладываемые системой OpenBSD по умолчанию на непривилегированных пользователей.

    Необходимо заметить, что в составе "пакетов" и "портов" OpenBSD имеется версия Apache и APR, но меня интересовал процесс компиляции вебсервера из исходного кода. Приведенные в моей заметке шаги вы можете использовать многократно, изменяя конфигурацию Апачи так, как вам нравится. Кроме того, конечный результат нашей компиляции тоже будет отличаться от вебсервера "из пакетов".

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

    ........................ == Книга пророка Варуха == ............................
    === Глава 2, Стих 11 ===
    11 И ныне, Господи, Боже  Израилев,  Ты,  Который  вывел  народ  Твой  из  земли
    Египетской рукою крепкою, и  знамениями,  и  чудесами,  и  силою  великою,  и
    мышцею высокою, и сотворил Себе имя, как сегодня:
    12 согрешили мы, поступали нечестиво,  неправедно  против  всех  уставов  Твоих,
    Господи Боже наш!
    13 Да отвратится от нас ярость  Твоя,  ибо  мало  осталось  нас  среди  народов,
    между которыми Ты рассеял нас.
    
    (b+/b-, c+/c-, +/-, *) >
    
    root:1# cd /var/www/
    root:2# ls -la
    total 72
    drwxr-xr-x  15 root  daemon   512 Jun 13 01:29 ./
    drwxr-xr-x  23 root  wheel    512 Feb 28 10:17 ../
    drwxr-xr-x   2 root  daemon   512 Mar 13 11:07 bin/
    drwxr-xr-x   2 root  daemon   512 Jun 13 03:08 build/
    drwx-----T   2 www   daemon   512 Mar 13 11:06 cache/
    drwxr-xr-x   2 root  daemon   512 Mar 13 11:07 cgi-bin/
    drwxr-xr-x   6 root  daemon   512 Jun 13 16:04 conf/
    drwxr-xr-x   2 root  daemon   512 Jun 13 18:48 dev/
    drwxr-xr-x   3 root  daemon  1024 Jun 12 04:21 error/
    drwxr-xr-x   2 root  daemon   512 Jun 13 01:56 htdocs/
    drwxr-xr-x   3 root  daemon  3584 Mar 13 11:06 icons/
    drwxr-xr-x   2 root  daemon   512 Jun 13 21:14 logs/
    drwxr-xr-x  14 root  daemon  6144 Jun 12 23:12 manual/
    drwxr-xr-x   2 root  daemon   512 Mar 13 11:06 users/
    drwxr-xr-x   3 root  daemon   512 Jun 13 01:29 var/
    root:3# ls -la bin/
    total 2536
    drwxr-xr-x   2 root  daemon     512 Mar 13 11:07 ./
    drwxr-xr-x  15 root  daemon     512 Jun 13 01:29 ../
    ----------   1 root  bin     275664 Mar 13 11:07 bgpctl
    ----------   1 root  bin     238800 Mar 13 11:07 ping
    ----------   1 root  bin     259280 Mar 13 11:07 ping6
    ----------   1 root  bin     210128 Mar 13 11:07 traceroute
    ----------   1 root  bin     210128 Mar 13 11:07 traceroute6
    root:4# which httpd
    /usr/sbin/httpd
    root:5# ls -la /usr/sbin/httpd
    -r-xr-xr-x  1 root bin 1788708 Jun 13 03:08 /usr/sbin/httpd*
    root:6#
    

    Конфигурирование и запуск вебсервера

    Прежде всего нам необходим подходящий конфигурационный файл. Не берите чей-то файл и не копируйте слепо его директивы - потратьте время, прочтите документацию вебсервера! Это время не будет потрачено напрасно. В конце концов, как можно полагаться в своей работе на программу, принцип работы которой тебе неизвестен?

    В качестве практики, прочтите о значении каждой директивы в моём файле.

    ......................... == Третья книга Ездры == .............................
    === Глава 5, Стих 12 ===
    12 Люди  в  то  время  будут  надеяться,  и  не   достигнут   желаемого,   будут
    трудиться, и не управятся пути их.
    
    (b+/b-, c+/c-, +/-, *) >
    
    root:# grep -v "^#" /var/www/conf/httpd.conf | egrep -v "(^$|\ *#)"
    ServerRoot "/var/www"
    Listen 80
    LoadModule   authz_core_module  /usr/lib/apache/modules/mod_authz_core.so
    LoadModule   authz_host_module  /usr/lib/apache/modules/mod_authz_host.so
    LoadModule   dir_module         /usr/lib/apache/modules/mod_dir.so
    LoadModule   status_module      /usr/lib/apache/modules/mod_status.so
    LoadModule   info_module        /usr/lib/apache/modules/mod_info.so
    LoadModule   log_config_module  /usr/lib/apache/modules/mod_log_config.so
    
    User www # Последующие 3 директивы очень важны
    Group www
    ChrootDir /var/www
    
    # С этого момента мы будем использовать "новый" DocumentRoot, т.е.
    # /var/www/var/www/htdocs,который для chroot процессов выглядит как
    # /var/www/htdocs :-)
    #root:# ls -la /var/www/var/www/
    #total 12
    #drwxr-xr-x  3 root  daemon  512 Jun 13 01:33 ./
    #drwxr-xr-x  3 root  daemon  512 Jun 13 01:29 ../
    #drwxr-xr-x  4 root  daemon  512 Jun 13 01:46 htdocs/
    #root:#
    
    ServerAdmin admin@read-and-think.org
    ServerName obsd64.read-and-think.org:80
    ServerLimit 10 # Моя система имеет одно ядро :-)
    MaxRequestWorkers 10 # Необязательно при наличии ServerLimit
    MaxConnectionsPerChild 1000
    KeepAlive Off
    LimitRequestBody 4096
    LimitRequestFieldSize 1024
    LimitRequestLine 200
    <Directory />
    AllowOverride none
    Require all denied
    <Limit POST PUT DELETE>
    Require ip 192.168.56.0/255.255.255.0
    </Limit>
    </Directory>
    DocumentRoot "/var/www/htdocs"
    <Directory "/var/www/htdocs">
    Options Indexes FollowSymLinks
    AllowOverride None
    Require all granted
    </Directory>
    <Directory "/var/www/manual">
    DirectoryIndex index.html.en
    AllowOverride None
    Options Indexes FollowSymLinks
    Require all granted
    </Directory>
    <IfModule dir_module>
    DirectoryIndex index.html.en index.html
    </IfModule>
    <Files ".ht*">
    Require all denied
    </Files>
    <Location /server-status>
    SetHandler server-status
    Require local
    Require ip 192.168.56.0/255.255.255.0
    </Location>
    <Location /server-info>
    SetHandler server-info
    Require local
    Require ip 192.168.56.0/255.255.255.0
    </Location>
    ErrorLog "logs/error_log"
    LogLevel crit
    <IfModule log_config_module>
    LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
    LogFormat "%h %l %u %t \"%r\" %>s %b" common
    <IfModule logio_module>
    LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" %I %O" combinedio
    </IfModule>
    CustomLog "logs/access_log" combined
    </IfModule>
    <IfModule mime_module>
    TypesConfig conf/mime.types
    AddType application/x-compress .Z
    AddType application/x-gzip .gz .tgz
    </IfModule>
    EnableSendfile on
    <IfModule userdir_module>
    UserDir disabled
    </IfModule>
    <IfModule ssl_module>
    SSLRandomSeed startup builtin
    SSLRandomSeed connect builtin
    </IfModule>
    root:#
    

    Ваши страницы, публикуемые в интернете через этот вебсервер, помещайте в директорию "/var/www/var/www/htdocs". Ручной запуск вебсервера производим так же, как и в стандартной поставке OpenBSD. Для автоматического старта Апачи при загрузке ОС просто включите опцию 'httpd_flags=""' в файле "/etc/rc.conf" или (предпочтительно) "/etc/rc.conf.local".

    ..................... == Книга Премудрости Соломона == .........................
    === Глава 6, Стих 17 ===
    17 Начало       ее       есть       искреннейшее       желание           учения,
    18 а  забота  об  учении  -  любовь,  любовь  же  -  хранение  законов   ее,   а
    наблюдение законов - залог бессмертия,
    19 а бессмертие приближает к Богу;
    20 поэтому      желание      премудрости      возводит      к           царству.
    
    (b+/b-, c+/c-, +/-, *) >
    
    root:# apachectl start
    root:# apachectl -S
    VirtualHost configuration:
    ServerRoot: "/var/www"
    Main DocumentRoot: "/var/www/htdocs"
    Main ErrorLog: "/var/www/logs/error_log"
    Mutex mpm-accept: using_defaults
    Mutex default: dir="/var/www/logs/" mechanism=default
    PidFile: "/var/www/logs/httpd.pid"
    Define: DUMP_VHOSTS
    Define: DUMP_RUN_CFG
    User: name="www" id=67
    Group: name="www" id=67
    ChrootDir: "/var/www"  -- Важно!
    root:# apachectl -M
    Loaded Modules:
    core_module (static)
    so_module (static)
    http_module (static)
    mpm_prefork_module (static)
    unixd_module (static)
    authz_core_module (shared)
    authz_host_module (shared)
    dir_module (shared)
    status_module (shared)
    info_module (shared)
    log_config_module (shared)
    root:#
    

    После запуска проверьте записи в логфайле:

    .......... == Первое соборное послание святого апостола Иоанна == ..............
    === Глава 5, Стих 13 ===
    13 Сие написал я вам, верующим во  имя  Сына  Божия,  дабы  вы  знали,  что  вы,
    веруя в Сына Божия, имеете жизнь вечную.
    
    (b+/b-, c+/c-, +/-, *) >
    
    root:# tail -20 /var/www/logs/error_log
    [. дата .] [mpm_prefork:notice] [pid 7839] AH00163: \
    Apache/2.4.4 (Unix) configured -- resuming normal operations
    [. дата .] [core:notice] [pid 7839] AH00094: Command line: '/usr/sbin/httpd'
    ...
    root:# ps -axcj | grep http
    root      7839     1  7839 fffffe8054b0b480    0 Ss    ??    0:00.02 httpd
    www      10206  7839  7839 fffffe8054b0b480    0 I     ??    0:00.00 httpd
    www       4311  7839  7839 fffffe8054b0b480    0 I     ??    0:00.00 httpd
    www      25649  7839  7839 fffffe8054b0b480    0 I     ??    0:00.00 httpd
    www       2283  7839  7839 fffffe8054b0b480    0 I     ??    0:00.00 httpd
    www       7845  7839  7839 fffffe8054b0b480    0 S     ??    0:00.00 httpd
    root:#
    

    Как видим, только самый первый процесс с номером 7839 запущен от имени суперпользователя и имеет полный доступ к файловой системе, но он не принимает ввод от пользователей. Запросы от веббраузеров обслуживают 5 "дочерних" процессов, "заключённых" в chroot jail и не имеющих возможности покинуть её, поскольку эти процессы запущены от имени пользователя без привилегий и могут видеть только файлы внутри "/var/www" (которая для них выглядит как "/").

    Проверим базовую функциональность нашего сервера.

    .......... == Второе послание к Тимофею святого апостола Павла == ..............
    === Глава 3, Стих 2 ===
    2 Ибо  люди  будут  самолюбивы,  сребролюбивы,   горды,   надменны,   злоречивы,
    родителям непокорны, неблагодарны, нечестивы, недружелюбны,
    3 непримирительны,  клеветники,  невоздержны,  жестоки,   не   любящие    добра,
    4 предатели,  наглы,  напыщенны,   более   сластолюбивы,   нежели    боголюбивы,
    5 имеющие  вид  благочестия,  силы  же  его   отрекшиеся.   Таковых    удаляйся.
    
    (b+/b-, c+/c-, +/-, *) >
    
    root:# apachectl status
    
    Apache Server Status for localhost (via 127.0.0.1)
    
    Server Version: Apache/2.4.4 (Unix)
    Server Built: Jun 13 2013 03:07:30
    __________________________________________________________________
    
    Current Time: Thursday, 13-Jun-2013 13:51:11 GMT
    Restart Time: Thursday, 13-Jun-2013 13:34:44 GMT
    Parent Server Config. Generation: 1
    Parent Server MPM Generation: 0
    Server uptime: 16 minutes 27 seconds
    Server load: 0.09 0.09 0.08
    Total accesses: 0 - Total Traffic: 0 kB
    CPU Usage: u0 s0 cu0 cs0
    0 requests/sec - 0 B/second -
    1 requests currently being processed, 4 idle workers
    
    W____.....
    
    Scoreboard Key:
    "_" Waiting for Connection, "S" Starting up, "R" Reading Request,
    "W" Sending Reply, "K" Keepalive (read), "D" DNS Lookup,
    "C" Closing connection, "L" Logging, "G" Gracefully finishing,
    "I" Idle cleanup of worker, "." Open slot with no current process
    root:#
    

    Тестирование производительности

    Апачи сам по себе значительно упрощает процесс тестирования. Всё, что мы должны сделать, это запустить поставляемую в составе вебсервера программу "ab". Я хочу создать некое подобие очереди из пользователей (что не должно быть сложно на моём одно-ядерном процессоре) - поэтому и использую 20 одновременно работающих виртуальных пользователей.

    Полностью команда выглядит так:
    ab -c 20 -t 600 -n 9999999 http://192.168.56.100/index.html
    

    Пока тестирование продолжается, я слежу за параметрами системы:

    systat output:
    =================
    3 users    Load 2.27 1.93 1.13                     Thu Jun 13 16:16:02 2013
    
    memory totals (in KB)            PAGING   SWAPPING     Interrupts
    real   virtual     free           in  out   in  out      111 total
    Active    49716     49716  1050092   ops                            100 clock
    All      295812    295812  1133176   pages                           11 pciide0
    em0
    Proc:r  d  s  w    Csw   Trp   Sys   Int   Sof  Flt     2 forks
    1    11      3512  4056 90035     8 18424 2307       fkppw
    fksvm
    0.6%Int  95.0%Sys   0.0%Usr   0.0%Nic   4.4%Idle       pwait
    |    |    |    |    |    |    |    |    |    |    |       relck
    ================================================          rlkok
    noram
    Namei         Sys-cache    Proc-cache    No-cache     143 ndcpy
    Calls     hits    %    hits     %    miss   %         fltcp
    66443    66443  100                                40 zfod
    126 cow
    Disks   wd0   wd1   cd0                             11215 fmin
    seeks                                               14953 ftarg
    xfers    11                                               itarg
    speed  176K                                             1 wired
    sec   0.0                                               pdfre
    pdscn
    pzidle
    10 kmapent
    
    
    
    18262 IPKTS
    18262 OPKTS
    

    Становится очевидным, что мне нужен более мощный процессор, и не один. Тем не менее посмотрим на результаты - насколько же действительно плоха производительность старого "prefork" MPM на маломощной машине?

    ......................... == Третья книга Царств == ............................
    === Глава 19, Стих 10 ===
    9 И вошел он там в пещеру и ночевал в ней. И вот, было к  нему  слово  Господне,
    и сказал ему _Господь:_ что ты здесь, Илия?
    10 Он  сказал:  возревновал  я  о  Господе  Боге  Саваофе,  ибо  сыны  Израилевы
    оставили завет  Твой,  разрушили  Твои  жертвенники  и  пророков  Твоих  убили
    мечом; остался я один, но и моей души ищут, чтобы отнять ее.
    
    (b+/b-, c+/c-, +/-, *) >
    
    root:1# apachectl status
    
    Apache Server Status for localhost (via 127.0.0.1)
    
    Server Version: Apache/2.4.4 (Unix)
    Server Built: Jun 13 2013 03:07:30
    __________________________________________________________________
    
    Current Time: Thursday, 13-Jun-2013 16:14:49 EST
    Restart Time: Thursday, 13-Jun-2013 16:04:56 EST
    Parent Server Config. Generation: 1
    Parent Server MPM Generation: 0
    Server uptime: 9 minutes 53 seconds
    Server load: 2.25 1.83 1.02
    Total accesses: 872063 - Total Traffic: 1.8 GB
    CPU Usage: u.02 s.95 cu0 cs0 - .164% CPU load
    1470 requests/sec - 3.2 MB/second - 2268 B/request
    10 requests currently being processed, 0 idle workers
    
    CCCCCCCCCW
    
    Scoreboard Key:
    "_" Waiting for Connection, "S" Starting up, "R" Reading Request,
    "W" Sending Reply, "K" Keepalive (read), "D" DNS Lookup,
    "C" Closing connection, "L" Logging, "G" Gracefully finishing,
    "I" Idle cleanup of worker, "." Open slot with no current process
    root:2#
    

    Что мы видим? Наш простой "форкающийся" сервер обслуживает 1470 запросов в секунду, каждый из которых - страница размером 2Кб (что далеко не одна строка "It Works!"). За 5 секунд система делает 90035 системных вызовов, из которых 3512 переключений контекста (4%). Вполне неплохо для MPM, неиспользующего threads. Это подтверждает правильность моего начального выбора MPM "prefork".

    Что же покажет нам "ab" в конце тестирования?

    AB output
    ==========
    Benchmarking 192.168.56.100 (be patient)
    Completed 999999 requests
    Finished 1060693 requests
    
    
    Server Software:        Apache/2.4.4
    Server Hostname:        192.168.56.100
    Server Port:            80
    
    Document Path:          /index.html
    Document Length:        2268 bytes                      ---1--
    
    Concurrency Level:      20                       ---2--
    Time taken for tests:   600.001 seconds
    Complete requests:      1060693
    Failed requests:        0                        ---3--
    Write errors:           0
    Total transferred:      2640064877 bytes
    HTML transferred:       2405651724 bytes
    Requests per second:    1767.82 [#/sec] (mean)          ---4--
    Time per request:       11.313 [ms] (mean)
    Time per request:       0.566 [ms] (mean, across all concurrent requests)
    Transfer rate:          4296.97 [Kbytes/sec] received
    
    Connection Times (ms)
    min  mean[+/-sd] median   max
    Connect:        0    0   0.4      0      11
    Processing:     3   11  13.7     10     741
    Waiting:        1    9  13.8      9     741
    Total:          3   11  13.8     10     741
    
    Percentage of the requests served within a certain time (ms)
    50%     10
    66%     10
    75%     11
    80%     11
    90%     14
    95%     15
    98%     16
    99%     18                       ---5--
    100%    741 (longest request)
    

    Наш сервер "подвергся нашествию" 20-ти (2) пользователей, каждый из которых запрашивал одну страницу размером 2Кб (1), при этом ни один из запросов не завершился неудачно (3). Сервер обслуживал 1767 запросов в секунду (4), около 12 миллисекунд каждый. 99% запросов были полностью завершены в течение 18 миллисекунд (5).

    Несложные подсчёты показывают, что наш очень хилый сервер легко выдержит 155 миллионов хитов в день. Неплохо для системы такого класса и конфигурации. При этом мы сохранили отличительные особенности апача, работающего на системе ОпенБСД, наиболее важной из которых является безопасность вебсервера и его изоляция от остальной системы.

    В заключение

    На мой взгляд, вебсервер Apache остаётся наилучшим выбором для небольшого вебсайта, работающего на ОС OpenBSD. Более того, установка последней версии Апачи предоставляет доступ ко всем новым возможностям программы, сохраняя при этом основные выгоды использования OpenBSD. Легко достигая уровня масштабируемости "сайта-миллионника", Apache может удовлетворить нужды почти любого бизнеса.

    Ну а когда ваш сайт превысит десяток миллионов дневных посещений - вебсервер будет одной из последних проблем, на которые вы захотите тратить деньги :-). Кроме того, за счёт использования "event" MPM (Multi-Processing Module) на современном компьютере возможно достижение очень высоких уровней масштабируемости, при которых основной проблемой станет производительность и эффективность вашего кода, а не вебсервера. И замена Апача на другой сервер при этом не поможет совершенно.

    Спасибо что зашли,

    Будьте благословенны!
    Денис

    13 Июня 2013 года.