← Весь справочник

ssh

Вход по ключу, ssh-keygen, права на ~/.ssh и authorized_keys, ~/.ssh/config, туннели, копирование через scp

ssh открывает шелл на удалённой машине или выполняет там одну команду. Вход по ключу работает так: закрытый ключ лежит у тебя, открытый — в ~/.ssh/authorized_keys пользователя на сервере. Сервер даёт клиенту доказать, что у него есть закрытый ключ, — сам ключ по сети не передаётся.

Синтаксис

ssh [опции] [пользователь@]хост [команда]
scp [опции] источник… назначение

Без команды открывается интерактивный шелл; с командой — она выполняется, вывод приходит к тебе, код выхода ssh равен коду выхода команды. У scp удалённый путь пишется как пользователь@хост:путь.

Опции ssh

ОпцияЧто делает
-i ключкакой закрытый ключ использовать
-p портпорт сервера (по умолчанию 22)
-l пользовательимя пользователя — то же, что пользователь@хост
-v, -vv, -vvvподробный лог подключения: какие ключи предложены, почему отказ
-qтихо: без предупреждений и баннеров
-o Опция=значениелюбая настройка из ssh_config (см. ниже)
-F файлдругой файл конфигурации вместо ~/.ssh/config
-G хостпоказать итоговые настройки для хоста и выйти, не подключаясь
-J [user@]прыжок[:порт]подключиться через промежуточный хост (jump host, bastion)
-L порт:хост:портлокальный туннель: свой порт → адрес, видимый с сервера
-R порт:хост:портобратный туннель: порт на сервере → адрес, видимый с твоей машины
-D портSOCKS-прокси через сервер
-Nне выполнять команду — только туннели
-fуйти в фон после входа (обычно вместе с -N)
-t / -ttвыделить терминал (нужно для sudo, top, vim в команде); -tt — даже без терминала у тебя
-Aпробросить ssh-agent на сервер (только на доверенные машины)
-Cсжатие трафика
-4 / -6только IPv4 / только IPv6

Частые настройки для -o и ~/.ssh/config

НастройкаЧто делает
HostName / User / Portнастоящий адрес, пользователь, порт
IdentityFile ~/.ssh/ключкакой ключ предлагать
IdentitiesOnly yesпредлагать только указанные ключи, а не все из агента
ProxyJump bastionходить через промежуточный хост (как -J)
StrictHostKeyChecking accept-newновый хост добавить в known_hosts без вопроса, изменившийся — отвергнуть
UserKnownHostsFile файлдругой файл known_hosts (/dev/null — не запоминать)
BatchMode yesникогда не спрашивать пароль и подтверждения — сразу ошибка; для скриптов
ConnectTimeout 5сколько секунд ждать подключения
ServerAliveInterval 30пинговать сервер, чтобы соединение не обрывалось по простою
LocalForward 9000 127.0.0.1:8000туннель как -L
ForwardAgent yesкак -A

ssh-keygen и ключи

КомандаЧто делает
ssh-keygen -t ed25519 -f ~/.ssh/id_x -C 'комментарий'создать пару: id_x (закрытый) и id_x.pub (открытый)
ssh-keygen -t rsa -b 4096RSA-ключ — для старых систем без ed25519
-N 'фраза' / -N ''парольная фраза / пустая — без вопросов
ssh-keygen -lf ключ.pubотпечаток (SHA256:…); -E md5 — в старом формате MD5
ssh-keygen -y -f ключвосстановить открытый ключ из закрытого
ssh-keygen -p -f ключсменить парольную фразу
ssh-keygen -c -C 'текст' -f ключсменить комментарий
ssh-keygen -F хост / -R хостнайти / удалить хост в known_hosts; хост с нестандартным портом пишется как [хост]:порт
ssh-copy-id -i ключ.pub [-p порт] user@хостдописать открытый ключ в authorized_keys на сервере
eval "$(ssh-agent -s)", ssh-add ключагент: ввести парольную фразу один раз на сессию; ssh-add -l — ключи в агенте

authorized_keys

Одна строка — один ключ: тип ключ комментарий, например ssh-ed25519 AAAAC3Nz… demo key. Перед ключом можно поставить ограничения через запятую:

