• Главная
  • Карта сайта
Не найдено

dkLab | конструктор | dkLab Apache: віртуальні хости з привілеями різних користувачів

  1. Використання
  2. Недоліки стандартного Apache
  3. Як працює dkLab Apache?
  4. Запуск віртуальних хостів під різними користувачами
  5. Віртуальні хости "за шаблоном"
  6. Модуль mod_rewrite, вільний від зациклення
  7. Відомі баги і зауваження
  8. резюме

2007-02-31

Завантажити dkLab Apache:
dklab_apache_34_rew_lim_rus_ssl_vh_fork_2005-12-04.tgz

dkLab Apache - це дистрибутив для тих, хто збирається використовувати Apache в Unix (Linux, FreeBSD і т. д.) для обслуговування декількох незалежних сайтів, що працюють під різними, повністю розмежовані один від одного користувачами Unix. Він позбавлений деяких недоліків, властивих аналогам, наприклад: не вимагає установки додаткових модулів ядра і заборон setuid, коректно і, головне, осмислено працює при включеному KeepAlive і перевищує одиницю MaxRequestsPerChild.

По суті це Apache 1.3.34, на ядро ​​якого накладені деякі "саморобні" патчі. Ось функціональність, яку вони додають:

  • Запуск різних віртуальних хостів під різними Unix-користувачами. Те, під яким користувачем працює віртуальний хост, задається в його стандартних директивах User і Group . Всі скрипти, включаючи скрипти для mod_php, CGI і т. Д., Працюють з правами зазначеного користувача і групи і не можуть отримати доступ до файлів іншого віртуального хоста. Геть safe_mode і проблеми з правами доступу в PHP!
  • Можливість створювати віртуальні хости за шаблоном: abc.example.com -> / home / example / abc. Ви можете посилатися в директиві DocumentRoot на потрібну частину доменного імені, наприклад, так: / home / example / $ - 3+ (в даному прикладі це "розгорнеться" в / home / example / abc). Просто створіть директорію, щоб додати на сайт новий піддомен!
  • Модуль mod_rewrite захищений від будь-якого роду "зациклення". Необережно або зловмисно написані директиви в .htaccess не зможуть захопити всі ресурси CPU і "підвісити" сервер.

У дистрибутив включені також такі популярні модулі:

  • модуль mod_limitipconn для можливості обмеження числа одночасних з'єднань з однієї IP-адреси.
  • модуль mod_charset - "Russian Apache", підтримка роботи з російськомовними кодуваннями.
  • модуль mod_ssl - підтримка протоколу SSL.

Деякі корисні утиліти і приклади конфігурації для масового хостингу ви можете знайти в піддиректорії! CONFIG всередині дистрибутива. Наприклад, для складання зручно використовувати скрипт! CONFIG / configure, він поставить низку додаткових питань і підключить перераховані вище модулі.

Увага! Якщо ви виявили баг в dkLab Apache, або у вас є просто якесь зауваження, то перш, ніж повідомляти про нього в форумі, прочитайте розділ Відомі баги і зауваження . Можливо, там проблема вже описана. Також, якщо ви - досвідчений Сі-Unix програміст, і у вас є якісь ідеї щодо виправлення багів або поліпшення дистрибутива, я буду радий активному (з вашого боку) співпраці, і особливо - надісланим коду.

Використання

dkLab Apache не визначає будь-яких нових директив конфігурації, і його використання має бути інтуїтивно зрозумілим. Наприклад, ось так ви можете завести 2 віртуальних хоста, що працюють під різними Unix-користувачами навіть з mod_php:

лістинг 1

# Limit by-clients resource usage. RLimitCPU 12 12 RLimitNPROC 15 15 RLimitMem 20000000 20000000 # You may freely enable these directives, wow! MaxRequestsPerChild 100 KeepAlive On # Limit the number of connections (standard mod_limitipconn directives). <Files ~ ". *"> MaxConnPerIP 15 NoIPLimit image / * </ Files> # Account dklab.ru <VirtualHost *: 80> ServerName dklab.ru ServerAlias ​​dklab.ru * .dklab.ru User dklab Group dklab # If not present , $ -3 + is interpolated to "www" string. DocumentRoot / home / dklab / domains / $ - 3+ ScriptAlias ​​/ cgi / /home/dklab/domains/$-3+/../../cgi/ ErrorLog / home / dklab / account / log / error_log CustomLog / home / dklab / account / log / access_log common </ VirtualHost> # Account denwer.ru <VirtualHost *: 80> ServerName denwer.ru ServerAlias ​​denwer.ru * .denwer.ru User denwer Group denwer DocumentRoot / home / denwer / domains / $ -3+ ScriptAlias ​​/ cgi / /home/denwer/domains/$-3+/../../cgi/ ErrorLog / home / denwer / account / log / error_log CustomLog / home / denwer / account / log / access_log common </ VirtualHost>

