惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Forbes - Security
Forbes - Security
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
F
Fortinet All Blogs
B
Blog
T
The Blog of Author Tim Ferriss
Engineering at Meta
Engineering at Meta
GbyAI
GbyAI
Y
Y Combinator Blog
Microsoft Azure Blog
Microsoft Azure Blog
L
LangChain Blog
Recent Announcements
Recent Announcements
U
Unit 42
Martin Fowler
Martin Fowler
M
MIT News - Artificial intelligence
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
The Register - Security
The Register - Security
Recorded Future
Recorded Future
C
Check Point Blog
V
V2EX
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
Hugging Face - Blog
Hugging Face - Blog
WordPress大学
WordPress大学
Google DeepMind News
Google DeepMind News
酷 壳 – CoolShell
酷 壳 – CoolShell
F
Full Disclosure
小众软件
小众软件
A
About on SuperTechFans
云风的 BLOG
云风的 BLOG
宝玉的分享
宝玉的分享
Last Week in AI
Last Week in AI
有赞技术团队
有赞技术团队
MongoDB | Blog
MongoDB | Blog
爱范儿
爱范儿
P
Proofpoint News Feed
罗磊的独立博客
量子位
D
Docker
博客园_首页
D
DataBreaches.Net
Project Zero
Project Zero
博客园 - 司徒正美
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
博客园 - Franky
Security Latest
Security Latest
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
N
Netflix TechBlog - Medium
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
博客园 - 三生石上(FineUI控件)
H
Hackread – Cybersecurity News, Data Breaches, AI and More
大猫的无限游戏
大猫的无限游戏

Все публикации подряд на Хабре

