Обновить

Изнурительно подробное руководство по SSH (лишь те аспекты, которые я нахожу полезными)

Время на прочтение13 мин
Охват и читатели24K
Всего голосов 57: ↑40 и ↓17+38
Комментарии41

Комментарии 41

Дошёл до "петлевого интерфейса" и полез в оригинал

only accessible on the loopback interface

Дальше можно не читать. Лучше потратить немного больше времени, но читать сразу оригинал

Дополнение к прошлому комменту. Специально в виде отдельного коммента. Ллмка, короткая была использована для перевода распознала рутового пользователя, записанного в виде рут@домен как email и защитила его!!

Команда для этого выглядит так: ssh -N -f -g -L 2222:localhost:22 [email protected]

В оригинале

ssh -N -f -g -L 2222:localhost:22 root@internal-web.int

Я сам использую ллм каждый день для переводов, но смысл выкладывать это без вообще минимальной вычитки, или хотя бы примерного понимания предметной области?

Есть вариант, что выложено было тоже автоматически

Не так страшен LLM, как его пользователь, не проверяющий результаты выдачи :)

Зато мы узнали, что рут это почтовый ящик)) Идеальный уровень погружения в системное администрирование

Так писали во всех книгах по Линуксу, которые я сдуру читал в 2005-ом.

В среде линукса всегда было плохо с документацией, и книги выходили такие же - компиляция наборов хаутушек, в которых запросто могли ходить кривые переводы. Говорю как участник команды перевода man-страниц FreeBSD на русский в 2006-м.

И сейчас так же. Вчера впервые пытался упаковать программу в AppImage. Сам-то он собрался без проблем. Но вот манифест, необходимый, чтобы его приняли в стор, противоречит требованиям утилиты для упаковки. Единственный способ ублажить софт - это иметь название программы, которое везде показывается пользователю и в меню, не "Application Name" а "org.MountainGoat.Application_Name", что конечно зашквар. Так за день и не нашёл, что делать.

Когда лень пройдёт, буду писать авторам программ, недавно принятых в стор, как они так извернулись. Может кто ответит. Вот и вся документация.

Вчера впервые пытался упаковать программу в AppImage.

Чем? appimagetool'ом? Если этой тулзой, то рекомендуется брать rolling release.

Единственный способ ублажить софт - это иметь название программы, которое везде показывается пользователю и в меню, не "Application Name" а "org.MountainGoat.Application_Name", что конечно зашквар.

Это очень странная хохма, потому что в файле org.MountainGoat.Application_Name.desktop, в поле Name= можно написать вообще любое название, хоть SilverShamrock. Если интересно, скачайте, например, тот же KeePassXC в виде .AppImage, распакуйте, да посмотрите, как там внутри всё устроено.

В Name можно написать что угодно. Но кроме показа пользователю, это поле ещё используется: в него переименовывается .desktop файл, который при установке в систему пишется в папку меню. А это название, по правилам Wayland, должно совпадать дословно с appID, который сигналит приложение. Который, по правилам AppStream, должен совпадать с ID в metadata приложения. Который должен быть в виде обратного домена. И совпадать с названием файла метадаты. Который, бадум-тыщ: AppImageTool ищет по имени, который получает из Name=.

Я разрулил уже, но головоломка была знатная. Секрет в том, чтобы бинарь в ApDir/usr/bin назвать полным appID, тогда всё начинает вставать на свои места. Самое главное, что все официальные примеры, по сути, игнорируют, что хочет AppStream. Бинарь там назван как попало.

Подписываюсь под каждым Вашим словом. Говорю как читатель этой самой документации с 2005 года. FreeBSD определенно имеет более качественную документацию.

Перевод, конечно, кривой. Но про консоль ssh (~C), что можно пробросить порт (-L, -R) или включить прокси (-D) прям в текущей сессии, не знал. Спасибо, реально полезная штука!

Хотите ещё полезных штук?

man ssh

Начало инструкции для чайников: "Итак, вы где-то услышали про SSH"

Начало инструкция для юзеров: "Итак, вы приступаете к использованию SSH"

Начало инструкции для хакеров: "Итак, вы сломали SSH"

