SSH

26 мая 2026 · ~13 мин чтения

протокол сеть безопасность история devops

SSH

SSH (Secure Shell) — сетевой протокол прикладного уровня, который даёт зашифрованный двусторонний канал между двумя машинами поверх обычного TCP. Через этот канал можно выполнять команды, копировать файлы, прокидывать порты — и всё это так, чтобы посторонний посередине не смог ни прочитать, ни подменить трафик.

История

SSH придумал финн Тату Юлёнен (Tatu Ylönen) в 1995 году в Хельсинкском технологическом университете (Helsinki University of Technology, ныне Aalto University). Прямой повод был очень житейский: летом 1995 года в университетской сети случилась атака с перехватом паролей (sniffer-атака), которая утащила сотни логинов и паролей у пользователей telnet и rlogin — а они тогда передавали пароль открытым текстом, как обычное письмо.

До SSH мир выглядел так:

Юлёнен в июле 1995 выложил SSH-1 как условно-бесплатное ПО. Через полгода — десятки тысяч пользователей. В 1996 он основал компанию SSH Communications Security и переключился на коммерческую версию.

Дальше — два больших шага:

Главная веха последних лет — переход с RSA-2048 и DSA на Ed25519 (это «эллиптическая криптография» — об этом ниже). Это умолчание в OpenSSH с 2014 года, ключ Ed25519 короче, быстрее и считается более стойким.

Что это такое

SSH — это не одна программа, а протокол (как HTTP — это протокол, а Chrome и curl — программы, которые его говорят). У него есть две стороны:

Что протокол даёт:

  1. Конфиденциальность — весь трафик шифруется симметричным ключом, согласованным на этапе handshake.
  2. Целостность — каждый пакет подписан MAC-кодом (Message Authentication Code), подмена байтов в пути ломает подпись.
  3. Аутентификацию сервера — клиент проверяет, что попал именно на тот сервер, который имел в виду (через known_hosts).
  4. Аутентификацию клиента — сервер проверяет, что подключающийся — это тот, за кого он себя выдаёт (пароль, ключ, Kerberos, hardware token).

И вот тут важное отличие: SSH — это не просто «защищённый telnet». Поверх одного SSH-соединения можно открыть несколько независимых каналов (channels):

Это близкий родственник того, что в HTTP/2 называется «мультиплексированием»: одно соединение, много логических потоков.

SSH vs TLS. Часто путают. TLS (бывший SSL) — это «защитная плёнка» поверх любого приложения (HTTPS = HTTP + TLS); сертификат подтверждает доменное имя; модель доверия — иерархия Центров сертификации (CA). SSH — самостоятельный протокол; «сертификат» хоста — это просто его публичный ключ; модель доверия — TOFU, «trust on first use»: первый раз ты ему веришь, дальше клиент кричит, если ключ сменился. Поэтому SSH незаменим для серверов без публичных DNS-имён (домашние, временные, внутренние).

Аналогии из жизни

1. Курьер с опечатанной коробкой. Telnet — это открытка: всё, что написано, видит любой почтальон. SSH — это курьер, который везёт коробку в опломбированном ящике, и пломбу может срезать только адресат своим ключом. Адресат, в свою очередь, показывает курьеру свой паспорт (известное лицо).

Где ломается: у курьера один маршрут, у SSH — много каналов одновременно по тому же «маршруту». И SSH сам генерирует одноразовый ключ на каждый сеанс, а не использует один «универсальный замок» — это называется forward secrecy (если ключ потом утечёт, прошлые сеансы всё равно не расшифровать).

2. Защищённая телефонная линия в посольстве. Когда дипломаты звонят в столицу, у них стоит «крипто-телефон»: оба аппарата делают рукопожатие (обмен ключами), и дальше голос шифруется. Если кто-то «врежется» в провод — услышит только шум.

Где ломается: у дипломатов аппарат знает «свой» центр заранее. У SSH в первый коннект нет способа узнать, какой ключ у сервера «настоящий» — приходится спрашивать у пользователя «доверяешь?». Это слабое место — атака MITM возможна именно в первый раз. Поэтому в серьёзных конторах ключи хостов разносят заранее или подписывают через SSH CA (есть и такая опция, мало кто пользуется).

