Разбираем процесс соединения и шифрования протокола SSH

SSH, или secure shell, — это наиболее распространенный способ безопасного удаленного администрирования серверов. Используя некоторые технологии шифрования, SSH предоставляет механизм для организации безопасного соединения, между двумя машинами.

В этой статье мы рассмотрим, какие именно подходы применяются в SSH.

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

Симметричное шифрование

Потому, как компоненты шифруют и дешифруют данные, можно сделать вывод, является ли оно симметричным или нет.

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

Такая схема еще часто называется с «общим секретом» (shared secret) или «секретный ключ». Чаще используется один ключ для всех операций, или пара ключей.

Симметричные ключи используются в SSH для шифрования всего соединения. Стоит отметить, что речь не о паре ключей public/private, которые применяются для авторизации. Они не имеют отношения к соединению, как таковому. Симметричное шифрование защищает, так же, и сам процесс ввода логина/пароля от «подслушивания».

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

Симметричный ключ, полученный таким образом, используется только для текущей сессии (соединения). Именно с помощью него, осуществляется передача данных между сервером и клиентом. Как только симметричный ключ «установлен», дальнейшее соединение шифруется, в том числе последующий процесс авторизации пользователя.

SSH можно сконфигурировать, чтобы использовались различные системы симметричного шифрования: AES, Blowfish, 3DES, CAST128 и Arcfour. Сервер и клиент, имеют список поддерживаемых систем, которые указаны в порядке приоритета. Первый из списка клиента, поддерживаемый сервером, используется для соединения.

В Ubuntu 14.04, список алгоритмов, по умолчанию, представлен следующим порядком: aes128-ctr, aes192-ctr, aes256-ctr, arcfour256, arcfour128, [email protected], [email protected], [email protected], aes128-cbc, blowfish-cbc, cast128-cbc, aes192-cbc, aes256-cbc, arcfour.

Если две машины, под управлением Ubuntu 14.04 соединяются друг с другом (при условии, конечно, что в конфигурационных файлах не изменялись настройки по умолчанию), они всегда будут использовать aes128-ctr.

Ассиметричное шифрование

Ассиметричное шифрование отличается от симметричного тем, что для передачи данных в одном направлении, требуются два связанных друг с другом ключа. Один из них известен как приватный (private key), другой называется публичным (public key).

Public key может быть свободно передан кому угодно. Несмотря на то, что он связан с private, получить или извлечь его из public ключа не представляется возможным. Криптографическая связь между ними позволяет зашифровывать данные публичным ключом, которые затем могут быть расшифрованы лишь приватным. И никак иначе, мы не можем с помощью public key расшифровывать, или с помощью private зашифровывать. Механизм работает, как бы, в одном направлении.

Private key должен храниться максимально безопасно. Никогда и ни при каких обстоятельствах его нельзя передавать третьим лицам или публиковать где-либо. Иначе парадигма public/private ключей работать не будет. Поскольку, расшифровать данные можно лишь с помощью него, сам факт извлечения информации говорит о том, что хост владеет приватным ключом.

SSH использует ассиметричное шифрование в процессе обмена ключами и «установке» симметричного шифрования, которое используется для сессии. На данном этапе, обе стороны создают временные пары и обмениваются публичными ключами.

Более детально можно рассмотреть ассиметричное шифрование на примере key-based авторизации. Клиент создает пару ключей, затем копирует свой публичный ключ на сервер, в специальный файл authorized_keys, в домашней директории пользователя (~/.ssh).

После того, как зашифрованное соединение будет установлено, клиент должен авторизоваться для дальнейшей работы. Сервер использует public key из указанного выше файла, для зашифровывания специального проверочного сообщения. Если клиент сможет его расшифровать, это означает, что он владеет «ответным» приватным ключом. Таким образом, сервер авторизует пользователя, поскольку ни у кого больше нет private key, по условиям парадигмы.

Хеширование (hashing)

Еще один вид криптографических манипуляций с данными, который используется в SSH. Функция хеширования – метод создания короткой «подписи» или некая сумма данных. Основное свойство хеша заключается в его необратимости. Из него невозможно получить те данные, над которыми была выполнена функция хеширования. А еще он уникален для каждого набора данных (файла, строки, объекта…)

Если такая функция применяется над одними и теми же данными, должен получиться один и тот же хеш. Любое, даже незначительное, изменение в них приводит к полностью другому результату.

Благодаря данному свойству, хеши, в основном, используются для верификации. Главное применение в SSH – HMAC – hash-based message authentication code (проверка подлинности сообщений при помощи хеширования). Для того чтобы убедиться, что полученное сообщение не было изменено в процессе передачи.

Алгоритм HMAC выбирается точно так же, как и алгоритм симметричного шифрования, из списка, в процессе выбора симметричного шифрования, о чем говорилось ранее. Первый поддерживаемый сервером используется для соединения.

Каждое сообщение, после того как будет зашифровано, «подписывается» с помощью MAC. Он вычисляется на основании симметричного ключа, порядкового номера пакета, и содержимого сообщения.

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

Как работает SSH?

Вы, вероятно, уже имеете общее представление о том, как же работает SSH.

Сервер «слушает» соответствующий порт и ждет к нему подключений. Он отвечает за безопасное соединение, авторизацию и предоставление соответствующих привилегий.

