Вопрос или проблема
У меня есть следующая запись в файле .ssh/config
Host AAA
User BBB
HostName CCC
ControlMaster auto
ControlPath ~/.ssh/%r@%h:%p
Это позволяет мне мультиплексировать несколько ssh-сеансов через одно соединение без необходимости вводить пароль каждый раз, когда мне нужен новый сеанс (пока главное соединение остается открытым).
Однако я заметил, что, когда у меня относительно большое количество мультиплексированных соединений (~7), я не могу добавить больше сеансов к тому же мультиплексированному соединению и получаю следующую ошибку:
> ssh -X AAA
mux_client_request_session: session request failed: Session open refused by peer
Password:
Мои вопросы:
Почему я получаю эту ошибку? Есть ли ограничение на количество ssh-сеансов, которые я могу мультиплексировать в одном соединении? Могу ли я изменить это ограничение? Будет ли это плохой идеей?
Демон sshd
на сервере ограничивает количество сеансов на одно сетевое соединение. Это контролируется опцией MaxSessions
в /etc/ssh/sshd_config
. Также опция MaxStartups
может нуждаться в увеличении, если вы используете большое количество сеансов. (Смотрите man sshd_config
для получения дополнительных деталей.) Возможность изменения лимита MaxSessions
была введена в OpenSSH 5.1 и, похоже, ранее количество было жестко фиксировано на уровне 10. Если вы превышаете MaxSessions
на сервере, вы увидите sshd[####]: error: no more sessions
в логе сервера.
Я столкнулся с этой проблемой на сервере с более ранней версией OpenSSH. Я контролирую сервер и решил проблему, создав два CNAME в моей конфигурации named:
realhost.myexample.com. IN A XXX.XXX.XXX.XXX
realhost2.myexample.com. IN CNAME realhost.myexample.com.
realhost3.myexample.com. IN CNAME realhost.myexample.com.
Затем, в моей локальной конфигурации ssh клиента:
ControlMaster auto
ControlPath ~/.ssh/%r_%p_%h
host realhost
hostname realhost.myexample.com
host realhost2
hostname realhost2.myexample.com
host realhost3
hostname realhost3.myexample.com
Оператор ControlPath нужен для того, чтобы названия сокетов управления не пересекались друг с другом.
Вот и все. Однако, чтобы упростить управление, я написал оболочку для ‘ssh’ на стороне клиента. Она понимает, что существуют ‘группы’ хостов (в данном случае realhost, realhost1, realhost2 составляют одну группу). Когда выполняется ‘sshwrapper realhost’, если нет открытых каналов, все три открываются, и сеанс начинается. В следующий раз при выполнении она подсчитывает открытые соединения на канал и открывает новый сеанс в канале с наименьшим числом соединений.
Используя один настоящий и два ‘фейковых’ хоста, я могу подключаться 30 раз перед получением ошибки. Вход в систему чрезвычайно быстро, за исключением того, что первый раз занимает секунду или две, так как все три контрольных канала открываются в это время.
Вам не нужно предварительно настраивать CNAME
или все необходимые псевдонимы в .ssh/config
.
-
Вы можете отредактировать ваш
.ssh/config
так, чтобы использовать другой управляющий сокет для каждого псевдонима командной строки, в то время как псевдонимы могут выбираться случайным образом во время выполнения в вашем скрипте, используя эту конфигурацию SSH:Host * ControlMaster auto ControlPath /path/to/sockets/%r@%h-%p.%n
Здесь
%n
заменяется указанным именем хоста на командной строке во время выполнения, что позволяет использовать любые суффиксы имен хостов с настройкойHost
, используя шаблон для их совпадения:Host foo-* HostName fooserver User foo
-
Затем вы можете вызвать
ssh
следующим образом:ssh foo-bob sleep 90 & ssh foo-bob sleep 90 & ssh foo-alice sleep 90 & ssh foo-alice sleep 90 &
чтобы использовать ровно два управляющих сокета для этих 4 вызовов.
-
Или, когда вы используете что-то вроде этого в скрипте:
do_ssh(){ tnr=$(( $tnr + 1 )) ssh "foo-$scriptname-$(( $tnr / 5 ))" $@ } tnr=0 scriptname=backup1 do_ssh sleep 1 & do_ssh sleep 2 & ... do_ssh sleep 5 &
вы получаете новый сокет для каждого 5-го вызова, а следующие 4 повторно используют тот же ControlPath, так как номер увеличивается, но сокет использует только
$tnr/5
, что bash округляет до целых чисел, таким образом, вы никогда не используете его 6 раз, эффективно предотвращая 7-е повторное использование, из-за которого возникли проблемы.
Вам просто нужно убедиться, что вы не используете один и тот же псевдоним чаще (чем максимально допустимое количество сессий на управляющий сокет) в вашей программе. Как именно это делать, зависит от вас, и конфигурация SSH может быть статической, используя шаблоны и %n
. В примерах функция do_ssh
просто следит за тем, чтобы новый сокет использовался каждое 5-е выполнение, в то время как в других скриптах можно использовать другие значения scriptname, чтобы не столкнуться с той же проблемой при одновременном выполнении нескольких скриптов, но другие решения могут быть более эффективными.
Я знаю, что вопрос довольно старый, но хотел поделиться этим решением, так как столкнулся с той же проблемой и обнаружил, что использование %n
и шаблонного сопоставления хостов оказалось самым бесшовным способом ее решения для меня.
.
Ответ или решение
SSH-мультиплексирование является важной возможностью, предоставляемой утилитой OpenSSH, которая позволяет использовать одно соединение для поддержки нескольких сессий SSH. Это не только повышает эффективность за счет уменьшения количества необходимых для аутентификации подключений, но и снижает нагрузку на систему. Однако эта технология имеет свои пределы, которые важно понимать и учитывать при ее использовании.
Теория
SSH-мультиплексирование основывается на концепции контроля соединений, где первое подключение выступает в роли "мастера", а последующие сессии становятся "клиентами", подключенными через этот мастер. Это позволяет избежать повторной аутентификации и снизить задержки при установлении новых соединений. Управление такими сессиями происходит через параметры ControlMaster
, ControlPath
и ControlPersist
.
Однако, мультиплексирование может столкнуться с ограничениями, являющимися результатом настроек серверной стороны, именно конфигурации SSH-демона (sshd). Важными настройками являются MaxSessions
, который определяет максимальное количество одновременных сессий, разрешенных на одном соединении, и MaxStartups
, который управляет количеством одновременных неаутентифицированных подключений.
Пример
В примере из исходного вопроса, пользователь столкнулся с ошибкой "Session open refused by peer" после достижения примерно семи мультиплексированных сессий. Это говорит о том, что было достигнуто максимальное количество разрешенных сессий на одно соединение. Причиной этого ограничения является настройка MaxSessions
на сервере. Значение по умолчанию в OpenSSH – 10 сессий, однако в некоторых установках это значение могло быть изменено в меньшую сторону.
Для наглядности, предположим, что файл конфигурации sshd на сервере имеет следующую запись:
MaxSessions 10
Это ограничивает количество одновременно открытых сессий до 10, что объясняет возникновение ошибки при попытке установить еще одну сессию сверх этого ограничения.
Применение
Для решения этого вопроса возможны следующие подходы:
-
Настройка сервера: Измените параметр
MaxSessions
в файле/etc/ssh/sshd_config
на более высокое значение и перезапустите sshd. Это увеличит количество сессий, доступных для одного соединения. Тем не менее, необходимо учитывать возможные риски, связанные с увеличением нагрузки на сервер. -
Использование разных имен узлов (CNAME): Еще один подход – создание дополнительных записей CNAME в DNS, что позволяет имитировать дополнительные хосты. Это может быть полезно как временное решение, чтобы обойти лимиты сессий.
-
Изменение конфигурации клиента: В клиентской части можно создать конфигурацию, которая использует различные ControlPath для разных подключений к тому же серверу, как предложено в примере с использованием
%n
в конфигурации SSH клиента. Это позволяет распределять сессии между несколькими соединениями.
Пример конфигурации клиента:
Host *
ControlMaster auto
ControlPath /path/to/sockets/%r@%h-%p.%n
Host AAA
User BBB
HostName CCC
Это позволяет управлять количеством коннектов более динамично, распределяя нагрузку. Также можно использовать скрипты-оболочки, чтобы систематизировать и автоматизировать этот процесс.
Заключение
Подводя итог, SSH-мультиплексирование является мощным инструментом для оптимизации работы с несколькими соединениями, однако его использование сопряжено с несколько ограничивающими факторами на стороне конфигурации сервера. Осознание и управление этими ограничениями позволяет добиться надежной и быстрой работы SSH-соединений, соответствующих конкретным нуждам пользователя. Правильная настройка и использование инструментов управления сессиями позволит эффективно справиться с большинством возникающих проблем и обеспечить стабильную работу системы.