September 29

Оптимизация управления ключами SSH на серверах Linux

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

Введение

Управление ключами Secure Shell (SSH) играет ключевую роль в обеспечении безопасного и масштабируемого контроля доступа в распределенных средах Linux. В этой статье разобраны методы оптимизации процесса управления жизненным циклом, ротации, распространения и аудита ключей SSH с использованием инструментов Bash, Python, Ansible, OpenSSH и принципов GitOps.

Генерация и ротация ключей

ssh-keygen -t ed25519 -C "infra-deploy@domain" -f /etc/ssh/keys/infra_ed25519 -N ""
chmod 600 /etc/ssh/keys/infra_ed25519

Что делает: создает пару ключей SSH ed25519 без пароля для автоматизированных деплоев с защищенными разрешениями.

find /home -name 'id_rsa.pub' -mtime +90 -exec echo "Rotate key:" {} \;

Что делает: сканирует открытые ключи старше 90 дней для пометки их на ротации.

import os, subprocess
key_path = "/etc/ssh/keys/infra_ed25519"
if os.path.exists(key_path):
    subprocess.run(["ssh-keygen", "-y", "-f", key_path])

Что делает: программно проверяет, что закрытый ключ существует и доступен для чтения, генерируя его открытый эквивалент.

Централизованное распределение ключей

- name: Push SSH public key to managed hosts
  hosts: all
  tasks:
    - name: Deploy public key
      authorized_key:
        user: deploy
        state: present
        key: "{{ lookup('file', '/etc/ssh/keys/infra_ed25519.pub') }}"

Что делает: распространяет централизованный открытый ключ SSH на все управляемые хосты при помощи сценария Ansible.

for host in $(cat inventory.txt); do
  ssh-copy-id -i ~/.ssh/infra_ed25519.pub deploy@$host
done

Что делает: распространяет открытый ключ SSH на несколько хостов, перечисленных в файле инвентаризации при помощи цикла Bash.

Аудит ключей на истечение срока действия

awk '{print $1, $2}' ~/.ssh/authorized_keys | sort | uniq -c

Что делает: проверяет наличие дубликатов или повторного использование открытых ключей SSH в файле authorized_keys.

