Двухфакторная аутентификация в OpenSSH: ключ+одноразовый код

    В предыдущей статье я рассказал, как добавить проверку одноразовых кодов при логине на свой сервер по SSH. Статья завершалась словами «если ходим по ключу — двухфакторная аутентификация не работает (не используется PAM)».

    С недавнего времени, после выпуска OpenSSH версии 6.2, ситуация поменялась к лучшему.

    +


    sshd(8): Added support for multiple required authentication in SSH protocol 2 via an AuthenticationMethods option. This option lists one or more comma-separated lists of authentication method names. Successful completion of all the methods in any list is required for authentication to complete.

    sshd(8): Добавлена поддержка множественных способов аутентификации в SSH протоколе 2 посредством параметра AuthenticationMethods. Этот параметр задаёт один или более списков с запятой-разделителем, перечисляющих названия методов аутентификации. Для аутентификации требуется успешное завершение всех методов в любом из списков.


    Начинаем


    Рассмотрю пример настройки: аутентификация по ключу и, затем, по одноразовому коду. У меня используется Debian Jessie (testing), там всё доступно «из коробки».

    Ставим нужный софт


    С момента написания прошлой статьи консольную тулзу положили рядом с модулем, поэтому на сервере нужен лишь один новый пакет:
    apt-get install libpam-google-authenticator


    На телефон с Android'ом ставим Google Autenticator и какой-либо сканер QR кодов, например такой. Если у вас на телефоне Windows Phone, то программа называется Authenticator (thnx to Skywrtr). Если у вас телефон с другой ОС, то вам сюда.

    Инициализация одноразовых кодов


    После запуска этой команды:
    google-authenticator

    первым вопросом будет, хотим ли мы time-based токены. Ответ — «y».

    В ответ получаем ASCII-art с таким симпатичным QR кодом, содержащим в себе секретный ключ (картинка кликабельная):


    Также, если вы хотите добавить данные в Google Authenticator вручную — выводятся сам секретный код инициализации и код для проверки.

    Также имеет смысл записать в надёжном месте 5 резервных кодов на случай, если вдруг с телефоном что-то случится. А по URL, который тулза тоже пишет, ходить не нужно — там лишь рисуется тот же самый QR код покрасивее. Вы ведь не хотите показывать свой секретный код Гуглу? :)

    QR код сразу сканируем из приложения в телефоне, потом отвечаем на вопросы в консоли.
    — Сохранить всё насовсем в ~/.google_authenticator?
    y
    — Запретить использование одного кода несколько раз? Помогает заметить или даже предотвратить атаку man-in-the-middle.
    y
    — Увеличить окно времени с приблизительно 1.5 минут до 4 минут?
    n (и тут сразу проверяем, точно ли время в телефоне; впрочем, Google Authenticator последних версий умеет синхронизировать время из интернета)
    — Ограничить число попыток логина за промежуток времени?
    y

    Настройка PAM


    В файле /etc/pam.d/sshd в группе «auth» должна быть лишь одна строка с вызовом модуля pam_google_authenticator.so:
    --- /etc/pam.d/sshd.orig   2013-05-22 05:05:49.000000000 +0400
    +++ /etc/pam.d/sshd        2013-09-04 16:36:43.141649326 +0400
    @@ -1,7 +1,9 @@
     # PAM configuration for the Secure Shell service
     
    +auth       required     pam_google_authenticator.so
    +
     # Standard Un*x authentication.
    -@include common-auth
    +#@include common-auth
     
     # Disallow non-root logins when /etc/nologin exists.
     account    required     pam_nologin.so
    


    Обращаю внимание на важный момент: с одной стороны, нужно закомментировать все строки и инклюды, добавляющие в группу «auth» проверку пароля, (например, «@include common-auth» выше), иначе у вас после одноразового кода спросят и пароль. С другой стороны, надо понимать, что аутентификация по паролю, которая в большинстве современных дистрибутивов также делается через PAM, будет таким образом сломана. Но это неопасно, т.к. ниже мы явно указываем серверу sshd, что проверка ключа обязательна и без правильного ключа авторизация будет неуспешна.

    Пока я не придумал, как можно сделать в PAM одновременно два сценария, например «ключ + одноразовый код» и «пароль + одноразовый код».

    Настройка PAM, дополнительные плюшки


    Можно сделать так, чтобы одноразовый код спрашивался не для всех. Для этого есть модуль pam_access.so, который нужно вписать перед pam_google_authenticator.so:
    auth       sufficient   pam_access.so accessfile=/etc/ssh/two-factor-skip.conf
    auth       required     pam_google_authenticator.so
    


    В файл /etc/ssh/two-factor-skip.conf можно указать что-то эдакое:
    # В локальной сети ходим только лишь с ключём
    + : ALL : 192.168.1.0/24
    # Этот юзер не может вводить одноразовые коды
    + : oldskool : ALL
    # Всех остальных заставим вводить ещё и одноразовый код
    - : ALL : ALL
    


    Настройка sshd


    В /etc/ssh/sshd_config включаем ChallengeResponse аутентификацию, PAM и указываем, что нужно проверять как ключ, так и одноразовый пароль.
    ChallengeResponseAuthentication yes
    UsePAM yes
    AuthenticationMethods publickey,keyboard-interactive
    


    Затем:
    service ssh reload


    Проверяем




    Совместимость


    Все консольные команды (ssh, scp, sftp) OpenSSH версии 5.9p1 и, очевидно, позднее — поддерживают ChallengeResponse аутентификацию. Более старые версии не проверял.

    lftp версий 4.3.3 и 4.4.8 не поддерживает. Другие версии не проверял.

    По данным funditus
    Irssi Conectbot на Android — поддерживает.
    SecureCRT — поддерживает, но в настройках соединения необходимо установить Keyboard-interactive и Publickey.
    Putty — поддерживает.


    Если кто-либо сможет проверить другие программы на (не)совместимость, пишите мне в личку — я допишу сюда.

    Ссылки


    1. OpenSSH 6.2 Release Notes
    2. Установка приложения Google Authenticator
    3. Google Authenticator
    4. Сканер QR кодов
    Ads
    AdBlock has stolen the banner, but banners are not teeth — they will be back

    More

    Comments 24

      0
      Спасибо за инструкцию, надо будет попробовать на Archlinux настроить. А с putty и connectbot что, они умеют такое?
        0
        У меня их под рукой нет. Будет хорошо, если вы попробуете и отпишите — я допишу в пост.
          0
          Irssi Conectbot на Android — поддерживает.
          SecureCRT — поддерживает, но в настройках соединения необходимо установить Keyboard-interactive
          Putty — поддерживает.
            0
            Пардон. Это я указал для входа по паролю, а не ключу.
              +1
              По ключу:
              Irssi Conectbot на Android — поддерживает.
              SecureCRT — поддерживает, но в настройках соединения необходимо установить Keyboard-interactive и Publickey.
              OpenSSH — поддерживает.
              Putty — поддерживает.

              Только всё равно надо вводить пароль для доступа во всех программах (google PAM модуль запрашивает и
              Verification code и Password). Не могу понять почему.
                0
                Нужно из группы auth удалить другие модули. У вас может быть инклюд другого файла, где вписан pam_unix.so, он как раз и спрашивает пароль.
            +1
            К слову, на WP программа называется «Authenticator».
              +1
              А куда делать удобная строка из предыдущей статьи в sshd_config?
              auth [success=1 default=ignore] pam_access.so accessfile=/etc/ssh/two-factor-skip.conf
              
                0
                My fault. Дописал в статью, но теперь строка немного другая.
                +3
                Кстати, сегодняшнее обновление Google Authentificator для IOS вышло с багом: при установке поверх имеющегося приложения, удаляются все настроенные ранее генераторы кодов. Как Google пропустили такую проблему при тестировании — непонятно. На этот момент приложение удалено (скрыто) из Apps Store.
                  +1
                  И Amazon Web Services, как приличные люди, написали об этом всем кастомерам. В отличии от Google…
                • UFO just landed and posted this here
                    +2
                    github.com/tadeck/onetimepass

                    import onetimepass as otp
                    my_secret = 'MFRGGZDFMZTWQ2LK'
                    my_token = otp.get_totp(my_secret)
                    
                    • UFO just landed and posted this here
                        +1
                        Сначала нужно получить ключ (который my_secret). Он передается google-authenticator'у в виде QR-кода (или его можно получить так). Как правило, реальный ключ, закодированный в base32. Он же передается на вход функции get_totp.

                        Далее поставить библиотеку onetimepass с помощью pip, как указано по ссылке выше.

                        Потом запустить python и набрать в нем код выше, заменив токен на свой.

                        Можно поэкспериментировать, добавив в ga аккаунт с ключом MFRGGZDFMZTWQ2LK.
                    0
                    В общем я так понял главный недостаток схемы — перестаёт работать вход по паролям.
                    Также хотел внести свои 5 копеек. Чтобы рисовался красивый QR-код, как указано в статье, необходима библиотека libqrencode3. В Debian, к примеру, её по умолчанию нет.
                      0
                      > В общем я так понял главный недостаток схемы — перестаёт работать вход по паролям.
                      Да.

                      > В Debian, к примеру, её по умолчанию нет.
                      Она есть и в jessie (testing), и в wheezy (stable). В статье описана настройка на jessie.
                        0
                        Она есть и в jessie (testing), и в wheezy (stable). В статье описана настройка на jessie.

                        Странно, я не нашёл в:
                        Debian GNU/Linux 6.0.7 (squeeze)
                        Debian GNU/Linux 7.0 (wheezy)
                        Debian GNU/Linux 7.1 (wheezy)
                        Linux Mint 13 Maya
                        CentOS release 6.4 (Final)
                          0
                          Debian GNU/Linux 7.0 (wheezy)
                          Debian GNU/Linux 7.1 (wheezy)


                          % apt-cache policy libqrencode3
                          libqrencode3:
                            Installed: (none)
                            Candidate: 3.3.0-2
                            Version table:
                               3.3.0-2 0
                                  500 http://ftp.debian.org/debian/ wheezy/main amd64 Packages
                          


                          Про другие вами упомянутые версии не в курсе.
                            0
                            Всё верно:
                            Installed: (none)
                            

                            Вы, вероятно, меня не правильно поняли или я неверно выразился. Я не говорил, что её нету в репозиториях. Она просто не установлена по умолчанию и, соответственно, без установки не рисуется QR-код.
                              0
                              А зачем ей быть установленной «по умолчанию»? :)

                              # apt-cache show libpam-google-authenticator |grep Depends
                              Depends: libc6 (>= 2.2.5), libpam0g (>= 0.99.7.1), libqrencode3
                              


                              По зависимостям подтянется. Причём, поставится обязательно, т.к. «depends», а не «recommended» или «suggested».
                                0
                                :).
                                Потому что в Squeeze и Wheezy 7.1:
                                # apt-cache show libpam-google-authenticator 
                                N: Unable to locate package libpam-google-authenticator
                                E: No packages found
                                

                                Соответственно надо собирать из исходников -> решать зависимости самим. Причём на отсутствие библиотеки libqrencode3 компиляция не ругается никак и всё работает. Просто не выводится QR-код.
                                  0
                                  Ну смотрите. В этой статье я указал

                                  У меня используется Debian Jessie (testing), там всё доступно «из коробки»


                                  В wheezy на сегодняшний момент, когда он стал stable, этого пакета уже нет. Однако ничто не мешает стандартным образом бэкпортировать пакет из jessie (testing). Более того, по-моему можно просто бинарный пакет поставить, судя по версиям в зависимостях.

                                  В предыдущей статье, написанной два года назад, упоминался wheezy, но тогда он был testing и там этот пакет был.

                                  Прошу прощения, если я недостаточно ясно осветил этот нюанс и упустил его в нашем общении.
                            0
                            Нашёлся squeeze ещё:

                            # apt-cache policy libqrencode3
                            libqrencode3:
                              Installed: (none)
                              Candidate: 3.1.1-1
                              Version table:
                                 3.1.1-1 0
                                    500 http://mirror.yandex.ru/debian/ squeeze/main amd64 Packages
                            

                      Only users with full accounts can post comments. Log in, please.