Назад к обновлениям
New releaseAug 20, 2026

sshroute v0.2.11

Сетевой SSH-роутер — направляет соединения на разные IP-адреса/порты/ключи/шлюзы в зависимости от активной VPN-сети или сетевого подключения.

Поделиться

sshroute

CICodeOpenSpecSecurity
CI
Release
OpenSpec Badge
Scorecard
Latest Release
codecov
Go Report Card
Go Reference
Specs
Requirements
Tasks
Open Changes
OpenSSF Scorecard
CII Best Practices
License: Apache 2.0

Сетевой SSH-маршрутизатор. Определяет вашу активную сеть или VPN и автоматически выбирает правильный хост, порт, файл ключа и шлюз для каждого SSH-подключения — без изменений в ~/.ssh/config.

Как это работает

Определите каждый логический хост один раз с профилем default и опциональными переопределениями для каждой сети. При каждом подключении sshroute определяет, в какой сети вы находитесь (VPN, офисная LAN, WireGuard-пир и т. д.), и разрешает правильные SSH-параметры перед передачей управления настоящему /usr/bin/ssh.

ssh myserver
  → sshroute определяет: corp-vpn активен
  → разрешает: 10.100.0.50:2222 через bastion.corp.internal
  → exec /usr/bin/ssh -p 2222 -i ~/.ssh/corp_key -J bastion.corp.internal 10.100.0.50

Зачем нужен sshroute?

Для домашних лабораторий

В вашей лаборатории, скорее всего, есть как минимум две реальности: вы либо дома в локальной сети, либо в отъезде и подключаетесь через WireGuard или другой VPN. Проблема в том, что ~/.ssh/config не знает, в какой из них вы находитесь — в итоге вам приходится создавать отдельные алиасы (server-lan, server-vpn), или шлюз, который работает только половину времени, или просто запоминать IP-адреса.

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

Кроме того, он прозрачно перехватывает SSH — git push, rsync, scp будут работать через него автоматически после настройки теневого режима. Никаких обёрток, шелл-функций или размышлений.

Для корпоративных сред

Корпоративные сети ещё сложнее. У вас есть публичный интернет, возможно, VPN «сайт-сайт», возможно, личный VPN с разделением трафика, а внутри — разные шлюзы в зависимости от целевой среды — dev, staging, prod, у каждой свой бастион и ключ. Поддерживать всё это в ~/.ssh/config означает либо один огромный конфиг, который ломается при любом изменении инфраструктуры, либо писать скрипт, который каждый член команды поддерживает по-своему.

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

Сравнение

Функция~/.ssh/configТолько WireGuardTeleport / Boundarysshroute
Определяет вашу текущую сеть
Автоматически выбирает лучший путь
Переключение при сбое подключения
Автопереподключение + смена маршрута при обрыве⚠️ туннель кочует⚠️ через фиксированный прокси
Одна команда на хост из любого места⚠️ VPN должен быть включён
Размер конфига для 10 хостов × 4 пути📄 ~600 строк📄 ~600 строк + конфиг VPN📄 конфиг на сервере📄 ~60 строк
Мобильные устройства в роуминге⚠️ ручные алиасы⚠️ требуется VPN
Автоматическая цепочка шлюзов⚠️ ручной -J➖ не применимо
Работает с scp / rsync / git / Ansible⚠️ частично
Не требует установки серверной части
Не требует сервера аутентификации или демона
Не требует клиентского агента
Open source, полностью самостоятельный⚠️ open-core

Teleport и Boundary — это другая категория: они добавляют контроль доступа, журналы аудита и аутентификацию на основе сертификатов поверх маршрутизации. Если вам нужно именно это — используйте их. sshroute предназначен для тех случаев, когда нужна интеллектуальная маршрутизация без операционных издержек центрального сервера аутентификации.

Установка

Загрузка бинарного файла

Загрузите последний релиз с GitHub Releases. Доступны бинарные файлы для Linux, macOS и Android на архитектурах AMD64 и ARM64.

Установка через Go

go install github.com/thereisnotime/sshroute@latest

Android (Termux)

Загрузите архив android_arm64 с GitHub Releases, распакуйте и поместите бинарный файл в ~/.local/bin:

