администрирование administration ,

SSH - коротко о главном SSH: The Basics

May 06, 2019 · 13 мин. на прочтение 13 min read
SSH - коротко о главном
Поделиться Share

Для лучшего понимания материалов этой статьи убедитесь, что вы хорошо представляете, как работает криптосистема с открытым ключом (Public-key cryptography). Так же необходим опыт использования SSH-клиента типа putty или kitty.

Для подключения к Linux мы используем Secure Shell или, как его называют, SSH. SSH - это криптографический сетевой протокол для защищённой передачи данных через не защищённые сети.

По сути SSH - это протокол, который реализует клиент-серверную модель и используется для подключения к удалённым компьютерам и запуска команд на них. Но он так же поддерживает туннелирование, что ставит его в один ряд с протоколами туннелирования (о протоколах туннелирования я писал ранее, в статье о VPN ). А также реализует протоколы SSH file transfer (SFTP) и secure copy (SCP). Для обеспечения защиты канала, SSH использует криптографическую систему с открытым ключом (Public-key cryptography).

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

Есть два пути использования защищённого SSH соединения.

Один - это автоматическая генерация пары (открытый/закрытый) ключей, для защиты сети, а затем использования аутентификации пользователя (логин/пароль) для входа в систему.

Другой путь - использование собственной пары ключей. При этом открытый ключ помещается на все системы, куда требуется доступ. Закрытый ключ остаётся у пользователя. Такой подход позволяет авторизовать пользователя без ввода пароля. Но с точки зрения безопасности — это не очень правильный способ. В следующей статье я расскажу, как настроить SSH аутентификацию при помощи открытого ключа и как сделать всё правильно.

Важно отметить, что закрытый ключ никогда не передаётся по сети. Он всегда остаётся в защищённом хранилище пользователя. SSH только проверяет, владеет ли тот же человек, который предлагает открытый ключ, соответствующим закрытым ключом или нет.

Существует несколько реализаций протокола SSH. Я знаком только с openssh. И чаще всего использовал его совместно с CentOS. Поэтому все примеры будут строятся на этой базе. Уверен, что на том базовом уровне, который описан в данной статье, все реализации протокола SSH, на всех OS одинаковы.

CentOS, даже в самой минимальной версии, устанавливает SSH по умолчанию. Сразу после установки мы имеем запущенный демон sshd, готовый принимать наши клиентские подключения на порту 22. Для подключения из Windows мы чаще всего используем putty/kitty. Хотя я недавно обнаружил, что Windows 10 имеет openssh-клиента в установке по умолчанию https://docs.microsoft.com/en-us/windows-server/administration/openssh/openssh_overview.

ssh-short-description/1.png

Я ещё не до конца разобрался с работой ssh-клиента под Windows. Где он хранит свои настройки, как их менят, подстраивая работу клиента под себя, поэтому для примера буду использовать kitty. Kitty - это форк putty. На мой взгляд там всё тоже самое, что в putty, но с дополнительными возможностями. Но вы можете использовать и putty. В рассматриваемом контексте их работа будет очень схожа.

Открываем kitty/putty и устанавливаем соединение с сервером. При первом подключении к серверу мы увидим Security Allert как показано на скриншоте. Я поясню важность этого предупреждения и почему не стоит автоматически наживать yes и продолжать работу.

ssh-short-description/2.png

Предупреждение гласит, что server’s host key не закеширован в реестре (registry). Имеется ввиду, на стороне клиента. И у Вас нет гарантий в том, что вы подключаетесь именно к тому компьютеру, к которому вы думаете. Давайте разберёмся, что такое “server’s host key” и как нам убедится в том, что мы подключаемся именно к тому самому серверу, к которому хотим. Как упоминалось выше, для шифрации трафика, SSH использует пару ключей (открытый/закрытый). При первом подключении клиент запрашивает у сервера открытый ключ, при помощи которого будет шифроваться трафик. А расшифровываться он будет закрытым ключом сервера.

На самом деле всё гораздо сложнее. Но мы же тут говорим о базовых вещах. Поэтому я не буду рассказывать о том, что для шифрования, на самом деле, SSH использует симметричный ключ. А ассиметричную пару ключей использует только для того, чтобы безопасно передать симметричный ключ шифрования. Так же называемый secret key или session key. Потому, что в данном контексте это не важно. Всё это происходит автоматически, без нашего ведома и участия. Если перед нами не стоит задача по расшифровке трафика, то единственное, с чем нам приходится иметь дело - это ассиметричная пара ключей - открытый/закрытый ключ. Поэтому ограничимся только ими. Так же я не буду рассказывать о том, что на текущий момент есть две версии протокола SSH1 и SSH2. И не буду рассказывать о различиях между ними. Скажу только, что лучше использовать SSH2.

Так вот в данном случае server’s host key - это открытый ключ сервера. MD5-хеш открытого ключа сервера мы видим в сообщении. В данном случае он имеет вид

