Skip to content
dreamcatcheredPublic

About

⚡ Доступ к терминалу через NAT одной командой — self-hosted аналог tmate/ngrok на Go: relay-сервер, PTY, эфемерные E2E-сессии

Resources

Stars

0 stars

Watchers

0 watching

Forks

Latest commit

 

History

11 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

* swagSSH

Мгновенный обратный SSH — self-hosted аналог tmate / ngrok / scp для машины за NAT

ssh.swag.best  •  Releases  •  Установка  •  Как работает  •  Сборка


Что это

swagSSH позволяет подключиться к любому компьютеру за NAT, файрволом или CG-NAT одной командой. Никакого проброса портов, VPN, Tailscale или WireGuard. Только исходящее SSH-соединение к вашему серверу.

  • Пользователь выполняет одну команду и получает ID сессии
  • Оператор вводит этот ID и получает полноценный интерактивный терминал, может передавать файлы и запускать команды
  • Сервер релеит трафик между ними, не храня ничего на диске

Установка

Для пользователя (поделиться терминалом)

Windows:

iwr -useb https://ssh.swag.best/install.ps1 | iex

Linux / macOS:

curl -fsSL https://ssh.swag.best/install.sh | bash

После выполнения появится ID сессии вида swag-a8f2d1.

Для оператора (подключиться)

Скачайте бинарник под вашу платформу из Releases или соберите из исходников:

swagssh connect swag-a8f2d1

Команды

swagssh share [options]              поделиться терминалом этой машины
    --id <name>                      свой ID сессии (например, my-laptop)
    --ttl <duration>                 время жизни сессии: 1m..24h (по умолчанию 1h)
    --no-reconnect                   не переподключаться при обрыве сети
    --retries <n>                    попыток подключения (по умолчанию 5)

swagssh connect <id>                 интерактивный терминал
swagssh send <id> <path> [-o name]   отправить файл или директорию (аналог scp)
swagssh recv <id> <path> [-o name]   забрать файл или директорию (аналог scp)
swagssh exec <id> <command...>       выполнить команду, вывести результат и код выхода
swagssh version                      версия

Глобальный флаг --server host:port меняет релей (по умолчанию ssh.swag.best:2222).

Примеры

# расшарить машину на 30 минут с запоминающимся ID
swagssh share --id my-laptop --ttl 30m

# подключиться к терминалу
swagssh connect my-laptop

# передать файл (как scp)
swagssh send my-laptop ./report.pdf
swagssh send my-laptop ./project/          # директория уедет рекурсивно (tar)

# забрать файл / директорию
swagssh recv my-laptop /var/log/app.log
swagssh recv my-laptop /etc/nginx/ -o nginx-config

# выполнить команду без интерактива
swagssh exec my-laptop "uname -a"
swagssh exec my-laptop "df -h /" ; echo "exit: $?"

Как работает

Пользователь ──(исходящее SSH)──▶  РЕЛЕ-СЕРВЕР  ◀──(исходящее SSH)── Оператор
    │                              swagSSH                               │
    │                          ssh.swag.best:2222                        │
    ▼                                                                    ▼
 [PTY] shell                                                      терминал, файлы,
powershell / bash                                                команды (exec)
  1. Пользователь запускает swagssh share — клиент создаёт локальный PTY, запускает shell и устанавливает исходящее SSH-соединение с сервером
  2. Сервер генерирует короткий ID сессии (swag-xxxxxx) или принимает пользовательский (--id), сохраняет канал в памяти и выводит ID пользователю
  3. Оператор подключается: connect даёт терминал, send/recv передают файлы и директории, exec выполняет команду — сервер открывает отдельные SSH-каналы к машине пользователя и прозрачно релеит байты

Файлы идут по тем же SSH-каналам (шифрование, flow control), директории упаковываются в tar на лету. Ничего не пишется на диск сервера.

Возможности

Одна команда Без установщиков, конфигураций и регистраций
Обход NAT Работает через CG-NAT, файрволы и любые ограничения
Self-hosted Весь трафик через ваш сервер, полный контроль
Кроссплатформенность Windows, Linux, macOS (amd64 / arm64 / 386) — один бинарник
Файлы как в scp send / recv для файлов и директорий, с прогрессом и проверкой доставки
exec Однократный запуск команды без открытия терминала
Свои ID и TTL --id my-laptop --ttl 30m — сессия на заданное время
Живучесть Авто-реконнект с сохранением ID и shell, keepalive, ретраи с backoff
TOFU-защита Host key сервера запоминается при первом соединении, смена = предупреждение о MITM
End-to-End шифрование SSH + Ed25519, эфемерные сессии
Интерактивный терминал PTY, resize, vim, htop, tmux, PowerShell

Архитектура

