Как создать ограниченного пользователя SSH для переадресации портов?
Ондрюк предложил обратное соединение для получения простого SSH-соединения с кем-то другим (для удаленной помощи). Чтобы это работало, требуется дополнительный пользователь, чтобы принять соединение. Этот пользователь должен иметь возможность перенаправлять свой порт через сервер (сервер действует как прокси).
Как создать пользователя с ограниченными правами, который не может сделать ничего, кроме описанного выше?
Новый пользователь не должен иметь возможность:
- выполнять команды оболочки
- получить доступ к файлам или загрузить файлы на сервер
- использовать сервер в качестве прокси (например, webproxy)
- доступ к локальным службам, которые в противном случае не были общедоступными из-за брандмауэра
- убить сервер
Подводя итог, как мне создать ограниченного пользователя SSH, который может подключаться только к серверу SSH без привилегий, чтобы я мог подключиться через это соединение к его компьютеру?
3 ответа
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. Если у вас есть другая уязвимая служба на компьютере, это может позволить возможному злоумышленнику выполнить команды, уничтожить сервер и т. д.)
Я уверен, что есть много решений для этого, и гораздо более надежных, чем тот, который я предлагаю. Однако этого может быть достаточно для ваших нужд. Для того, чтобы сделать это, я предполагаю, что пользователь может выполнить аутентификацию на основе ключей 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
) но ограничить (ssh -L
). Возможно, можно использовать 'allowopen'. Поиск в Google не очень помог. Казалось бы, что-то вроде "no-port-forwarding, allowremoteopen=10001" было бы полезно ssh -R 6901:localhost:6901
,
Это решение. Это может быть определенно улучшено, и любое открытие удаленных портов должно быть тщательно изучено. Если бы моей целью было позволить моей бабушке подключиться к моей локальной сети, чтобы я мог использовать vnc для просмотра ее экрана, и доступ к этим клавишам был ограничен для нее, я лично чувствовал бы себя в достаточной безопасности. Если бы это было для предприятия, более тщательное расследование было бы необходимо. Одна вещь, о которой нужно знать, это ssh -N
вообще не запрашивает оболочку, поэтому код 'command =' не выполняется.
Другие, возможно, более безопасные механизмы могут включать создание пользовательской оболочки и даже блокировку ее с помощью apparmour.
Пытаться
command="exit"
Это заставит пользователей использовать эту команду для переадресации портов.
ssh -NfR EXTERNAL_PORT:localhost:INTERNAL_PORT usr@server -i key