Даний приклад ілюструє відразу 2 операції: прив'язку віртуального хоста до виділеного користувачеві і групі, а також визначення "динамічного" DOCUMENT_ROOT, що обчислюється на основі доменного імені. Тут $ -3 + означає "відрахувати частину справа ($ -) від третьої (3) частини доменного імені і далі (+) і вставити в зазначену позицію". Цей синтаксис докладніше описаний в документації до модуля mod_vhost_alias (Тільки врахуйте, що замість% в dkLab Apache використовується $).

Зверніть ще увагу на те, що якщо висловом $ -3 + не відповідає ніяка частина доменного імені, то замість порожнього рядка підставляється "www". Наприклад, це вірно для імені dklab.ru в прикладі вище - у нього немає "третьої справа частини", а тому запити до dklab.ru йдуть в / home / dklab / domains / www - так само, як і www.dklab.ru .

Недоліки стандартного Apache

Apache - один з найбільш популярних web-серверів в світі. Однак доводиться констатувати, що при організації масового хостингу на цьому сервері розкривається ряд його істотних недоліків, в числі яких:

  1. Неможливість повного розмежування користувачів по віртуальним хостам. Наприклад, хостинг-провайдер може мати на одній і тій же машині кілька сотень різних сайтів, що належать різним користувачам (клієнтам). Один користувач не повинен мати можливість як-небудь втрутитися в роботу іншого: наприклад, він не має права читати чужі файли. В Apache передбачений механізм suEXEC , Проте він працює тільки для CGI-скриптів і повністю непридатний, наприклад, до mod_php (одному з найпопулярніших скриптових модулів для Apache в світі).
  2. Неможливість підміни DOCUMENT_ROOT для "шаблонних" віртуальних хостів. Зазвичай клієнти хочуть мати можливість заводити на своїх сайтах домени третього рівня, не звертаючись при цьому до хостера. Ідеальний варіант виглядає як "власник example.com створив папку abc і тут же отримав домен abc.example.com з DOCUMENT_ROOT в цій папці". Apache, звичайно, має можливість призначати папки доменів виду * .example.com, однак DOCUMENT_ROOT при цьому залишається невірним. (Навіть написавши модуль Apache 1.3, не можна "підмінити" цю змінну оточення.)
  3. Проблема з "зациклення" mod_rewrite. Починаючи з деякої версії, модуль mod_rewrite має механізм захисту від "зациклення" правил (раніше такі "зациклення" вели до повного зависання сервера зі споживанням 100% ресурсів CPU). На жаль, цей захист досі не повна: існують методи все так же "підвісити" Apache, що абсолютно неприпустимо в контексті масового хостингу (один клієнт не повинен мати можливість "вбити" весь сервер).

Уже багато років розробники Apache "закривають очі" на всі ці недоліки. Навіть у версії 2 цієї статті не намітилося більш-менш значних просувань. Складається враження, що вони і не підозрюють, що хтось використовує Apache для обслуговування безлічі сайтів, що належать незалежним клієнтам.

Складається враження, що вони і не підозрюють, що хтось використовує Apache для обслуговування безлічі сайтів, що належать незалежним клієнтам

У той же час, кожен більш-менш великий хостинг-провайдер додає підтримку "багатокористувацької" роботи самостійно, але категорично відмовляється ділитися отриманим результатом з громадськістю. Мабуть, це комерційна таємниця; до того ж, якщо в патчі буде знайдена уразливість, під загрозу ставиться весь хостинг. На щастя, я не працюю в хостинг-компанії, а тому ділюся.