Начало инструкции для админов: "Итак, вам сломали SSH"

[email protected]

Ну вы молодец. Прогнали через нейросеть статью и запостили не читая, и не понимая о чём она. Это уровень.

Для понимания - нейросеть в этом блоге не используется никогда и никакая. Перевод делается вручную, впрочем, могу с вами согласиться, что какие-то вещи у нейросети получаются лучше. Вставки [email protected] остались при копировании абзацев из оригинала, но замечания справедливы - действительно, в некоторых примерах автор противопоставляет root@internal-web.int и root@vuln-server.int, поэтому без них не обойтись. Все эти адреса-примеры я вернул.

Скрытый текст

Ой, а откуда в переводе другой статьи с другого сайта взялся [email protected]? Не говоря о том, что вы не вычитываете машинный перевод.

Если вы за «красных» в области компьютерной безопасности, то, чтобы обрести в сети суперсилу и в дальнейшем бесчинствовать, вы должны понимать сеть лучше, чем те, кто её проектировал

После такого начала я ожидал чего-то большего, чем описание работы десятка ключей ssh...

Просто оставлю это здесь sshto - ssh с интерфейсом.

Чуть устарели сведения, в современных дистрибутивах по умолчанию ключи ed25519

OpenSSH 9.5 (октябрь 2023):Это официальная дата смены значения по умолчанию в коде OpenSSH. В заметках к этому релизу указано, что ssh-keygen теперь по умолчанию генерирует ключи Ed25519

Поскольку export | grep PROXYME=TRUE

Использование переменной среды для условного включения SSH Proxy, который ProxyJump — это не очень удобный и красивый способ. Вместо него желательно использовать суффиксы в имени хоста.

Ниже приведён способ настройки в .ssh/config суффиксов имени хоста для обеспечения различных способов подключения к одному и тому же серверу как напрямую, так через промежуточный SSH Proxy.

Допустим, у нас есть хост server, с именем srv-3-14 в домене company.com, и нам нужно обеспечить к нему доступ как напрямую, когда мы сидим непосредственно в локальной сети company.com, так и удалённо, через граничный маршрутизатор gate сети company.com, подключенный к интернет через двух провайдеров Provider1 и Provider2 с сетями provider1.net и provider2.net, соответственно.

Вначале оформим подключение к граничному маршутизатору gate через его внешние интерфейсы в сетях провайдеров под именами SSH хостов gate+wan1 и gate+wan2 через провайдеров Provider1 и Provider2, соответственно.

Для удобства примем, что оба провайдера включили адрес интерфейса gate в выделенные ими для подключения транспортных сетях в свои поддомены DNS с именами b2b.

Match originalhost "gate+*" originalhost "*+wan1,*+wan1+*"
  HostName gw-company-net.b2b.provider1.net

Match originalhost "gate+*" originalhost "*+wan2,*+wan2+*"
  HostName gw-company-net.b2b.provider2.net

Теперь вместо того, чтобы писать длинную и утомительную команду

ssh gw-company-net.b2b.provider1.net

мы можем написать

ssh gate+wan1

и получить то же самое.

Далее оформим подключение к маршрутизатору gate из внутренней сети.

Допустим, интерфейс gate для подключения ко внутренней сети внесён в домен company.com под именем gw-5-1. Допустим также, что доступ к маршрутизатору осуществляется от имени gwuser, и ещё мы страдаем паранойей и перевесили SSH с порта по умолчанию на случайный порт 38262.

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

Match originalhost "gate,gate+*"
  HostName gate.company.com
  User gwuser
  Port 38262

Настало время приступить к настройке доступа к нашему серверу server.

Вначале оформим подключение к серверу снаружи через SSH proxy.

Match originalhost "server+*" originalhost "*+wan1,*+wan1+*"
  ProxyJump gate+wan1

Match originalhost "server+*" originalhost "*+wan2,*+wan2+*"
  ProxyJump gate+wan2

Если нам нужно обеспечить проброс портов через наш сервер server, самое время внести эти сведения в файл конфигурации.

Допустим, нам нужно отобразить порты сервера 445/tcp и 8080/tcp в локальные порты на машине, с которой мы к нему подключились и организовать SOCKS5 прокси через наше подключение к серверу server.

