Как правильно общаться с удаленным сервером через SSH

Как правильно общаться с удаленным сервером через SSH

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

Как правильно общаться с удаленным сервером через SSH

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

Следующий уровень секьюрности после ключей – SSH-сертификаты, которые поддерживаются с OpenSSH 5.4, выпущенного ещё в 2010 году.

С помощью SSH-сертификатов вы создаете центр сертификации (CA), а затем используете его для выдачи и криптографической подписи, которая аутентифицирует пользователей. Вы можете создать пару ключей, например, с помощью команды ssh-keygen :

Файл host_ca является закрытым ключом центра сертификации хоста и должен храниться в защищенном месте. Не выдавайте его никому, не копируйте куда-либо и убедитесь, что как можно меньше людей имеют к нему доступ. В идеале он «живет» на машине, которая не допускает прямого доступа, и все сертификаты выдаются автоматически.

Рекомендуется использовать два отдельных CA – один для подписания сертификатов хостов, другой для пользователей. Одни и те же процессы не будут добавлять и хосты, и юзеров. А если закрытый ключ скомпрометируют, нужно будет лишь пересоздать сертификаты для хостов или пользователей, а не оба сразу.

Вот так создается user_ca :

Файл user_ca – закрытый ключ пользователя, который должен быть защищен, как и закрытый ключ хоста.

Выдача сертификатов хостам

Как правильно общаться с удаленным сервером через SSH

Создадим новый ключ и подпишем с помощью центра сертификации.

ssh_host_rsa_key-cert.pub содержит подписанный сертификат хоста.

Вот описание используемых флагов:

  • -s host_ca: указывает имя файла закрытого CA-ключа, используемого для подписи.
  • -I host.example.com: буквенно-цифровая строка, идентифицирующая сервер. При необходимости значение можно использовать для отзыва сертификата.
  • -h: указывает, что сертификат выдается хосту, а не юзеру.
  • -n host.example.com: указывает разделенный запятыми список участников, для проверки подлинности которых будет действителен сертификат.
  • -V +52w: срок действия сертификата. В данном случае 52 недели (один год). По умолчанию сертификаты действительны вечно. Указание периода истечения срока действия сертификатов хоста настоятельно рекомендуется для ротации и замены сертификатов.

Настройка SSH для использования сертификатов

Нужно указать серверу, чтобы он использовал новый сертификат. Скопируйте три сгенерированных файла на сервер в каталог /etc/ssh , установите разрешения и добавьте в файл /etc/ssh/sshd_config следующую строку:

Перезагрузите sshd с помощью systemctl restart sshd . Теперь сервер настроен на выдачу сертификата. Чтобы локальный ssh-клиент мог автоматически доверять хосту на основе удостоверения сертификата, нужно добавить открытый ключ CA в known_hosts . Вы можете сделать это, добавив в начало файла host_ca.pub следующее: @cert-authority *.example.com , а затем и в

Значение *.example.com указывает на то, что этому сертификату следует доверять для идентификации любого хоста, к которому вы подключаетесь и который имеет домен *.example.com . Это разделенный запятыми список имен хостов для сертификата: host1, host2, host3 или 1.2.3.4, 1.2.3.5 в зависимости от обстоятельств.

Как только закончите настройку, удалите все старые записи для host.example.com в

/.ssh/known_hosts и запустите подключение. Правильность создания сертификата проверяется так:

На этом этапе вы можете продолжить выдачу сертификатов всех хостов, используя центр сертификации. Польза от этого следующая: вам больше не нужно полагаться на небезопасную модель Trust On First Use (TOFU) для новых хостов, и если вы когда-нибудь повторно развернете сервер и, следовательно, измените ключ хоста, новый хост автоматически представит подписанный сертификат без ужасного предупреждения: WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!

Выдача сертификатов пользователям (для аутентификации пользователей на хостах)

В этом примере мы создадим новый ключ пользователя и подпишем с помощью центра сертификации.

user-key-cert.pub содержит подписанный сертификат пользователя. Для входа в систему понадобится как этот, так и приватный ключ. Вот описание используемых флагов:

  • -s user_ca: указывает приватный ключ CA, используемый для подписи.
  • -I [email protected]: буквенно-цифровая строка, которая будет видна в логе SSH. Для точной идентификации пользователя рекомендуем использовать адрес электронной почты или логин.
  • -n palpatine, tatooine: указывает разделенный запятыми список участников, для проверки подлинности которых будет действителен сертификат. В примере мы предоставляем сертификат доступа как для palpatine , так и для tatooine .
  • -V +1d: указывает срок действия сертификата, в данном случае +1d означает 1 день.

