SSH далек от совершенства, но он был разработан с учетом безопасности, и на протяжении многих лет было написано огромное количество инструментов для облегчения его использования. Кроме того, большинство популярного софта комплектуются SSH. Он поддерживается практически во всех архитектурах и дистрибутивах, начиная от Raspberry Pi и заканчивая массивными суперкомпьютерными кластерами.
Сертификаты
Вы наверняка согласитесь с тем, что аутентификация с открытым ключом лучше, чем использование паролей. Не приходится вводить пароль, никто его не взломает и не подсмотрит через плечо.
Следующий уровень секьюрности после ключей – SSH-сертификаты, которые поддерживаются с OpenSSH 5.4, выпущенного ещё в 2010 году.
С помощью
SSH-сертификатов вы создаете центр сертификации (CA), а затем используете его
для выдачи и криптографической подписи, которая аутентифицирует пользователей.
Вы можете создать пару ключей, например, с помощью команды ssh-keygen
:
Файл
host_ca
является закрытым ключом центра сертификации хоста и должен храниться в
защищенном месте. Не выдавайте его никому, не копируйте куда-либо и убедитесь,
что как можно меньше людей имеют к нему доступ. В идеале он «живет» на
машине, которая не допускает прямого доступа, и все сертификаты выдаются автоматически.
Рекомендуется использовать два отдельных CA – один для подписания сертификатов хостов, другой для пользователей. Одни и те же процессы не будут добавлять и хосты, и юзеров. А если закрытый ключ скомпрометируют, нужно будет лишь пересоздать сертификаты для хостов или пользователей, а не оба сразу.
Вот так создается
user_ca
:
Файл
user_ca
– закрытый ключ пользователя, который должен быть защищен, как и закрытый
ключ хоста.
Выдача сертификатов хостам
Создадим новый ключ и подпишем с помощью центра сертификации.
Вот описание используемых флагов:
- -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
, а затем и в ~/.ssh/known_hosts
:
Значение
*.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 tatooine@proglib.io: буквенно-цифровая строка, которая будет видна в логе 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 Host
Еще один способ повысить безопасность SSH – принудительно использовать bastion-хост – ssh-шлюз, служащий единственной точкой входа в инфраструктуру. Уменьшение вероятности любой потенциальной поверхности атаки за счет использования файерволов позволяет лучше следить за тем, кто к чему обращается.
Переход к
использованию такого метода не должен быть трудной задачей, особенно если вы уже
применяете сертификаты. Все настройки совершаются через локальный конфиг:
~/.ssh/config
.
Вот пример принудительного использования SSH-доступа к любому хосту в домене example.com, который будет перенаправлен через bastion-хост, в bastion.example.com:
Вместе с bastion для своих подключений вы можете использовать iptables (или другой *nix-вый файервол на ваш выбор) на серверах за bastion-ом, для блокировки входящих 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-код, который пользователь может сканировать с помощью приложения.
Если вам
потребуется изменить какие-либо настройки в будущем, или полностью удалить
функциональность, конфигурация будет сохранена в разделе
~/.google_authenticator
.
Настройка 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, предоставляя пользователям возможность гибко продолжать использовать инструменты, с которыми они знакомы.
Комментарии