Ловим музу за клавиатуру: как айтишнику стать автором Что умеет Midjourney в 2026? Мой немного грустный разбор этого шикарного инструмента Никто не любит писать тесты, но ИИ может исправить это IPv8 выглядит как мечта. Поэтому почти наверняка не взлетит Производители вернули в продажу материнки с DDR3. Что происходит? Управление агентом с телефона через Telegram теперь в KodaCode От координации к лидерству: как меняется роль руководителя разработки Я сделала родителям бизнес вместо пенсии: зарабатываем 70 тысяч, мама не даёт продать В три раза быстрее приемка товара и оптимизация трудозатрат на 73%: как «РСТ-Инвент» помог Gulliver Group ИИ-шечный мир победил? О влиянии искусственного интеллекта на игропром Кремль снижает давление на Телеграмм пока Европа строит интернет по паспорту Как CEO, CTO и CIO за 8 часов собрали ИИ-директора, который умеет держать позицию под давлением Как (не) потерять домен за выходные Вместо 8 разных VPS: как я организовал практику студентам на одном сервере Почему твой Open Source проект не замечают? R&D: искусство управления неопределенностью в разработке AI-дефляция: вакансий для разработчиков больше, а рост зарплат — худший за 15 лет Мы отдали управление роботами OpenClaw. Что из этого вышло Галактический ID: система идентификации для всех форм разумной жизни Шесть основ бизнес-анализа: начинаем с вопроса «Кто в игре?» Код-ревью, в котором дело не в коде Данные переехали. Команда — нет Системной подход к сдаче OSWE в 2025 Почему комната управления реактором покрашена в цвет морской пены 4 YAML-файла вместо PySpark: как аналитикам строить пайплайны без разработчиков LLM-агент для поиска свободных доменов: автоматизируем подбор Когда, зачем и как правильно начинать новую сессию в Claude Code? Как я заставил нейросеть писать макросы для FreeCAD Анатомия ИИ‑агента для подбора персонала. От тысячи резюме к топ‑10 за минуты Опыт разработчика как экономика внимания Автономность как точка невозврата: кто будет субъектом в цифровом будущем Обучение ИИ в «диких» условиях: как рутинные действия превращаются в датасеты Как измерить LLM для задач кибербеза: обзор открытых бенчмарков Где хранить код? Сравнение GitHub, GitLab и Bitbucket Математика объясняет, почему нормальное распределение встречается повсюду Почему ваш FinOps не работает: 12 тезисов от практиков Как подписать проектную документацию УКЭП с использованием бесплатных лицензий Pilot Адаптивное администрирование Sigla Vision Я грузил уран в бочки, а потом 20 лет строил ИТ в атомной отрасли Чем позвонить с Эвереста? История и обзор спутниковой связи. Часть 2 Как языковая модель помогает контролировать качество инструктажей по охране труда в металлургии Как не передать на desktop свой IP в РКН Анатомия SAP Privileges: как устроено управление правами в macOS MoneyDev: Сказка про три главных слова Обновлённый токенизатор видео K-VAE 2.0 от Сбера Как сделать диспетчеризацию дома на 1284 квартиры почти бесплатно Как мы разогнали железную дорогу Мы дали агентам рутину. Теперь надо решить — что делать с освободившимся временем Токсичный контент, промпт-хакинг и защита ИИ — всё о Guardrails для LLM Умный город начинается с точного взгляда: как «Фалькон Тех» меняет пространство к лучшему Навайбкодил приложение для анализа графов Почему Дюну так интересно читать? Упрощаем работу с рутиной или как стать Гендальфом Белым Деконструкция Go: CPU, RAM и что там происходит. Go Assembler база. Часть 1.1 Какие профессии исчезнут из-за ИИ, а какие появятся? И что с этим делать Как мы построили IT-отдел, где хочется расти: архитектурные встречи, прозрачные метрики и книжные подарки Rufler: Делаем из Claude Code автономный рой через один YAML-конфиг Sing-box и белый список приложений Как построить надёжный обмен сообщениями в микросервисах: лучшие практики для enterprise OpenAI строит MLM-пирамиду, а McKinsey и Accenture помогают ей в этом Дом, который не построил Фишер (Часть 2) «Сверхзвуковой математик» против «Вдумчивого логиста»: битва алгоритмов 3D-упаковки Мультимодальные модели – грубый и дорогой инструмент Разговоры ничего не стоят. Код тоже Проверки физических лиц: с кого начнет ФНС Топ-10 бесплатных нейросетей для создания видео в 2026 году Первые слои кода: как наши решения сегодня определяют архитектуру ИИ на десятилетия Разработка нового статического анализатора: PVS-Studio JavaScript Поиск уязвимостей ПО: базовый минимум или роскошный максимум Почему оценка персонала не работает как инструмент управления Как мы разработали ИИ-ассистента и сократили рутину продуктовой команды на 50% Как я ушел из найма, нажарил косточек и продал на маркетплейсах на 168 млн в год Когда 1С:ERP уже внедрена, а нормального производственного плана всё ещё нет Как я сделал Claude мультимодальным, подключив к нему Qwen Omni Как приглашение на вакансию мечты превращается в атаку Infrastructure as Code: философия и лучшие практики IaC Тестируем Yandex Code Assistant на задаче, в которой нужно хранить секреты nxs-universal-chart v3.0: новое поколение универсального Helm-чарта Callback Injection: Техника, которая отправила Microsoft Defender в глухой нокаут «Все идеи на стол»: митап как способ вывести проект из тупика Сегодня я узнал нечто новое о GPU благодаря багу в своей игре Как заставить LLM ̶ ̶г̶а̶л̶л̶ю̶ ̶ эволюционировать Карта событий как фундамент аналитики: практический кейс для E-commerce Что выбрать для AI: x86, ARM или RISC-V? Дайджест железа за март Роль соматических мутаций в развитии аутоиммунных заболеваний: путь к избирательной терапии Mythos от Anthropic — тревожный сигнал для всех, а не только для банков Guardrails для LLM на Java: как приручить промпт‑инъекции и токсичные ответы Green-VLA: как мы собрали VLA-модель для реального антропоморфного робота и не потеряли обобщение Финансовая гонка вооружений: почему умные люди добровольно в ней участвуют Эра ИИ-агентов наступила: выбираем лучшего цифрового сотрудника # Практический опыт внедрения WinCC Redundancy на производственном предприятии Сделал MVP за 3 дня, а потом неделю прикручивал оплату. Оно того стоило? Физика против Маска: почему Starship V3 может оказаться ещё одной катастрофой Нефть Венесуэлы: крупнейшие запасы в мире, но не крупнейшая нефтяная держава JPA 4. Переосмысление Hibernate Почему зеркальная фотокамера Nikon D5 десятилетней давности идеально подошла для миссии «Артемида-2» Проект «Уровень-Спутник» или как мы сделали платформу для гидрологов «Замедлиться, чтобы ускориться»: почему ИИ повышает цену ошибок в требованиях и архитектуре Как с нуля поднять трафик IT-компании на 1657% при бюджете 55 тыс. и выжить Pixel-perfect Downsampling — идеальная отрисовка 50 миллионов точек без потерь
Изнурительно подробное руководство по SSH (лишь те аспекты, которые я нахожу полезными)
Sivchenko_tr · 2026-05-20 · via Все публикации подряд на Хабре

О, вам нравится SSH? А перечислите-ка все флаги!

Приветствую

Все мы видели эти красивые схемы, демонстрирующие, как в SSH устроен проброс  портов. Но, если мы с вами мыслим хотя бы немного схоже, то эти схемы оставляют у вас больше вопросов, чем дают ответов. Если вы за «красных» в области компьютерной безопасности, то, чтобы обрести в сети суперсилу и в дальнейшем бесчинствовать, вы должны понимать сеть лучше, чем те, кто её проектировал. Один из инструментов, наделяющих вас такой суперсилой — SSH. Но иногда нам мешают добиться поставленных целей сам синтаксис инструмента и другие концепции, на основе которых этот инструмент работает. Чтобы вы могли бесчинствовать эффективнее, не срывая сроков, я собрал для вас длинный список присущих SSH штук, которые я нахожу полезными. Хорошо, если вы его тоже почитаете, но составлял я его в основном для себя. Заметил, что сам я качественно усваиваю те или иные концепции, только если, изучая информацию, повторяю упражнения на клавиатуре. В этом посте я, в сущности, рассказываю, чему научился таким образом. Должен отметить, что во всех этих примерах я демонстрирую проброс портов при помощи веб-сервера, но таких же результатов можно добиться и при помощи почти любого сервиса, в частности, RDP, SQL, т.д.

Проброс локального порта (-L)

Как понятно из названия, при пробросе локального порта можно создать локальный порт, информация с которого переадресовывается на удалённый порт. Предположим, что на сервере internal-web.int располагается веб-страница, доступная только через петлевой интерфейс. Таким образом, чтобы обратиться к этой веб-странице, нужно обратиться к internal-web.int. Обойти это препятствие можно, например, воспользовавшись пробросом локального порта по SSH. Допустим, мы обращаемся по SSH к странице internal-web.int, расположенной на хост-машине campfire.int. В таком случае мы пробрасываем локальный порт, что в дальнейшем позволит нам обратиться к удалённому веб-серверу через локальный порт.

Вот как выглядит команда для этого: ssh -N -f -L 1337:127.0.0.1:80 [email protected]. Эта команда выполняется на campfire.int. Это сложная команда, поэтому давайте, как обычно, разберём каждый её флаг отдельно, чтобы сориентироваться, что именно здесь происходит.

  • ‑N: так мы сообщаем SSH, что за пределы сервера мы никакие команды отправлять не будем. Без этого мы бы получили оболочку на [email protected]

  • ‑f: так мы переводим работу SSH в фоновый режим. Если бы мы так не сделали, то окно терминала зависло бы, и пользоваться терминалом мы бы не смогли.

  • ‑L так мы приказываем SSH пробросить локальный порт.

  • 1337:127.0.0.1:80: так мы приказываем SSH связать локальный порт 1337 с удалённым портом 80 (тем самым, на котором включён наш веб‑сервер).

Примечание: насколько мне известно, лучше всего это делать именно с помощью флага -L, означающего локальность слева от адреса или -R, означающего локальность порта справа от адреса.

  • [email protected] так мы сообщаем SSH, что хотим зайти под именем и паролем на удалённый сервер с правами администратора, что позволит нам открыть SSH-туннель. Напомню, что порт 1337 на нашей локальной машине будет связан с портом 80 на удалённом сервере.

  • [email protected] так мы сообщаем SSH, что хотим зайти под именем и паролем на удалённый сервер с правами администратора, что позволит нам открыть SSH‑туннель. Напомню, что порт 1337 на нашей локальной машине будет связан с портом 80 на удалённом сервере.