По кожному з наведених вище пунктів є вільно поширювані альтернативи. На жаль, вони все далекі від ідеалу:

  1. Запуск віртуальних хостів під різними користувачами реалізується в модулях: perchild , peruser , mod_diffpriv , mod_suid і деяких інших. На жаль, вони всі мають недоліки: необхідність відключати KeepAlive, або ж встановлювати MaxRequestsPerChild рівним 1, або ж встановлювати додаткові модулі ядра і штучним чином обмежувати доступ до setuid-функцій.

    Директива KeepAlive дозволяє Apache обробляти запити до декількох URL в рамках одного HTTP-з'єднання. Наприклад, якщо ви зайшли на сторінку з 10 картинками, то буде відкрито всього 1 з'єднання з сервером, в яке надійде 11 запитів: 1 - для HTML-коду сторінки і 10 - для картинок. Якщо KeepAlive відключений, браузер буде змушений відкрити 11 з'єднань, що в кілька разів сповільнить відображення сторінки. Директива MaxRequestsPerChild дозволяє одному і тому ж демона Apache обративать послідовно кілька прийшли з'єднань. Таким чином економиться на системних викликах fork: немає потреби створювати нові процеси, коли відбувається чергове з'єднання.

  2. Можливість "динамічного зв'язування" доменів третього рівня з різними директоріями реалізрована, наприклад, в модулі mod_vhost_alias . На жаль, він не може змінювати DOCUMENT_ROOT, так що "шаблонні" хости будуть не такими ж повноправними, як і основний хост.
  3. Як вже говорилося вище, стандартний mod_rewrite бореться з "зациклення", але лише частково.

Як працює dkLab Apache?

Дистрибутив dkLab Apache позбавлений описаних вище недоліків. (Правда, у нього є свої власні, про які поговоримо нижче.)

)

У коді я намагався виділити всі основні зміни в ядрі Apache тегами <dk> ... </ dk>. Якщо ви хочете подивитися код, має сенс спочатку пошукати в ньому саме дані теги як підрядка.

Запуск віртуальних хостів під різними користувачами

Схема обробки запиту в dkLab Apache виглядає так.

  1. При старті демон, слухає запити, виконує системний виклик fork і чекає завершення нащадка, передаючи йому всі вступники сигнали.
  2. Як тільки відбувається чергове з'єднання, його перехоплює дочірній процес демона.
  3. Він розбирає заголовки самого першого запиту в рамках цього з'єднання і визначає, якому віртуальному хосту слід зайнятися обробкою.
  4. Демон викликає setgroups, setgid і setuid і продовжує обробку всіх запитів до закриття з'єднання.
  5. Якщо дочірній процес-демон "вмирає", батьківський демон також завершує свою роботу.

В общем-то, це досить "стандартна" схема для такого роду модулів, за одним важливим винятком: виклик fork відбувається не в момент встановлення нового з'єднання, а в момент ініціалізації нового слухача примірника Apache, причому - вже після більшості ресурсномістких ініціалізацій, які виконує будь-демон Apache при старті. Таким чином, при надходженні нового запиту fork не виконується, що значно прискорює роботу. Крім того, ми можемо вільно використовувати відмінний від одиниці MaxRequestsPerChild, і це дає значний приріст продуктивності! Адже при MaxRequestsPerChild, що дорівнює 1, демон Apache змушений кожного разу виконувати всі свої стартові ініціалізації, в той час як в dkLab Apache при MaxRequestsPerChild, більшому 1, цикл обробки з'єднань виконується вже "після" першої ініціалізації демона і виконання fork.

Адже при MaxRequestsPerChild, що дорівнює 1, демон Apache змушений кожного разу виконувати всі свої стартові ініціалізації, в той час як в dkLab Apache при MaxRequestsPerChild, більшому 1, цикл обробки з'єднань виконується вже після першої ініціалізації демона і виконання fork

Можливо, ви вже задалися питанням: у скільки приблизно раз MaxRequestsPerChild = 1 повільніше, ніж, скажімо, MaxRequestsPerChild = 100. Відповідь - в десятки разів! Якщо не вірите, проведіть свої власні тести і переконайтеся, що рішення, яке потребує обов'язкового MaxRequestsPerChild = 1, взагалі непрацездатних при скільки-небудь високому навантаженні.

Звичайно, ця схема має недоліки: якщо в одному і тому ж поєднанні відбудуться звернення до двох віртуальним хостам, що належать різним користувачам, друге звернення закінчиться помилкою. Тобто в рамках одного з'єднання ми можемо обробляти запити тільки до одного і того ж віртуального хосту. На щастя, всі популярні браузери працюють саме так. (Виняток становлять пошукові роботи, проте, як показала практика, вони також прекрасно "перетравлюють" цю помилку і намагаються виконати запит в новому з'єднанні.)