Match originalhost "server+*" originalhost "*+vpn,*+vpn+*"
  DynamicForward 127.100.100.100:1080
  LocalForward 127.100.100.100:4445 127.0.0.1:445
  LocalForward 127.100.100.100:8080 127.0.0.1:8080

Теперь мы сможем подключаться к портам 445 и 8080 сервера как к портам 4445 и 8080 локального адреса 127.100.100.100, а также пользоваться SOCKS5 прокси с этим же адресом. Почему для локального отображения портов следует использовать любой другой адрес из сети 127.0.0.0/8, за исключением 127.0.0.1? Чтобы случайно не отобразить порты удалённой машины в уже открытые локальными сервисами порты с теми же номерами.

Ну и, наконец, оформим непосредственное подключение к серверу server через внутреннюю сеть company.com, в которой он зарегистрирован под именем srv-3-14, как это было указано выше. Допустим, что доступ к нему нам разрешён от имени srv_user.

Match originalhost "server,server+*"
  HostName srv-3-14.company.com
  User srv_user

Сведём конфигурацию воедино.

Match originalhost "gate+*" originalhost "*+wan1,*+wan1+*"
  HostName gw-company-net.b2b.provider1.net

Match originalhost "gate+*" originalhost "*+wan2,*+wan2+*"
  HostName gw-company-net.b2b.provider2.net

Match originalhost "gate,gate+*"
  HostName gate.company.com
  User gwuser
  Port 38262

Match originalhost "server+*" originalhost "*+wan1,*+wan1+*"
  ProxyJump gate+wan1

Match originalhost "server+*" originalhost "*+wan2,*+wan2+*"
  ProxyJump gate+wan2

Match originalhost "server+*" originalhost "*+vpn,*+vpn+*"
  DynamicForward 127.100.100.100:1080
  LocalForward 127.100.100.100:4445 127.0.0.1:445
  LocalForward 127.100.100.100:8080 127.0.0.1:8080

Match originalhost "server,server+*"
  HostName srv-3-14.company.com
  User srv_user

Теперь мы сможем подключаться к серверу server из внутренней сети командой

ssh server

а снаружи — командами

ssh server+wan1

ssh server+wan2

через провайдеров Provider1 и Provider2, соответственно.

Если же нам потребуется настроенное нами для server отображение портов и SOCKS5 прокси, мы можем просто добавить к имени server суффикс vpn, причём как до, так и после любых других настроенных нами суффиксов wan1 и wan2:

ssh server+vpn

ssh server+vpn+wan1

ssh server+vpn+wan2

ssh server+wan1+vpn

ssh server+wan2+vpn

Следует, однако, помнить, что наша конфигурация не сообщит об использовании не настроенных нами суффиксов. Такие суффиксы будут молча пропущены ssh без вывода сообщения об ошибке.

Хабр, нужен совет специалистов по SSH:

В том же PuTTY есть немало настроек, например, в Connection -> SSH (обмен ключами, ключи, шифры, ...).

Можно ли там настроить какие-то манипуляции с пакетами наподобие того, как это делается у современных ПНВ, чтобы соединение не резалось особо активными провайдерами, считающими, что я иду "куда-то не туда"?

Я попробовал повыбирать там разные варианты, получилось немного улучшить время до разрыва, но работать нормально всё равно невозможно.

Если нужно что-то настроить со стороны сервера, то сделать это тоже могу.

SSH прятаться не умеет. Когда его делали, не то, что цели – а и мысли такой не было. Поэтому и как туннель он так себе, а ещё он от congestion страдает если им Ютуб смотреть. Выглядит, как будто провайдер скорость режет, хотя это SSH сам давится.

Если хочется SOCKS-ов, посмотрите на ssltunnel или shadowsocks.

как туннель он так себе, а ещё он от congestion страдает если им Ютуб смотреть

Мне в основном работать и время от времени файлы перебрасывать (совсем огромных нет).

посмотрите на ssltunnel или shadowsocks

Полагаю, что если даже SSH режется, то теневые носки зарежут и подавно.