find /home/*/.ssh/authorized_keys -type f -exec grep -H '2023-' {} \;

Что делает: отмечает ключи, выпущенные в прошлом, на основе встроенных комментариев к ключам или тегов.

import datetime
cutoff = datetime.datetime.now() - datetime.timedelta(days=90)
print(f"Remove keys older than: {cutoff.isoformat()}")

Что делает: определяет дату окончания срока действия ключа SSH при помощи кода Python.

Реализация политики через SSHD

cat <<EOF >> /etc/ssh/sshd_config
PasswordAuthentication no
PermitRootLogin prohibit-password
AuthorizedKeysCommand /usr/local/bin/lookup_keys.sh
AuthorizedKeysCommandUser nobody
EOF

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

systemctl restart sshd

Что делает: перезагружает службу SSH для применения изменений конфигурации.

Деплой ключей на основе GitOps

git clone git@github.com:org/ssh-keys.git /opt/ssh-keys
cp /opt/ssh-keys/devops.pub /home/devops/.ssh/authorized_keys

Что делает: использует шаблон GitOps для извлечения и применения открытых ключей из репозитория с контролем версий.

inotifywait -m /opt/ssh-keys -e modify | while read path action file; do
  systemctl reload sshd
done

Что делает: следит за обновлениями в ключах SSH, управляемых Git, и перезагружает sshd при изменении.

Отзыв и судебная экспертиза

echo 'SHA256:xyz...' >> /etc/ssh/revoked_keys

Что делает: добавляет отпечаток ключа в глобальный список отзыва SSH.

sshd -T | grep revokedkeys

Что делает: проверяет, распознается ли файл отозванных ключей демоном SSH.

journalctl -u sshd | grep "Authentication"

Что делает: регистрирует попытки криминалистической экспертизы, включая принятие и сбои ключа.

Интеграция с Vault или Secrets Manager

vault kv get -field=private_key secret/ssh/infra > ~/.ssh/id_ed25519
chmod 600 ~/.ssh/id_ed25519

Что делает: безопасно извлекает закрытый ключ из хранилища HashiCorp.

import boto3
client = boto3.client('secretsmanager')
key = client.get_secret_value(SecretId='ssh-key-dev')['SecretString']
with open('/home/dev/.ssh/id_ed25519', 'w') as f:
    f.write(key)

Что делает: интегрируется с AWS Secrets Manager для извлечения закрытого ключа SSH.

Закрепление ключа хоста

ssh-keyscan -t ed25519 server1.example.com >> ~/.ssh/known_hosts

Что делает: предварительно заполняет known_hosts доверенными ключами хостов для предотвращения атак MITM.

StrictHostKeyChecking yes
UserKnownHostsFile /etc/ssh/known_hosts

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

Безопасность перенаправления агентов SSH

Host *
   ForwardAgent no

Что делает: глобально отключает перенаправление агента SSH для предотвращения утечки учетных данных.

eval $(ssh-agent -s)
ssh-add ~/.ssh/id_ed25519

Что делает: запускает временный сеанс агента для использования в ограниченных масштабах.

Мониторинг и оповещение

ausearch -k ssh_login -ts recent

Что делает: использует auditd для отслеживания последних событий входа в SSH.

tail -F /var/log/auth.log | grep --line-buffered 'Accepted' | while read l; do
  echo "Login: $l" | mail -s "SSH Login Alert" admin@example.com
done

Что делает: отслеживает входы в SSH и выполняет оповещения по электронной почте в режиме реального времени.

Лучшие практики

Используйте краткосрочные SSH-сертификаты сгенерированные OpenSSH или Vault вместо долгосрочных статических ключей. Ротируйте ключи каждые 90 дней. Храните закрытые ключи только на зашифрованных томах. Используйте отдельные пары ключей для каждой среды и каждой роли. Отслеживайте использование ключей с помощью централизованного логирования. Отключайте SSH для сервисных учётных записей, где это не требуется. Используйте политику доступа к ключам на основе RBAC с помощью GitOps. Используйте неизменяемую инфраструктуру для минимизации сохраняемости ключей. Избегайте доступа по SSH с использованием подстановочных знаков.

Ещё немного безопасности

Не допускайте перехвата пароля. Убедитесь, что скрипт AuthorizedKeysCommand не может быть перехвачен или подделан. Ограничьте права доступа к ~/.ssh до 700, а к ключам — до 600. Убедитесь, что нет ключей, доступных для чтения всем. Избегайте повторного использования пар ключей между клиентами или командами. Создавайте резервные копии known_hosts для предотвращения атак типа «доверие при первом использовании». Контролируйте доступ к хранилищам или хранилищам ключей.

Производительность и масштабируемость

Пакетные операции с ключами выполняйте с помощью Ansible или SaltStack. Для больших парков устройств интегрируйте SSH с LDAP или сертификатами, чтобы избежать создания файлов authorized_keys для каждого пользователя. Предварительно загружайте ключи хоста для уменьшения задержки сканирования. Используйте переадресацию на основе сокетов с осторожностью. Дедуплицируйте избыточные записи ключей. Отслеживайте производительность SSHD с помощью таких инструментов, как perf или eBPF. Нагрузочно тестируйте параметры sshd_config, такие как MaxSessions и MaxStartups.

Техническое обслуживание и мониторинг

Автоматизируйте проверку срока действия ключей с помощью cron или таймеров systemd. Ротацию и повторную проверку ключей выполняйте в рамках конвейеров непрерывной интеграции и непрерывной доставки (CI/CD). Аудит авторизованных ключей выполняйте с помощью ежедневных скриптов. Делайте оповещения об изменении прав доступа в ~/.ssh. Ведите централизованный учёт всех активных ключей SSH. Создавайте отчёты о соответствии требованиям с указанием возраста ключа, владельца, исходного репозитория и связанного пользователя.

Поиск неисправностей

Если вход при помощи ключа не удаётся, выполните команду ssh -vvv для диагностики проблем с рукопожатием. Проверьте наличие неверных прав доступа к ~/.ssh. Убедитесь, что в authorized_keys указан правильный открытый ключ. Убедитесь в правильности синтаксиса sshd_config. Если ключи не подходят, отладьте разрешения Ansible или Vault. Если срок действия ключа истёк, выполните ротацию и повторите проверку. Следите за блокировками SELinux или AppArmor в журналах авторизации.

Проверка

Выполните команду ssh-keygen -lf для проверки отпечатка ключа. Выполните команду ssh-keyscan для проверки ключа хоста. Убедитесь, что команда sshd -T соответствует ожидаемой конфигурации. Проверьте, что задачи Ansible выполнены без ошибок. Проверьте журналы Vault или Secrets Manager на наличие доступа. Попробуйте войти по ключу и подтвердите уровень доступа. Убедитесь, что файл отзыва загружен.

Заключение

Управление ключами SSH играет основополагающую роль в обеспечении безопасности автоматизации, удалённого доступа и доверия внутри инфраструктуры. Автоматизация ротации, распространения, аудита и отзыва ключей с помощью централизованных инструментов повышает уровень безопасности и сокращает количество ошибок, связанных с ручным управлением. Интеграция управления ключами с GitOps, Vault и CI/CD создаёт масштабируемую и отказоустойчивую модель безопасного доступа к системе.

На этом все! Спасибо за внимание! Если статья была интересна, подпишитесь на телеграм-канал usr_bin, где будет еще больше полезной информации.