Замена удостоверяющего центра VPN — это не подмена файла. В тот момент, когда новый УЦ подписывает первый сертификат, каждый валидатор, который всё ещё доверяет только старому, должен принять решение, а узлы, которые так и не получают новый якорь, продолжают отвергать добросовестных партнёров. Я видел, как это ломается в обе стороны: шлюз выучил новый УЦ, а клиенты нет, поэтому новые подключения срывались, тогда как уже поднятые туннели оставались и делали сбой похожим на проблему маршрутизации. Вот что меняется, в том порядке, в каком проявляются отказы.

Одна замена, два отдельных изменения

Удостоверяющий центр — это имя, открытый ключ и закрытый ключ, которым подписывают. Валидаторы никогда не доверяют «УЦ» абстрактно. Они доверяют одному конкретному сертификату, который уже лежит в хранилище доверия, и принимают издателя, только если цепочка подписей доходит до этой сохранённой копии. Поэтому замена УЦ меняет две вещи, которые отказывают независимо: какие якоря принимаются и какие идентичности партнёров под ними выданы.

Большинство развёртываний VPN проверяют в обе стороны. Клиент аутентифицирует сертификат шлюза, а шлюз — сертификат клиента. Ротация, которая обновляет только клиентский пакет, оставляет сервер отвергающим каждого клиента, который всё ещё предъявляет идентичность старого УЦ, и обратное столь же обычно. Сначала перечислите точки применения: хранилища доверия клиентов, файл ca шлюза, любой прокси, завершающий TLS перед ним, и щуп, проверяющий конечную точку снаружи.

Что проверяет валидатор, по порядку

Проверка пути поднимается от сертификата партнёра через промежуточные до доверенного якоря. На каждом шаге она проверяет подпись, следит, чтобы каждый сертификат был внутри срока действия, и подтверждает, что базовые ограничения и назначение ключа позволяют издателю подписывать. Только затем приложение смотрит на конечный сертификат: альтернативные имена субъекта должны покрывать запрошенное имя, а расширенное назначение ключа должно разрешать аутентификацию сервера или клиента.

Чтобы повторить этот проход офлайн, направьте -CAfile на тот самый пакет, который будете развёртывать, а не на системное хранилище. Иначе вы проверяете узел, а не изменение:

openssl verify -CAfile new-ca.crt gateway.crt
openssl verify -CAfile new-ca.crt -untrusted intermediate.crt client.crt
openssl x509 -in gateway.crt -noout -subject -issuer -dates
openssl s_client -connect gw.example.net:443 -CAfile new-ca.crt

Эта команда работает только против обычного TLS-слушателя вроде страницы администрирования HTTPS на шлюзе; управляющий канал OpenVPN идёт до TLS, поэтому s_client не может заглянуть в рукопожатие туннеля.

Правила построения пути, стоящие за этими ошибками, находятся в RFC 5280 раздел 6. Они объясняют отказы, которые иначе кажутся произвольными: просроченный промежуточный сертификат, о котором никто не помнил, сертификат, чьё назначение ключа запрещает подпись, или ограничение имени, исключающее проверяемый узел.

Почему старый туннель продолжает работать

TLS и OpenVPN оба сохраняют установленный сеанс живым после завершения рукопожатия. Ничего не перепроверяет сертификат партнёра на каждый пакет, поэтому клиент, подключившийся до изменения, продолжает пропускать трафик, пока не пересогласует параметры, не переподключится или туннель не упадёт. Именно этот промежуток позволяет замене УЦ час выглядеть нормально, а затем отказать в самый неподходящий момент: ноутбук просыпается, сопоставление NAT истекает, шлюз перезапускается.

Возобновление сеанса растягивает иллюзию ещё сильнее. Билет сеанса TLS позволяет клиенту вернуться без повторной отправки сертификатов, а возобновление пропускает проверку пути, потому что первое рукопожатие её уже выполнило. Поэтому честная проверка — полное рукопожатие в новом процессе. Перезапустите клиент, а не переподключайте туннель, и на тестовом профиле рассмотрите отключение билетов, чтобы путь возобновления не мог скрыть порванную цепочку.

Держите слой статического ключа отдельно от этого. tls-auth добавляет HMAC в управляющий канал, tls-crypt шифрует и аутентифицирует его, и ни один не несёт материал сертификата, поэтому ротация любого из них — отдельное изменение со своим режимом отказа. Развёртывания, которые смешивают оба, получают клиента, у которого статический ключ в порядке, сертификат устарел, а сообщение об ошибке не упоминает ни то, ни другое.

Ловушка повторного использования имени субъекта

Соблазнительно повторно использовать отличительное имя предшественника, чтобы ничего ниже по цепочке не приходилось менять. Это удерживает строку издателя стабильной в интерфейсе и уничтожает единственный сигнал, который вам нужен. Два сертификата с одинаковыми субъектами и разными ключами нельзя различить по имени, поэтому пакет с обоими якорями даёт валидатору двух кандидатов и никакого правила выбора.

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

Ротация, которая не роняет сеть

Для плановой замены принимайте оба якоря ограниченное время, вместо того чтобы переключаться одним шагом. Выпустите новый УЦ и его промежуточные сертификаты, положите новый якорь в пакет каждого валидатора рядом со старым и только потом начинайте выпускать из него сертификаты партнёров. Партнёры со старыми идентичностями проверяются по старому якорю; новые работают по новому.

Сделанная в таком порядке, замена обратима на каждом шаге. Отказ, которого вы избегаете, — одновременное переключение: клиент, пропустивший обновление пакета, встречает шлюз, который уже вывел старый якорь из эксплуатации, рукопожатие умирает, и ни один журнал не говорит, какая сторона устарела.

Выводите из эксплуатации в обратную сторону. Перевыпустите каждую идентичность, которая должна сохраниться, подтвердите, что каждая предъявляет новую цепочку, и затем уберите старый якорь из пакетов. Выведите закрытый ключ старого УЦ из работы, потому что издатель, который всё ещё может подписывать, означает, что ротация не завершена. Сохраните сертификаты и записи о выпуске для аудита. Потерянный издатель восстанавливается к тому же доверию; компрометация требует новых идентичностей и не допускает возврата к старому якорю.

Проверяйте результат, а не список файлов

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

Подтвердите, что свежее подключение с новой идентичностью удаётся, а затем подтвердите, что идентичность, выпущенная выведенным УЦ, отвергается. Именно второй тест люди пропускают, и только он показывает, что старая инстанция больше не даёт доступа. Там, где развёртывание опирается на CRL или OCSP, проверьте, что точки распространения в новых сертификатах разрешаются и что опрашивающие партнёры достигают ответчика.

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

Похожие статьи