Когда я стал счастливым обладателем устройства Yubikey 5 nfc и узнал, что при помощи него можно авторизовываться по ssh, я столкнулся с множеством статей про настройку подобной связки на unix-системах… И с полнейшим отсутствием адекватного материала про Windows.
Разобравшись в теме, собрав информацию из многих источников и проверив работоспособность связки на личном опыте, я пишу эту статью для тех, кто решит повторить мой путь.


О чём эта статья


Я предполагаю, что, читая мой гайд, вы уже создали gpg-ключи в нужной вам конфигурации и записали их на Yubikey. Информации о том, как это сделать, достаточно много, и инструкции не отличаются для Linux и Windows.


Также, я предполагаю, что в вашей системе уже установлен GnuPG последней версии (на момент написания статьи — версия 2.40), и вы умеете базово с ним обращаться.


Почитать про создание ключей и запись их на Yubikey можно здесь.


Скачать GnuPg для Windows можно здесь (во всяком случае, я использовал именно gpg4win).


Желаемый результат


Выполнив все шаги, описанные ниже, вы получите:


  • Возможность использовать Yubikey вместе с OpenSSH в Windows;
  • Возможность использовать Yubikey вместе с ssh внутри Wsl.

Подготовка


Перед тем, как приступить к настройке, убедитесь, что:


  • У вас установлена Windows 10 версии 1803 или новее;
  • У вас установлен gpg4win или другая версия GnuPg;
  • Команда gpg --card-status корректно отображает информацию о вашем Yubikey и ключах, записанных на нём;
  • Соответствующие публичные ключи хранятся в gpg на компьютере и отображаются по команде gpg --list-keys.

Настройка GnuPg


Первым делом нам необходимо изменить конфигурацию GnuPg таким образом, чтобы GnuPg использовал gpg-agent, а также включить поддержку OpenSsh в самом агенте.


Для начала выясним, где GnuPg будет искать конфигурационные файлы. Для этого введём в командной строке следующее:
gpgconf --list-dirs homedir
В ответ мы получим путь, по которому и хранятся все данные и настройки gpg в вашей системе.
Далее необходимо открыть папку по указанному пути и создать в папке два файла: gpg.conf и gpg-agent.conf.


Затем, в файле gpg.conf мы должны написать следующее:
use-agent
Таким образом мы укажем gpg необходимость использовать gpg-agent.


А в файле gpg-agent.conf мы пишем это:


enable-putty-support
enable-ssh-support

Если у вас в системе установлен Windows OpenSsh версии 9.0 или новее, вы можете добавить третьей строкой следующее:
enable-win32-openssh-support
Зачем это нужно, я объясню чуть позже.


Теперь, изменив конфигурацию gpg, мы можем запустить gpg-agent такой командой:
gpg-connect-agent /bye
А остановить запущенный агент при помощи команды
gpg-connect-agent killagent /bye


Убедившись, что агент запускается без ошибок, мы должны создать ещё один файл в директории gnupg.
Файл должен называться sshcontrol, а поместить в него нужно keygrip вашего ключа для аутентификации (то есть ключа с capability a).


Чтобы получить keygrip 'ы всех ваших ключей, используйте команду
gpg --list-keys --with-keygrip


Вывод команды будет выглядеть примерно так:


pub   rsa4096 2022-07-18 [SC]
      58DE66838D1CFAD22A5283F3AEFB45ACA247412F
      Keygrip = B53F9C92114AB637817A4EE28242654636D718A2
uid           [ultimate] Kirill Belousov <belousov.k.m@yandex.ru>
uid           [ultimate] Kirill Belousov <bkm.grotschool@yandex.ru>
uid           [ultimate] Kirill Belousov <funnytastymeat@gmail.com>
sub   rsa4096 2022-07-18 [E]
      Keygrip = B68CC0A9905D5737547DDC8AEA532259F2679107
sub   rsa4096 2022-07-18 [A]
      Keygrip = B21B4285DC89262A7EF194E68C73AE76C793D591

Обратите внимание на две последние строки. Буква [a] в квадратных скобках означает, что сабключ предназначен именно для аутентификации, а строчка keygrip=... — и есть искомый keygrip.
Необходимо скопировать всё, что написано после keygrip= и вставить в файл sshcontrol.
Обратите внимание, что до и после вставленной строки не должно быть пустых строк, а на самой строке не должно быть пробелов в начале и в конце.


Сохранив файл sshcontrol, перезапустите gpg-agent при помощи описанных выше команд.


Ещё одна утилита


После запуска gpg-agent в системе появится сокет, при помощи которого ssh может подключаться к gpg и запрашивать ssh-ключи… На linux.
Ssh в Windows с такими сокетами работать не умеет. Именно поэтому нам понадобится внешняя утилита под названием wsl-ssh-pageant.


Скачать утилиту можно здесь.
Для загрузки доступны две версии программы: версия для командной строки (запускается с окном командной строки, которое будет висеть открытым, пока программа работает), и gui-версия, которая запускается в фоне, не "светится" окном командной строки и может быть остановлена только через диспетчер задач или при помощи иконки в системном трее.
Для использования с планировщиком задач (для автоматического запуска) больше подойдёт первый вариант, а для ручного запуска по нажатию на ярлык — вторая. Но какую версию использовать — исключительно ваш выбор, по функционалу они идентичны.


Скачав утилиту и сохранив её в удобном месте, запустите её со следующими параметрами:
--wsl C:\path\to\wsl\socket.sock --winssh pipe-name-for-windows-ssh --systray --force