Наскільки ресурсоемок цей алгоритм? Адже, фактично, він означає, що на кожне з'єднання система виконує зайвий виклик fork. Безумовно, це сповільнює роботу, однак, якщо ви використовуєте dkLab Apache для організації хостингу, а не для віддачі виключно статичних даних сотнями міліонів штук в день, все буде працювати нормально, тим більше що:

  • Fork виконується асинхронно, як це описано вище, і тому не "торозіт" сам запит. Через це візуально затримки не помітно взагалі.
  • У порівнянні зі стандартними витратами на скриптові мови втрати від зайвого fork майже розчиняються. Наприклад, мені відомо, що даний дистрибутив досі успішно працює на досить слабкою машині 2xP1000 з 1 ГБ пам'яті і 2.5 млн хітів на добу (більше 500 хостинг-користувачів з mod_php, perl, ssi і т. Д.).
  • В сучасних Unix-системах fork працює дуже швидко, тому що не копіює в реальності всю пам'ять процесу. Копіювання відбувається лише в момент зміни тієї чи іншої сторінки пам'яті (технологія copy-on-write ).
  • Fork виконується не для кожного запиту, а для кожного KeepAlive-з'єднання. Оскільки в типовому хостингу 90% запитів припадає на статичні файли (картинки), які віддаються в тому ж поєднанні, що і сама сторінка, fork запускається в середньому на 1 раз на 10 запитів (до того ж - асинхронно).

Якщо ви віддаєте статику десятками мільйонів штук в день, значить ви - не хостер, а якийсь великий одиничний проект, і запуск віртуальних хостів під різними користувачами вам абсолютно ні до чого. Використовуйте стандартний Apache.

Віртуальні хости "за шаблоном"

Мої дослідження показали, що можливість повноцінно "підміняти" DOCUMENT_ROOT в залежності від доменного імені неможливо реалізувати за допомогою написання "чистого" модуля Apache. Тому зміни вносилися безпосередньо в ядро, там, де визначається змінна оточення DOCUMENT_ROOT (а також ще подекуди).

Власне, ці шаблони можна використовувати не тільки в директиві DocumentRoot, але також і в будь-який інший, що працює з шляхами - наприклад, ScriptAlias, як продемонстровано в прикладі вище.

Модуль mod_rewrite, вільний від зациклення

Стандартне рішення mod_rewrite запобігає тільки від зациклення при редирект. Однак, якщо, наприклад, запущена команда RewriteRule. - [N], воно не рятує.

Патч в складі dkLab Apache вирішує проблему. Заради справедливості потрібно зауважити, що основна ідея і перша реалізація патча для mod_rewrite належить Дмитру Мельнику. Я лише допрацював її і впровадив в dkLab Apache. Сенс полягає в тому, що в цикл обробки директив mod_rewrite вставляється інкремент деякого лічильника, при переповненні якого обробка завершується і в логи сервера записується повідомлення про помилку. Це гарантовано не дає "підвісити" весь Apache одному конкретно взятому користувачеві.

Відомі баги і зауваження

