OpenSSH с аутентификацией как по пустому паролю, так и по открытым ключам.

Вопрос или проблема

Я хотел бы настроить Git-хостинг, обеспечивающий:

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

В идеале, OpenSSH должен информировать мое приложение о публичном ключе клиента и позволять приложению самостоятельно решать, предоставить ли доступ к службам.

Я могу контролировать все на сервере, но клиент — это обычный upstream Git-клиент, и я не могу им управлять.

Попытка 1: AuthorizedKeysCommand

/etc/ssh/sshd_config

Match User forge
    AuthorizedKeysFile none
    AuthorizedKeysCommand /usr/libexec/lindenii/forge/ssh_authorized_keys_command %C %D %f %h %k %t %U %u
    AuthorizedKeysCommandUser root
    PasswordAuthentication no
    PermitEmptyPasswords no
    DisableForwarding yes
    PermitTTY no

/usr/libexec/lindenii/forge/ssh_authorized_keys_command

#!/bin/sh

# Позволяет авторизоваться с любым ключом

# Прототип, поэтому не заботимся о гонках и других проблемах с логированием
printf 'Endpoints: %s\n' "$1" > /var/log/lindenii/authkeys.last
printf 'Routing domain: %s\n' "$2" >> /var/log/lindenii/authkeys.last
printf 'Fingerprint: %s\n' "$3" >> /var/log/lindenii/authkeys.last
printf 'Home: %s\n' "$4" >> /var/log/lindenii/authkeys.last
printf 'Key/cert base64: %s\n' "$5" >> /var/log/lindenii/authkeys.last
printf 'Key/cert type: %s\n' "$6" >> /var/log/lindenii/authkeys.last
printf 'UID: %s\n' "$7" >> /var/log/lindenii/authkeys.last
printf 'Username: %s\n' "$8" >> /var/log/lindenii/authkeys.last

[ "$8" != "forge" ] && exit

# TODO: убедитесь, что тип и base64 ключа/сертификата безопасны и не приводят к инъекциям
# В любом случае, эта строка выводит строку, схожую с форматом authorized_keys, и
# фактически позволяет любому публичному ключу войти в систему, передавая в forge/ssh_shell
# тип ключа и ключа base64.
printf 'command="/usr/libexec/lindenii/forge/ssh_shell --ssh-key-type %s --ssh-key-base64 %s" %s %s\n' "$6" "$5" "$6" "$5"

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

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

Попытка 2: Пользователь с пустым паролем и ForceCommand

Проблемы:

  • AuthorizedKeysCommand не запускается, когда доступна аутентификация с пустым паролем, даже если у клиента есть публичный ключ.
  • ForceCommand берет верх над command=, предоставляемой AuthorizedKeysCommand в любом случае.

Попытка 3: ExposeAuthInfo

Проблемы:

  • Файл $SSH_USER_AUTH всегда none, когда доступна аутентификация с пустым паролем, даже если у клиента есть публичный ключ.

Вопросы

  • Есть ли способ настроить OpenSSH в соответствии с моими нуждами? (Возможно, с помощью особой настройки PAM?)
  • Если нет, существуют ли альтернативные реализации SSH, которые могли бы это сделать?
  • Если нет, может ли OpenSSH передать соединение на кастомный SSH-сервер (возможно, через проксирование или SCM_RIGHTS), как только он узнает, что входящее соединение направлено пользователю forge?
  • Если нет, существуют ли альтернативные реализации SSH, которые могли бы это сделать?

Ответ или решение

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

Теория

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

  1. Чтение и анонимный доступ через SSH без какой-либо аутентификации. Это можно реализовать путем разрешения подключения с пустым паролем, однако этот подход небезопасен и обычно не рекомендуется в производственных средах.
  2. Запись и доступ с аутентификацией через известные SSH-публичные ключи, где сервер проверяет, у кого есть разрешение на запись. Этот метод основывается на проверке подлинности через файлы authorized_keys.

Пример

Рассмотрим предложенные попытки:

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

  2. Пользователь с пустым паролем и ForceCommand. Этот метод предполагает, что для анонимных пользователей будет создана учетная запись с пустым паролем. Однако в этом случае AuthorizedKeysCommand не запускается даже если у клиента есть публичный ключ. К тому же, ForceCommand имеет приоритет над любым command=, переданным AuthorizedKeysCommand.

  3. ExposeAuthInfo. Этот подход позволяет получать более подробную информацию о процессе аутентификации. Тем не менее, в случае доступности пустого пароля содержимое $SSH_USER_AUTH будет none, что не разрешает различать анонимный и публично аутентифицированный доступ.

Применение

Теперь перейдем к анализу и решению задачи:

  1. Настройка PAM (Pluggable Authentication Module): Возможно, стоит обратить внимание на возможность настройки PAM для реализации более гибкой схемы аутентификации. PAM позволяет настраивать модульную систему проверки подлинности, которая может сыграть ключевую роль в различении пользователей по типу входа.

  2. Альтернативные реализации SSH: Рассмотрите использование альтернативных SSH-серверов, которые могут предлагать более гибкие механизмы аутентификации. Такие серверы, как LSH или Dropbear, могут предоставлять функциональные возможности, которых нет в OpenSSH.

  3. Проксирование или передача подключения: Если OpenSSH не предоставляет требуемую функциональность, рассмотрите возможность проксирования или использования SCM_RIGHTS для передачи контролируемых соединений на ваш пользовательский SSH-сервер. Это возможно, но может потребовать значительных усилий по разработке и тестированию.

Заключение

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

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

Оцените материал
Добавить комментарий

Капча загружается...