Всем привет!

Некоторое время назад ко мне обратился один мой хороший знакомый с внезапно образовавшейся у него проблемой и попросил помочь в её решении. Проблема заключалась в следующем: организация, в которой он работал, имела у себя Windows-сервер с поднятым на нём почтовиком MDaemon от компании Alt-N Technologies. Пару лет назад на этот почтовик был установлен SSL-сертификат StartSSL от компании StartCom. И всё работало вполне себе нормально, каши не просило, как вдруг от StartCom пришло грустное письмо, информирующее о том, что скоро всем их сертификатам придёт полный и безоговорочный кирдык. Мол, спасайтесь — кто может, пока не бомбануло. Сегодня я расскажу вам, как мы спасались — глядишь, кому-нибудь эта информация окажется полезной.

Немного лирики


Что перво-наперво приходит в голову нормальному человеку, когда ему задают вопрос про замену сертификата? Вариантов два: или — а почему бы вам не купить его? Или — так есть же замечательная артель Let's Encrypt, которая бесплатно раздаёт сертификаты направо и налево! Первый вариант был смущённо отвергнут как несостоятельный, ввиду того, что, как было сказано ранее, сервер работал, каши не просил, и объяснять руководству, почему оно должн�� расстаться с энной суммой вечнозелёных денег желания не было никакого. Второй вариант был просто суперпривлекательным, но на горизонте маячили кое-какие проблемы, которые предстояло объехать: оконность почтовика наводила на грустные размышления о его совместимости со скриптами LetsEncrypt, а получать и устанавливать сертификат вручную каждые три месяца совершенно не хотелось.

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

Начали мы, естественно, с перекапывания великого и ужасного Интернета в поисках уже готового решения. И, о чудо! Оказалось, что доблестные программисты из Alt-N Technologies уже озаботились этим и выдали на-гора скрипты, делающие всё что нужно! Как говорится — снимаю шляпу! Но и тут не обошлось без ложки дёгтя: эти скрипты просто так всем и каждому не раздавались, а были включены в состав последних версий MDaemon. Однако наш подопечный сервер имел на борту довольно старую версию MDaemon — 13.6.3. Софт был совершенно легальный, купленный некогда за самые что ни на есть настоящие деньги, работал замечательно и его апгрейд в планы руководства конечно же не входил (см. пункт про покупку сертификата).

Поэтому было принято решение попытаться хирургическим путём пересадить скрипты из новой версии MDaemon в старую и заставить их там заработать. Подумано — сделано: на виртуальную машину была установлена самая свежая на тот момент триальная версия MDaemon и из неё изъята папка LetsEncrypt со всем содержимым. Что теперь делать с этим добром? — читайте ниже.

Исходные данные


  • Сервер под управением ОС Windows Server 2008 R2.
  • Почтовый сервер MDaemon версии 13.6.3.
  • На этом же сервере поднят IIS, обслуживающий корпоративный сайт организации.
  • MDaemon использовал собственный встроенный WEB-сервер WorldClient, который был доступен из интернета через порт 3000.

Обязательные требования


Как было написано в этой статье, скрипты LetsEncrypt для MDaemon не являются абсолютно универсальными и предполагают выполнение следующих обязательных условий:

  • Наличие оболочки PowerShell версии 3.0.
  • Наличие установленного фреймворка Microsoft .NET версии не ниже 4.0.
  • Наличие установленного пакета IIS Management Scripts and Tools.
  • Из интернета через порт 80 должен быть доступен WorldClient сервера — либо напрямую, либо через IIS.

Как видим — часть из этих требований исходно не выполнялась, поэтому сначала была выполнена привязка WorldClient к IIS с целью пересадки его на порт 80. Информация о том, как это сделать была получена из вот этой статьи с сайта Alt-N.

Пара слов о «граблях»


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

Во-первых, практически в самом начале скрипта была реализована проверка на то, что параметр 'EnableWCServer' в файле 'Mdaemon.ini' установлен в 'Yes'. И если это было не так, то скрипт немедленно завершал свою работу с выдачей сообщения о критической о��ибке 'Error: WorldClient must be enabled'. Но, как это ни странно, в нашем случае этот параметр был установлен в 'No' — несмотря на то, что нами уже была выполнена привязка WorldClient к IIS и WorldClient прекрасно открывался из интернета. Недолго думая, мы отключили эту проверку, закомментарив её в скрипте. Это позволило скрипту продолжить работу.