3. Замок с двумя ключами (асимметричная криптография). Представь почтовый ящик: каждый может бросить туда письмо (публичный ключ), но открыть и прочитать может только владелец (приватный ключ). При аутентификации по SSH-ключу сервер бросает в ящик «загадку», и только владелец приватного ключа может её решить.

Где ломается: настоящий почтовый ящик нельзя «подделать», а файл id_ed25519 можно скопировать. Поэтому ключ обычно ещё и парольной фразой защищают, и/или держат в хардварном токене (YubiKey, Secure Enclave на Mac).

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

Соединение SSH идёт в три фазы. Цифры приблизительные — на современном железе и проводе всё это занимает 50–150 мс.

Фаза 1: транспортный слой (transport layer)

Клиент → TCP SYN → Сервер
        ← SYN-ACK ←
        → ACK →                       // обычный TCP-handshake

Клиент → "SSH-2.0-OpenSSH_9.6" →      // строка-баннер, версия
        ← "SSH-2.0-OpenSSH_9.0" ←     // сервер отвечает версией

Дальше — обмен ключами (KEX, Key Exchange):

После KEX оба знают общий сеансовый ключ, и весь дальнейший трафик шифруется симметричным алгоритмом (обычно chacha20-poly1305 или aes256-gcm).

Фаза 2: аутентификация пользователя

Сервер спрашивает «кто ты?», клиент перебирает методы в порядке PreferredAuthentications:

  1. publickey — самый частый. Клиент шлёт «у меня есть ключ для пользователя pavel», сервер ищет соответствие в ~/pavel/.ssh/authorized_keys. Если найден — посылает challenge, клиент подписывает его приватным ключом, сервер проверяет подпись публичным.
  2. password — клиент шлёт пароль (внутри уже шифрованного канала). Безопасно от прослушки, но уязвимо к брутфорсу и плохим паролям. На современных серверах обычно отключают для root и для прода.
  3. keyboard-interactive — обёртка для PAM, через неё работают TOTP/2FA.
  4. gssapi-with-mic — Kerberos. В корпоративных Linux-сетях.

Фаза 3: соединение (connection layer)

Аутентифицировались — теперь можно открывать каналы. Клиент шлёт channel-open с типом канала. Сервер либо принимает, либо отвергает.

Самое полезное:

Forced-command — про вчерашнее

В authorized_keys рядом с публичным ключом можно прописать ограничения:

command="/usr/local/bin/mcp-clients-server",no-pty,no-port-forwarding ssh-ed25519 AAAAC3...

Эта строка значит: «когда зайдут с этим ключом — не давай шелл, не давай туннели, запусти ровно вот эту команду и закрой соединение, когда она завершится». Это forced-command — стандартный приём для безопасной «выдачи» одного конкретного сервиса по SSH без полного доступа.

Именно так был устроен вчерашний MCP-сервер clients: SSH-ключ только запускает на сервере MCP-демон, а попытка ssh server 'whoami' возвращает пустой ответ — потому что вместо whoami всё равно запускается MCP. Защищает от ситуации «ключ утёк → у злоумышленника шелл».

Один протокол, две модели доверия

TLS говорит: «верь сертификату, который подписал известный тебе центр». SSH говорит: «верь ключу, который ты увидел в первый раз». Эти модели — не «лучше/хуже», а под разные задачи: TLS для миллиардов незнакомых клиентов (веб), SSH для пары десятков серверов, которые ты сам и поставил.

Где встречается в обычной жизни

Где встречается в IT и бизнесе

Кто пользуется

Альтернативы и конкуренты

Когда НЕ стоит использовать

Связанные понятия

Литература и источники

Где встретилось у меня

Вчера всплыло, когда проверял доступ к MCP-серверу clients: подключение к нему сделано через SSH с forced-command в authorized_keys — ключ запускает только сам MCP-демон, попытка любой другой команды (ssh server 'whoami') возвращает пустой ответ. Это та самая модель «делегировать одно действие, а не дать шелл», о которой говорится выше. Параллельно вспомнил про деплой блога на VPS — это тоже SSH, только без forced-command, и rsync built/ server:/var/www/ едет поверх него же.

Краткое резюме