ОпцияЧто делает
from="10.0.0.0/8"пускать с этим ключом только с этих адресов
command="…"при входе выполнять только эту команду, что бы ни просил клиент
restrictзапретить проброс портов, агента, терминал

Права

sshd игнорирует authorized_keys, если в него или в каталоги на пути к нему могут писать посторонние (проверка StrictModes):

ПутьПрава
домашний каталогникто, кроме владельца, не может писать: 755 или строже
~/.ssh700
~/.ssh/authorized_keys600
закрытый ключ у клиента600

Владелец всех этих файлов — сам пользователь, а не root.

Опции scp

ОпцияЧто делает
-P портпорт (заглавная!)
-i ключключ
-rкаталоги рекурсивно
-pсохранить время изменения и права
-qбез индикатора прогресса
-Cсжатие
-o Опция=значениекак у ssh; псевдонимы из ~/.ssh/config тоже работают

Примеры

# создать ключ ed25519 без парольной фразы
ssh-keygen -t ed25519 -f ~/.ssh/id_demo -N '' -C 'demo key'

# выполнить одну команду на сервере
ssh -i ~/.ssh/id_demo -p 2222 user@localhost 'uname -a'

# разложить открытый ключ пользователю с правильными правами
install -d -m 700 -o user -g user /home/user/.ssh
cat ~/.ssh/id_demo.pub >> /home/user/.ssh/authorized_keys
chown user:user /home/user/.ssh/authorized_keys
chmod 600 /home/user/.ssh/authorized_keys

# копировать файл туда и каталог обратно
scp -P 2222 -i ~/.ssh/id_demo notes.txt user@localhost:/tmp/
scp -r -P 2222 user@localhost:~/project ./project-copy

# передать данные через stdin
ssh user@localhost 'cat > /tmp/copy.txt' < notes.txt

# туннель: порт 8000, открытый только на сервере, становится localhost:9000 у тебя
ssh -f -N -L 9000:127.0.0.1:8000 user@server

# через промежуточный хост
ssh -J user@bastion user@internal

# почему не пускает: смотри строки Offering и Authentications that can continue
ssh -v -i ~/.ssh/id_demo user@localhost

# итоговые настройки для хоста с учётом config
ssh -G demo | grep -E '^(hostname|port|user|identityfile) '

Чтобы не повторять опции, опиши хост в ~/.ssh/config:

cat >> ~/.ssh/config <<'EOF'
Host demo
    HostName localhost
    Port 2222
    User user
    IdentityFile ~/.ssh/id_demo
    IdentitiesOnly yes
EOF

ssh demo              # то же, что ssh -i ~/.ssh/id_demo -p 2222 user@localhost
scp file.txt demo:/tmp/

Подводные камни

  • Плохие права = молчаливый отказ. authorized_keys с правами 666 или домашний каталог 777 — и сервер просто отвечает Permission denied (publickey,…). Причина видна только в логе sshd (Authentication refused: bad ownership or modes), клиент её не узнает.
  • -p у ssh, -P у scp. У scp строчная -p значит «сохранить время и права файлов», а не порт.
  • Закрытый ключ с правами 644 клиент откажется использовать: WARNING: UNPROTECTED PRIVATE KEY FILE!. Нужно chmod 600.
  • В authorized_keys — одна строка на ключ. Ключ, разорванный переносом при копировании, не сработает. Добавляй через >>, а не >, чтобы не стереть чужие ключи.
  • Too many authentication failures — клиент перебрал все ключи из агента раньше нужного. Помогает IdentitiesOnly yes с явным IdentityFile.
  • REMOTE HOST IDENTIFICATION HAS CHANGED — ключ сервера не совпал с known_hosts. Если смена ожидаема (сервер пересоздали), удали старую запись ssh-keygen -R, а не отключай проверку целиком.
  • Кавычки в удалённой команде. ssh host echo $HOME подставит твой $HOME ещё локально. Бери команду в одинарные кавычки.
  • Интерактивным программам нужен терминал. ssh host sudo … с запросом пароля без -t отвечает a terminal is required to read the password; полноэкранным vim, less, top тоже нужен -t.
  • В ~/.ssh/config срабатывает первое найденное значение: общий Host * ставь в конец файла.
  • После правки /etc/ssh/sshd_config проверь его через sshd -t до перезапуска службы — иначе можно потерять доступ.

См. также

chmod · chown · rsync · useradd · openssl · ansible