Теперь, обустроив проброс локального порта, можно взаимодействовать с портом  80 на internal-web.int, отправляя запросы на порт 1337 нашей локальной машины ( campfire.int).

Взаимодействие с портом 80 на internal-web.int.

Взаимодействие с портом 80 на internal-web.int.

Проброс удалённого порта (-R)

Проброс удалённого порта — это операция, противоположная пробросу локального. Допустим, у нас есть доступ к internal-web.int, и на нём располагается веб-страница, доступная только через петлевой интерфейс. Также предположим, что   campfire.int не может напрямую обращаться к internal-web.int. В таком сценарии хотелось бы обратиться к internal-web.int от campfire.int. Проблема в том, что из-за брандмауэра невозможно наладить прямой обмен данными между campfire.int и internal-web.int. Пытаясь с этим справиться, обнаруживаем, что vuln-server.int доступен как с campfire.int, так и с internal-web.int. В данном случае нужно воспользоваться пробросом удалённого порта через SSH, чтобы переадресовывать данные порта 80 с internal-web.int на произвольный порт vuln-server.int. Организовав проброс удалённого порта, мы сможем открывать внутреннюю веб-страницу с internal-web.int, работающую на порте 80. Для этого направим команду curl на vuln-server.int.

Вот команда для этой цели: ssh -N -f -R 3000:127.0.0.1:80 [email protected].

  • N: так мы сообщаем SSH, что за пределы сервера мы никакие команды отправлять не будем. Без этого мы бы получили оболочку на [email protected]

  • f: так мы переводим работу SSH в фоновый режим. Если бы мы так не сделали, то окно терминала зависло бы, и пользоваться терминалом мы бы не смогли.

  • R так мы приказываем SSH пробросить удалённый порт

  • 3000:127.0.0.1:80: В результате SSH должна связать удалённый порт 3000 с портом 80 локального компьютера.

Замечание
Что касается запоминания, я обнаружил, что удобнее всего понимать -L как «локальный слева от адреса». При пробросе удалённого порта с флагом -R локальный порт указывается справа от адреса. local port is on the right-hand side of the address.

  • [email protected]: так мы сообщаем SSH, что хотим зайти под именем и паролем на удалённый сервер с правами администратора, что позволит нам открыть SSH-туннель. Напомню, что порт 3000 (на vuln-server.int) будет связан с портом 80 на данном сервере.

Теперь, обустроив проброс удалённого порта, можно взаимодействовать с портом  80 на internal-web.int, отправляя запрос curl на vuln-server.int:3000

Динамический проброс порта (-D)

Динамический проброс порта при помощи опции -D — интересный вариант опосредованной передачи трафика через прокси SOCKS. Допустим, что на internal-web.int  размещено веб-приложение, доступное только из внутрикорпоративной сети. Также предположим, что по SSH можно получить доступ к vuln-server.int, он находится в той же самой внутренней сети, и так нам открывается путь к internal-web.int. Вот чего хотелось бы добиться в данном случае: достучаться до веб-сервера, работающего по адресу internal-web.int, пустив через прокси весь наш трафик от campfire.int через vuln-server.int. При этом задействуются обе цепочки прокси и браузер с нашей локальной машины. Сначала давайте убедимся в том, что конфигурация в файле /etc/proxychains.conf записана правильно.

  • Socks5: сообщает цепочкам прокси, что нужно использовать socks5 (а не socks4)

  • 127.0.0.1: приказывает цепочкам прокси использовать наш localhost

  • 8080: именно этот порт мы будем динамически пробрасывать. Указанный здесь порт должен совпадать с тем, который вы задали с опцией ‑D в рамках вашей команды SSH.

Вот команда для этой цели: ssh -N -f -D 8080 [email protected]

  • ‑N: так мы сообщаем SSH, что за пределы сервера мы никакие команды отправлять не будем. Без этого мы бы получили оболочку на [email protected]

  • ‑f: так мы переводим работу SSH в фоновый режим. Если бы мы так не сделали, то окно терминала зависло бы, и пользоваться терминалом мы бы не смогли.

  • ‑D 8080 приказывает SSH создать на локальной машине динамический порт, через который мы будем посылать наш трафик.

  • [email protected]: так мы сообщаем SSH, что хотим зайти под именем и паролем на удалённый сервер с правами администратора, что позволит нам открыть SSH‑туннель. Через него мы сможем проксировать наш трафик.

