SSL-сертификат на Windows Server, когда порт 80 занят: win-acme
Порт 80 на Windows Server занят чужим приложением, а сертификат нужен. Разбираю проверку TLS-ALPN на порту 443 по RFC 8737, клиент win-acme, автопродление и скрипт, который раскладывает сертификат по службам, а также три ошибки: две A-записи у домена, чужой сервис на соседнем порту и проверку здоровья с ответом 400.
Коротко (TL;DR)
- Если порт 80 на Windows Server занят чужим приложением, сертификат Let's Encrypt можно выпустить с проверкой TLS-ALPN: её делают на порту 443, порт 80 не нужен.
- Клиент для Windows называется win-acme, запускается файл wacs.exe. Официальный сайт: win-acme.com, исходники и сборки на GitHub.
- Продление идёт по задаче планировщика, а после каждого продления можно запускать свой скрипт и раскладывать сертификат по службам.
- Три ошибки, которые я встречал на практике: у домена две A-записи, соседний порт занят чужим сервисом, проверка здоровья после включения защищённого соединения отвечает 400.
Сделаю под ключ: разберу задачу, назову срок и цену. Чтобы начать, напишите в Telegram одной фразой.
Автоматизация процессовВыпустить SSL-сертификат на Windows Server, когда порт 80 занят, можно с проверкой владения доменом по TLS-ALPN: центр сертификации подключается к вашему серверу на порт 443 и проверяет временный сертификат, а порт 80 ему не нужен. На Windows это делает клиент win-acme командой с параметром проверки tls-alpn-01. Ниже разбираю, как это работает, как настроить автопродление и что ломается чаще всего.
Почему HTTP-проверка не подходит, когда порт 80 занят
Обычный путь выглядит так. Центр сертификации просит положить файл с заданным содержимым по адресу вида http://домен/.well-known/acme-challenge/токен и сам его скачивает. По стандарту RFC 8555 (раздел 8.3) такой запрос идёт именно на TCP-порт 80, и по HTTPS проверку делать нельзя. Значит, на порту 80 должен отвечать тот, кто умеет отдать этот файл.
На практике порт 80 часто занят. На одной машине живёт 1С, веб-сервер для чужой программы, шлюз или старый сервис, который нельзя трогать. Останавливать его на время проверки неудобно, а при автопродлении тем более: сертификат продлевается ночью, и никто не должен для этого выключать рабочие системы.
Как работает проверка TLS-ALPN на порту 443
Для таких случаев есть другой тип проверки, описанный в RFC 8737. Центр сертификации подключается к домену на порт 443, указывает в TLS-рукопожатии специальный протокол acme-tls/1 и ожидает в ответ временный самоподписанный сертификат. В этом сертификате в обязательном расширении лежит хеш SHA-256 от ключевой авторизации, а в списке имён только проверяемый домен. Соединение после рукопожатия закрывается, никаких данных по нему не передаётся.
У способа есть условия. По документации Let's Encrypt проверка работает, когда порт 80 недоступен, но поддерживают её не все клиенты, и выпустить так сертификат на подстановочный домен со звёздочкой нельзя. Согласно справке win-acme, запрос всегда идёт на порт 443, изменить это нельзя, и домен должен быть доступен из интернета на время проверки. Если у домена несколько записей A или AAAA, соединений может быть несколько, по одному на адрес.
Есть и ограничение, о котором в документации win-acme сказано прямо: встроенному слушателю для TLS-ALPN нужен эксклюзивный доступ к порту. Пока на 443 кто-то принимает соединения, этот вариант не сработает. В моём случае порт 443 был свободен, поэтому он и подошёл.
Как называется клиент для Windows и где его брать
Программу ищут под разными названиями, поэтому уточню. Проект называется win-acme, на сайте он описан как простой клиент ACMEv2 для Windows. Исполняемый файл называется wacs.exe, отсюда второе название WACS. Официальный сайт: win-acme.com, сборки лежат на GitHub в разделе Releases. В инструкции рекомендуют распаковать архив в папку %programfiles%win-acme и запускать wacs.exe от имени администратора. Скачивайте только с этих двух адресов: на сервере с рабочими системами программу с зеркал брать нельзя.
Выпуск сертификата с проверкой на 443
Интерактивный режим подходит для первого раза: wacs.exe задаёт вопросы, просит принять условия и указать почту для уведомлений. Для повторяемости удобнее командная строка. Параметры я беру из справочника командной строки: тип проверки задаёт параметр validationmode со значением tls-alpn-01, плагин проверки selfhosting, а хранилище и способ установки выбирают параметры store и installation.
Перед запуском я проверяю четыре вещи:
- домен указывает на этот сервер, и других адресов у него нет (подробнее в разделе об ошибках);
- порт 443 на сервере свободен, а в межсетевом экране открыт снаружи;
- на время проверки ни одна служба не принимает соединения на 443;
- запуск идёт под учётной записью администратора.
Если сертификат нужен нескольким службам, его выпускают один раз на домен, а дальше раскладывают. Об этом следующий раздел.
Автопродление и скрипт, который раскладывает сертификат по службам
По документации win-acme, после первого успешного выпуска программа создаёт одну задачу планировщика на все свои сертификаты. Задача запускается каждый день, но продлевает только когда нужно. Срок продления по умолчанию 55 дней, время запуска 9:00 под учётной записью SYSTEM, настройки лежат в settings.json. Для tls-alpn-01 в момент запуска порт 443 должен быть свободен, поэтому я проверяю на тестовом прогоне, как продление поведёт себя рядом с вашими службами.
Продлить сертификат мало: его нужно доставить службам. Для этого в win-acme есть плагин установки script. По документации, скрипт запускается после каждого успешного продления, а в параметры можно передать имя домена, путь к файлу PFX, пароль к нему и отпечаток сертификата. Запуск без вопросов задают тремя параметрами: installation со значением script, script с путём к файлу и scriptparameters со списком подстановок.
Вот каркас скрипта, который я использую как основу. Это пример: его надо адаптировать под ваши службы и сначала прогнать вручную.
param([string]$PfxFile, [string]$PfxPassword, [string]$Thumbprint)
$ErrorActionPreference = 'Stop'
$log = 'C:ssldeploy.log'
function Log($m) { Add-Content $log ((Get-Date -Format s) + ' ' + $m) }
try {
Copy-Item 'C:sslcurrent' ('C:sslackup-' + (Get-Date -Format yyyyMMdd)) -Recurse -Force
Copy-Item $PfxFile 'C:sslcurrentsite.pfx' -Force
# здесь конвертация под службу, которой нужны отдельные файлы crt и key
Import-Module WebAdministration
(Get-WebBinding -Name 'External' -Protocol https).AddSslCertificate($Thumbprint, 'My')
foreach ($s in 'ServiceOne', 'ServiceTwo') { Restart-Service $s }
Log ('ok ' + $Thumbprint)
} catch {
Log ('error ' + $_.Exception.Message)
exit 1
}
В нём важны резервная копия перед заменой, запись в журнал и ненулевой код выхода при ошибке. Тогда сбой раскладки не остаётся незамеченным до дня, когда сертификат на одной из служб истечёт.
Типичные ошибки: две A-записи, чужой сервис, проверка здоровья
У домена две A-записи. По RFC 8555 сервер проверки подключается минимум к одному из адресов из записей A и AAAA, на своё усмотрение. Если вторая запись указывает на старый хостинг или конструктор сайтов, проверка может уйти туда и провалиться, причём не каждый раз. Такую плавающую ошибку трудно поймать. Лечится просто: завести отдельный поддомен, который смотрит только на ваш сервер, и выпускать сертификат на него. В моём проекте у основного домена заказчика было две A-записи, и я попросил его администратора завести поддомен.
Чужой сервис на соседнем порту. Мне встретился порт 8443, который отвечал кодом 401. Сначала это выглядело как готовое защищённое соединение. Проверка показала обычный HTTP от постороннего приложения. Правило простое: прежде чем что-то считать готовым, подключитесь к порту и посмотрите, какой сертификат он отдаёт и отдаёт ли вообще.
Проверка здоровья отвечает 400. После включения защищённого соединения мой скрипт проверял здоровье службы запросом по HTTPS снаружи, по имени домена, и получал 400. Скрипт решил, что всё сломалось, и откатил настройки, а служба осталась остановленной, её пришлось запускать вручную. Вывод: проверка здоровья должна ходить так, как ходит реальный клиент, а откат должен возвращать службу в рабочее состояние. Признаком живого соединения я теперь считаю конкретные вещи: сертификат на нужное имя на нужном порту и ожидаемый код ответа.
Как я это делаю
Так я сделал в проекте MinIO для сервера взаимодействия 1С. Порт 80 на виртуальной машине заказчика занимало другое приложение, поэтому я выпустил сертификат Let's Encrypt через win-acme с проверкой TLS-ALPN на свободном 443. Продление идёт по задаче планировщика, а после него скрипт пересобирает хранилище ключей и раскладывает сертификат по хранилищу файлов, сайту и серверу взаимодействия. Работал по RDP, каждый этап отдельным скриптом с резервной копией настроек и откатом.
Мой порядок на любом сервере такой. Сначала смотрю, что слушает 80 и 443 и какие записи у домена. Потом делаю пробный выпуск и ручной прогон скрипта раскладки. Затем запускаю продление принудительно, задолго до срока, и смотрю, что все службы получили новый сертификат. В конце оставляю журнал и понятный способ отката. Если вам нужна такая настройка на вашем сервере, это входит в автоматизацию процессов. А почему сертификаты вообще нужно продлевать всё чаще, объясняет статья про сокращение срока жизни сертификатов.
Если у вас несколько доменов и серверов, посмотрите разбор Certimate: одна панель на все сертификаты. Для файлового хранилища рядом есть материал про MinIO, а чтобы узнавать о падении сайта раньше клиентов, пригодится мониторинг сайта и домена.
Сколько стоит настройка сертификата и автопродления
Отдельной цены именно на выпуск сертификата у меня нет, потому что объём зависит от числа служб и от того, насколько запутан сервер. Ориентиры по моему прайсу:
- разработка по часам от 3 000 ₽/час: так обычно считается выпуск сертификата и скрипт раскладки на одном сервере;
- технический аудит от 50 000 ₽, срок от 1 недели, если сначала нужно разобраться во всей инфраструктуре;
- автоматизация процессов и документов от 60 000 ₽, срок от 2 недель, когда сертификаты часть большей задачи;
- поддержка от 20 000 ₽/мес: исправления, доработки, обновления, мониторинг.
Точную оценку делаю после доступа к серверу и списка служб. Актуальные цены собраны на странице цен.
Частые вопросы
Можно ли выпустить сертификат без порта 80?
Да. Для этого используют проверку TLS-ALPN по RFC 8737 или проверку через DNS. Первая требует свободного порта 443 для встроенного слушателя win-acme, вторая не требует открытых портов, но нужен доступ к управлению DNS домена.
Можно ли так выпустить сертификат на домен со звёздочкой?
Нет. По документации Let's Encrypt, проверка TLS-ALPN не подходит для подстановочных доменов. Для них нужна проверка через DNS.
Как понять, что продление сработало?
По журналу скрипта раскладки, по отпечатку сертификата на каждой службе и по сроку, который показывает браузер. Принудительное продление я запускаю заранее и смотрю, что все службы получили новый сертификат.
Что делать, если на 443 тоже кто-то слушает?
Встроенный слушатель тогда не подойдёт, потому что ему нужен эксклюзивный доступ к порту. Остаются проверка через DNS или проверка на веб-сервере, стоящем перед сервисом и умеющем сам отвечать на ACME. Это вопрос архитектуры сервера, его лучше разобрать отдельно.
Коротко о главном
- HTTP-проверка по RFC 8555 идёт на порт 80. Если он занят, есть проверка TLS-ALPN по RFC 8737 на порту 443.
- Клиент для Windows называется win-acme, файл wacs.exe, официальный сайт win-acme.com.
- Продление автоматическое, но без скрипта раскладки сертификат остаётся только в одном месте. Скрипту нужны резервная копия, журнал и код ошибки.
- Перед выпуском проверьте записи домена и то, что на самом деле слушает 80, 443 и соседние порты.
Если у вас такой сервер и нужно выпустить сертификат без остановки рабочих систем, напишите мне в Telegram с кодовым словом «ПОРТ»: посмотрю, что занято, и подскажу вариант.
Сертификат и автопродление на вашем Windows Server
Напишите одной фразой, что нужно. Отвечу, что подойдёт, сколько займёт и сколько стоит. Сообщение уже подготовлено.
- Выпуск сертификата с проверкой на 443, когда порт 80 занят
- Скрипт, который раскладывает сертификат по службам
- Резервная копия настроек и откат на каждом этапе
- Проверка продления до срока, журнал и мониторинг
Разборы, кейсы и практика — без воды. Выходит регулярно, читать 3–5 минут.