Если нужно увидеть параметры подписи сертификата, используйте ssh-keygen -L :

Настройка SSH для проверки подлинности

После того как сертификат подписан, нужно сообщить серверу, что можно доверять пользователским сертификатам. Копируем user_ca.pub в директорию /etc/ssh , поправляем права и добавляем в конфиг /etc/ssh/sshd_config строку:

Как раньше, перезагружаем sshd с помощью systemctl restart sshd . Теперь сервер настроен на пропуск всех, кто представляет сертификат, выданный центром сертификации при подключении. Если сертификат хранится в том же каталоге, что и ваш приватый ключ (указанный с флагом -i , например ssh -i /home/tatooine/user-key palpatine @proglib.io ), он будет автоматически использоваться при подключении к серверам.

Проcмотр логов

Если вы посмотрите в журнал sshd сервера, запустив journalctl -u sshd , то увидите имя используемого для аутентификации сертификата, а также данные центра сертификации:

Если пользователь попытается войти в систему под логином, у которого нет доступа, в логе вы увидите такую ошибку:

Если срок действия сертификата истек, вы увидите следующую ошибку:

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

Взгляните на man ssh-keygen для новых идей.

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

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

Вот пример принудительного использования SSH-доступа к любому хосту в домене example.com, который будет перенаправлен через bastion-хост, в bastion.example.com:

Вместе с bastion для своих подключений вы можете использовать iptables (или другой *nix-вый файервол на ваш выбор) на серверах за bastion-ом, для блокировки входящих SSH-соединений. Например, вот так:

Хорошая идея оставить второй SSH-сеанс активным – если что-то пойдет не так, вы должны иметь возможность исправить ситуацию через установленное соединение.

Как правильно общаться с удаленным сервером через SSH

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

Давайте установим подключаемый модуль аутентификации google-authenticator, который потребует от пользователей на своем телефоне ввести код из приложения Google Authenticator. Вы можете скачать приложение для iOS и Android.

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

Установка google-authenticator

В системах на базе RHEL/CentOS можно установить модуль google-authenticator из репозитория EPEL:

Для систем на базе Debian / Ubuntu решение доступно в виде пакета libpam-google-authenticator:

Модуль имеет множество опций. В интересах экономии времени мы используем некоторые значения по умолчанию: запретить использование одного и того же токена дважды, выдавать временные коды и ограничивать пользователя максимум тремя входами в систему каждые 30 секунд. Настроим это все одной командой:

Вы также можете запустить google-authenticator без флагов и настроить его в интерактивном режиме.

Выполнение предоставит QR-код, который пользователь может сканировать с помощью приложения.

Если вам потребуется изменить какие-либо настройки в будущем, или полностью удалить функциональность, конфигурация будет сохранена в разделе

Настройка PAM для двухфакторной аутентификации

Чтобы заставить систему использовать коды OTP (one-time password), нужно отредактировать конфиг PAM sshd. Добавьте следующую строку в конец файла /etc/pam.d/sshd :

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

В завершение, измените методы аутентификации по умолчанию, чтобы SSH не запрашивал у пользователей пароль, если они не представляют двухфакторный токен. Эти изменения также вносятся в файл /etc/pam.d/sshd :

  • В RHEL/CentOS закомментируйте auth substack password-auth, добавив # в начало строки: #auth substack password-auth .
  • В Debian/Ubuntu, закомментируйте @include common-auth: #@include common-auth .
  • Сохранитесь.

Настройка SSH для двухфакторной аутентификации

Для того чтобы сервер требовал использования такой аутентификации, внесем несколько изменений в /etc/ssh/sshd_config :

  • изменим ChallengeResponseAuthentication no на ChallengeResponseAuthentication yes , чтобы разрешить использование pam.
  • установим список допустимых методов аутентификации, добавив следующую строку в конец файла (или отредактировав строку, если она уже существует): AuthenticationMethods publickey,keyboard-interactive

На этом этапе вы должны перезапустить sshd с помощью systemctl restart sshd . Убедитесь, что вы оставили SSH-соединение открытым, чтобы при необходимости исправить ошибки. Перезапуск SSH оставит существующие соединения активными, но если есть проблема с конфигурацией, новые соединения могут быть запрещены.

Тестируем

Подключаемся к bastion-у и видим приглашение:

Вводим код, представленный приложением Google Authenticator. Если вы проверите журнал sshd и если все настроено верно, перед вами будет следующее:

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