Организовав динамический проброс порта через 8080 и установив socks5 127.0.0.1 8080 в /etc/proxychains.conf, можно выполнить proxychains curl 192.168.1.185 и увидеть нашу веб-страницу, размещённую по адресу 192.168.1.185. Кроме того, DNS по SOCKS кажется мне ненадёжным решением, почему я и указал конкретный IP-адрес в приведённой ниже команде curl.

Теперь сконфигурируем Firefox так, чтобы можно было просматривать наш внутренний сервер через прокси SOCKS. Для этого понадобится поставить правильные настройки прокси внутри самого firefox. Для этого откроем Firefox и перейдём в: Settings -> Privacy & Security -> Network Settings. Там выберите конфигурирование прокси «вручную» и отметьте “Proxy DNS when using SOCKS V5”. Наконец, сообщите Firefox о прокси SOCKS, который мы только что настроили. Для этого задайте хосту SOCKS адрес 127.0.0.1 и порт 8080 (или другой порт, тот, который вы указали в вашей команде SSH).

Теперь, когда прокси у нас настроен, можно обратиться к веб-странице на internal-web.int, поскольку весь наш трафик перенаправляется с локальной машины через vuln-server.int. Круто, правда?

Инсталляционные серверы или jump-серверы (-J)

По сравнению с предыдущими командами перепрыгивание с хоста на хост через SSH не составляет труда. В данном сценарии мы проксируем наш трафик через два хоста, намереваясь добраться до искомого хоста, куда не достучаться с нашего актуального хоста campfire.int. Цепочка переходов будет выглядеть так: campfire.int -> vuln-server.int -> internal-web.int -> dns.int.

Это делается при помощи команды ssh -J [email protected],[email protected] [email protected]. Обратите внимание: переходы разделяются запятыми.

Агентская переадресация (-А)

Агентская переадресация по SSH — интересная концепция, о которой подробно рассказано в статье Zero Effort Private Key Compromise: Abusing SSH-Agent for Lateral Movement. Если вы планируете заниматься агентской переадресацией, то настоятельно рекомендую её прочитать. Вкратце: SSH-агент позволяет добавлять приватные ключи/идентификаторы к агенту, работающему на вашей локальной машине. Это делается командой ssh-add <private_key_file>. Список этих ключей выводится командой ssh-add -l. Добавив ключ в утилиту ssh-agent, можно по SSH попасть на сервер, воспользовавшись одним лишь ключом, не вводя пароль повторно. Это удобно при работе как с пользовательскими, так и с сервисными аккаунтами. При помощи опции -A можно переадресовать ваш агент для работы с ключами на ту машину, к которой вы подключаетесь. Так вы сможете пользоваться вашими приватными ключами с той машины, к которой подключаетесь.

В качестве демонстрации давайте предположим, что хотим перепрыгнуть через vuln-server.int на internal-web.int, в то же время переадресуя ключи в нашем ssh-агенте, так, чтобы можно было ими пользоваться, оказавшись на internal-web.int.

Это делается при помощи следующей команды: ssh -A -J [email protected] [email protected]

  • ‑A приказывает SSH переадресовывать ключи в нашем SSH‑агенте на удалённую машину internal‑web.int

  • ‑J [email protected] приказывает SSH проксировать наш трафик через vuln‑server.int перед тем, как обращаться к internal‑web.int

  • [email protected]: так мы сообщаем SSH, что хотим зайти под именем и паролем на удалённый сервер с правами администратора, что позволит нам открыть SSH‑туннель.

Как видите, выполнив ssh -A -J [email protected] [email protected], можно пользоваться ssh [email protected], и при этом не требуется указывать ни приватный ключ, ни какие-либо учётные данные. Дело в том, что на нашей локальной машине campfire.int есть ssh-ключ для dns.int, загруженный в ssh-агент. Чтобы убедиться в этом, запустим ssh-agent -l.

Выделение TTY-команд (-t)

Этот вариант проще некуда, однако он очень пригодится, если требуется быстро выполнять на удалённом сервере такие команды, которые предполагают те или иные взаимодействия — например, Vim или top. Мой любимый пример такого рода — случай, когда требуется быстро отредактировать файл на удалённом сервере. Для этого нужно всего лишь выполнить команду ssh [email protected] -t top —  вы получите приветствие TTY, в котором будет команда top.