mkdir -p ~/.local/bin
curl -Lo "$TMPDIR/sshroute.tar.gz" \
  https://github.com/thereisnotime/sshroute/releases/latest/download/sshroute_android_arm64.tar.gz
tar -xzf "$TMPDIR/sshroute.tar.gz" -C ~/.local/bin sshroute
chmod +x ~/.local/bin/sshroute

Добавьте ~/.local/bin в PATH в ~/.bashrc или ~/.profile, если ещё не добавлено:

echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.bashrc
source ~/.bashrc

В качестве альтернативы скомпилируйте из исходного кода с Go от Termux. Поскольку официальный набор инструментов Go не публикует бинарные файлы для android/arm64, установите GOTOOLCHAIN=local, чтобы использовать то, что поставляется с Termux:

GOTOOLCHAIN=local go install github.com/thereisnotime/sshroute@latest

После установки укажите путь к SSH-бинарнику, так как в Termux нет /usr/bin/ssh:

# ~/.config/sshroute/config.yaml
ssh_binary: /data/data/com.termux/files/usr/bin/ssh

Или через переменную окружения: export SSHROUTE_SSH=$(which ssh)

Docker

docker run --rm -v ~/.config/sshroute:/root/.config/sshroute \
  ghcr.io/thereisnotime/sshroute network

Podman

podman run --rm -v ~/.config/sshroute:/root/.config/sshroute \
  ghcr.io/thereisnotime/sshroute network

В системах с SELinux (Fedora, RHEL и т.д.) добавьте :Z к флагу тома:

podman run --rm -v ~/.config/sshroute:/root/.config/sshroute:Z \
  ghcr.io/thereisnotime/sshroute network

Теневой режим (прозрачная замена SSH)

Установите sshroute как ssh раньше в $PATH. Все вызовы SSH — из терминала, git, rsync, scp — будут перехватываться автоматически. Хосты, отсутствующие в вашем конфиге, будут передаваться /usr/bin/ssh без изменений.

mkdir -p ~/.local/bin
ln -s $(which sshroute) ~/.local/bin/ssh

# Добавьте в ~/.bashrc или ~/.zshrc, если ещё нет:
export PATH="$HOME/.local/bin:$PATH"

Быстрый старт

# Добавьте хост с профилем по умолчанию
sshroute add myserver --host myserver.example.com --user alice --key ~/.ssh/id_ed25519

# Добавьте переопределение для конкретной сети
sshroute add myserver --network vpn --host 10.8.0.50 --port 2222 --jump bastion.vpn

# Подключитесь — сеть определяется автоматически
sshroute connect myserver

# Просмотрите разрешённую команду без выполнения
sshroute connect myserver --dry-run

# Посмотрите, какая сеть сейчас активна
sshroute network

Команды

Глобальные флаги

Эти флаги применяются к каждой команде:

ФлагПеременная окруженияПо умолчаниюОписание
--configSSHROUTE_CONFIG~/.config/sshroute/config.yamlПуть к файлу конфигурации
-o, --outputtableФормат вывода: table, json, yaml
-v, --verboseSSHROUTE_VERBOSE=1falseОтладочный вывод в stderr
--dry-runfalseВывести разрешённую SSH-команду без выполнения

init

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

ФлагПо умолчаниюОписание
--forcefalseПерезаписать существующий файл конфигурации

connect <alias>

Определить активную сеть, разрешить SSH-параметры для alias и выполнить настоящий SSH-бинарник. Любые дополнительные аргументы после алиаса передаются SSH без изменений.

ФлагПо умолчаниюОписание
--fallbackfalseПробовать каждый профиль в порядке приоритета, переходя к следующему только при сбое подключения (код выхода 255)
--reconnectfalseКонтролировать подключение и автоматически переподключаться при обрыве, каждый раз заново определяя активную сеть и маршрут
--reconnect-delay2sПауза между попытками переподключения при включённом --reconnect

