Смарт-карта, на которой уже есть правильный ключ, всё равно должна получить указание, какой объект на ней использовать. OpenConnect в такой ситуации не хочет скопированный файл .key; ему нужен PKCS#11 URI, который называет сертификат и, когда автоматический поиск не может завершить работу, закрытый ключ рядом. Неудобство в том, что синтаксически корректный URI ничего не доказывает. Он должен называть регистрацию, которой шлюз уже доверяет, а не просто объект, который карта готова открыть.

Что клиент хочет вместо экспортированного ключа

Параметр -c обычно принимает путь к файлу, но когда значение разбирается как PKCS#11 URI, OpenConnect рассматривает его как ссылку на объект внутри токена, а не на файл на диске. Параметр -k ведёт себя так же для закрытого ключа. Ничего не экспортируется, и ключ никогда не покидает защиту, которую обеспечивает карта. Клиенту от вас нужно имя, с которым согласны модуль токена, хранилище сертификатов и регистрация на шлюзе.

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

Два URI, две разные задачи

URI сертификата отвечает, какую личность вы заявляете. Он указывает на объект сертификата, открытый ключ и строка субъекта которого совпадают с профилем учётной записи или устройства, выданным администратором VPN. Тот же сертификат обычно поставляется с объектом закрытого ключа, сохранённым рядом, и именно эта пара нужна рукопожатию TLS.

URI ключа отвечает, где находится соответствующий закрытый материал, когда OpenConnect не может его вывести. При заданном только -c клиент строит поиск ключа из свойств сертификата; указание -k заменяет догадку явной ссылкой на объект. PIN токена — третий, не связанный вход: он разблокирует карту для операции и никогда не идентифицирует объект.

openconnect --protocol=anyconnect \
  -c 'pkcs11:model=PKCS%2315%20emulated;manufacturer=piv_II;serial=1a2b3c4d;id=%01' \
  vpn.example.net

Всё в этой строке в кавычках — данные. Точки с запятой разделяют атрибуты URI, а процентные escape-последовательности кодируют символы, которые иначе сломали бы разбор, поэтому весь аргумент должен невредимым пройти через оболочку.

Поиск URI, соответствующего вашей регистрации

GnuTLS поставляет p11tool, который перечисляет, до чего текущий пользователь действительно может добраться через p11-kit. Начните с p11tool --list-tokens, затем перечислите объекты сертификатов на нужном токене. Добавьте --login, когда объекты появляются только после PIN, и сравните субъект и издателя с записью регистрации, а не выбирайте первое, что появится.

Если токен вообще не показывается, проблема ниже OpenConnect: в p11-kit нет зарегистрированного модуля для этого промежуточного слоя или модуль зарегистрирован для другой учётной записи. Системная регистрация находится в /etc/pkcs11/modules, а каталог пользователя может содержать то же самое, не трогая системную копию. Проверьте, что путь поставщика в файле модуля указывает на библиотеку, которую программное обеспечение читателя действительно установило.

Копируя URI из списка, сохраняйте кавычки вокруг него. Точки с запятой без кавычек обрывают аргумент на первом атрибуте, и клиент затем сообщает об объекте, который не может найти.

Когда автоматический поиск ключа сдаётся

OpenConnect может вывести поиск ключа из URI сертификата, но точное сопоставление, которое он выполняет, зависит от версии, а обработка типа объекта и метки менялась со временем. Совет сокращать URI, пока он не заработает, описывает старый обходной путь, а не требование. Если выведенный поиск не удаётся, назовите ключ явно с помощью -k, вместо того чтобы превращать URI сертификата во что-то более расплывчатое.

Прежде чем винить клиент, убедитесь, что ключ существует и виден с помощью p11tool --list-keys. Затем проверьте, помечен ли объект как пригодный для подписи или расшифровки, потому что ключ, созданный с неправильными атрибутами, не сможет завершить рукопожатие, каким бы правильным ни был URI. Не переносите сериализованное значение pkcs11-id из профиля OpenVPN в параметр OpenConnect; два клиента используют разные форматы идентификатора, даже когда обращаются к одной и той же карте.

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

Сбои, которые только выглядят как проблемы с URI

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

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

Двигайтесь от объекта наружу: видит ли p11tool токен, видит ли сертификат и ключ, принимает ли OpenConnect URI, и только потом спрашивайте, принимает ли шлюз личность. У каждого шага своё сообщение об ошибке, и каждый дешевле проверить, чем следующий.

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