Сайт FSA
17.03.2024

SSH

Изначально эта статья была опубликована на Хабре.

Как гласит википедия, «SSH — сетевой протокол прикладного уровня, позволяющий производить удалённое управление операционной системой и туннелирование TCP-соединений (например, для передачи файлов). Схож по функциональности с протоколами Telnet и rlogin, но, в отличие от них, шифрует весь трафик, включая и передаваемые пароли. SSH допускает выбор различных алгоритмов шифрования. SSH-клиенты и SSH-серверы доступны для большинства сетевых операционных систем». Когда в первый раз знакомишься с ним, то, скорее всего, он представляется как средство для доступа к удалённому серверу. В первую очередь, так оно и есть. Однако его возможности намного шире.

Что может протокол SSH:

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

Часть функционала ssh-сервера может быть отключена, при необходимости через файл конфигурации.

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

SSH, работает в режиме точка-многоточка. В этом режиме есть некоторый узел, к которому могут подключаться другие узлы — сервер. Все клиенты подключаются к этому серверу.

В Linux системах обычно используется OpenSSH, где сервер обозначается sshd, что означает SSH демон (Daemon). Клиент SSH — ssh. Все необходимые настройки для клиента и сервера, в Linux системах, обычно хранятся в директории /etc/ssh/. По префиксу имени файла можно догадаться к клиенту или серверу имеет отношение файл настройки. Все настройки имеют глобальный характер, т.е. актуальны для всех пользователей устройства.

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

Пользовательские Файлы настроек SSH

Как уже было сказано ранее, файлы настроек хранятся по пути ~/.ssh/.

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

Файл authorized_keys содержит список ключей для доступа к этому пользователю через сервер sshd на этой машине. Обычно этот файл отсутствует, но если вы хотите использовать при подключении к данной машине под данным пользователем не только имя пользователя и пароль, но и ключ, то этот файл должен быть создан, и содержать публичные необходимые публичные ключи.

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

Файлы id_* содержат закрытые ключи доступа для текущего устройства. Вместо * в имени файла присутствует имя используемого алгоритма шифрования. Ключей может быть несколько, для каждого запрошенного алгоритма шифрования. Эти файлы должны храниться в полной секретности. Никому их передавать нельзя. На ключи доступа можно установить пароль, без которого невозможно будет воспользоваться этим ключом. В таком случае даже в случае утечки ключа, воспользоваться им будет невозможно без знания пароля.

Файлы id_*.pub содержат публичные ключи доступа, которые используются для подключения к другим устройствам. Вместо * в имени файла присутствует имя используемого алгоритма шифрования, которые предоставляет удалённое устройство при подключении. Ключей может быть несколько, для каждого доступного алгоритма шифрования.

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

Удалённое управление через SSH

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

ssh user@host

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

Копирование файлов на удалённый хост и обратно через SSH

Для копирования файлов через ssh существует свой аналог утилиты cpscp. Работает она аналогично, однако в качестве источника или получателя может быть указан файл или директория на удалённом хосте. Например, чтобы передать файл my_file в домашнюю папку пользователя на удалённом хосте необходимо выполнить команду:

scp my_file user@host:~/

user@host может быть сокращено до host, тогда будет использован текущий пользователь.

Socks прокси через SSH

Практически любой ssh сервер можно превратить в socks прокси. Для этого необходимо указать ключ -D и указать номер порта:

ssh user@host -D 1080

После успешного входа на сервер на локальной машине по адресу 127.0.0.1:1080 будет доступен socks-сервер. Его можно использовать с любыми программами, которые его поддерживают. Кроме номера порта можно указать адрес, который следует использовать для открытия порта. При указании вместо адреса *, порт будет открыт на всех доступных адресах на хосте.

Перенаправление портов через SSH

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

Для получения доступа к удалённому порту необходимо использовать опцию -L. Кроме протокола IP, доступ можно получить также и к Unix-сокетам на удалённой машине. Для доступа к порту IP команда имеет следующий формат:

ssh -L [bind_address:]port:host:hostport user@host

IP адрес bind_address можно не указывать. В таком случае будет открыт порт по адресу 127.0.0.1. port должен содержать номер порта. host — адрес, к которому имеет доступ удалённая машина, hostport — соответствующий порт. Адрес сервера SSH указывается аналогично другим командам.