С --reconnect sshroute поддерживает ssh активным при разрывах (сон ноутбука, переключение Wi-Fi, роуминг между сетями). Поскольку при каждом переподключении сеть определяется заново, он может переключиться на другой маршрут: например, засыпание в локальной сети и пробуждение в хот-споте приведёт к переподключению через публичный маршрут вместо повторной попытки подключиться к теперь недоступному локальному адресу. Чистый выход (exit 0) или сбой аутентификации/удалённой команды останавливают цикл; переподключаются только настоящие обрывы. Переподключение запускает ssh как дочерний процесс (как и --fallback), поэтому sshroute остаётся резидентным на время сессии; SIGINT/SIGTERM завершают его. Сохранение состояния сессии при прерывании — задача вашего мультиплексора (tmux/zellij); комбинируйте --reconnect с -- tmux attach или -- zellij attach -c <имя>, чтобы сразу вернуться в сессию:

sshroute connect myserver --reconnect --fallback -- zellij attach -c work

list

Вывести список всех настроенных хостов и SSH-параметров, которые будут использоваться в текущей сети. Поддерживает -o table|json|yaml.

add <alias>

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

ФлагПо умолчаниюОписание
--hostИмя хоста или IP-адрес
--port22SSH-порт
--userИмя пользователя SSH
--keyПуть к файлу ключа (поддерживается ~)
--jumpШлюз — передаётся как -J в SSH
--networkdefaultПрофиль сети, в который записать параметры

remove <alias>

Удалить все профили для alias из конфигурации.

network

Вывести имя текущей обнаруженной сети (или default, если ни одна не подошла).

network list

Вывести список всех настроенных сетей с их приоритетом, правилами проверки и текущим состоянием активности. Поддерживает -o table|json|yaml.

network test <name>

Выполнить все проверки для сети name и вывести результат (пройдено/не пройдено) для каждого правила. Полезно для отладки логики обнаружения.

config

Вывести разрешённый путь к файлу конфигурации.

config edit

Открыть файл конфигурации в $EDITOR (по умолчанию nano). Создаёт файл и родительский каталог, если они не существуют.

resolve <alias>

Вывести SSH-параметры, которые будут использоваться для alias в текущей сети. Полезно для отладки и написания скриптов. Используйте --network <name>, чтобы переопределить обнаруженную сеть. Поддерживает -o table|json|yaml.

ФлагПо умолчаниюОписание
--networkавтоопределениеПрофиль сети, для которого разрешать параметры

copy <alias> <src> <dst>

Копировать файлы на настроенный хост или с него с помощью scp с теми же разрешёнными параметрами (ключ, порт, шлюз), что и connect. Используйте синтаксис <alias>:<path> для удалённых путей:

sshroute copy myserver ./local.txt myserver:/remote/path/
sshroute copy myserver myserver:/remote/file.txt ./local/

Переменная окружения SSHROUTE_SCP переопределяет используемый бинарник scp.

version

Вывести версию, коммит Git, дату сборки и информацию о среде выполнения Go.

update

Обновить sshroute на месте до последнего релиза GitHub. Он загружает архив для вашей платформы, проверяет его sha256 по checksums.txt, и — если установлен cosign — проверяет подпись релиза cosign, после чего атомарно заменяет запущенный бинарник.

sshroute update            # загрузить, проверить и установить последний релиз
sshroute update --check    # только сообщить, доступна ли более новая версия
sshroute update --force    # переустановить последнюю версию, даже если уже актуальная

Если проверка sha256 (или cosign, если он установлен) не удалась, обновление прерывается, и бинарник остаётся нетронутым. Это предназначено для установок из релизного бинарника; если вы устанавливали через go install или пакетный менеджер, обновляйтесь с их помощью.

Файл конфигурации

Расположение по умолчанию: ~/.config/sshroute/config.yaml

networks:
  corp-vpn:
    priority: 10          # меньше = проверяется первым
    checks:
      - type: interface
        match: wg0
      - type: route
        match: 10.100.0.0

  office:
    priority: 20
    checks:
      - type: ping
        host: 192.168.1.1
        timeout: 500ms