Во-вторых, на этом же сервере был поднят корпоративный сайт и к кое-каким страницам этого сайта доступ выполнялся по протоколу https с использованием самоподписанного сертификата. А старые Windows-сервера предполагают, что к одному IP может быть привязан только один сертификат. Мы наступили на эти грабли в самом конце пути — когда сертификат от LE уже успешно получался, но никак не мог прибиндиться к адресу 0.0.0.0. В итоге проблема была решена быстрым, но несколько кривоватым способом: WorldClient был отсажен на отдельный IP-адрес (благо он был в наличии) и опять же пришлось править скрипт — в список его входных параметров был добавлен IP-адрес, к которому нужно было привязывать сертификат. А так как привязка WorldClient к IIS была уже полностью выполнена, то мы не стали запускать собственный WEB-сервер MDaemon-а и оставили всё как есть.

Поехали.

Часть 1: предварительная подготовка


  1. Любым известным вам способом делаем бакап сервера!
  2. Устанавливаем .NET версии выше или равной 4.0.
  3. Добавляем Role Services: идём в 'Control Panel' -> 'Administrative Tools' -> 'Server Manager' -> 'Roles' и нажимаем на линк 'Add Role Services'.

    Ставим крыжики на:
    • Web Server/Application Development/ISAPI Extensions
    • Web Server/Application Development/ISAPI Filters
    • Management Tools/IIS Management Scripts and Tools

    Нажимаем 'Next', ну и так далее.
  4. Устанавливаем Windows Management Framework 3.0 — это установит в систему PowerShell версии 3.0 (см. раздел 'Обязательные требования'):
    • Скачиваем WMF 3.0 с сайта Microsoft.
    • Устанавливаем нужный WMF. Для Windows Server 2008 R2 это 'Windows6.1-KB2506143-x64.msu'.
    • Перезагружаем сервер.


Часть 2: создание в IIS сайта для доступа к серверу WorldClient


Примечание 1: если у вас используется встроенный в MDaemon сервер WorldClient и он уже монопольно сидит на порту 80, то можете смело пропустить эту часть и перейти сразу к части 3.

Примечание 2: 'Host name' сайта должно быть таким-же, как полное доменное имя хоста MDaemon, по которому он доступен из интернета.

Чтобы узнать полное доменное имя хоста MDaemon: запускаем GUI Mdaemon, идём в меню: 'Настройка' -> 'Первичный домен/серверы' -> 'Домен и серверы по умолчанию' -> 'Домен' и смотрим поле 'Полное доменное имя хоста'.

Итак, приступим. Запускаем IIS-менеджер и добавляем в нём новый сайт:

  1. В поле 'Site name' вводим название сайта — какое нравится.
  2. В поле 'Physical path' вводим путь к папке HTML World-клиента.
  3. В поле 'Host name' прописываем полное доменное имя хоста (см. примечание 2 выше).
  4. В поле 'IP-address' оставляем 'All unassigned', если интерфейс используется монопольно, или выбираем из списка IP, при��адлежащий почтовику.
  5. Поля 'Type' и 'Port' оставляем как есть — 'http' и '80', соответственно.

Редактируем список дефолтных документов сайта - заходим в подраздел 'Default Document':


  1. Очищаем весь список.
  2. Добавляем документ 'WorldClient.dll': в правой панели 'Actions' нажимаем 'Add...' и в поле 'Name' набираем 'WorldClient.dll'.
  3. Добавляем документ 'MDSyncML.dll': в правой панели 'Actions' нажимаем 'Add...' и в поле 'Name' набираем 'MDSyncML.dll'.
  4. Ставим 'WorldClient.dll' первым в списке: выделяем его и нажимаем 'Move Up' в правой панели 'Actions'.

Переходим в раздел 'Handler Mappings':


  1. Редактируем 'Feature Permissions': в правой панели 'Actions' нажимаем на 'Edit Feature Permissions...' и ставим все крыжики - 'Read', 'Script' и 'Execute'.
  2. Находим в списке 'ISAPI-dll' и заходим в него.

  3. В поле 'Request path' пишем 'WorldClient.dll'.
  4. В списке 'Module' выбираем 'IsapiModule'.
  5. В поле 'Executable (optional)' указываем путь к WorldClient.dll.
  6. Добавляем новый обработчик: в правой панели 'Actions' нажимаем 'Add Module Mapping...'

  7. В поле 'Request path' пишем 'MDSyncML.dll'.
  8. В списке 'Module' выбираем 'IsapiModule'.
  9. В поле 'Executable (optional)' указываем путь к MDSyncML.dll.
  10. В поле 'Name' пишем что-нибудь членораздельное. Например, 'SyncML-ISAPI'.

