Предположим, у тебя есть зоопарк на десяток серверов и каждый раз ты колотишь в терминал что-то типа ssh -p 22 user@176.111.222.333, предварительно скопировав это из какого-нибудь файлика - у меня для тебя новость. Так делать не надо. Вообще. Ну или иногда, если прям очень приперло.
Есть такая штука ~/.ssh/config. Замечательный файл, в который один раз записываешь все свои сервера с нужными параметрами подключения, а потом ходишь к ним вот так ssh user@hostname. Звучит банально, но оказывается многие про это не ведают, потому этот пост я и написал.
Давай покажу кусок своего реального конфига и пройдусь по нему построчно. А ты уже решай, что из него можно вытащить полезного.
Host *
ServerAliveInterval 60
ServerAliveCountMax 3
TCPKeepAlive yes
Host dz-net
Hostname 176.222.222.222
User dz
Port 22
LocalForward 8443 127.0.0.1:8443
LocalForward 8006 127.0.0.1:8006
LocalForward 2053 127.0.0.1:2053
LocalForward 3000 127.0.0.1:3000
Host dz-net-irunode
Hostname 91.222.222.222
User dz
Port 22
LocalForward 2054 127.0.0.1:2053
Host lf
Hostname 176.222.222.222
User lf-sys
Port 22
Host lf-sys-node
#Hostname 176.222.222.222
Hostname 10.15.15.100
User lf-sys
Port 22
ProxyJump lf
IdentityFile ~/.ssh/id_rsa.lf-sys-node
Host dz-lab-local
Hostname 192.168.000.000
User dz
Port 22
Host dz-lab
Hostname 212.222.222.222
User dz
Port 5022
Блок Host * - настройки для всех соединений сразу.
Звёздочка означает применить параметры ко всем хостам, к которым ты подключаешься. Удобно. Вообще, эти строки можно прописать в /etc/ssh/ssh_config.d/, но это system-wide файл, и закинутые тобой параметры распространятся на всех юзеров системы, а ~/.ssh/config только на пользователя, в чьей домашней папке он лежит. Как тебе лучше решай сам.
ServerAliveInterval 60 - раз в 60 секунд клиент отправляет на сервер маленький служебный пакет. Просто чтобы соединение не считалось простаивающим. Если этого не делать, любой роутер по дороге через несколько минут молчания может решить, что соединение мёртвое, и прибить его. Знакомая боль: открыл ssh, начал что-то делать, отвлёкся на чай/кофе/фаянсовый_трон, вернулся - а терминал не алё.
ServerAliveCountMax 3 - сколько таких пакетов может остаться без ответа, прежде чем клиент решит "ну всё, прощаемся" и отвалится. У меня три пакета по 60 секунд - то есть три минуты тишины и разрыв. Можно поставить больше, если у тебя связь так себе.
TCPKeepAlive yes вроде то же самое что ServerAliveInterval, но на уровне TCP.
В сумме эти три строчки делают одну простую вещь: ssh-сессия не отваливается. После того как я это прописал, я забыл, что такое протухшая сессия.
Блок Host dz-net - алиас вместо IP.
Вот тут самый сахар. Помнить кучу IP адресов не очень приятно, гораздо приятней помнить понятные имена, которые в свою очередь примаплены к этим IP.
Теперь вместо ssh -p 22 dz@176.222.222.222 я пишу:
ssh dz-net
И всё. Имя пользователя, IP, порт - берутся из конфига. Память освобождается под более полезные вещи, например под то, что бы не забыть как выйти из vim. Ух как классно пошутил.
Маленький, но приятный бонус - табуляция. После ssh нажимаешь Tab, и шелл подставляет имена хостов из конфига. Дальше, если хост короткий, можно вообще писать первые две буквы и добивать табом.
Кстати, имена хостов - это место, где стоит подумать заранее. Как правило формат "проект-роль", но у меня основной хост имеет просто имя проекта, а остальные хосты этого проекта имеют маску "проект-роль": например dz-net и dz-net-irunode, или lf и lf-sys-node. Когда пара серверов в целом пофиг как ты их обзовешь. А вот когда 30 - лучше заморочься.
Блок с LocalForward - автоматический проброс портов.
Это та фича, ради которой стоит читать всё остальное. Смотри, что делает эта пачка строк:
LocalForward 8443 127.0.0.1:8443
LocalForward 8006 127.0.0.1:8006
LocalForward 2053 127.0.0.1:2053
LocalForward 3000 127.0.0.1:3000
Когда я подключаюсь к dz-net, ssh автоматически пробрасывает с моей локальной машины на удалённый сервер четыре порта. Простыми словами: на сервере по адресу 127.0.0.1:8006 крутится морда Proxmox, на 127.0.0.1:8443 web сервер VSCode, на 127.0.0.1:3000 - Grafana, на 127.0.0.1:2053 наверное уже сам знаешь что. Всё это работает на localhost'е сервера, наружу не торчит, и мне так спокойнее спится.
Вообще, конечно лучше поставить на 443 порт nginx, подкинуть tls и разруливать это дело по поддоменам - но мне лень, так у меня другие проекты работают. Тут просто и быстро, после ssh dz-net я на своей машине открываю http://localhost:8006 - и вижу веб-морду Proxmox, которая физически крутится за тысячу километров от меня.
Без конфига это выглядело бы так:
ssh -L 8443:127.0.0.1:8443 -L 8006:127.0.0.1:8006 -L 2053:127.0.0.1:2053 -L 3000:127.0.0.1:3000 dz@176.222.222.222
Каждый раз. Пездес гемморой.
Что ещё полезного сюда можно добавить.
Пара моментов, не претендую на истину, но глянь - может зайти.
IdentityFile - тут можно указать, какой именно ключ использовать для конкретного хоста. Если у тебя один ключ на всё - оно тебе не надо. Если для работы один, для пет-проектов другой, для какого-нибудь GitLab третий - норм штука.
Host work-server
Hostname 1.2.3.4
User me
IdentityFile ~/.ssh/work_rsa
ProxyJump (он же -J) - классная фишка для серверов, до которых нет прямого доступа. Например, у вас есть бастион (jump-хост), и через него надо ходить на внутренние машины. В моем случае, есть сервер на котором нарезана пачка виртуалок, которые из вне не доступны по ряду причин.
Раньше не знал про эту штуку и ходил таким способом: на бастионе сделал отдельного пользователя lf-sys, в ~/.ssh/config локальной тачки и в /etc/ssh/sshd_config бастиона добавил блоки:
Host lf-sys-node
Hostname 176.222.222.222
User lf-sys
Port 22
И вот такой блок залетел в самый низ файлика /etc/ssh/sshd_config:
Match User lf-sys
X11Forwarding no
AllowTcpForwarding yes
PermitTTY yes
AllowAgentForwarding yes
ForceCommand ssh lf-sys@10.15.15.100
И так, что тут произошло? Когда на ноутбуке я ввел команду ssh lf-sys-node ssh пошел смотреть мой файл ~/.ssh/config, нашел блок с алиасом lf-sys-node и начал подключаться к удаленной машине по указаному в этом блоке адресу. Удаленная машина получив запрос на подключение проверила ключи, дала добро. После создания сессии сработала строка Match User lf-sys, потом ForceCommand ssh lf-sys@10.15.15.100 и тебя пробросило на виртуалочку. Прикольно, да? Область применения параметра ForceCommand ограничена исключительно твоими фантазиями.
Ну а потом, почитав умных дядек я прозрел и понял что надо переделать на фен-шуй:
Host lf-sys-node
Hostname 10.15.15.100
User lf-sys
Port 22
ProxyJump lf (тут указываем хост, через который прокинется сессия)
IdentityFile ~/.ssh/id_rsa.lf-sys-node (если у тебя спец ключик для доступа)
Теперь ssh lf-sys-node сначала молча зайдёт на lf, а оттуда на 10.15.15.100. При этом, обрати внимание, для хоста lf будет использоваться ключ по умолчанию, а вот для хоста lf-sys-node уже специальный. В итоге получилось просто и красиво, и если что-то понадобится поправить - весь блок подключения в одном месте. На удаленной машине можно убрать добавленные строки в /etc/ssh/sshd_config.
Как итог.
~/.ssh/config - это не что-то мега продвинутое для супер профи. Это базовая база. Десять минут на настройку - и каждый день ты экономишь время, нервы и вот эти микроскопические порции раздражения, из которых складывается твое ощущение взаимодействия с такой прекрасной штукой, как консолька. Люблю ее :*
В следующем посте накидаю свою базовую базу по первоначальной настройке серверов после нарезки, и быть может закину примеры и ссыль на репозиторий с небольшой автоматизацией этой однотипной и скучной задачи. Да, и пиши комментарии.
Комментарии (0)
Войдите, чтобы оставить комментарий.