hosts:
  myserver:
    default:              # обязательный — используется, когда ни одна сеть не подходит
      host: myserver.example.com
      port: 22
      user: alice
      key: ~/.ssh/id_ed25519
      options:            # опционально — передаётся как флаги SSH -o Key=Value
        ConnectTimeout: "10"
        ServerAliveInterval: "30"
    corp-vpn:
      host: 10.100.0.50
      port: 2222
      key: ~/.ssh/corp_key
      jump: bastion.corp.internal
      options:
        ConnectTimeout: "5"   # переопределяет значение по умолчанию только для этой сети
    office:
      host: 192.168.1.50

Каждый хост должен иметь профиль default. Профили сетей могут указывать только поля, отличающиеся от default — неуказанные поля наследуются из default.

Поля профиля хоста

ПолеТипОписание
hoststringИмя хоста или IP-адрес
portintSSH-порт (по умолчанию: 22)
userstringПользователь SSH
keystringПуть к файлу ключа (~ раскрывается)
jumpstringАлиас шлюза или user@host
optionsmapПроизвольные флаги SSH -o Key=Value (например, ConnectTimeout, StrictHostKeyChecking)
commentstringОписание, отображаемое в sshroute list
tagslistТеги для фильтрации с помощью sshroute list --tag

Ключи options объединяются из default в профили сети — значения из сети переопределяют соответствующие ключи, непересекающиеся ключи наследуются.

Обнаружение сети

Сети оцениваются в порядке priority (наименьшее значение проверяется первым). Алфавитный порядок используется при равенстве приоритетов. Используется первая сеть, все проверки которой пройдены; если ни одна не подходит, применяется default.

Тип проверкиУспешна, когдаОбязательные поля
routeПодсеть/IP присутствует в таблице маршрутизации ядраmatch
interfaceИменованный интерфейс существует и операционно поднятmatch
pingХост отвечает на ICMP echo в течение тайм-аутаhost, timeout (опционально, по умолчанию 2s)
execКоманда оболочки завершается с кодом 0command

Несколько проверок в одном определении сети используют логику И — все должны быть пройдены.

Примеры

Готовые к использованию файлы конфигурации находятся в examples/:

ФайлСценарий использования
basic.yamlОдин хост, VPN vs публичный запасной вариант
multi-network.yamlОфисная LAN, корпоративный VPN, удалённый VPN, публичный
wireguard-backconnect.yamlWireGuard-пир, подключающийся к вам
jump-hosts.yamlРазные бастионы для каждой сети
multi-zone-roaming.yamlМногозонная домашняя лаборатория с WireGuard-шлюзом и мобильными устройствами в роуминге

Документация

Подробные руководства находятся в docs/:

РуководствоОписание
Настройка домашней лабораторииМногозонная домашняя лаборатория с WireGuard, шлюзами, NAS, узлами k3s
Многозонный роумингНесколько LAN, WireGuard-шлюз, мобильные устройства, перемещающиеся между сетями
Корпоративная / многопользовательская средаDev/staging/prod с бастионами для каждой среды и обнаружением VPN
Теневой режимПрозрачная замена SSH — git, rsync, scp, Ansible
Завершение в оболочкеДинамическое завершение алиасов для bash, zsh, fish
Скриптинг и автоматизацияИспользование resolve и copy в скриптах и CI-пайплайнах

Форматы вывода

Все команды списка поддерживают несколько форматов вывода:

sshroute list                  # таблица (по умолчанию)
sshroute list -o json          # JSON — для скриптов
sshroute list -o yaml          # YAML
sshroute network list -o json

Сообщество

Получить программу — загрузите готовый бинарный файл с Releases, установите через go install github.com/thereisnotime/sshroute@latest или соберите из исходников.

Обратная связь и сообщения об ошибках — откройте задачу на GitHub Issues. Используйте шаблон отчёта об ошибках для неожиданного поведения и шаблон запроса функции для идей.

Вклад — смотрите CONTRIBUTING.md о том, как настроить проект, запустить тесты и открыть pull request. Уязвимости в безопасности следует сообщать конфиденциально через GitHub Security Advisories.

Сборка из исходников

Требуется Go 1.22+ и just.

git clone [email protected]:thereisnotime/sshroute.git
cd sshroute

just build        # вывод в bin/sshroute
just build-all    # кросскомпиляция linux/darwin × amd64/arm64
just test         # запуск тестов с детектором гонок
just install      # go install с injected ldflags версии

Категории