Например, если есть необходимость подключиться к PostgreSQL сервер на удалённой машине, то можно выполнить следующую команду:

ssh -L 5433:127.0.0.1:5432 user@host

После подключения к серверу можно использовать порт 127.0.0.1:5433 на локальной машине для доступа к PostgreSQL на удалённой машине.

Для того, чтобы предоставить удалённой машине доступ к порту, который доступен с вашей машины, необходимо использовать опцию -R:

ssh -R [bind_address:]port:host:hostport user@host

В этом случае bind_address также не обязателен, а вместе с port они теперь указывают на адрес и порт на удалённой машине. host и hostport указывают на хост и порт, который вам доступен с вашей машины.

Например, если вы хотите, чтобы на удалённой машине могли подключиться к вашему веб-серверу, то выполните команду:

ssh -R 8080:127.0.0.1:80 user@host

В этом случае на удалённой машине по адресу 127.0.0.1:8080 будет доступен веб-сервер в вашей машины.

Обратите внимание, что ssh клиент не может использовать порты ниже 1024, поскольку они являются привилегированными и доступны только пользователю root.

Выполнение команд на удалённой машине через SSH

SSH позволяет выполнять команды на удалённом сервере. При этом весь их вывод может быть перенаправлен в консколь текущей машины. Например, выполним дамп базы данных PostgreSQL с помощью команды pg_dump gitea -Fc на удалённой машине.

ssh user@host "pg_dump gitea -Fc" > gitea.pg.dump

Команда создания дампа будет выполнена на удалённой машине, то всё выводимое ей будет доступно локально и может быть перенаправлено, например, в файл gitea.pg.dump, стандартными методами.

Использование ключей

Самый простой способ аутентификации при соединении — использование пароля. Однако есть более безопасный способ — использование ключей. Для того, чтобы сформировать свою пару ключей можно воспользоваться утилитой ssh-keygen. По умолчанию она создаёт ключи rsa. Сейчас рекомендуется использовать ключи формата ed25519. Они более компактные и обеспечивают достаточный уровень защищённости. Создайте пару ключей с помощью команды

ssh-keygen -t ed25519

Во время создания ключа будет уточнено куда сохранять пару ключей и какой пароль использовать для доступа к ключу. Можно не указывать пароль, но в таком случае, в случе утечки вашего закрытого ключа, злоумышленники легко смогут им воспользоваться. Конечно, вводить пароль при каждом использовании ключа неудобно и есть соблазн не использовать его. Но эту проблему легко решить с помощью ssh-agent, о чём будет рассказано далее. Поэтому при создании ключа смело указывайте пароль.

Generating public/private ed25519 key pair.
Enter file in which to save the key (/home/user/.ssh/id_ed25519):       
Enter passphrase (empty for no passphrase): 
Enter same passphrase again: 
Your identification has been saved in /home/user/.ssh/id_ed25519
Your public key has been saved in /home/user/.ssh/id_ed25519.pub
The key fingerprint is:
SHA256:Q8iNlV3kFMGi40OrqOLIn/PPHWKuj/ccom6hs8U1coA user@alpha
The key's randomart image is:
+--[ED25519 256]--+
|        .o +*o   |
|    .. =. oo.    |
|   E .+ o. ..    |
|      ..+        |
|     . *So       |
|    ..+ =.       |
|    .+.= +       |
|+  ++.B.= o      |
|o+o=B*==.+       |
+----[SHA256]-----+

После этих действий будет создано два файла: один с приватным ключом, другой с открытым (имя файла имеет расширение .pub). Теперь, чтобы использовать ключ при подключении к удалённым машинам, необходимо скопировать открытый ключ на нужный узел. После этого вы сможете подключаться на него используя ваш приватный ключ. Скопировать ключ можно просто копируя содержимое файла id*.pub в файл authorized_keys в папке нужного вам пользователя на удалённой машиной. Кроме этого, свой публичный ключ можно скопировать с помощью команды

ssh-copy-id user@host

Естественно, у вас должен быть доступ на эту машину на момент копирования, например, с помощью пароля. Если вы имеете несколько пар ключей, то вы можете указать какой конкретно ключ необходимо использовать:

ssh-copy-id -i ~/.ssh/id_ed25519 user@host

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

