Debian.pro/

Про Debian


SSH ключи.

Я часто упоминаю в статьях ssh ключи. В определенный момент ко мне пришло осознание того, что про них-то написать я и забыл. Статья примитивная, но «чтобы было». Опытные пользователи в статье заметят много странностей, они смогут сказать много «а вот тут можно и так». man ssh-keygen я и сам могу почитать. И вы можете. Я не собираюсь его в сотый раз здесь переписывать.

SSH ключи позволяют авторизовываться нам на сервере без ввода пароля пользователя. Для чего оно? Кто-то говорит, что так безопаснее (отчасти они правы, в конце статьи покажу почему). Для меня же это удобный способ авторизовываться на тех пачках серверов, куда у меня есть доступ.
Логика действия простая — на сервере хранится открытая часть ключа, у вас — закрытая. При попытке авторизации происходит обмен частями ключа, если они «подойдут друг к другу» — сервер вас пустит. Мы сидели и считали — ssh ключик могут поломать года за 3 большим кластером (впрочем, могут и с первой попытки). Но вы же настроили fail2ban, верно? В любом случае, шанс — меньше.

Теперь по поводу пароля на ключ. Для кросс-авторизации между серверами (для работы rsync, например) использовать пароль — глупо. Поэтому я создаю отдельные ключи для каждого сервера (без пароля), кладу их подальше и кроном каждый час дергаю откуда-нибудь актуальный список.

Для себя же я использую запароленный ключ. Один черт, убунта или дебиан после первого ввода сохраняют ключ расшифрованным в памяти до логаута (а когда мы отходим от ноута — мы нажимаем ctrl-alt-l, right?). Остальным, вероятно, придется вводить пароль при каждом коннекте или настроить ssh-agent ручками.

Ну да ладно. Всё равно ssh ключи — они из разряда «must have».

Сначала создадим ключ у себя на локальной машине (тем пользователем, которым мы обычно сидим в системе. Хотя, можно и рутом создать, но и ходить по ssh нужно будет тоже рутом):
inky@laptop:~$ ssh-keygen -t dsa -b 1024
# создаем ключ зашифрованный алгоритмом dsa, 1024 бита
дальше нам задают вопросы:
Enter file in which to save the key (/home/inky/.ssh/id_dsa): жмем enter
Enter passphrase (empty for no passphrase): вводим пароль от ключа
Enter same passphrase again: и ещё раз пароль от ключа
Дальше нам напишут:
Your identification has been saved in /home/inky/.ssh/id_dsa.
Your public key has been saved in /home/inky/.ssh/id_dsa.pub.

Файлик /home/inky/.ssh/id_dsa нужно беречь как зеницу ока и не допускать его попадания в чужие руки.
/home/inky/.ssh/id_dsa.pub — открытая часть ключа, её содержимое кидаем на сервер.
Как закидывать Pub часть. Простейший способ, который есть не везде:
inky@laptop:~$ ssh-copy-id root@server -p22
У нас спросят пароль.
После этого мы сможем подключаться к серверу по ключу. И спрашивать у нас будут пароль ключа (если будут). Всё это актуально, если вы не отключили авторизацию по ключам на сервере.
Если у вас нет утилиты ssh-copy-id, то вам нужно закинуть содержимое файла id_dsa.pub в ~/.ssh/authorized_keys одной строкой. Например:
inky@laptop:~$ cat ~/.ssh/id_dsa.pub | ssh user@server "touch ~/.ssh/authorized_keys && tee ~/.ssh/authorized_keys" && ssh user@server "cat ~/.ssh/authorized_keys"

Возьмите в привычку всегда делать вот такое:
inky@laptop:~$ chmod -R 600 ~/.ssh/
user@server:~$ chmod -R 600 ~/.ssh/

Ну и да. Если вы сохранили ключ в недефолтное место, то используйте параметр -i (и для ssh-copy-id, и для ssh):
inky@laptop:~$ ssh-copy-id -i /somedir/id_dsa.pub user@server
inky@laptop:~$ ssh -i /somedir/id_dsa.pub user@server

А теперь почему безопаснее. Вы представляете насколько сложнее нагенерировать столько 1024 битных ключей, чтобы один из них подошел? нет? http://ru.wikipedia.org/wiki/DSA почитайте) А там ещё и псевдослучайные цифры.
И запароленный файлик менее уязвим, чем куча паролей, которые нам приходится где-либо хранить.


Комментарии (13):

  1. velizarov :

    Пожалуй только упускаете момент, если работать не из под root, пароль всё равно нужен. Чтобы «не забывать» 38-ми символьный пароль от пачки серверов купил себе yubikey, благодаря ему жизнь становится проще.

  2. Ну рутом можно сделать su в любого пользователя.
    PermittRootLogin without-password никто не отменял)

  3. Логика действия простая – на сервере хранится открытая часть ключа, у вас – закрытая. При попытке авторизации происходит обмен частями ключа, если они «подойдут друг к другу» – сервер вас пустит.
    То есть клиент посылает закрытую часть ключа на сервер? Вот уж действительно: «Для каждой вещи есть 2 объяснения — одно простое, другое правильное».

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

  4. Taz :

    inky@laptop:~$ ssh-copy-id root@server -p22

    нахера? оно и так по дефолту на 22 идет.

    Если у вас нет утилиты ssh-copy-id

    lolwut? http://packages.ubuntu.com/oneiric/amd64/openssh-client/filelist
    она в ЛЮБОМ дистре идет из коробки, вместе с ссх.
    если нет ssh-keygen, то и нету ssh-copy-id
    но я такого еще не разу не видел :)

  5. > она в ЛЮБОМ дистре идет из коробки, вместе с ссх.
    в «дистре» под названием FreeBSD:
    [root@xxx ~]# which ssh-keygen
    /usr/bin/ssh-keygen
    [root@xxx ~]# which ssh-copy-id
    [root@xxx ~]# ssh-copy-id root@somewhere
    bash: ssh-copy-id: command not found

  6. жопа :

    ssh-copy-id это шелл-скрипт.

    cat `which ssh-copy-id`
    #!/bin/sh

    # Shell script to install your identity.pub on a remote machine
    # Takes the remote machine name as an argument.
    # Obviously, the remote machine must accept password authentication,
    # or one of the other keys in your ssh-agent, for this to work.

    ID_FILE=»${HOME}/.ssh/identity.pub»

    if [ «-i» = «$1» ]; then
    shift
    # check if we have 2 parameters left, if so the first is the new ID file
    if [ -n «$2» ]; then
    if expr «$1» : «.*\.pub» > /dev/null ; then
    ID_FILE=»$1″
    else
    ID_FILE=»$1.pub»
    fi
    shift # and this should leave $1 as the target name
    fi
    else
    if [ x$SSH_AUTH_SOCK != x ] ; then
    GET_ID=»$GET_ID ssh-add -L»
    fi
    fi

    if [ -z «`eval $GET_ID`» ] && [ -r «${ID_FILE}» ] ; then
    GET_ID=»cat ${ID_FILE}»
    fi

    if [ -z «`eval $GET_ID`» ]; then
    echo «$0: ERROR: No identities found» >&2
    exit 1
    fi

    if [ «$#» -lt 1 ] || [ «$1» = «-h» ] || [ «$1» = «—help» ]; then
    echo «Usage: $0 [-i [identity_file]] [user@]machine» >&2
    exit 1
    fi

    { eval «$GET_ID» ; } | ssh $1 «umask 077; test -d .ssh || mkdir .ssh ; cat >> .ssh/authorized_keys» || exit 1

    cat <<EOF
    Now try logging into the machine, with "ssh '$1'", and check in:

    .ssh/authorized_keys

    to make sure we haven't added extra keys that you weren't expecting.

    EOF

  7. Людмила :

    А можно сделать так, чтобы все пользователи могли авторизоваться только по ключам, а какой-то один — и по паролю тоже?

  8. /usr/sbin/usermod $username —lock можно сделать, если в него su делать не нужно.

  9. Людмила :

    Нет. Надо наоборот — одному пользователю разрешить авторизацию по паролю, а не запретить. Запрет авторизации по паролю стоит в конфиге SSH, можно ли этот запрет сделать не для всех?

  10. Match user
    PasswordAuthentication yes

  11. Если у кого при этом всплывет трабл «agent admitted failure to sign using the key» — Нужно просто выполнить команду ssh-add

  12. AC :

    @
    Возьмите в привычку всегда делать вот такое:
    inky@laptop:~$ chmod -R 600 ~/.ssh/
    user@server:~$ chmod -R 600 ~/.ssh/
    @
    Если же сделать так, то нету прав на execute, и получаю.
    [sun@st ~]$ chmod -R 600 ~/.ssh/
    chmod: cannot access ‘/home/sun/.ssh/known_hots’: Permission denied
    chmod: cannot access ‘/home/sun/.ssh/id_rsa’: Permission denied
    …..
    [sun@st ~]$ ssh debsrv
    ssh: Could not resolve hostname debsrv

Написать комментарий