d2:d6:d3:7c:cb:eb:c9:ab:6a:4f:22:78:c1:23:ac:86.

"ed25519" - схема подписи EdDSA использующая SHA-512 и Curve25519 (https://ru.wikipedia.org/wiki/EdDSA).

Q/A:

Q: Откуда берётся server’s host key?
A: Его сообщает сервер. Он генерит его в момент установки и первого запуска ssh-сервера.

Q: Где сервер его хранит?
A: В /etc/ssh/.

Q: Как убедиться в том, что я подключаюсь именно к тому серверу, к которому хочу.
A: Сверить MD5 открытого ключа из сообщения и с тем, что хранится на сервере.

Q: Как это сделать?
A: Взять открытый ключ и вычислить MD5 функцию. Например, на сервере, к оторому мы подключаемся, выполнить команду “ssh-keygen -E md5 -lf /etc/ssh/ssh_host_ed25519_key.pub”. На выходе мы получим MD5-хеш публичного ключа.

ssh-short-description/3.png

Можно попросить администратора сервера сделать это за нас. Или предоставить нам открытый ключ сервера и вычислить MD5 сервера самостоятельно, например, используя Powershell.

Открытый ключ на сервере - это строка вида

"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDKEmQW2NUcy4waXWiKjI3hDa7YCvE49Eoekjdk2BLcl"

Здесь нас интересует только цифробуквенный код “AAAAC3NzaC1lZDI1NTE5AAAAIDKEmQW2NUcy4waXWiKjI3hDa7YCvE49Eoekjdk2BLcl” - это закодированный открытый ключ в кодировке Base64. Для начала декодируем его.

$serverPublicKey = [System.Convert]::FromBase64String("AAAAC3NzaC1lZDI1NTE5AAAAIDKEmQW2NUcy4waXWiKjI3hDa7YCvE49Eoekjdk2BLcl")

Затем вычислим MD5-хеш полученной строки

$md5 = new-object -TypeName System.Security.Cryptography.MD5CryptoServiceProvider
$hash = [System.BitConverter]::ToString($md5.ComputeHash($serverPublicKey ))

ssh-short-description/4.png

В результате, посмотрев значение переменной $hash, мы увидим строку D2-D6-D3-7C-CB-EB-C9-AB-6A-4F-22-78-C1-23-AC-86. Что полностью совпадает с тем хешем, который мы видим в предупреждении.

ЗАЧЕМ ТАКИЕ СЛОЖНОСТИ? ЧТО НАМ ВСЁ ЭТО ДАЁТ?

Проверив таким образом ключ сервера, и убедившись в том, что мы подключаемся именно туда, куда нужно, мы можем смело нажимать Yes, в диалоговом окне Security Alert, которое нам выдаёт putty/kitty при подключении. Сделав это, наш ssh-клиент закеширует fingerprint. В следующий раз, при подключении к тому же серверу, SSH клиент сравнит полученный от сервера fingerprint с теми, что находятся у него в кеше. И если найдёт совпадение, то подключение пройдёт без предупреждения. До тех пор, пока ключ на сервере не поменяется. Не очистится локалный кеш доверенных ключей или… нас не перенаправят на другой сервер. Вот ради последнего всё это и нужно. Если злоумышленники, каким-то образом, перенаправят нас на другой сервер или подменят его, то мы опять получим предупреждение, но несколько иного вида.

ssh-short-description/5.png

И тогда нам придётся разобраться в ситуации и решить - устанавливать соединение с сервером или нет. Без этого механизма мы были бы в неведении. И могли бы передать на сервер злоумышленников конфиденциальную информацию или получить с него зловредные данные.

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

To better understand this article, make sure you are familiar with how Public-key cryptography works. Some experience with an SSH client like putty or kitty is also helpful.

To connect to Linux we use Secure Shell — SSH. SSH is a cryptographic network protocol for secure data transfer over insecure networks.

SSH implements a client-server model and is used to connect to remote computers and run commands. It also supports tunneling, which makes it similar to tunneling protocols (I wrote about tunneling earlier in my VPN article). SSH also provides SSH file transfer (SFTP) and secure copy (SCP). To protect the channel, SSH uses Public-key cryptography.

Public-key cryptography uses an asymmetric key pair: a public key and a private key. The public key can be known to everyone. Data is encrypted with the public key and decrypted with the private key, which is only known to the intended recipient. This is a very simplified overview.

There are two ways to use a protected SSH connection.

One way is automatic generation of a server key pair (public/private) to protect the channel, and then using user authentication (login/password) to log in.

The other way is using your own key pair: the public key is placed on all systems you need access to, while the private key stays with the user. This allows passwordless authentication, but from a security perspective it’s not always the best approach. In the next article I describe how to set up SSH authentication with a public key properly.

It’s important to note that the private key is never sent over the network. It always stays in the user’s secure storage. SSH only checks whether the person presenting the public key actually possesses the corresponding private key.

There are several SSH implementations. I’m familiar only with OpenSSH and used it mostly with CentOS, so the examples here are based on that. At the basic level described in this article, SSH works similarly across OSes.

CentOS installs SSH by default (even in minimal installs). Right after installation you have sshd running and listening on port 22. From Windows I typically use PuTTY/KiTTY, although Windows 10 includes an OpenSSH client by default: https://docs.microsoft.com/en-us/windows-server/administration/openssh/openssh_overview.

ssh-short-description/1.png

I haven’t fully explored the Windows OpenSSH client (where settings are stored, how to customize it, etc.), so for this example I’ll use KiTTY — it’s a PuTTY fork. In practice, PuTTY and KiTTY behave very similarly for the purposes of this article.

Open kitty/putty and connect to the server. On the first connection you will see a Security Alert like in the screenshot. This warning is important, and you shouldn’t blindly click “Yes”.

ssh-short-description/2.png

The warning says that the server’s host key is not cached in the registry (on the client side). That means you don’t have a guarantee you’re connecting to the server you think you are. Let’s break down what the “server’s host key” is and how to verify you’re connecting to the right machine.

As mentioned earlier, SSH uses a key pair (public/private) for encryption. On the first connection, the client requests the server’s public key and uses it to encrypt the traffic. The traffic is decrypted using the server’s private key.

In reality it’s more complex: SSH uses a symmetric session key to encrypt the traffic, and the asymmetric keys are used only to safely exchange that session key. This all happens automatically. Since this is a “basics” article and we are not trying to decrypt traffic, we can treat it as working with a public/private key pair. Also note there are SSH1 and SSH2 — use SSH2.

In this context, the server’s host key is the server’s public key. The warning shows its MD5 fingerprint, for example:

d2:d6:d3:7c:cb:eb:c9:ab:6a:4f:22:78:c1:23:ac:86.

"ed25519" - EdDSA signature scheme using SHA-512 and Curve25519 (https://ru.wikipedia.org/wiki/EdDSA).

Q/A

Q: Where does the server’s host key come from?
A: The server generates it during installation/first start of the SSH server and reports it to the client.

Q: Where is it stored on the server?
A: In /etc/ssh/.

Q: How can I be sure I’m connecting to the server I intend to?
A: Compare the MD5 fingerprint shown in the warning to the fingerprint of the public host key on the server.

Q: How do I check it?
A: Take the public key and compute its MD5. For example, on the server run: ssh-keygen -E md5 -lf /etc/ssh/ssh_host_ed25519_key.pub. The output contains the MD5 fingerprint.

ssh-short-description/3.png

You can ask the server administrator to do this for you. Or you can request the server public key and compute the MD5 yourself, for example using PowerShell.

The public key on the server looks like:

"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDKEmQW2NUcy4waXWiKjI3hDa7YCvE49Eoekjdk2BLcl"

We only care about the Base64-encoded part: “AAAAC3NzaC1lZDI1NTE5AAAAIDKEmQW2NUcy4waXWiKjI3hDa7YCvE49Eoekjdk2BLcl”.

First, decode it:

$serverPublicKey = [System.Convert]::FromBase64String("AAAAC3NzaC1lZDI1NTE5AAAAIDKEmQW2NUcy4waXWiKjI3hDa7YCvE49Eoekjdk2BLcl")

Then compute the MD5 hash:

$md5 = new-object -TypeName System.Security.Cryptography.MD5CryptoServiceProvider
$hash = [System.BitConverter]::ToString($md5.ComputeHash($serverPublicKey ))

ssh-short-description/4.png

If you look at $hash, you’ll see D2-D6-D3-7C-CB-EB-C9-AB-6A-4F-22-78-C1-23-AC-86, which matches the fingerprint shown in the warning.

Why do all this?

If you verify the host key and confirm you’re connecting to the right server, you can safely click “Yes” in the PuTTY/KiTTY Security Alert. The SSH client will cache the fingerprint. Next time you connect to the same server, the client will compare the fingerprint it gets from the server with the cached one. If it matches, you won’t see the warning again — until the server key changes, you clear your cache, or you get redirected to a different server.

That last scenario is the important one. If attackers redirect you to a different server (or spoof it), you’ll get a warning again, but of a different kind:

ssh-short-description/5.png

Then you need to investigate and decide whether to connect or not. Without this mechanism you might unknowingly send sensitive information to an attacker’s server or download malicious data.

In the next article, how to set up SSH public key authentication, I explain how to generate your own public/private key pair, how to store it correctly, what to copy to the server, and which settings should be configured on the client and on the server.

ssh
Заходите в группу Telegram Join the Telegram group
Если есть вопросы или хотите пообщаться, то заходите в мою группу Telegram. If you have questions or want to chat, join my Telegram group.