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

Шаг 1: создайте ключ там, где он будет жить

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

Программный процесс выглядит так, ключ и запрос создаются в одной сессии:

umask 077
openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:3072 -out client.key
openssl req -new -key client.key -out client.csr -subj "/CN=alice-vpn/O=Example"

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

Шаг 2: поместите личность в запрос, а не в письмо

Решите, что VPN на самом деле аутентифицирует, до создания запроса, потому что этот ответ принадлежит внутрь CSR. OpenVPN традиционно привязывает личность клиента к общему имени сертификата, а такие инструменты, как strongSwan, сопоставляют строку личности с субъектом или альтернативным именем субъекта. Письмо, в котором сказано, что меня зовут alice, не является доказательством, а запрос, в субъекте которого сказано то же самое, лишь немного лучше.

Добавьте альтернативное имя субъекта, когда ваш проверяющий проверяет его, поскольку современное сопоставление часто игнорирует старый CN:

openssl req -new -key client.key -out client.csr \
  -subj "/CN=alice-vpn/O=Example" \
  -addext "subjectAltName=DNS:alice-vpn"

Держите CN коротким, стабильным и привязанным к учётной записи, а не к модели ноутбука. Имя, содержащее серийный номер устройства пользователя, — это проблема поддержки, ждущая первой замены оборудования.

Шаг 3: проверьте запрос, прежде чем подписывать его

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

Механическая часть — одна команда, и она должна вывести результат проверки вместе с субъектом:

openssl req -in client.csr -noout -verify -subject
openssl req -in client.csr -noout -pubkey | openssl pkey -pubin -noout -text

Обратите внимание, что это доказывает. Запрос, прошедший проверку, показывает только то, что отправитель владел соответствующим закрытым ключом на момент подачи; он не доказывает, что отправитель — лицо, указанное в субъекте, и не авторизует доступ к запрашиваемой группе или маршруту. Проверка регистрации — отдельные ворота, и запрос на группу, которую никто не утвердил, следует отклонить, а не тихо отредактировать.

Шаг 4: авторизуйте, затем подпишите с явными расширениями

Подписание — это место, где CA решает политику, а не принимает запрос дословно. Срок действия, использование ключа и расширение роли относятся к файлу расширений, а не к значениям по умолчанию, которые вы не вспомните через полгода. Клиентскому сертификату для аутентификации VPN в качестве назначения нужна аутентификация клиента.

cat > client.ext <<'EOF'
basicConstraints = CA:FALSE
keyUsage = digitalSignature
extendedKeyUsage = clientAuth
EOF
openssl x509 -req -in client.csr -CA ca.crt -CAkey ca.key \
  -CAcreateserial -days 365 -extfile client.ext -out client.crt

Используйте -CAserial с существующим файлом серийных номеров, если он уже применяется, и держите ключ CA офлайн или в том защищённом хранилище, которое называет ваша политика. Серийные номера сертификатов должны быть уникальными для каждого издателя; пересоздание файла серийных номеров с нуля рискует коллизиями, которые делают отзыв неоднозначным.

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

Шаг 5: установите его рядом с соответствующим ключом и докажите пару

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

openssl x509 -in client.crt -noout -pubkey | openssl pkey -pubin -outform DER | openssl sha256
openssl pkey -in client.key -pubout -outform DER | openssl sha256

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

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