Природно, dkLab Apache не ідеальний. Він просто цілком стерпно працює (як водиться, нічого при цьому не гарантуючи). Ось відомі на даний момент проблеми, робота над вирішенням яких ведеться в уповільненому режимі (і вже для Apache 2.2).

  • Збільшене споживання ресурсів: додається 1 зайвий fork на кожне надходить KeepAlive-з'єднання. (Цей fork виконується, втім, у фоновому режимі, а не під час вступу з'єднання, що сильно прискорює роботу в порівнянні з іншими рішеннями.) На жаль, навіть в архітектуру Apache 2.2 не закладаються ніяких коштів для розподілу запитів по динамічно створюваним Apache-процесів, тому відхід від цього обмеження в доступному для огляду майбутньому не передбачається.
  • Віддача "порожнього" відповіді при запиті до двох різних віртуальним хостам в рамках одного з'єднання. Знову ж таки, на практиці ця подія неможливо в браузерах, а пошуковики досить розумні, щоб через деякий час повторити запит. (По хорошому, замість порожнього відповіді повинні приходити спеціальні заголовки - Retry-After: 0, Refresh: 0 і 503 Service unavailable, але у мене все не доходять руки це реалізувати. Якщо зробите - надішліть, будь ласка, патч мені.)
  • У деяких директивах mod_rewrite зрідка "спливають" макроси виду $ -3 + при явних підстановках% {DOCUMENT_ROOT} в вирази. Швидше за все, ви з цим не зіткнетеся, тому що випадки вже дуже екзотичні. Але якщо зіткнетеся, то ось один їх способів обходу: створити символьне посилання з ім'ям $ -3 + в папці, де розташована директорія документів віртуального хоста.
  • Іноді виявлялися ситуації, коли після тривалої роботи один з дочірніх процесів демона Apache (httpd) "отщепляют" від кореневого процесу httpd і стає нащадком init. Зараз з достовірною точністю не можна сказати, чи був це демон, реально обробляє запит, або його "чекає пара". Але можна впевнено сказати одне: якщо щоночі після ротації логів влаштовувати повний перезапуск apache, дана проблема не повторюється ніколи. (Я підозрюю, що тут біда з якимось пропущеним перехопленням longjmp. Взагалі-то, патч перехоплює виклики longjmp, але, можливо, не всі. Я не зміг більше нічого розкопати. І ще одне: в Apache 2.2 ніяких longjmp немає, тому дана проблема там, швидше за все, не могла б виникнути навіть теоретично.)
  • Sometimes after very long Apache uptime you may watch a "chip off" httpd daemon as a child of init process. Seems there is a bug in setjmp / longjmp processing somewhere (jongjmp is handled in dkLab Apache, but possibly not fully successful). But if you restart Apache nightly after log rotation you will be guaranteed avoided of this problem.
  • Поставляється дистрибутив Apache з уже накладеними патчами, а не тільки самі ці патчі. На жаль, так вийшло історично - виділити окремий патч зараз досить важко, тому що mod_ssl також накладається на дистрибутив Apache у вигляді патча, і відрізнити одне від іншого - велика робота. Втім, якщо ви це зробите і надішлете сюди вийшов патч, все будуть вам тільки вдячні.
  • Поки що dkLab Apache працює тільки з Apache 1.3, проте в бущущем серйозно розвивати цю гілку не планується. Замість цього розробка повинна зосередитися на Apache 2.2 - у нього значно більше струнка внутрішня архітектура.

резюме

Якщо ви збираєтеся відкрити власний хостинг, але не хочете при цьому зв'язуватися з cPanel і іншими системами, розмежовують хостинг-користувачів "аби-як", dkLab Apache дозволить вам легко це зробити. Він також стане в нагоді, якщо ви маєте кілька різних проектів на одній машині, але не хочете, щоб злом одного з них ставив під загрозу інший.

За фактом dkLab Apache досить стабільний, щоб назвати його production-версією: на ньому вже багато років працюють кілька навантажених серверів (зокрема, сервер dklab.ru ).

І Останнє. Примерно Чотири роки тому я віклав деякі Ідеї, покладені в основу dkLab Apache, в статті. Ця стаття пролежала у відкритому доступі всього 2 тижні (після чого хостинг-провайдер, який використовує в той час патч, попросив її прибрати), але і за цей час вона "витекла" на безліч інших серверів. Там, до речі, була вразливість в безпеці, яка вже давним-давно виправлена ​​в dkLab Apache. Так що - користуйтеся на здоров'я, на цей раз - готовим дистрибутивом!


Як працює dkLab Apache?
Наскільки ресурсоемок цей алгоритм?
Провайдеры:
  • 08.09.2015

    Batyevka.NET предоставляет услуги доступа к сети Интернет на территории Соломенского района г. Киева.Наша миссия —... 
    Читать полностью

  • 08.09.2015
    IPNET

    Компания IPNET — это крупнейший оператор и технологический лидер на рынке телекоммуникаций Киева. Мы предоставляем... 
    Читать полностью

  • 08.09.2015
    Boryspil.Net

    Интернет-провайдер «Boryspil.net» начал свою работу в 2008 году и на данный момент является одним из крупнейших поставщиков... 
    Читать полностью

  • 08.09.2015
    4OKNET

    Наша компания работает в сфере телекоммуникационных услуг, а именно — предоставлении доступа в сеть интернет.Уже... 
    Читать полностью

  • 08.09.2015
    Телегруп

    ДП «Телегруп-Украина» – IT-компания с 15-летним опытом работы на рынке телекоммуникационных услуг, а также официальный... 
    Читать полностью

  • 08.09.2015
    Софтлинк

    Высокая скоростьМы являемся участником Украинского центра обмена трафиком (UA — IX) с включением 10 Гбит / сек... 
    Читать полностью