Как создать ключ VPN-клиента и отправить CSR на подпись
Держите закрытый ключ у клиента и отправляйте только запрос. Проверьте CSR, утвердите личность, подпишите с явными расширениями, затем подтвердите пару.
Рано или поздно пользователь 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Оба дайджеста должны совпасть. Затем подключитесь и подтвердите, что личность, которую регистрирует сервер, — это та, которую вы авторизовали, а не просто то, что туннель поднялся. Если ключ потерян или устройство заменено, ответ — отзыв плюс новый запрос с нового устройства; просьба к администратору прислать ключ откуда-то ещё не восстанавливает оригинал и тихо ломает модель, которая делала запрос безопасным.