Если вы часто заходите на внешние сервера по SSH, или же у вас запускаются процессы, требующие сделать что-то на удалённом сервере, то вместо постоянного ввода пароля можно настроить аутентификацию в SSH по публичным ключам. К этому нужно подходить с умом и осторожностью – если у вас украдут ключи из каталога ~/.ssh, и у вас не настроен passphrase, то злоумышленники получат доступ ко всем вашим серверам. Лучший метод – установка passphrase во время генерации ключа или использование ssh-agent.

Давайте рассмотрим, как настроить аутентификацию.

Действия на локальном компьютере

Ключи находятся в каталоге ~/.ssh:

$ ls -al ~/.ssh/
total 32
drwx------   6 ctrld  staff   204 Oct 23 17:39 .
drwxr-xr-x+ 40 ctrld  staff  1360 Oct 22 21:01 ..
-rw-r--r--   1 ctrld  staff    78 Sep 26 20:02 config
-rw-------   1 ctrld  staff   668 Oct 23 17:39 id_dsa
-rw-r--r--   1 ctrld  staff   626 Oct 23 17:39 id_dsa.pub
-rw-r--r--   1 ctrld  staff  2410 Oct 13 11:44 known_hosts

Если каталог .ssh отсутствует, то достаточно попытаться зайти куда-нибудь по ssh. Если файлов id_dsa.* (я использую DSA, но можно и RSA) нет, то их нужно сгенерировать. Во время генерации ssh-keygen спросит passphrase (можно просто нажать Enter и она при входе не будет спрашиваться).

$ ssh-keygen -t dsa
Generating public/private dsa key pair.
Enter file in which to save the key (/Users/ctrld/.ssh/id_dsa):
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /Users/ctrld/.ssh/id_dsa.
Your public key has been saved in /Users/ctrld/.ssh/id_dsa.pub.
The key fingerprint is:
e3:9a:18:f0:4c:6e:3e:44:8f:d3:a3:cc:c2:db:e0:b5 ctrld@129-149-179-94.pool.ukrtel.net
The key's randomart image is:
+--[ DSA 1024]----+
|                 |
|                 |
|                 |
|    .            |
|  ...+  S        |
|   *+ +. .       |
| ..+Bo ..        |
| .o*=+ o         |
|  ooE.o          |
+-----------------+

Если вы предпочитаете RSA, то:

$ ssh-keygen -t rsa

Копируем строку с публичным ключом – он нам понадобится на удалённом компьютере (remote, а не removed :)

$ cat ~/.ssh/id_dsa.pub
ssh-dss AAAAB3............Pbec= ctrld@hostname.local

Для RSA:

$ cat ~/.ssh/id_rsa.pub
ssh-rsa AAAAB3............IJAw== ctrld@hostname.local

Действия на удалённом компьютере

Конечно же, на удалённом сервере должен быть запущен SSH-сервер. Обычно это OpenSSH, но встречаются и недобитые динозавры с коммерческими SSH-серверами (это вызывает моё искреннее удивление – да, есть и такое).

Заходим на удалённый сервер:

$ ssh ctrld@remote.net

Проверяем, есть ли каталог .ssh:

$ ls -al ~/.ssh

Если его нет, то делаем простой трюк – “ssh ctrld@localhost”, и .ssh создаётся автоматически.

Редактируем файл с публичными ключами, и добавляем соответствующий скопированный ключ.

Для DSA (authorized_keys2):

$ vi ~/.ssh/authorized_keys2

Вариант:

$ echo "ssh-dss AAAAB3............Pbec= ctrld@hostname.local" >> ~/.ssh/authorized_keys2

Для RSA (authorized_keys):

$ vi ~/.ssh/authorized_keys

Сохраняем файл, и (!) обязательно меняем права доступа на 0600, иначе файл публичных ключей не будет восприниматься:

$ chmod 600 ~/.ssh/authorized_keys*

Выходим с удалённого компьютера и пытаемся зайти на него снова по ssh. Если всё было сделано правильно, то будет запрошен passphrase, а если он был пустой, то будет произведён вход без запроса.

Альтернатива – скрипт ssh-copy-id

@andy_shev и @akaDimiG порекомендовали гораздо более простой вариант – использовать скрипт ssh-copy-id (по домену вижу, что это разработчики Putty, поэтому доверять можно). Но его первый недостаток в том, что он не входит в штатную поставку Mac OS X. Списать скрипт можно по простому рецепту:

sudo curl "http://www.chiark.greenend.org.uk/ucgi/~cjwatson/cvsweb/openssh/contrib/ssh-copy-id?rev=1.8;content-type=text%2Fplain" -o /usr/bin/ssh-copy-id
sudo chmod +x /usr/bin/ssh-copy-id

Второй недостаток – для использования нестандартных портов ssh скрипт нужно модифицировать. Третий – он использует ключи RSA, я же – DSA. Но если вас эти недостатки не смущают, то скрипт можно вполне использовать. Я же буду пользоваться описанным выше методом :-)

А вот скрипт с MacOSXHints, который мне понравился гораздо больше (спасибо за ссылку @akaDimiG):

#!/bin/sh

KEY="$HOME/.ssh/id_dsa.pub"

if [ ! -f ~/.ssh/id_dsa.pub ];then
    echo "private key not found at $KEY"
    echo "* please create it with "ssh-keygen -t dsa" *"
    echo "* to login to the remote host without a password, don't give the key you create with ssh-keygen a password! *"
    exit
fi

if [ -z $1 ];then
    echo "Please specify user@host.tld as the first switch to this script"
    exit
fi

echo "Putting your key on $1... "

KEYCODE=`cat $KEY`
ssh -q $1 "mkdir ~/.ssh 2>/dev/null; chmod 700 ~/.ssh; echo "$KEYCODE" >> ~/.ssh/authorized_keys; chmod 644 ~/.ssh/authorized_keys"

echo "done!"