Клиент отвечает за инициализацию подключения, выбор алгоритмов и проверку информации о сервере, которая была сохранена в ходе прошлого сеанса. Так же, клиент предоставляет данные для авторизации.

Соединение можно разделить на два этапа. На первом, клиент с сервером «договариваются» об алгоритмах шифрования. На втором – происходит авторизация и принимается решение, имеет ли пользователь доступ к серверу.

Этап первый — согласование алгоритмов.

После того, как TCP соединение установлено (handshake), сервер присылает ответ с версиями поддерживаемых им протоколов. Если клиент поддерживает один из них, соединение продвигается дальше. Сервер так же предоставляет свой public host key, который клиент может использовать для проверки (known hosts).

Следующим шагом, обе стороны генерируют симметричный ключ, используя одну из модификаций алгоритма Диффи-Хеллмана (Diffie-Hellman). Алгоритм (и его вариации) дают возможность каждой стороне комбинировать свои private ключи с public ключами стороны, с которой происходит соединение. В результате чего получается один и тот же секрет для симметричного шифрования.

В целом, классический алгоритм Диффи-Хеллмана выглядит так:

  1. Обе стороны выбирают одинаковое больше целое число.
  2. Обе стороны выбирают, так называемый, генератор (обычно AES), который будет использоваться для вычислений.
  3. Независимо друг от друга, каждая сторона выбирает еще одно число, которое хранится в секрете. Оно используется в качестве private ключа для данной операции.
  4. Сгенерированный приватный ключ, генератор AES и общее число (п.1) используются для создания публичного ключа, который, в итоге, связан с приватным, но может быть передан другой стороне.
  5. Обе стороны меняются только что созданными публичными ключами.
  6. Каждая сторона использует свой приватный ключ, публичный ключ другой стороны и число из п.1, для вычисления общего секретного ключа. Хотя, процесс вычисления независимый для каждой из сторон, в итоге получаются одинаковые ключи. В этом суть алгоритма Диффи-Хеллмана.
  7. Затем, полученный секретный ключ используется для симметричного шифрования соединения.

Симметричное шифрование, которое используется с этого момента на протяжении всего соединения, называется бинарным пакетным протоколом (binary packet protocol). Вышеизложенный процесс, позволяет каждой стороне принимать участие в генерировании общего секретного ключа. Не позволяет одной из сторон контролировать его. Но самое главное, появляется возможность создать одинаковый ключ на каждой из машин, без его передачи через незащищенное соединение.

Получившийся ключ – симметричный. То есть используется для шифрации и дешифрации. Его назначение защитить все передаваемые данные между клиентом и сервером, создать, своего рода, туннель, содержимое которого не смогут читать третьи лица.

Авторизация пользователей на сервере

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

Вероятно, самый простой – с помощью пароля, когда сервер попросту предлагает пользователю набрать его на клавиатуре. Пароль передается через установленное к этому моменту защищенное соединение. То есть третьи лица не смогут «подсмотреть» пароль во время передачи (так называемая атака MITM – Man In The Middle).

Но, несмотря на то, что пароль будет передан в зашифрованном виде, данный способ не рекомендуется, поскольку сложность пароля имеет очевидные ограничения. Появляется возможность подбора пароля автоматизированным способом (Brute-force атака).

Популярная и рекомендуемая альтернатива – использовать авторизацию по ключам. Пары SSH ключей ассиметричные, то есть два связанных друг с другом ключа используются для разных целей.

Публичный ключ для шифрования данных и только для этого. Тогда, как приватный для дешифрации того, что было зашифровано парным публичным ключом. Последний может быть передан кому угодно, но, несмотря на его связь с приватным, не существует способа получить (вычислить) private key из public key.

Авторизация по ключам начинается только после того как зашифрованное соединение установлено. Процесс проходит так:

  1. Клиент отсылает серверу ID ключа, по которому он желает авторизоваться.
  2. Сервер проверяет файл authorized_keys в домашней директории пользователя, под которым клиент желает войти.
  3. Если публичный ключ с указанным ID найден, сервер генерирует случайное число (challenge message) и шифрует его с помощью этого ключа.
  4. Сервер посылает клиенту шифрограмму.
  5. Если клиент имеет приватный ключ, парный публичному на сервере, он в состоянии расшифровать то, что было передано п.3 — 4
  6. Клиент объединяет дешифрованное число с общим секретным ключом, установленным для текущей сессии. Затем вычисляет md5 хеш полученных после объединения данных.
  7. Клиент отправляет хеш из п.6 обратно серверу, в качестве ответа на его шифрограмму
  8. Сервер использует тот же секретный ключ от сессии, и число, которое сгенерировал в п.3 и тоже вычисляет md5, как клиент до этого. Если полученный хеш и принятый от клиента совпадают, это доказывает что последний владеет приватным ключом. Поэтому пользователь считается авторизованным.

Как видите, ассиметричность ключей позволяет серверу зашифровать сообщение для клиента с помощью публичного ключа. Затем клиент может доказать что он владеет ответным приватным ключом, правильно расшифровав сообщение. Два типа шифрования были использованы (симметричное и ассиметричное), каждое из которых имеет свои сильные стороны в данной модели.

Заключение

Изучение процесса соединения, согласования и авторизации SSH, поможет лучше понять, что происходит под капотом, когда вы подключаетесь к удаленному серверу. Надеюсь, теперь Вы лучше понимаете взаимосвязь между различными компонентами и алгоритмами, и как всё это работает вместе.