Диагностика ошибок подключения

Если есть проблема с подключением, можно активировать вывод диагностических сообщений:

ssh -v gitea@gitea.example

Это позволит подробнее изучить то, что происходит при подключении и выявить проблему.

Подробнее о файле конфигурации ~/.ssh/config

Файл конфигурации ssh клиента представляет из себя текстовый файл, где перечисляются настройки для различных хостов. Директива Host указывает, что далее идут настройки для определённого хоста или нескольких хостов. Далее можно указать какое имя хоста использовать для подключения, какой порт использовать, какой файл ключа, а также, например, использовать только аутентификацию по ключу:

Host my_server
Hostname fd12::8
Port 8022
IdentityFile ~/.ssh/id_ed25519
IdentitiesOnly yes

В данном случае при выполнении команды ssh my_server с такими настройками будет произведено подключение к хосту по протоколу IPv6 на адрес fd12::8 и порт 8022. Будет использован ключ ~/.ssh/id_ed25519. Идентификация по паролю не будет использована.

Можно сделать аналогичные настройки для всех необходимых для вас хостов.

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

chmod 600 ~/.ssh/config
chown $USER ~/.ssh/config

Подробная информация о доступных опциях файла конфигурации доступна в man ssh_config.

ssh-agent

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

Чтобы воспользоваться этим сервисом необходимо его предварительно запустить. Сделать это можно автоматически при каждом входе в систему, например, с помощью systemd-юнита. Для этого создайте файл ~/.config/systemd/user/ssh-agent.service со следующим содержимым:

[Unit]
Description=SSH key agent

[Service]
Type=simple
Environment=SSH_AUTH_SOCK=%t/ssh-agent.socket
ExecStart=/usr/bin/ssh-agent -D -a $SSH_AUTH_SOCK

[Install]
WantedBy=default.target

Далее необходимо создать или добавить в файл ~/.config/environment.d/ssh_auth_socket.conf:

SSH_AUTH_SOCK="${XDG_RUNTIME_DIR}/ssh-agent.socket"

После этого можно активировать сервис и запустить его:

systemctl --user enable --now ssh-agent

Теперь можно вручную добавлять необходимые ключи с помощью ssh-add. Однако это не очень удобно. Чтобы ключи автоматически добавлялись в агент, необходимо в файле настройки клиента ~/.ssh/config добавить следующую строчку:

AddKeysToAgent yes

После этого любой используемый ключ будет автоматически добавлен в агента.

Кроме этого, агент умеет пробрасывать ключ на удалённые машины, если необходимо соединиться с другими машинами. Разрешить это можно с помощью добавления ForwardAgent yes в файле настроек ~/.ssh/config:

Host my_server
ForwardAgent yes

Настройка сервера SSH

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

Все дальнейшие настройки необходимо выполнить в файле /etc/ssh/sshd_config. Но в современных дистрибутивах этот файл рекомендуется оставлять без изменений, а необходимые настройки выполнить с помощь файлов в директории /etc/ssh/sshd_config.d/ с расширением .conf. Например, 10-my.conf.

Настройка по умолчанию обычно достаточно безопасна, но, скорее всего, включен доступ по паролю. Также может быть разрешён удалённый вход для пользователя root. После настроек доступа по ключу, лучше отключить возможность входа по паролю.

Явно укажем, что аутентификацию нужно делать по ключам, отключим аутентификацию по паролю, запретим вход пользователю root:

PubkeyAuthentication yes
PasswordAuthentication no
PermitRootLogin no

Кроме этого, нужно установить или убедиться, что установлено в вашей системе:

KbdInteractiveAuthentication no

Этот параметр разрешает интерактивный вход в систему с помощью клавиатуры. Кроме простого запроса пароля, ваш сервер может использовать дополнительные способы аутентификации реализуя двухфакторную аутентификацию. В современных дистрибутивах Ubuntu и Fedora он установлен в no по умолчанию. Ранее этот параметр назвался ChallengeResponseAuthentication, но это имя признано устаревшим и может быть удалено в новых версиях OpenSSH.

Если вы не хотите отключать вход по паролю, то стоит запретить использование пустого пароля:

PermitEmptyPasswords no

Заключение

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


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


Если данная заметка оказалась вам полезной, можете поблагодарить автора финансово.