Как создать ограниченного пользователя SSH для переадресации портов?

106

Ондрюк предложил обратное соединение для получения простого SSH-соединения с кем-то другим (для удаленной помощи). Чтобы это работало, требуется дополнительный пользователь, чтобы принять соединение. Этот пользователь должен иметь возможность перенаправлять свой порт через сервер (сервер действует как прокси).

Как создать пользователя с ограниченными правами, который не может сделать ничего, кроме описанного выше?

Новый пользователь не должен иметь возможность:

  • выполнять команды оболочки
  • получить доступ к файлам или загрузить файлы на сервер
  • использовать сервер в качестве прокси (например, webproxy)
  • доступ к локальным службам, которые в противном случае не были общедоступными из-за брандмауэра
  • убить сервер

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

Lekensteyn
источник

Ответы:

166

TL; DR - перейти к нижней части ответа «Применение ограничений»

Добавление ограниченного пользователя состоит из двух частей: 1. Создание пользователя. 2. Настройка демона SSH (sshd).

Конфигурирование sshd

Лучшее место, чтобы узнать о возможностях SSH, читая соответствующие страницы руководства:

Где SSH-клиент может выполнять действия?

Прежде чем вы сможете что-то ограничить, вам нужно знать особенности SSH. Плевание по страницам справочника дает:

  • Выполнение команд оболочки
  • Загрузка файла через sftp
  • Перенаправление порта
    • Клиент перенаправляет (не) используемый порт на сервер
    • Сервер перенаправляет свой порт клиенту
    • Сервер перенаправляет порт другого хоста клиенту (proxy-ish)
  • Пересылка X11 (переадресация дисплея)
  • Переадресация агента аутентификации
  • Пересылка туннельного устройства

Из раздела Аутентификация страницы руководства по sshd (8) :

Если клиент успешно аутентифицирует себя, вводится диалог для подготовки сеанса. В это время клиент может запросить такие вещи, как выделение псевдотерминала, пересылка соединений X11, пересылка соединений TCP или пересылка соединения агента аутентификации по безопасному каналу.

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

Варианты ограничения функций SSH

Файлы и их параметры, которые изменяют поведение:

  • ~/.ssh/authorized_keys - содержит ключи, которые разрешено подключать, которым могут быть предоставлены опции:
    • command="command"- Команда, предоставленная пользователем (если есть), игнорируется. Обратите внимание, что клиент может указать переадресацию TCP и / или X11, если они явно не запрещены . Обратите внимание, что этот параметр применяется к выполнению оболочки, команды или подсистемы.
    • no-agent-forwarding - Запрещает пересылку агента аутентификации, когда этот ключ используется для аутентификации.
    • no-port-forwarding - Запрещает пересылку TCP, когда этот ключ используется для аутентификации
    • no-X11-forwarding - «Запрещает пересылку X11, когда этот ключ используется для аутентификации».
    • permitopen="host:port" - Ограничить переадресацию локального порта 'ssh -L', чтобы он мог подключаться только к указанному хосту и порту.
  • ~/.ssh/environment- Этот файл считывается в среду при входе в систему (если он существует). Обработка среды по умолчанию отключена и контролируется с помощью параметра PermitUserEnvironment
  • ~/.ssh/rc - Содержит процедуры инициализации, которые должны быть выполнены до того, как домашний каталог пользователя станет доступным.
  • /etc/ssh/sshd_config - общесистемный файл конфигурации
    • AllowAgentForwarding - Указывает, разрешена ли пересылка ssh-agent (1).
    • AllowTcpForwarding
    • ForceCommand - «Принудительно выполняет команду, указанную ForceCommand, игнорируя любую команду, предоставленную клиентом, и ~ / .ssh / rc, если он присутствует. Команда вызывается с использованием оболочки входа пользователя с параметром -c.»
    • GatewayPorts - "Указывает, разрешено ли удаленным хостам подключаться к портам, перенаправленным для клиента. По умолчанию sshd (8) связывает перенаправления удаленных портов с адресом обратной связи. Это не позволяет другим удаленным хостам подключаться к перенаправленным портам. GatewayPorts можно использовать для указания что sshd должен позволять перенаправлениям удаленных портов связываться с нециклическими адресами, что позволяет другим хостам подключаться ».
    • PermitOpen:

      Определяет пункты назначения, к которым разрешена переадресация портов TCP. Спецификация пересылки должна иметь одну из следующих форм:

      PermitOpen host:port
      PermitOpen IPv4_addr:port
      PermitOpen [IPv6_addr]:port
      

      Несколько форвардов могут быть указаны путем разделения их пробелами. Аргумент 'any' может использоваться для снятия всех ограничений и разрешения любых запросов на пересылку. По умолчанию все запросы на переадресацию портов разрешены.

    • PermitTunnel- Указывает, разрешена ли пересылка устройства tun (4). По умолчанию «нет»
    • X11Forwarding- Указывает, разрешена ли пересылка X11. По умолчанию «нет»

Применение ограничений

Изменение общесистемного файла конфигурации /etc/ssh/sshd_configпозволяет применять конфигурацию даже в том случае, если применяется проверка подлинности на основе пароля или ~/.ssh/authorized_keysслучайное снятие ограничений . Если вы изменили глобальные значения по умолчанию, вы должны соответствующим образом раскомментировать параметры.

Match User limited-user
   #AllowTcpForwarding yes
   #X11Forwarding no
   #PermitTunnel no
   #GatewayPorts no
   AllowAgentForwarding no
   PermitOpen localhost:62222
   ForceCommand echo 'This account can only be used for [reason]'

Теперь добавьте пользователя:

sudo useradd -m limited-user

Эта опция ForceCommandможет быть опущена, если для оболочки задана не-оболочка типа /bin/false(или /bin/true), так как /bin/false -c [command]ничего не будет делать.

Теперь клиент может подключаться только к порту 62222 по адресу обратной связи сервера через SSH (он не будет прослушивать общедоступный IP-адрес)

Отключение AllowTcpForwardingтакже запретило бы использование -R, тем самым исключив использование такой ограниченной учетной записи для переадресации одного порта. PermitOpen localhost:62222предполагается, что порт 62222 на сервере никогда не используется, потому что клиент может счастливо подключиться к нему и прослушивать его тоже.

Если пересылка TCP разрешена в общесистемной конфигурации и отключена аутентификация на основе пароля, вы также можете использовать настройки для каждого ключа. Отредактируйте ~/.ssh/authorized_keysи добавьте следующие параметры перед ssh-(с пробелом между параметрами и ssh-):

command="echo 'This account can only be used for [reason]'",no-agent-forwarding,no-X11-forwarding,permitopen="localhost:62222"

проверить

Чтобы быть уверенным, что все работает как положено, необходимо выполнить несколько тестов. В приведенных ниже командах hostдолжен быть заменен реальным логином, если он не установлен в ~/.ssh/config. За командой показана команда, которая должна быть выполнена либо на клиенте, либо на сервере (как указано).

# connection closed:
ssh host
# connection closed (/bin/date is not executed):
ssh host /bin/date
# administratively prohibited (2x):
ssh host -N -D 62222 # client: curl -I --socks5 localhost:62222 example.com
ssh host -N -L 8080:example.com:80 # client: curl -I localhost:8080
sftp host
# should be possible because the client should forward his SSH server
ssh host -N -R 8080:example.com:80 # server: curl -I localhost:8080
# This works, it forwards the client SSH to the server
ssh host -N -R 62222:localhost:22
# unfortunately, the client can listen on that port too. Not a big issue
ssh host -N -L 1234:localhost:62222

Заключение

Контрольный список: пользователь SSH не должен:

  • выполнить команды оболочки - сделано
  • получить доступ к файлам или загрузить файлы на сервер - готово
  • использовать сервер в качестве прокси (например, webproxy) - готово
  • получить доступ к локальным службам, которые в противном случае не были общедоступными из-за брандмауэра - частично клиент не может получить доступ к другим портам, кроме 62222, но может прослушивать и подключаться к порту 62222 на сервере
  • уничтожить сервер - сделано (обратите внимание, что эти проверки ограничены сервером SSH. Если у вас есть другая уязвимая служба на компьютере, это может позволить возможному злоумышленнику выполнить команды, уничтожить сервер и т. д.)
Lekensteyn
источник
3
Чтобы это работало, аккаунт, добавленный пользователем, useraddдолжен быть разблокирован. Это можно сделать, заменив пароль /etc/shadowна звездочку ( *) или установив пароль с помощью sudo passwd limited-user.
Лекенштейн
2
SFTP работает, потому что команда SSH выполняет sftp-serverкоманду. С помощью ForceCommandэтой команды больше не будет выполняться.
Лекенштейн
2
Также полезной является from=опция в authorized_keys. Это позволяет ограничить использование ключа источниками с определенным IP-адресом или именем хоста. Пример, from="1.1.1.1"или from="10.0.0.?,*.example.com". См. Раздел «ФОРМАТ ФАЙЛА AUTHORIZED_KEYS» на странице руководства ( linux.die.net/man/8/sshd ) для получения информации о всех параметрах авторизованных ключей .
Донн Ли
2
«AllowTcpForwarding local» запрещает удаленную пересылку. (Я не знаю, существовал ли он, когда был написан этот ответ.)
Саймон Сапин
1
Обратите внимание, что это нарушается постоянными ssh-соединениями, поэтому у вас не должно быть ничего похожего Host * ControlMaster autoна ваш ~/.ssh/configфайл при соединении с ssh -N. Если вам это нужно, используйтеssh -N -o ControlMaster=no
nh2
3

Я уверен, что есть много решений для этого, и гораздо более надежных, чем тот, который я предлагаю. Однако этого может быть достаточно для ваших нужд. Для того, чтобы сделать это, я предполагаю, что пользователь может выполнить аутентификацию на основе ключей ssh ​​(замазка или любой Unix ssh должен поддерживать это).

  • Добавьте пользователя как обычно («adduser» или любой другой инструмент)

  • Создайте пользователей .ssh dir и .ssh / authorized_keys

your_user $ sudo -Hu ssh_forwarder /bin/bash

ssh_forwarder $ cd ~
ssh_forwarder $ mkdir .ssh
ssh_forwarder $ ( umask 066 && cat > .ssh/authorized_keys ) <<EOF
no-agent-forwarding,no-X11-forwarding,command="read a; exit" ssh-rsa AAAB3NzaC1y....2cD/VN3NtHw== smoser@brickies
EOF
  • Отключить пароль доступа к этой учетной записи.
your_user $ sudo usermod --lock ssh_forwarder

Теперь единственный способ, которым пользователь может войти в вашу систему, - это получить доступ к соответствующему ключу ssh, и ssh запустит для них «/ bin / bash -c 'read a'», независимо от того, что они пытаются запустить. «read a» будет просто читать до новой строки, а затем оболочка завершится, поэтому пользователю просто нужно нажать «enter», чтобы разорвать соединение.

Есть много других вещей, которые вы могли бы сделать в 'command ='. Смотрите man authorized_keysи ищите «команду» для получения дополнительной информации.

Если вам не нравится тот факт, что нажатие клавиши enter уничтожает соединение, вы можете использовать что-то вроде следующего для записи 'command =':

command="f=./.fifo.$$ && mkfifo $f && trap \"rm -f $f\" EXIT && read a <$f && echo $a; exit;"

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

 your_user$ echo GOODBYE | sudo tee ~ssh_forwarder/.fifo.*

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

sleep 1h; echo You have been here too long. Good bye.

Я не видел, как вы можете разрешить пользователю удаленную пересылку вперед ( ssh -R), но limit ( ssh -L). Возможно, можно использовать 'allowopen'. Поиск в Google не очень помог. Казалось бы, что-то вроде «no-port-forwarding, allowremoteopen = 10001» было бы полезно разрешить ssh -R 6901:localhost:6901.

Это решение. Это может быть определенно улучшено, и любое открытие удаленных портов должно быть тщательно изучено. Если бы моей целью было позволить моей бабушке подключиться к моей локальной сети, чтобы я мог использовать vnc для просмотра ее экрана, а доступ к этим клавишам был ограничен для нее, я лично чувствовал бы себя в достаточной безопасности. Если бы это было для предприятия, более тщательное расследование было бы необходимо. Следует помнить , что оболочка вообще не запрашивает оболочку, поэтому код command = не выполняется.ssh -N

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

smoser
источник
3
Это выглядит очень странно, даже не обязательно иметь оболочку, потому что не нужно выполнять никакие команды. См. Страницу руководстваssh для -Nвыбора. Должен быть более чистый способ сделать это.
Лекенштейн
Это правда. Я надеюсь также увидеть более чистое решение. Я думаю, что authorized_keys в сочетании с переадресацией без порта было бы довольно хорошим решением, если бы была опция 'allowremoteopen'.
smoser
Я сделал некоторые исследования (см. Выше). Поскольку ssh -Nкоманда вообще не выполняется, нет проблем с command="something"закрытием сессии.
Лекенстейн
Я что-то пропустил? Казалось, chsh ssh_forwarder -s /bin/false это все, что нужно.
typelogic