Глобальный порт (-g)

Такой вариант встречается реже, но с его помощью можно определить локально переадресуемый порт как «глобальный» (это моя терминология, а не официальная). Тогда мы сможем проксировать и направлять на порт внешнего сервера весь трафик, поступающий на указанный порт нашей локальной машины. Этот вариант напоминает опцию -L, упоминавшуюся выше, но далее мы получаем доступ через оболочку к vuln-server.int и попробуем проксировать любые соединения, идущие на порт 2222, перенаправляя их на порт 22 машины internal-web.int.

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

  • ‑N: так мы сообщаем SSH, что за пределы сервера мы никакие команды отправлять не будем. Без этого мы бы получили оболочку на [email protected]

  • ‑f: так мы переводим работу SSH в фоновый режим. Если бы мы так не сделали, то окно терминала зависло бы, и пользоваться терминалом мы бы не смогли.

  • ‑g так мы приказываем SSH разрешить удалённым хостам подключаться к локальным переадресуемым портам

  • ‑L приказывает SSH переадресовать локальный порт

Как видите, пусть даже наша исходная команда SSH была адресована на порт 2222 машины vuln-server.int,  теперь оболочка сообщает нам, что на самом деле мы находимся на internal-web.int, поскольку ssh -N -f -g -L 2222:localhost:22 [email protected]

SSH-консоль (~?)

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

Вторая опция — это  «Консоль», активируется командой ~C. В ней предусмотрено несколько вариантов переадресации. Если вы зашли на сервер по SSH и решили, что эту сессию будете использовать для проброса портов (например, динамического проброса с применением опции -D, которую мы обсуждали выше), то переадресовать эту сессию можете при помощи опции -D 8080. Тогда данные этой сессии будут пробрасываться на лету. Так, я подключился к vuln-server.int через обычный ssh. Нажал ~C, набрал -D 8080, после чего дважды нажал «ввод» — в ответ мне открылось обычное приглашение командной строки. Но, если мы используем прокси-цепочки на хост-машине campfire.int (и удостоверились, что файл /etc/proxychains.conf настроен для работы с портом 8080), то сессию SSH можно задействовать так, как будто она была инциирована при помощи ssh -D. Ловко.

Конфигурационный файл SSH

Файл с конфигурацией SSH находится по адресу ~/.ssh/config и помогает экономить время, когда вы устанавливаете соединения по SSH. Используемый в нём синтаксис очень легко прослеживается. Кроме того, конфигурацию SSH можно сохранять, чтобы не приходилось заново вводить в командную строку все нужные опции при каждой новой сессии. При установлении соединения SSH выполняет синтаксический разбор этого файла. Если конфигурация того сервера, к которому вы подключаетесь, определена в файле ~/.ssh/config, то именно она и будет использоваться. Обратите внимание: параметры, указанные в командной строке, имеют приоритет над прописанными в конфигурационном файле. Таким образом, если у вас в файле ~/.ssh/config написано, что пользователь internal-web.int должен обладать правами администратора (root), но вы выполняете команду SSH ssh [email protected], SSH попытается запустить вас в систему как graham, а не как root. Ниже в качестве примера приведён элементарный файл ~/.ssh/config.

# Комментарии, начинающиеся с `#`, можно ставить только в начале строки. 
host internal-web.int
    User root
    IdentityFile /home/smores/ssh_agent/internal-web-no-pw
    Port 2222

Вот как SSH будет разбирать этот файл, выполняя команду ssh internal-web.int:

  • Пытается сопоставить internal‑web.int, фигурирующий в вызове командной строки, с ключевым словом host, сравнивая это значение с internal‑web.int, указанным в ~/.ssh/config

  • Если удаётся найти internal‑web.int в ~/.ssh/config, то будут задействованы все опции, прописанные под хостом и при этом не указанные при вызове в командной строке

  • Если совпадений не найдено, то SSH будет использовать лишь те опции, что вы сами указали в командной строке при вызове SSH.

Ключевые слова для конфигурирования SSH