Stunnel (полагаю, вы имели в виду его) выглядит занятно, если вы им пользовались, может быть сможете подсказать пару моментов? А то я с наскока не понял.

Подключение к нему можно защитить паролем? А то там всё про ключи, да ещё и соединение Линукс-Линукс. А мне обычно с винды подключаться нужно.

Ну и то же самое, что с носками: стоит ли начинать эксперименты с stunnel, если SSH режется? Не отрежут и его так же?

Если вы за «красных» в области компьютерной безопасности, то, чтобы обрести в сети суперсилу и в дальнейшем бесчинствовать, вы должны понимать сеть лучше, чем те, кто её проектировал

Чё? Они всегда назывались “черными”.

команда для этого: ssh -N -f -L 1337:127.0.0.1:80 root@internal-web.int. Эта команда выполняется на campfire.int. Это сложная команда

Уууу… После такого введения и вот это считать СЛОЖНОЙ командой…

Чтобы вывести меню справки по консоли, нажмите ~?. Если вы умеете работать с vim, то эта комбинация может напомнить вам ведущий символ. Итак, таким образом открывается справочная консоль. Две из имеющихся в ней опций я нахожу очень полезными. Во-первых, это ~, убивающая ваш сеанс

…и ни слова о том, что это работает только после Enter. Выделения моноширинным тоже нет, и получается ошибка - сессию убьет тильда-точка, но никак не тильда-запятая.

В общем, что-то действительно интересное было только про Match, остальная часть статьи - вода для чайников.

Они всегда назывались “черными”.

Только у нас и только в казённой литературе. А в мире всегда было red team/blue team

Первый раз слышу вообще. Всегда было black hat и white hat. Ну и, у нас “красные директора” и “черные зоны” - это ни разу не казённая литература, а народное как раз.

Red team/blue team это терминология CTF(capture the flag), где две команды WHITE HAT которые борются друг с другом.

Black hat просто по определению участвовать в CTF не может, или он не будет black hat. Так что red-blue и white-black это разных оси дихотомии.

То есть тут важно что имел в виду автор. Если он имел в виду настоящего злоумышленника который хочет поломать сервер Пентагона то правильно использовать тут black. Если он имел в виду участвующих в соревновании CTF то red.

По поводу агента.

В KeePassXC есть возможность сложить ключи SSH в хранилище и подключиться к SSH агенту. В результате, чтобы куда-то зайти, нужно открыть KeePassXC в фоне, и с любого терминала заходи куда хочешь или коммить из IDE на гитхаб.

Получается, что украсть ключи сложнее, а пользоваться удобнее. KeePassXC умеет разблокироваться по паролю, по YubiKey, по биометрии. На Linux работает даже если KeePassXC в флатпаке.

В итоге в ~/.ssh у меня лежит один только файл config. А функцию known_hosts я отключаю, у меня всё по ключам.

У Bitwarden видел похожий пункт в справке, но не вчитывался.

P.S. Осторожно, на KeePassXC очень много поддельных сайтов. Только https://keepassxc.org

В итоге в ~/.ssh у меня лежит один только файл config. А функцию known_hosts я отключаю, у меня всё по ключам.

А коим боком свои ключи к known_hosts серверов?

А чем ещё может быть опасна подмена сервера, кроме как стырить пароль? Тем более что я сразу пойму, что не туда попал, так как у меня всегда есть свои кастомизации.

Так классический MitM - это не “не туда” попал, это именно “туда”, но с перехватом. Что там может быть ценного кроме паролей, сильно зависит от назначения сервера. Как минимум, промежуточный сервер может открыть дополнительные шеллы внутри той же сессии и продолжить там что-то делать, когда ничего не подозревающий пользователь уже отключился.

Верно. Но по ключу ему не светит. SSH не передаёт закрытый ключ при логине, даже успешном. Так что вредный сервер не сможет перекинуть меня на нужный.

Если трафик перехвачен, MitM позволяет пробросить агент авторизации дальше

И вот тогда твои ключи радостно пойдут гулять по всей инфре

В KeePassXC есть возможность сложить ключи SSH в хранилище и подключиться к SSH агенту. В результате, чтобы куда-то зайти, нужно открыть KeePassXC в фоне, и с любого терминала заходи куда хочешь или коммить из IDE на гитхаб.