Параметр --wsl <path> позволяет указать путь, по которому будет создан файл сокета для wsl. Если вам не нужна поддержка Wsl, можете опустить этот параметр.
--winssh <pipe-name> позволяет указать имя для именованой трубки, при помощи которой OpenSsh в Windows будет пытаться подключиться к агенту.
--systray включает отображение иконки в системном трее,
а --force перезапускает утилиту и пересоздаёт все сущности, если утилита уже запущена (полезно для быстрого перезапуска по нажатию на ярлык).


Я обычно запускаю gui-версию программы при помощи ярлыка со следующим содержимым:
C:\wsl-ssh-pageant\wsl-ssh-pageant-amd64-gui.exe --wsl C:\wsl-ssh-pageant\ssh-agent.sock --winssh ssh-pageant --systray --force


Запустив утилиту и убедившись, что она стартовала без ошибок (по иконке в трее или по выводу командной строки), перейдём к последнему шагу.


Изменение переменной окружения SSH_AUTH_SOCK


Последним штрихом, после которого всё должно заработать, станет установка переменной окружения, при помощи которой Windows OpenSsh будет искать подключение к gpg через настроенную выше утилиту.


Чтобы добавить необходимую переменную окружения, в командной строке выполняем команду
setx SSH_AUTH_SOCK \\.\pipe\<name>
Вместо <name> подставьте то, что вы указали в параметре --winssh при запуске wsl-ssh-pageant.


Настройка Wsl


Если вам необходима авторизация по ssh при помощи Yubikey в Wsl, вы должны создать переменную окружения SSH_AUTH_SOCK в Wsl, а в качестве её значения указать путь к файлу сокета, создаваемому wsl-ssh-pageant.
В моём случае команда выглядит следующим образом:
export SSH_AUTH_SOCK=/mnt/c/wsl-ssh-pageant/ssh-agent.sock


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


Для тех, у кого Windows OpenSsh версии 9.0


При настройке gpg я упоминал об опции, доступной "не для всех".
Если у вас gpg версии 2.40 или новее и Windows Openssh версии 9.0 или новее, вы можете обойтись без wsl-ssh-pageant и использовать gpg-agent и ssh напрямую.


Если вы при заполнении файла gpg-agent.conf вписали опцию enable-win32-openssh-support, вернитесь к шагу с настройкой переменной окружения и в качестве значения для переменной установите \\.\pipe\openssh-ssh-agent.


Внимание! Несмотря на то, что версии всех компонентов у меня подходят по условиям, на моей системе этот способ не сработал, и мне пришлось вернуться к использованию wsl-ssh-pageant.
Если вы столкнётесь с такой же проблемой и найдёте её решение, пожалуйста, расскажите о своём опыте в комментариях. Не забудьте указать версии всех используемых компонентов и версию вашей системы.


Проверка


Чтобы убедиться, что все компоненты видят друг друга, и настройка выполнена правильно, выполните две команды
gpg --export-ssh-key <id_публичного_ключа>
Эта команда выведет в консоль публичный ssh-ключ, соответствующий аутентификационному сабключу.


Затем, убедившись, что gpg-agent и wsl-ssh-pageant запущены, запустите команду
ssh-add -L
Эта команда выведет все ssh-ключи, которые Windows OpenSsh смог найти в вашей системе.
Если среди выводимых ключей отображается такой же ключ, который отобразила предыдущая команда gpg --export-ssh-key, значит вы настроили всё правильно и теперь можете авторизоваться по ssh при помощи вашего Yubikey.


Заключение


Я надеюсь, что статья оказалась для вас полезной, и у вас всё получилось.


Если у вас есть какие-либо дополнения, рекомендации и советы, не стесняйтесь оставлять их в комментариях. Думаю, другие читатели будут вам благодарны.

Комментарии (5)


  1. l0ser140
    22.01.2023 14:06

    Данное решение работает с WSL2?

    При прокидывании сокета от keeagent в WSL2 мне приходилось использовать socat + npiperelay, т.к. при монтировании внутрь WSL2 сокеты не работали.


    1. cyrmax Автор
      22.01.2023 23:39

      Кажется, что, несмотря на то, что разработчик wsl-ssh-pageant утверждает обратное, с wsl2 оно не работает.
      У меня получилось прокинуть в wsl2 только при помощи socat + npiperelay. Так что, видимо, это единственный рабочий вариант


    1. FFxSquall
      23.01.2023 15:30
      +1

      вот это завелось с wsl2 (поддержка прекращена), но там есть баги в этом issue можно взять исправленную версию. В целом всё работало на момент когда тестировал


  1. Johan_Palych
    22.01.2023 14:09
    +1

    И с полнейшим отсутствием адекватного материала про Windows


    Использовал данный материал в 2020г.
    SSH on Windows with private key on Yubikey(Posted on March 24, 2020 by Sid) - WSL, minGW/GIT Bash and Yubikey 5.
    Автор статьи писал:
    "...Я также связался с Yubico, чтобы узнать, есть ли у них какая-либо внутренняя документация, поскольку внешней документации по этому поводу было мало.
    Удивительно, но они только что отправили несвязанные ссылки на сторонние посты в блогах..."

    На сегодня, похоже качество материалов изменилось к лучшему:
    Using Your YubiKey with OpenPGP
    YubiKey-Guide-wsl


    1. cyrmax Автор
      22.01.2023 23:42

      Большое спасибо за последнюю ссылку :)
      Предпоследняя есть у меня в статье, в самом начале, а вот последняя - действительно хороший материал, который интересно прочитать.

      Кстати, если бы я изначально нашёл именно его, я бы не совершил глупейшую ошибку, когда мастер-ключ является ещё и ключом для подписания [S].

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