Есть множество ключевых слов, которые можно задействовать в конфигурационном файле SSH. Но некоторые из тех, которыми я часто пользуюсь, не самоочевидны (например, Port и User) .

IdentityFile /path/to/private_key: позволяет указать приватный ключ, который вы собираетесь использовать на хосте. Семантически равноценно ‑i.

ForwardAgent: то же самое, что выполнить ssh ‑A (опять же, прежде, чем этим пользоваться, почитайте статью Zero Effort Private Key Compromise: Abusing SSH‑Agent for Lateral Movement.)

ProxyJump [email protected]: указываем сервер, через который будет проксироваться трафик. Семантически равноценно опции ‑J, которую мы упоминали выше. Обратите внимание, что в следующем примере требуется аутентифицироваться с адресом [email protected]. Это показывает, что наш трафик действительно маршрутизируется через vuln‑server.int, прежде, чем мы получим оболочку на internal‑web.int, как и просили в команде SSH.

Match: это немного сложнее. Ключевое слово Match предназначено для определения условий в конфигурации SSH. В следующем примере SSH выполняет команду export | grep PROXYME=TRUE. Если программа возвращается с кодом состояния 0 (в данном случае это означает, что grep нашла совпадение), то будет использовать те ключевые слова SSH, которые были определены в блоке Match (здесь — ProxyJump). В противном случае будет использоваться лишь обычный блок host internal‑web.int.

В следующем примере мы сначала выполняем команду ssh internal-web.int, при помощи которой успешно подключаемся к серверу, воспользовавшись при этом приватным ключом, который обозначается ключевым словом IdentityFile. Поскольку export | grep PROXYME=TRUE возвращается с кодом состояния 1 (это означает, что grep не нашла совпадений), мы не выполняем ключевого слова ProxyJump, находящегося в инструкции match.

Далее устанавливаем переменную окружения PROXYME в значение TRUE, воспользовавшись export PROXYME=TRUE, и повторно выполняем всё ту же ssh internal-web.int. На этот раз нам поступает требование аутентифицироваться на time vuln-server.int перед тем, как мы получим оболочку на internal-web.int. Дело в том, что SSH вычислила блок Match и выполнила export | grep PROXYME=TRUE, в ответ на что получила код состояния 0 (это означает, что grep нашла совпадение). Поскольку команда вернула true, она выполнила тот вариант кода, в котором фигурирует ключевое слово ProxyJump, определённое в блоке Match.

Также следует указать, что scp (и некоторые другие утилиты на основе SSH) могут пользоваться вашим конфигурационным файлом SSH! Как правило, это делается по умолчанию, но мне известны случаи, когда это не так. Если вы работаете в такой системе, где scp не использует ваш конфигурационный файл ~/.ssh/config автоматически, то можно явно определить это при помощи аргумента -F ~/.ssh/config.

ssh-copy-id

Утилита ssh-copy-id — это небольшой инструмент, при помощи которого удобно быстро загружать публичный ключ на сервер.

Вот команда для этого: ssh-copy-id -i internal-web [email protected]

  • ‑i internal‑web: указываем имя того приватного ключа, при помощи которого мы хотим аутентифицироваться на сервере.

  • [email protected] указываем тот сервер, на который мы хотим загрузить публичный ключ.

ssh-keygen

При помощи этой утилиты генерируются пары, в каждую из которых входят публичный и приватный ключ. Обычно рекомендуется задавать ключ побольше при помощи опции -b. Хотя я и не эксперт по криптографии, обычно чем длиннее — тем лучше, и по умолчанию размер ключа равен 3072 (как минимум, на моей машине). По умолчанию ssh-keygen использует алгоритм RSA, но можно использовать и другие (более предпочтительные и сильные) алгоритмы, указав флаг -t. IE ssh-keygen -t ecdsa -b 521 Кроме того, можно проверять ключи, просматривать их фингерпринт и размер в байтах при помощи команды ssh-keygen -lf <file-name>.

Заключение

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

Ссылки

https://github.com/cwolff411/redteamvillage-sshtunnels

https://www.ssh.com/academy/ssh/tunneling-example

https://goteleport.com/blog/ssh-tunneling-explained/

https://linuxize.com/post/how-to-setup-ssh-tunneling/

https://iximiuz.com/en/posts/ssh-tunnels/