├── cmd/
│   ├── server/main.go        # SSH Relay Server (systemd-сервис)
│   └── client/               # CLI клиент
│       ├── main.go           # команды share/connect/send/recv/exec
│       ├── share.go          # шеринг: PTY, реконнект, keepalive
│       ├── shareaux.go       # приём файлов/exec на стороне пользователя
│       ├── transfer.go       # send/recv на стороне оператора
│       ├── exec.go           # exec на стороне оператора
│       ├── knownhosts.go     # TOFU known_hosts
│       ├── connect_unix.go   # терминал оператора (Unix)
│       ├── connect_windows.go# терминал оператора (Windows)
│       ├── pty_unix.go       # Unix PTY
│       └── pty_windows.go    # Windows pipe-PTY
├── internal/proto/           # общий wire-протокол (каналы, init, статусы)
├── web/
│   ├── index.html            # Лендинг
│   ├── install.sh            # Установщик Linux/macOS
│   └── install.ps1           # Установщик Windows
└── dist/                     # Скомпилированные бинарники

Стек

Слой Технология
Язык Go 1.22+
SSH golang.org/x/crypto/ssh
PTY (Unix) github.com/creack/pty
PTY (Windows) Pipe-эмуляция с CR/LF-конверсией
Архивы (директории) archive/tar (потоково, без диска)
Веб-сервер Nginx + Let's Encrypt (автопродление certbot)
Управление сессиями sync.Map in-memory + TTL cleanup
Сервис systemd

Сборка

# Сервер
go build -ldflags="-s -w" -o swagssh-server ./cmd/server/

# Клиент (все платформы)
GOOS=linux   GOARCH=amd64 go build -ldflags="-s -w" -o dist/swagssh-linux-amd64       ./cmd/client/
GOOS=linux   GOARCH=arm64 go build -ldflags="-s -w" -o dist/swagssh-linux-arm64       ./cmd/client/
GOOS=darwin  GOARCH=amd64 go build -ldflags="-s -w" -o dist/swagssh-darwin-amd64      ./cmd/client/
GOOS=darwin  GOARCH=arm64 go build -ldflags="-s -w" -o dist/swagssh-darwin-arm64      ./cmd/client/
GOOS=windows GOARCH=amd64 go build -ldflags="-s -w" -o dist/swagssh-windows-amd64.exe ./cmd/client/
GOOS=windows GOARCH=386   go build -ldflags="-s -w" -o dist/swagssh-windows-386.exe   ./cmd/client/

Серверное развёртывание

# systemd сервис
systemctl enable --now swagssh

# Флаги сервера
#   -port 2222            порт релея
#   -host-key <path>      Ed25519 host key (генерируется при первом запуске)
#   -max-sessions 256     максимум одновременных сессий
#   -max-conns-per-ip 16  максимум одновременных соединений с одного IP
#   -admin 127.0.0.1:8022          админ-панель (пусто = выключена)
#   -admin-password-file <path>     пароль админки из файла
#   -ban-file /etc/swagssh/bans.json   персистентные баны IP (переживают рестарт)

# Nginx конфигурация
# /etc/nginx/sites-available/swagssh
# server_name ssh.swag.best;
# Проксирует: web/ → лендинг, /releases/ → dist/, /install.* → скрипты

Админ-панель

swagssh-server -admin 127.0.0.1:8022 -admin-password-file /etc/swagssh/admin.pass -ban-file /etc/swagssh/bans.json

Панель слушает только localhost — наружу публикуется через nginx (location /admin/ { proxy_pass http://127.0.0.1:8022/; }). Вход по паролю (cookie-сессия, HttpOnly + SameSite=Strict, Secure за HTTPS), 5 неверных попыток = бан IP на час.

Что видно и чем можно управлять:

  • Сессии — live-просмотр: ID, IP пользователя, TTL, подключённый оператор, трафик; разрыв сессии одной кнопкой
  • История — завершённые сессии: кто делился, кто подключался оператором и когда, сколько трафика прошло
  • IP-адреса — коннекты, сессии, фейлы хендшейка, перебор ID; блокировка на 1ч / 24ч / 7д / 30д / навсегда (персистентно)
  • События — полный журнал: создания/закрытия сессий, подключения операторов, передачи, баны, отклонённые коннекты

Защита от перебора ID сессий: 10 несуществующих ID за 10 минут с одного IP → автобан (24ч → 7д → навсегда при рецидивах). Все баны пишутся в JSON-файл и переживают рестарт сервера.

Безопасность

  • Ed25519 host-ключи (генерируются автоматически при первом запуске)
  • TOFU: клиент запоминает host key сервера (known_hosts) и прерывает соединение при его смене — защита от MITM (--insecure-host-key для обхода)
  • Эфемерные сессии — ничего не хранится на диске сервера
  • TTL сессии: от 1 минуты до 24 часов (по умолчанию 1 час), не продлевается при реконнекте, автоматическая очистка
  • Криптографически безопасная генерация ID сессий (crypto/rand)
  • Лимиты: максимум сессий и соединений с одного IP, таймаут хендшейка
  • При приёме файлов имена санитизируются (без .. и абсолютных путей), tar-архивы распаковываются только внутри целевой директории
  • Все данные только в памяти

Лицензия

MIT


* swagSSH®

About

⚡ Доступ к терминалу через NAT одной командой — self-hosted аналог tmate/ngrok на Go: relay-сервер, PTY, эфемерные E2E-сессии

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages