Браузер ругается на внутренний GitLab? Разбираемся с SSL без лишних трат
Красный экран с надписью «Ваше подключение не защищено» на внутреннем сервисе — вещь, которую я лично терпеть не могу. Не потому что это какая-то угроза. Просто раздражает людей, подрывает доверие к инструментам и иногда буквально блокирует работу. За несколько лет я перепробовал всё: самоподписанные сертификаты, Let's Encrypt, корпоративный CA. Расскажу, что реально работает — и что создаёт только видимость решения.
Почему браузер ругается на внутренние сервисы — и почему это не мелочь
Открываешь GitLab, Nextcloud или корпоративный портал — и вместо нужной страницы красный экран. Телефон начинает разрываться: «У нас всё упало?» Кто-то жмёт «Принять риск» и продолжает работать. Кто-то закрывает вкладку и идёт разбираться лично. Это не про эстетику. Это про доверие к инструменту, которым люди пользуются каждый день.
Chrome с версии 94 принудительно переходит на HTTPS для всего, что хоть немного похоже на серьёзный адрес. Корпоративные домены, диапазон 192.168.x.x, имена вида gitlab.company.local — всё под раздачей. Firefox пока мягче, но это ненадолго. Edge, которым пользуется добрая половина офиса на Windows 11, работает на хромиумовском движке — то есть история та же самая. А начиная с Chrome 99 кнопка «Принять риск» на ряде ошибок вообще исчезла с экрана.
Был у нас клиент — небольшая юридическая контора, 12 человек. Подняли им Nextcloud для внутреннего документооборота, без сертификата. Полгода все давили «Принять риск» и как-то привыкли. Потом Chrome обновился — и кнопка пропала. Войти стало невозможно совсем. Приехали, за три часа настроили корпоративный CA, раскатили корневой сертификат через групповую политику — и всё заработало. Три часа работы против шести месяцев ежедневного раздражения.
Три пути — и почему два из них создают больше проблем, чем решают
Видишь предупреждение на внутреннем сервисе — мозг сразу предлагает три пути. Первый: сделать самоподписанный сертификат. Второй: взять Let's Encrypt. Третий: поднять собственный корневой центр сертификации. Все три технически работают. Но на нашей практике два из трёх рождают новые головные боли вместо того, чтобы закрыть старые.
Самоподписанный сертификат — это когда сервер сам себе выдаёт справку о надёжности. Примерно как человек, написавший себе рекомендательное письмо. Браузер это понимает и отвечает просто: «Не верю». Для одноразового теста или локального контейнера на машине разработчика — ещё куда ни шло. Но как только к сервису обращаются хотя бы три человека, начинается боль. Каждому объясняешь, как добавить исключение. На телефонах это вообще отдельный квест. Через полгода сертификат истекает — и всё по новой. Снова. Каждый раз.
Let's Encrypt — отличный сервис, я сам его использую для публичных сайтов. Бесплатно, автоматически, 90 дней с продлением через certbot. Для внутренней инфраструктуры он работает только при одном условии: домен обязан быть публичным. Если у вас gitlab.company.local или сервер на адресе 192.168.1.50 — сертификата не видать. Публичные центры сертификации не подписывают приватные адреса. Это не баг — это политика.
Когда Let's Encrypt всё-таки подходит для внутренних сервисов
Есть один легальный способ выбить сертификат Let's Encrypt для внутреннего сервиса — DNS-01 challenge. Схема простая: вместо HTTP-запроса к вашему серверу Let's Encrypt проверяет TXT-запись в DNS. Вы добавляете запись, они убеждаются, что домен ваш, и выдают сертификат. Сам сервер при этом может вообще не иметь выхода в интернет.
Но есть условие. Домен должен быть настоящим публичным — company.ru или company.com, но не company.local. И нужен DNS-провайдер с API: Cloudflare, Route53, Reg.ru, Selectel DNS и ещё пара десятков вариантов. Certbot работает с ними через плагины. Итоговая схема выглядит так: сервер закрыт, домен публичный, сертификат выдаёт Let's Encrypt, браузеры его знают и доверяют без какой-либо дополнительной настройки на клиентах. Красивое решение — когда всё сходится.
Мы так делаем для клиентов, у которых уже есть нормальный публичный домен и адекватный DNS-провайдер. Конкретный пример: небольшая медклиника, внутренний Nextcloud на nextcloud.clinic-name.ru, IP сервера 192.168.10.20, снаружи недоступен. DNS у них на Cloudflare. Настроили certbot с плагином certbot-dns-cloudflare, автообновление через systemd timer — и всё. Врачи и администраторы видят зелёный замочек, вопросов ноль. Стоимость: ноль рублей за сертификат плюс час нашей работы.
Корпоративный CA — когда это единственный правильный ответ
Домен .local, несколько серверов, RDP-сессии и VPN? Тогда корпоративный CA — это именно то, что нужно. Один раз поднял, один раз раскатил корневой сертификат по машинам — и дальше выпускаешь новые сертификаты сам: бесплатно, без зависимости от интернета, без каких-либо ограничений на адреса. Хоть 192.168.x.x, хоть company.local, хоть отдельный поддомен под каждый сервис.
Что такое корпоративный CA? Это ваш собственный центр сертификации — программа, которая хранит корневой сертификат и умеет им подписывать другие. Когда браузер видит подписанный вашим CA сертификат, он задаёт один вопрос: «Знаю ли я этот корневой CA?» Если да — доверяет. Весь механизм именно такой, без лишних деталей. Главное — один раз добавить ваш корневой сертификат в доверенные на всех устройствах.
Инструментов несколько. На Windows Server есть встроенная роль Active Directory Certificate Services (AD CS) — полноценный корпоративный CA с глубокой интеграцией в домен. Мощно, но нужны Windows Server и Active Directory. Для небольших офисов без домена или с Linux-серверами есть step-ca от Smallstep — открытый проект с автообновлением через ACME-протокол, как Let's Encrypt, только внутри сети. Совсем базовый вариант — OpenSSL: командная строка, никаких зависимостей, работает везде. С него и начну.
Как поднять CA на OpenSSL: практический минимум
OpenSSL есть на любом Linux — Ubuntu, Debian, CentOS, без разницы. Ничего дополнительно устанавливать не нужно, никаких лицензий, никаких подписок. В первый раз занимает полтора-два часа. Потом работает годами без вашего участия.
Начинаем с корневого ключа и сертификата. Ключ: openssl genrsa -aes256 -out rootCA.key 4096. Потом сам корневой сертификат: openssl req -x509 -new -nodes -key rootCA.key -sha256 -days 3650 -out rootCA.crt. Срок 3650 дней — десять лет. Корневой CA специально делают долгосрочным, чтобы не перераскатывать доверие по всем машинам каждые два года. Файл rootCA.crt — это то, что потом добавляется на все устройства в доверенные корневые сертификаты.
Под каждый сервис — свой сертификат. Для gitlab.company.local генерируете один CSR, для nextcloud.company.local — другой, для rdp.company.local — третий. Подписываете корневым ключом, получаете пару .key + .crt. Nginx, Apache, Nextcloud, GitLab — все работают именно с таким форматом, без лишних танцев. Теперь про момент, который реально убивает: в конфиге OpenSSL обязательно прописывайте subjectAltName = DNS:gitlab.company.local, IP:192.168.1.100. Не факультативно — обязательно. Современные браузеры смотрят только на поле SAN. CN им не интересен уже несколько лет. Забыли SAN? Chrome будет ругаться. Даже если сертификат правильный во всём остальном — всё равно будет ругаться.
Раскатываем доверие: как добавить корневой сертификат на все машины
Вот где чаще всего спотыкаются. Выпустить корректный сертификат — это половина дела. Вторая половина — добиться, чтобы каждый браузер и каждая ОС в вашей сети считали ваш CA доверенным. Не сделаете это — красные экраны никуда не денутся, просто текст ошибки станет другим.
Есть домен Active Directory? Тогда всё решается в несколько кликов. Открываете «Управление групповой политикой», заходите в нужный GPO: Computer Configuration → Windows Settings → Security Settings → Public Key Policies → Trusted Root Certification Authorities. Импортируете rootCA.crt. После gpupdate /force все Windows-машины в домене подтягивают ваш CA в доверенные автоматически. Edge и Chrome читают системное хранилище Windows — и сразу начинают доверять. Никаких перезагрузок, никаких действий от пользователей.
Firefox — это отдельная история, и тут надо держать ухо востро. Он не читает системное хранилище Windows по умолчанию. Варианта два: либо прописать путь к сертификату через policies.json или ADMX-шаблоны Mozilla — и раздать это через ту же GPO, либо попросить каждого пользователя зайти вручную в Настройки → Конфиденциальность → Просмотр сертификатов и добавить CA самостоятельно. Мы на практике почти всегда идём первым путём: раскладываем policies.json через GPO. На настройку уходит около двадцати минут, дальше всё работает само.
На Linux корневой сертификат копируете в /usr/local/share/ca-certificates/ и запускаете update-ca-certificates — готово. На macOS либо через Keychain Access, либо командой security add-trusted-cert -d -r trustRoot -k /Library/Keychains/System.keychain rootCA.crt. С мобильными чуть сложнее. Android позволяет установить пользовательский CA через настройки безопасности. iOS требует профиля конфигурации с явным включением доверия — просто закинуть файл не выйдет. Если в компании есть MDM — Microsoft Intune или Jamf — сертификат раскатывается на все устройства минут за пять, без участия пользователей вообще.
Типичные ошибки, на которых обжигаются даже опытные
Самая частая ошибка — не прописан Subject Alternative Name. Скажу об этом ещё раз, потому что это стабильно ломает людям нервы. Chrome, Edge и Safari не смотрят на поле CN — точка. Им нужен SAN. Выпустили сертификат с CN=gitlab.company.local, но без явного SAN в расширениях? Браузер выдаст NET::ERR_CERT_COMMON_NAME_INVALID. Всегда прописывайте subjectAltName в конфиге OpenSSL. Если уже выпустили без него — перевыпускайте, обходного пути нет.
Второй косяк — про сроки. Серверный сертификат выпускают на год и благополучно забывают. Сам пару раз так попадал на старте. Сейчас либо ставлю напоминание в календаре за месяц до истечения, либо — и это куда лучше — поднимаю step-ca с ACME. Работает ровно так же, как certbot для Let's Encrypt, только внутри вашей инфраструктуры. Для офисов с несколькими серверами это сейчас мой первый выбор: настроили step-ca, раздали доступ по ACME — и все сертификаты обновляются сами каждые 90 дней. Никаких авралов в воскресенье ночью.
Третья ошибка — корневой сертификат с коротким сроком жизни. Видел своими глазами: сисадмин сделал root CA на один год. Через год умерло всё и сразу — и корневой, и все серверные сертификаты под ним. Раскатывать новый CA по всем машинам пришлось в пятницу вечером в режиме аврала. Удовольствие ниже среднего. Правило тут простое: root CA делаете на десять-пятнадцать лет, серверные сертификаты — на один-два года.
И ещё один момент, который нельзя игнорировать: приватный ключ корневого CA не должен лежать на том же сервере, где крутится всё остальное. Утечка rootCA.key — это конец вашему PKI. Злоумышленник сможет выпустить доверенный сертификат на любое имя в сети. Оптимальный вариант — отдельная виртуалка только под CA, без открытых портов снаружи, с регулярным зашифрованным бэкапом ключа. Мы обычно делаем задание Veeam на бэкап этой VM и отдельно экспортируем ключ в запароленный архив на изолированный диск. Потеряете ключ — придётся перевыпускать всю инфраструктуру сертификатов с нуля и снова раскатывать доверие по каждой машине.
Частые вопросы
Можно ли использовать Let's Encrypt для сервера без выхода в интернет?
Да, через DNS-01 challenge. Ваш сервер может быть полностью изолирован от интернета, но вам нужен публичный домен — не .local — и доступ к API вашего DNS-провайдера. Certbot запрашивает сертификат через TXT-запись в DNS, а не через HTTP-запрос к серверу. Если ваш DNS-провайдер поддерживается — Cloudflare, Route53, Selectel DNS и многие другие — работает без проблем и продлевается автоматически.
Сколько времени занимает настройка корпоративного CA с нуля?
На OpenSSL — от полутора до трёх часов, включая настройку первого сервиса и раскатку корневого сертификата через GPO. На step-ca примерно столько же, но потом проще жить — автообновление сертификатов встроено. На Windows AD CS с нуля — около дня, если первый раз. Мы обычно закладываем полдня на типовой офис до тридцати рабочих мест.
Как это работает на смартфонах сотрудников?
На корпоративных устройствах под управлением MDM — автоматически, через профиль конфигурации. На личных смартфонах придётся попросить установить корневой сертификат вручную: Android через Настройки → Безопасность → Установить из памяти, iOS через открытие файла .crt и явное включение доверия в Настройки → Основные → Об устройстве → Доверие сертификату. Звучит страшно, но на практике занимает две минуты.
Что выбрать: AD CS, step-ca или OpenSSL?
AD CS — если у вас домен Active Directory на двадцать и более человек: тесная интеграция с GPO, автоматическое распространение сертификатов, поддержка смарт-карт. Step-ca — если нет домена или инфраструктура смешанная: Linux, Windows, Mac, и вы хотите автообновление без ручного труда. OpenSSL — когда нужно быстро, без лишних зависимостей, и обслуживать будет технический человек, которому не лень изредка перевыпустить сертификат вручную.
Оставьте заявку — разберёмся с вашей инфраструктурой и настроим SSL так, чтобы красных экранов больше не было.
Бесплатная консультация →
Подпишитесь на рассылку ITfresh
Каждую неделю — практические гайды для руководителей и системных администраторов: безопасность, 1С, миграции, резервное копирование, лайфхаки из реальных проектов.
