USSH
USSH — это протокол оболочки и пара клиент/сервер, построенные поверх USTP-Secure.
Это не TCP-туннель и не обёртка SSH внутри TCP.
Статус: Beta
Лицензия: MIT
Имена AEAD-шифров
chacha20 = CHACHA20_POLY1305
aes-256-gcm = AES_256_GCM
aes-128-gcm = AES_128_GCM
- AEAD-шифр по умолчанию:
chacha20
Порт по умолчанию
Сервер
python3 ussh_server.py \
--peer-ip <CLIENT_IP_OR_DOMAIN> \
--peer-port 0 \
--bind-ip 0.0.0.0 \
--bind-port 5322 \
--cipher chacha20 \
--congestion-control auto
Если --password опущен, сервер запрашивает пароль для входа в USSH при запуске.
При интерактивном запуске сервер спрашивает, следует ли установить его как службу systemd. Ответьте n, чтобы запустить его обычным образом. Используйте --no-systemd-prompt, чтобы пропустить этот вопрос.
Клиент
python3 ussh_client.py \
--peer-ip <SERVER_IP_OR_DOMAIN> \
--peer-port 5322 \
--bind-ip 0.0.0.0 \
--bind-port 0 \
--cipher chacha20 \
--congestion-control off \
--cleartext off
Клиент запрашивает пароль интерактивно, как SSH.
Клиент сохраняет первый увиденный открытый ключ X25519 сервера в ~/.ussh_known_hosts.json.
Если этот ключ позже изменится, клиент прерывает работу с ошибкой несоответствия TOFU, а не молча доверяет новому ключу.
Если вы намеренно ротировали ключ хоста сервера, запустите клиент с --regen-key, чтобы разрешить замену сохранённого ключа TOFU после интерактивного подтверждения.
Internet-Drafts
- Internet-Draft
USSH: https://datatracker.ietf.org/doc/draft-x1co-ussh/
Примечания
- Транспорт — USTP-Secure поверх UDP.
- USSH также поддерживает необязательный режим DATA в открытом виде (cleartext) с целостностью HMAC для каждого пакета:
- На стороне сервера:
--cleartext auto|on|off
- На стороне клиента:
--cleartext on|off
- При значении сервера
auto USSH следует запросу клиента.
- При значении сервера
on или off сервер принудительно задаёт итоговый режим открытого текста.
- При использовании
--cleartext on USSH выводит предупреждение, что открытый текст опасен в реальном интернете и рекомендуется только в контролируемых средах, например в локальной сети.
- Под USSH протокол USTPS использует читаемые ASCII управляющие строки, такие как
ACK: 10 MAC:<tag>, NACK: 42 MAC:<tag>, HELLO: ..., CLOSE:, а также бинарные DATA-кадры UPACK (UPAK).
ACK и NACK остаются в открытом виде для удобства отладки, но они аутентифицируются тегом HMAC для каждой сессии, чтобы предотвратить поддельные атаки на управление ACK/NACK.
- В обычном режиме полезные данные DATA используют AEAD-шифрование.
- В режиме открытого текста полезные данные DATA не шифруются, но всё равно содержат HMAC, поэтому третья сторона не может изменить их без обнаружения.
- USSH наследует потолок полезной нагрузки транспорта USTPS в
900 байт на полезную нагрузку DATA UPACK.
- USSH не определяет второй уровень фрагментации ниже USTPS.
- Поведение MTU, PMTU, nonce, обработка дубликатов и устаревших пакетов на транспортном уровне наследуются от USTPS.
- Автоматическая миграция сети/пути удалена.
- Если клиент меняет сеть и его исходный
IP:port изменяется, ожидается, что текущая сессия USSH закроется, и пользователь должен чисто переподключиться.
- Реализация миграции была удалена, поскольку вызывала практические проблемы с надёжностью и безопасностью:
- повторяющиеся потоки миграции при быстрой смене путей в NAT или мобильных сетях
- сессии, которые казались восстановленными, но переставали доставлять данные терминала
- длительные периоды тишины, прежде чем клиент замечал, что путь мёртв
- неоднозначность между реальным роуминг-клиентом и поддельными пакетами, заявляющими о существующей сессии
- состояние восстановления, которое могло оставить терминал зависшим вместо чистого переподключения
- Текущее поведение намеренно проще: проверять клиента на текущем
IP:port, привязывать сессию к этой конечной точке и переподключаться, если конечная точка меняется.
- USSH наследует необязательный
USTPS Congestion от транспорта.
- На стороне сервера:
--congestion-control auto|on|off
- На стороне клиента:
--congestion-control on|off
- При значении сервера
auto USSH следует запросу клиента. При значении сервера on или off сервер принудительно задаёт итоговый режим.
- Сам USTP-Secure остаётся неупорядоченным.
- USSH не превращает транспорт в упорядоченный TCP-подобный канал.
- USSH собирает только логический поток байтов
stdout перед записью в терминал.
- USSH также может поддерживать упорядочивание на уровне приложения для фрагментов ввода/вывода оболочки, где PTY ожидает связного поведения байтового потока.
- Такая сборка существует, потому что вывод интерактивной оболочки — это непрерывный поток байтов, и отображение байтов терминала в порядке сырого поступления может повредить большие объёмы вывода, такие как
ls, find или журналы компилятора.
- Это означает, что USTP-Secure по-прежнему избегает блокировки Head-of-Line на транспортном уровне, тогда как USSH восстанавливает только порядок на уровне приложения, необходимый для отображения терминала.
- Полезные данные шифруются по пакетно с помощью AEAD.
- Статический PSK не используется.
- Каждый клиент получает отдельный эфемерный ключ сессии AEAD через X25519.
- Пароль используется для аутентификации USSH после установления защищённой сессии.
- Сервер запускает реальную оболочку с PTY на машине, где выполняется
ussh_server.py.
- Клиент отправляет байты stdin и отображает байты stdout.
- Сервер поддерживает несколько клиентов, по одной оболочке/сессии на клиента.
- Если
--cipher задан на сервере, сервер использует именно этот шифр.
- Если
--cipher опущен или установлен в auto, сервер использует шифр, запрошенный клиентом.
- Клиенты отклоняют неожиданное согласование шифра.
- TOFU (Trust On First Use) включён на клиенте для обнаружения неожиданных изменений ключа сервера после первого подключения.
- Сервер по умолчанию хранит постоянный ключ хоста X25519 в
~/.ussh_host_key, чтобы TOFU оставался стабильным при переподключениях и перезапусках.
- Обычный перезапуск сервера не меняет ключ хоста.
- Используйте
--regen-key на сервере только тогда, когда вы намеренно хотите ротировать этот ключ хоста.
- Записи TOFU хранятся для каждого
<peer-ip-or-domain>:<peer-port>, поэтому другой сервер по другому адресу/порту рассматривается как другая идентичность хоста.
Транспортное рукопожатие
- USSH наследует то же рукопожатие с retry-токеном USTPS, что и USTP-Secure.
- Сервер сначала отправляет клиенту вызов с retry-токеном и метаданными сессии.
- Клиент должен вернуть этот токен, прежде чем зашифрованная сессия USSH будет принята.
- То же рукопожатие также согласовывает итоговый AEAD-шифр и то, включён ли
USTPS Congestion (on или off).
- То же рукопожатие также согласовывает, использует ли DATA AEAD-шифрование или открытый текст плюс HMAC.
- Retry-токен — это лишь доказательство достижимости перед созданием сессии.
- Это не ключ сессии, не nonce пакета и не замена для позднее выведенного ключа сессии AEAD.