SSH вглубь: ключи, конфиг, туннели, rsync

Базовый ssh user@host с паролем — только начало. Настоящая сила SSH — в ключах, конфиге, туннелях и быстрой синхронизации файлов. Разберём это слой за слоем.

SSH-ключи — пара из приватного и публичного ключа: публичный кладётся на сервер, приватный остаётся у вас. Аутентификация по ключу безопаснее пароля и позволяет заходить без ввода пароля каждый раз.

Зачем это на практике

Пароли можно подобрать, и серверы в интернете круглосуточно перебирают их по SSH. Ключи решают эту проблему: подобрать 4096-битный ключ невозможно. А ~/.ssh/config, туннели и rsync превращают SSH из «зайти на сервер» в полноценный инструмент: пробросить порт к закрытой базе данных, пройти через бастион-хост, синхронизировать каталог за секунды. Это ежедневная рутина любого DevOps.

Генерация ключей: ssh-keygen и ssh-copy-id

Создаём современную пару ключей на алгоритме Ed25519 (короче и быстрее RSA при той же стойкости):

ssh-keygen -t ed25519 -C "ernest@laptop"   # создать пару ключей
# приватный: ~/.ssh/id_ed25519  (никому не отдавать!)
# публичный: ~/.ssh/id_ed25519.pub (его кладём на серверы)

На вопрос про passphrase лучше задать пароль — это шифрует приватный ключ на диске. Теперь скопируем публичный ключ на сервер одной командой:

ssh-copy-id [email protected]   # добавит .pub в ~/.ssh/authorized_keys

После этого ssh [email protected] пустит вас по ключу, без пароля. Файл ~/.ssh/authorized_keys на сервере хранит список публичных ключей, которым разрешён вход.

Файл ~/.ssh/config: алиасы и настройки

~/.ssh/config — личный конфиг SSH-клиента: задаёт короткие имена (Host) и параметры подключения, чтобы не печатать длинные команды каждый раз.

Вместо ssh -i ~/.ssh/work_key -p 2222 [email protected] прописываем один раз:

cat ~/.ssh/config
Host prod
    HostName 10.20.30.40
    User deploy
    Port 2222
    IdentityFile ~/.ssh/work_key

Host *.internal
    User admin
    ProxyJump bastion

Теперь достаточно ssh prod — клиент сам подставит хост, пользователя, порт и ключ. Шаблоны вроде *.internal применяют настройки к группе хостов. Этот файл — основа удобной работы: scp, rsync и git тоже читают его.

Туннели: проброс портов -L и -R

Туннель заворачивает TCP-трафик внутрь зашифрованного SSH-соединения. Два направления:

Локальный проброс -L (доступ к закрытому сервису)

База данных слушает только на 127.0.0.1:5432 сервера и снаружи закрыта. Пробросим её к себе на ноутбук:

ssh -L 5432:localhost:5432 prod
# теперь localhost:5432 на ноутбуке == 127.0.0.1:5432 на сервере prod

Читается как «локальный порт 5432 → через prod → на его localhost:5432». Подключаете клиент БД к localhost:5432 — и работаете с удалённой базой через шифрованный канал.

Удалённый проброс -R (показать наружу свой сервис)

ssh -R 8080:localhost:3000 prod
# порт 8080 на сервере prod пробрасывается на localhost:3000 у вас

Полезно, чтобы временно показать коллегам локально запущенное приложение через публичный сервер.

ProxyJump: проход через бастион

Доступ к внутренним серверам часто только через один шлюз (bastion). Раньше для этого городили ProxyCommand, теперь есть лаконичный -J:

ssh -J bastion.example.com app-01.internal   # прыжок через бастион
# или в ~/.ssh/config:  ProxyJump bastion.example.com

Копирование файлов: scp vs rsync

Скопировать файл по SSH можно через scp — простой, но «тупой»: всегда копирует целиком. rsync умнее — передаёт только изменившиеся части и умеет докачивать:

scp report.pdf prod:/var/www/           # один файл на сервер
scp -r ./dist prod:/var/www/app/        # каталог рекурсивно

rsync -avz ./dist/ prod:/var/www/app/   # синхронизация: только различия
rsync -avz --delete ./dist/ prod:/var/www/app/   # + удалить лишнее на той стороне

Флаги rsync: -a архивный режим (права, время, симлинки), -v подробно, -z сжатие в пути. Для повторной выкладки каталога rsync в разы быстрее scp, потому что не гоняет неизменившиеся файлы.

ssh-agent: помнить ключ один раз

Чтобы не вводить passphrase ключа при каждом подключении, его держит в памяти ssh-agent:

eval "$(ssh-agent -s)"    # запустить агента
ssh-add ~/.ssh/id_ed25519 # добавить ключ (passphrase спросят один раз)
ssh-add -l                # список загруженных ключей

Опция ForwardAgent yes в конфиге позволяет «протащить» агента на сервер, чтобы оттуда ходить дальше по тем же ключам — удобно, но включайте только для доверенных хостов.

Как это работает под капотом

Аутентификация по ключу — это асимметричная криптография: сервер шлёт случайный вызов, клиент подписывает его приватным ключом, сервер проверяет подпись публичным ключом из authorized_keys. Приватный ключ при этом никогда не покидает вашу машину. Туннель -L/-R работает так: ssh открывает локальный слушающий сокет и каждый пришедший на него байт заворачивает в уже установленное шифрованное SSH-соединение, разворачивая на другом конце. ProxyJump устанавливает вложенное SSH-соединение: сначала к бастиону, а внутри него — к целевому хосту, так что трафик к цели шифруется дважды. rsync поверх SSH запускает свою копию на той стороне и обменивается контрольными суммами блоков, передавая только то, что реально различается.

Частые ошибки

  • Слишком открытые права на ключи и каталог .ssh. SSH откажется работать, если ~/.ssh доступен другим: нужно chmod 700 ~/.ssh и chmod 600 ~/.ssh/id_ed25519.
  • Скопировать или потерять приватный ключ. Публичный (.pub) раздаём, приватный — никогда; его утечка = доступ ко всем серверам с этим ключом.
  • Забыть / в конце пути rsync. rsync src/ dst/ и rsync src dst/ ведут себя по-разному: первый копирует содержимое, второй — сам каталог внутрь. Источник классических сюрпризов.
  • Путать -L и -R. -L тянет удалённый сервис к себе, -R выставляет ваш сервис на удалённой стороне. Перепутали направление — туннель «не работает».

Итоги

  • Ключи: ssh-keygen -t ed25519 + ssh-copy-id; приватный ключ держим у себя, публичный кладём в authorized_keys сервера.
  • ~/.ssh/config задаёт алиасы (Host) с хостом, портом, ключом и ProxyJump — короткий ssh prod вместо длинной команды.
  • Туннели: -L тянет закрытый удалённый порт к себе, -R выставляет локальный сервис наружу; -J ходит через бастион.
  • rsync -avz быстрее scp для повторной выкладки (шлёт только различия); ssh-agent + ssh-add избавляют от повторного ввода passphrase.
Проверьте себя
1. Какой ключ из пары нужно скопировать на сервер (в authorized_keys), а какой держать только у себя?
AНа сервер — публичный (.pub), у себя — приватный
BНа сервер — приватный, у себя — публичный
CОба на сервер
DНе важно, какой именно
2. База данных на сервере слушает только 127.0.0.1:5432. Как достучаться до неё с ноутбука через SSH?
Assh -R 5432:localhost:5432 server — удалённый проброс
Bssh -L 5432:localhost:5432 server — локальный проброс, после чего подключаться к localhost:5432 на ноутбуке
Cscp 5432 server
DНикак, локально слушающий сервис недостижим