Редактируем 'MIME Types' - если этого не сделать, то робот LetsEncrypt не сможет получить от нас файл без расширения:


  1. Переходим в раздел 'MIME Types'.
  2. В правой панели 'Actions' нажимаем 'Add...'.
  3. В поле 'File name extension' пишем точку.
  4. В поле 'MIME type' пишем 'text/plain'.

Редактируем 'Application Pool', автоматически созданный при создании нашего сайта:


  1. Идём в 'Application Pools' -> 'MDaemon WorldClient' -> 'Advanced Settings...'.
  2. В секции 'Process Model' меняем 'Identity' на 'Network Service'.
  3. Если операционка — 64-разрядная, то в секции 'General' меняем 'Enable 32-Bit Applications' на 'True'.

Закрываем консоль. IIS настроен.

Далее, даём пользователям 'IUSR' и 'NETWORK SERVICE' полный доступ к папке MDaemon:

  1. Идём в проводник, открываем 'Properties' папки 'MDaemon', переходим на закладку 'Security', нажимаем 'Edit'.
  2. Нажимаем 'Add' -> 'Advanced' -> 'Find Now' — выделяем в списке 'Search Results' пользователя 'IUSR', нажимаем 'OK'.
  3. Ставим крыжик 'Full control' в списке 'Permissions for IUSR'.
  4. Нажимаем 'Add' -> 'Advanced' -> 'Find Now' — выделяем в списке 'Search Results' пользователя 'NETWORK SERVICE', нажимаем 'OK'.
  5. Ставим крыжик 'Full control' в списке 'Permissions for NETWORK SERVICE'.
  6. Закрываем оба окна нажатием на 'OK'.

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

Часть 3: установка и настройка скриптов LetsEncrypt


  1. Скачиваем архив со скриптами отсюда и распаковываем его в корень папки 'MDaemon'. Важное примечание: в скрипте основной сервер LetsEncrypt заменён на тестовый — чтобы предотвратить бан из-за многократных попыток получить сертификат во время процесса отладки. В следующей части будет написано — как переключиться на основной сервер.
  2. Дописываем в переменную окружения 'PSModulePath' путь к модулям, используемым скриптом:


    • Идём в 'Control Panel' -> 'System' -> 'Advanced system settings' -> 'Advanced' -> 'Environment Variables'.
    • Ищем в списке 'System Variables' переменную 'PSModulePath'.
    • Дописываем через ';' в её конец путь к папке 'Modules', находящейся внутри папки 'LetsEncrypt'. В моём случае такой: 'c:\MDaemon\LetsEncrypt\Modules\'
    • Перелогиниваемся.
  3. Запускаем консоль cmd.
  4. Запускаем скрипт letsencrypt.ps1 командой:

    powershell -ExecutionPolicy ByPass -File c:\mdaemon\letsencrypt\letsencrypt.ps1
    Здесь параметром 'File' задаётся путь к скрипту.

    Можно использовать дополнительные параметры:
    • -IISSiteName «MDaemon WorldClient»
      Если WorldClient работает через IIS, то этим параметром нужно указать скрипту имя сайта WorldClient (см. часть 2)
    • -WCIPAddress xxx.xxx.xxx.xxx
      Этим параметром задаётся IP-адрес, к которому скрипт должен прибиндить полученный сертификат. Его нет необходимости указывать, если к порту 443 не привязано никаких других сертификатов.
    • -To «admin@server.com»
      Этим параметром задаётся имейл, на который будет отправлен лог работы скрипта в случае возникновения какой-либо ошибки.

    Смотрим в окно консоли - скрипт должен выполниться без ошибок.

    Если что-нибудь пойдёт не так — вам придётся разобраться с этой проблемой самостоятельно.

    Если всё выполнилось успешно, то можно попробовать зайти в WorldClient браузером по протоколу https: так как мы использовали тестовый сервер LetsEncrypt, то браузер должен выругаться на сертификат сайта сообщением 'SEC_ERROR_UNKNOWN_ISSUER'.

    Кстати говоря, помните — я рассказывал про «грабли» с параметром 'EnableWCServer' в файле 'Mdaemon.ini' — что при использовании связки с IIS он установлен в 'No'? Так вот после успешной отработки скрипта этот параметр изменился на 'Yes'. Однако произошло это несколько поздновато, поэтому раскомментаривать проверку этого параметра в скрипте мы не стали.