Данная схема работает также в Windows 10/11 со штатным виндовым портом OpenSSH и ssh-agent'ом из его состава, однако есть небольшой нюанс.

К своему невероятному удивлению я заметил, как ключи SSH, загруженные KeePassXC в виндового ssh-агент'а, успешно пережили перезагрузку системы, и мне даже удалось подключиться с их помощью к своим машинам по SSH без разблокировки своей базы паролей, где они лежат. С линуксовым ssh-agent'ом я такого не замечал.

После этого неприятного открытия мне пришлось поставить ключам, хранимым в базе паролей KeePassXC, признак принудительного удаления из агента при блокировке или закрытии базы.

Насчёт безопасности.

Помните, что SSH светит наружу, есть ли у него данный публичный ключ. То есть любой майор с тремя классами образования может узнать, что вот этот сервер менеджерится тем же чуваком, что и вон тот сервер, а вон его профиль на Гитхабе: если у чувака один ключ на все случаи жизни.

Помогает иметь секретный, стойкий к брутфорсу юзернейм. Получить список юзеров нельзя. Можно его брутить, но fail2ban не спит, да и брутить 20 символов по сети просто так никто не будет. Тут важно не спалить юзернейм через другой сервис, типа почты.

А если вы используете ssh-agent, то знайте, что он по очереди посылает при коннекте публичные ключи, пока один не подойдёт. То есть, как только вы подключитесь к чужому/не тому серверу, даже если он вас не пустит, вы предъявите ему к осмотру все ключи, которые у вас есть. Дальше см. выше.

Пруфы 1 2 3

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

Насколько мне известно, SSH сервер не сообщает наружу открытые ключи, которые лежат в связке ключей учётной записи пользователя authorized_keys.

Также, насколько я понимаю, атакующий может только убедиться в том, что уже имеющийся у него конкретный открытый ключ лежит в связке открытых ключей authorized_keys некоей учётной записи с уже известным атакующему именем.

Да, именно так.

А вот клиент с ssh-agent, в свою очередь, светит серверу все публичные ключи, которые у него есть.

А гитхабы всякие светят ваш публичный SSH ключ (которым вы коммитите) вообще всем.

А вот клиент с ssh-agent, в свою очередь, светит серверу все публичные ключи, которые у него есть.

Да понятно, что светит. Однако хорошо было бы уточнить, что это можно использовать в целях деанонимизации только если товарищ майор сообразил включить запись попыток аутентификации SSH.

А гитхабы всякие светят ваш публичный SSH ключ (которым вы коммитите) вообще всем.

Гитхабы не светят. Вы сами светите свой публичный SSH ключ, когда что-то коммитите в гитхаб. И если Вам не нравится, что товарищ майор спалит ваш единственный открытый ключ на все случаи жизни, заведите себе отдельный открытый ключ для гитхаба и настройте себе в ~/.ssh/config отдельный Host для github.com c IdentityFile, в котором укажите путь к этому ключу:

Host github.com *.github.com
  IdentityFile ~/.ssh/me@github.com

А если не хотите каждый раз вводить пароль к этому отдельному ключу для гитхаба, настройте себе запуск отдельной копии ssh-agent'а, укажите ему специфический сокет с помощью ключа -a, например, ~/.ssh/ssh-agent-for-github и после IdentityFile допишите IdentityAgent с указанием пути к этому сокету, а также AddKeysToAgent yes:

Host github.com *.github.com
  IdentityFile ~/.ssh/me@github.com
  IdentityAgent ~/.ssh/ssh-agent-for-github
  AddKeysToAgent yes

Сам не пробовал, но, согласно документации, ssh после первой попытки зайти на github.com и любые хосты в этом домене, должен спросить пароль ключа ~/.ssh/me@github.com и засунуть его в указанного агента, если пароль подойдёт. А при следующих попытках входа ssh должен, по идее, брать ключ уже из агента.

Совет про использование -A очень вредный без серьезных оговорок. Перебрасывать сокет агента на чужой сервер это прямой путь к утечке доступов, лучше всегда юзать ProxyJump

Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации