Перейти к содержимому

// Engineering Log

HTTPS и веб-сервер на практике: Часть 6 — HTTPS во внутренней сети: mkcert, свой удостоверяющий центр step-ca и Let's Encrypt через DNS

Опубликовано 11.11.2026 · Автор:

// Быстрый маршрут

Эта статья относится к теме Безопасность и защита.

Внутренние сервисы — Grafana, Proxmox, NAS, веб-интерфейс роутера, тестовый стенд — часто работают по HTTP или с самоподписанным сертификатом, и пользователи привыкают нажимать «Всё равно перейти». Это плохая привычка: пароль администратора идёт по сети открытым текстом, а предупреждение о настоящей подмене сертификата никто не заметит. Кроме того, браузеры всё строже относятся к HTTP: часть возможностей (Service Workers, доступ к буферу обмена, камере, Secure-cookie) работает только в защищённом контексте, то есть по HTTPS или на localhost. Ниже — три способа получить нормальные сертификаты для внутренней сети и как выбрать между ними.

Выбор доменной зоны

Сначала — как называть внутренние хосты. От этого зависит, какие сертификаты можно получить.

  • Поддомен вашего публичного домена (grafana.int.example.ru) — лучший вариант. Для него можно получить сертификат Let’s Encrypt, а в DNS внутренние имена можно отдавать только внутренним клиентам (split DNS).
  • .internal — зона, которую ICANN в 2024 году зарезервировала для частных сетей: она никогда не появится в интернете. Публичные центры для неё сертификаты не выпускают — нужен свой центр.
  • .home.arpa — зона для домашних сетей (RFC 8375), тоже только свой центр.
  • Не используйте .local (занята mDNS/Bonjour — будут конфликты разрешения имён), выдуманные зоны вроде .lan, .corp, .office (любую из них могут делегировать в интернете, как это произошло с .dev) и чужие домены.

Способ 1. mkcert — для разработки на своём компьютере

mkcert создаёт локальный удостоверяющий центр, добавляет его в хранилища системы и браузеров и выпускает сертификаты для любых имён.

bash
brew install mkcert nss          # macOS; nss нужен для Firefox
mkcert -install                  # создать CA и добавить его в доверенные
mkcert app.test localhost 127.0.0.1 ::1
# создаст app.test+3.pem и app.test+3-key.pem

Сертификат подключается к серверу разработки (Vite: server.https, Nginx: ssl_certificate), и браузер открывает https://app.test без предупреждений.

Ограничения:

  • только для вашего компьютера: на других устройствах этого CA нет;
  • закрытый ключ CA лежит в $(mkcert -CAROOT) — не передавайте его никому и не используйте mkcert для общих серверов;
  • чтобы открыть сайт с телефона, CA придётся установить и на телефон — для этого лучше подходит способ 2.

Способ 2. Свой удостоверяющий центр на step-ca

step-ca (Smallstep) — удостоверяющий центр с открытым кодом, который выдаёт сертификаты по тому же протоколу ACME, что и Let’s Encrypt. Для внутренних сервисов вы получаете ту же автоматизацию — certbot, Caddy, Traefik, cert-manager — но от своего центра.

Установка и инициализация:

bash
step ca init --name "Example Internal CA" --dns ca.example.internal \
  --address :9000 --provisioner admin@example.ru
step ca provisioner add acme --type ACME
step-ca $(step path)/config/ca.json      # запуск; для постоянной работы — systemd-сервис

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

Выпуск сертификата через ACME:

bash
# certbot должен доверять вашему CA
export REQUESTS_CA_BUNDLE=/usr/local/share/ca-certificates/example-internal-root.crt

certbot certonly --standalone -d grafana.example.internal \
  --server https://ca.example.internal:9000/acme/acme/directory

В Caddy достаточно указать центр в глобальных настройках:

{
    acme_ca https://ca.example.internal:9000/acme/acme/directory
    acme_ca_root /etc/ssl/example-internal-root.crt
}
grafana.example.internal {
    reverse_proxy 127.0.0.1:3000
}

Короткие сроки. По умолчанию step-ca выдаёт сертификаты на 24 часа. Это нормально: продление автоматическое (certbot renew, встроенный ACME или step ca renew --daemon), а короткий срок снимает проблему отзыва. Если какой-то сервис умеет только загрузку сертификата вручную (веб-интерфейс коммутатора, ИБП), для него срок увеличивают в настройках центра или выпускают сертификат отдельно.

Ограничение имён. Обязательно ограничьте центр своими зонами — тогда даже при утечке его ключа им не подписать сертификат для sberbank.ru или google.com. В step-ca это делается политикой в ca.json:

json
"policy": {
  "x509": {
    "allow": { "dns": ["*.example.internal", "*.int.example.ru"] }
  }
}

Для полной защиты ограничение имён (name constraints) лучше записать и в сам промежуточный сертификат при его выпуске — тогда его проверяют клиенты, а не только сам центр.

Распространение корневого сертификата. Корень нужно добавить в доверенные на всех устройствах:

  • Windows — групповые политики (Конфигурация компьютера → Политики → Параметры безопасности → Политики открытого ключа → Доверенные корневые центры сертификации);
  • macOS и iOS — профили MDM;
  • Linux-серверы — через Ansible или образ: файл в /usr/local/share/ca-certificates/ и update-ca-certificates;
  • Docker-образы — в Dockerfile тем же способом; иначе сервисы внутри контейнеров не смогут обращаться друг к другу по HTTPS;
  • Firefox — политика Certificates.ImportEnterpriseRoots или отдельный импорт;
  • Java — keytool -importcert -cacerts.

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

Способ 3. Let’s Encrypt через DNS-01 для внутренних имён

Если внутренние хосты названы поддоменами публичного домена, свой центр не нужен вовсе. Проверка DNS-01 не требует доступа к серверу из интернета — только возможности создать TXT-запись в публичной зоне («Сертификаты Let’s Encrypt: ACME, проверки домена, CAA и Certificate Transparency»).

bash
certbot certonly --dns-cloudflare --dns-cloudflare-credentials /root/.cf.ini \
  -d grafana.int.example.ru

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

Недостатки:

  • имена попадают в журналы Certificate Transparency. Каждый сертификат на grafana.int.example.ru виден всем через crt.sh. Если список внутренних сервисов раскрывать нежелательно, выпускайте один wildcard *.int.example.ru и раздавайте его на внутренний прокси;
  • нужен API вашего DNS-провайдера с ключом, который хранится во внутренней сети; ограничьте его одной зоной или делегируйте _acme-challenge в отдельную зону;
  • A-записи внутренних имён не должны указывать на внутренние адреса в публичном DNS — используйте внутренний DNS-сервер (split DNS) или отдавайте их только из внутреннего резолвера.

Удобная схема: один обратный прокси во внутренней сети (Caddy, Traefik, Nginx) с wildcard-сертификатом, за ним все сервисы по HTTP. Сертификат продлевается в одном месте, а сервисам не нужно уметь TLS.

Что выбрать

ЗадачаРешение
Разработка на своём компьютереmkcert
Домашняя сеть или небольшой офис, есть публичный доменLet’s Encrypt через DNS-01, wildcard на обратный прокси
Компания, много сервисов, нельзя раскрывать имена, нужен mTLSсвой центр на step-ca с ACME и ограничением имён
Имена в .internal или .home.arpaтолько свой центр
Устройство, которое не умеет ACME и загрузку сертификатовобратный прокси перед ним

Типичные ошибки

  • Самоподписанный сертификат на каждом сервисе и привычка подтверждать предупреждения — теряется защита от подмены.
  • Свой центр без ограничения имён — его ключ позволяет подписать сертификат для любого сайта в интернете на всех устройствах компании.
  • Корень установлен на рабочие места, но не в Docker-образы и не в Java — сервисы не могут обращаться друг к другу.
  • .local или выдуманная зона для внутренних имён — конфликты с mDNS и риск, что зону делегируют в интернете.
  • Сертификат Let’s Encrypt на каждое внутреннее имя — полный список внутренних сервисов публично доступен через журналы CT.
  • Ключ CA mkcert или step-ca лежит в общей папке или в репозитории.

// Похожая задача

Если у вас похожая ситуация

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

Тема статьи

Безопасность и защита

SSL, hardening, доступы, защита сервисов и безопасные конфигурации.

Часто с этим приходят

  • Настроить SSL, сертификаты и безопасные подключения
  • Ограничить доступы и закрыть лишние точки входа
  • Усилить конфигурацию сервера и сервисов

// Следующий шаг

Если вам нужна не только статья, а помощь по этой теме, удобнее сразу перейти в услугу. Главная и подборка материалов остаются рядом.

Открыть услуги

// Contact

Нужна помощь?

Свяжись со мной и я помогу решить проблему

Написать в Telegram

Отвечаю в течение рабочего дня (03:00–13:00 GMT)

Или оставьте заявку здесь:

Подтвердите, что вы не бот.

Написать и получить быстрый ответ