Часть 4: перевод скрипта в «боевой режим»


  1. Открываем в текстовом редакторе скрипт letsencrypt.ps1 из папки LetsEncrypt.
  2. Находим в нём строки:

    
    #Initialize-ACMEVault -ErrorVariable LogText
    Initialize-ACMEVault -BaseURI https://acme-staging.api.letsencrypt.org/ -ErrorVariable LogText
    
  3. Первую строку раскомментариваем, а вторую закомментариваем:

    
    Initialize-ACMEVault -ErrorVariable LogText
    #Initialize-ACMEVault -BaseURI https://acme-staging.api.letsencrypt.org/ -ErrorVariable LogText
    
  4. Сохраняем скрипт.

Часть 5: Удаление всех следов «тестовой» жизнедеятельности


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

  1. Удаляем тестовый сертификат из MDaemon:
    • Запускаем GUI MDaemon и идём в меню 'Безопасность' -> 'Параметры безопасности' -> 'SSL & TLS'.
    • В списке сертификатов выделяем наш тестовый сертификат (у него в поле 'Отправитель' будет 'Fake LE Intermediate X1') и нажимаем кнопку 'Удалить' под списком.
    • Если список сертификатов стал пуст — придётся создать самоподписанный сертификат, иначе MDaemon будет ругаться при попытке закрыть окно.
  2. Удаляем хранилище ключей, созданное скриптом: если работали под админским аккаунтом, то идём в 'c:\ProgramData\', а если под пользовательским — в 'C:\Users\имя_пользователя\AppData\Local\' и удаляем оттуда папку 'ACMESharp' вместе со всем содержимым.
  3. Удаляем XML-файл, созданный скриптом: идём в папку 'MDaemon\LetsEncrypt' и удаляем файл LetsEncrypt.XML оттуда.
  4. Удаляем тестовый сертификат: идём в папку 'MDaemon\Pem', находим там сертификат (файл с расширением 'pfx') и удаляем его.

Часть 6: Настройка запуска скрипта по расписанию


  1. Идём в 'Control Panel' -> 'Administrative Tools' -> 'Computer Management' -> 'System Tools' -> 'Task Scheduler' -> 'Task Scheduler Library'.
  2. Создаём новую задачу: нажимаем 'Create Task...' в правой панели 'Actions'.
  3. На закладке 'General':
    • В поле 'Name' пишем имя задачи — произвольно по вашему желанию.
    • В подразделе 'Security Options' выбираем пункт 'Run whether user is logged on or not'.
  4. На закладке 'Triggers':
    • Нажимаем кнопку 'New...' — откроется окно 'New Trigger'.
    • В списке 'Begin the task' выбираем 'On a schedule'.
    • Устанавливаем подходящую периодичность запуска: например, раз в неделю по воскресеньям. Скрипт при каждом старте будет проверять — сколько сертификату осталось жить: и если меньше месяца, то обновит его.
  5. На закладке 'Actions':
    • Нажимаем кнопку 'New' — откроется окно 'New Action'.
    • В списке 'Action' выбираем 'Start a program'.
    • В поле 'Program/script' пишем 'powershell'.
    • В поле 'Add arguments (optional)' пишем '-ExecutionPolicy ByPass -File c:\MDaemon\LetsEncrypt\letsencrypt.ps1'. В хвост строки дописываем требуемые дополнительные параметры (см. часть 3).
  6. На закладке 'Conditions' ставим крыжики по своему усмотрению.
  7. На закладке 'Settings' ставим крыжики:
    • Allow task to be run on demand
    • Stop the task if it runs longer than 1 hour
    • If the running task does not end when requested, force it to stop
  8. Нажимаем кнопку 'OK'. Вводим пароль текущего пользователя.

Часть 7: первый «боевой» запуск


Выполняем старт скрипта вручную:

  1. Выделяем только-что созданную задачу в списке.
  2. Нажимаем 'Run' в правой панели Actions'. Никакого окна при этом не откроется.
  3. Время от времени рефрешим список задач — чтобы видеть изменения в поле 'Status': 'Status' должен смениться на 'Run'. Рефрешим список, пока 'Status' снова не станет 'Ready'.
  4. Смотрим результат выполнения скрипта в лог-файле 'MDaemon\Logs\LetsEncrypt.log'.

Если, судя по лог-файлу, всё прошло успешно, значит дело сделано — сертификат получен и можно проверять работоспособность приёма/отправки почты по защищённому каналу. И да, не забудьте зайти в почтовик браузером по протоколу https — чтобы убедиться, что WorldClient тоже работает без проблем.

Часть последняя — заключительная


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

Ну вот и всё. Всё что знал — рассказал. Поздравляю всех с наступающим Новым Годом! Здоровья вам и удачи!