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 4096 | RSA-ключ — для старых систем без 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 или строже |
~/.ssh | 700 |
~/.ssh/authorized_keys | 600 |
| закрытый ключ у клиента | 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до перезапуска службы — иначе можно потерять доступ.