Вопрос или проблема
Возможно ли изменить строку, которую сервер OpenSSH отображает при установлении сырого соединения?
Речь идет не о текстовом баннере, который отображается после установления соединения и который можно настроить с помощью параметра Banner
в sshd_config
, а о сыром выводе, который SSH-сервер отправляет при попытке подключения до начала обмена данными.
Например, при установлении сырого соединения telnet:
$ telnet localhost 22
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
SSH-2.0-OpenSSH_7.2p2
Есть ли способ сократить идентифицирующую информацию до минимально необходимого?
Я понимаю, что SSH-2.0-
должен присутствовать, потому что это требуется SSH-протоколом, но строка, которая следует за ним – OpenSSH_7.2p2
– скорее всего не обязательна по требованиям протокола, и я не вижу способа изменить или удалить ее без повторной компиляции.
Цель состоит в том, чтобы избежать предоставления больше информации, чем это строго необходимо для функционирования протокола.
Нет. Строка версии определяется в version.h исходного кода OpenSSH как
#define SSH_VERSION "OpenSSH_7.4"
.
Вы можете изменить ее, но это требует компиляции.
Она затем отправляется формируется с помощью:
snprintf(buf, sizeof buf, "SSH-2.0-%.100s\r\n", SSH_VERSION)
(ssh_api.c строка 381, в функции _ssh_send_banner
)
Смотрите также: Предотвратить SSH от рекламы номера своей версии.
Недавние версии OpenSSH позволяют добавлять пользовательский текст через VersionAddendum
, но не позволяют удалять имя продукта/версии. Для этого вам придется изменить исходный код.
Проблема
OpenSSH (и на самом деле каждая другая реализация SSH) раскрывает важную информацию о безопасности для каждого входящего соединения. Обратите внимание:
# telnet localhost 22
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
SSH-2.0-OpenSSH_9.2p1 Debian-2+deb12u3
Это раскрывает версию OpenSSH и версию операционной системы для всех, кто пытается подключиться.
Это вызывает проблемы с двух сторон: безопасность и конфиденциальность.
Безопасность
(Утомительно) часто повторяемое замечание тех, кто не понимает фразы, состоит в том, что воздержание от выдачи информации о системе является “безопасностью за счет неясности”. Это не так. Эта фраза относится только к идее, что если криптографический примитив безопасен только тогда, когда алгоритм неизвестен, то он не является безопасным. Эта фраза не имеет, и никогда не имела намерения касаться концепции, что воздержание от выдачи информации о вашей криптосистеме, реализации или операционной системе – это плохая вещь. Все, что увеличивает активационную энергию, необходимую для того, чтобы противник взломал систему, является хорошей вещью. На самом деле это, в единственном числе, всё, что любой замок (криптографический или физический) делает в любом случае. Идея о том, что усилия по повышению сложности для противника ошибочны, является неправильным применением иначе важного принципа обеспечения безопасности (среди прочих способов) с помощью правильной криптографии.
Конфиденциальность
Предположим, вы поддерживаете частный VPS, который мы назовем JOURNALISTHAVEN в скрытом месте. Допустим, вы хотите скрыть факт подключения к нему, но при этом иметь возможность подключаться к нему через ssh
откуда угодно. Вы переадресовываете порт с другого VPS, PUBLICVILLE, через коммерческий VPN на JOURNALISTHAVEN. Теперь вы можете использовать любой компьютер где угодно, чтобы подключиться к вашему частному VPS, не делая очевидным, что вы подключаетесь к нему. Теперь представьте, что версия реализации ssh на PUBLICVILLE отличается от версии JOURNALISTHAVEN – теперь становится очевидным, что переадресованный порт – это не просто еще один порт, на котором слушает демона ssh PUBLICVILLE, а что он идет куда-то еще. Да, есть и другие способы, которыми эта информация может быть раскрыта понимающим и сосредоточенным противником, но действительно ли нам нужно выдавать эту информацию каждому новичку? Никто не может утверждать, что конфиденциальность за счет неясности – это нечто, кроме единственного вида конфиденциальности, который существует.
Вопрос
Возможно ли изменить строку, которую сервер OpenSSH отображает при установлении сырого соединения?
Ответ, в основном, да – 50% через конфигурационные средства. Остальное – путем повторной компиляции или изменения вашего двоичного файла.
Строка подключения
RFC 4253, раздел 4.2 требует, чтобы строка подключения имела:
SSH-2.0-softwareversion
…где softwareversion не содержит пробелов и символа -. Поэтому его нельзя полностью исключить, и он не может быть просто пробелом или -. Это должно быть хотя бы один печатный символ. К сожалению, OpenSSH педантичен в этом, поэтому если вы полностью удалите softwareversion, клиент OpenSSH откажется подключаться к серверу.
Сервер OpenSSH
К сожалению, нельзя заставить сервер OpenSSH молчать о своей версии или настроить его с помощью параметра конфигурации. Вы можете заставить его молчать о системе с помощью параметра /etc/ssh/sshd_config.d/*
:
DebianBanner no
Это только частично решает задачу. Это все равно оставляет OpenSSH, объявляющим о своей версии и даже уровне патча для каждого желающего.
Вам необходимо отредактировать исходный код OpenSSH и перекомпилировать его, чтобы заставить его убрать эту информацию, или изменить бинарный файл.
Редактировать исходный код и перекомпилировать
OpenSSH доступен по адресу https://www.openssh.com/. Полные инструкции по сборке выходят за рамки этого, но вы можете найти строку версии для редактирования в version.h:
#define SSH_VERSION "OpenSSH_9.9"
Вы можете изменить это по своим требованиям. Строка “SSH” достаточно обобщенная.
Редактировать бинарный файл
ПРЕДУПРЕЖДЕНИЕ: Это имеет последствия.
Недавние версии бинарного файла OpenSSH можно редактировать. Для этого:
- Узнайте точную строку подключения, которую нужно отредактировать.
sshd -x
– это на самом деле неправильная команда, но это единственный способ заставить sshd напечатать использование и строку версии подключения (sshd -V
не печатает ту же строку) - Используйте шестнадцатеричный редактор (hexcurse или аналогичный) на копии /usr/sbin/sshd и найдите ВТОРОЕ вхождение строки.
- Замените первые три символа на ‘SSH’, за которыми следует нулевой символ.
mv /usr/sbin/sshd /usr/sbin/sshd.orig
- Скопируйте отредактированный бинарный файл в /usr/sbin/sshd
- Перезапустите службу. Для большинства это будет
systemctl restart sshd
- Проверьте новую версию.
systemctl status sshd
, чтобы убедиться, что служба работает, иtelnet localhost 22
для тестирования строки версии. Если вы редактируете бинарный файл, вам все равно нужно будет отключить DebianBanner.
Если вы не хотите редактировать бинарный файл в шестнадцатеричном формате, то этот скрипт сделает то же самое для большинства недавних версий sshd на Linux:
# VERSION="OpenSSH_9.2p1" NEW="SSH" perl -0777 -pe 'BEGIN { $version = $ENV{VERSION}; $new = $ENV{NEW} . "\0"; }
$pos = index($_, $version, index($_, $version) + 1);
substr($_, $pos, length($new), $new) if $pos != -1;' /usr/sbin/sshd > sshd_patched
VERSION должен быть установлен на точную строку версии, полученную на этапе 1 выше. NEW должен быть установлен на то, что вы хотите отобразить вместо этого.
Следуйте шагам 5, 6 и 7, перечисленным выше.
Последствия редактирования бинарного файла
- Менеджеры пакетов могут иметь проблемы с обновлением sshd в будущем. Перед обновлением пакета sshd вы должны:
- systemctl stop sshd
- mv /usr/sbin/sshd.orig /usr/sbin/sshd
- systemctl start sshd
- Указанный выше метод редактирования в шестнадцатеричном формате или скрипт могут не сработать на будущих версиях sshd или очень старых версиях. Это следует тестировать, прежде чем полагаться на это.
Заключение
Многие другие ответы и городские мифы предполагают, что информация о версии программного обеспечения SSH в строке подключения необходима для корректного подключения клиентов. Сегодня это универсально неверно. В прошлом были некоторые ошибки, которые обходились подобным образом клиентами, и это совершенно неизвестно на сегодня. Нет информации, необходимой клиенту в строке версии программного обеспечения – вся информация о соединении SSH содержится в дальнейших обменах данными.
RFC 4253 на самом деле подразумевает требование строки версии программного обеспечения в ssh-соединениях для диагностических целей. Что-то, что клиент, испытывающий трудности с подключением к серверу, может использовать telnet и просмотреть, чтобы диагностировать, если возникли проблемы с совместимостью. Это не было так уже в течение некоторого времени. Это было сомнительной полезностью 18 лет назад, когда был написан RFC, и тогда не было такой военной обстановки, как сегодня. Вы не можете запустить ssh-сервер на новом IP-адресе более чем на две минуты, не привлекая к нему ботнеты. Когда бомбы падают, выключите свет и закройте занавески. Если, конечно, некоторые крипто-воины с дивана не хотят назвать это безопасностью через неясность тоже. В таком случае им будет хорошо поднять голову над окопом и закурить сигарету. Или включить свет во время воздушной тревоги.
Ответ или решение
Конечно, изменение строки ответа, которую сервер OpenSSH отображает при установлении соединения, является важной задачей, особенно с точки зрения безопасности и конфиденциальности. Давайте разберем этот вопрос подробнее.
Возможность изменения строки версии OpenSSH
По умолчанию при установлении подключения к OpenSSH серверу клиент получает строку в формате:
SSH-2.0-OpenSSH_<версия>
Изменение строки версии
-
Строка версии обязательна: Согласно RFC 4253, строка версии должна начинаться с
SSH-2.0-
и содержать по крайней мере один печатаемый символ после этого. Это означает, что строка не может быть полностью удалена. -
Конфигурация через
sshd_config
: В последние версии OpenSSH добавлена возможность использования директивыVersionAddendum
в конфигурационном файлеsshd_config
, но она не позволяет удалить или изменить строку версии, а только добавить дополнительный текст. Таким образом основной текстOpenSSH_<версия>
остается неизменным. -
Редактирование исходного кода: Для изменения текста версии или его удаления необходимо редактировать исходный код OpenSSH. Строка, ответственный за вывод версии, определяется в файле
version.h
в исходном коде. Например:#define SSH_VERSION "OpenSSH_9.2"
Вы можете изменить строку на менее идентифицирующую, например, на
SSH
, однако для этого вам понадобиться заново скомпилировать сервер. -
Редактирование бинарного файла: Существует также возможность редактирования бинарного файла OpenSSH, чтобы изменить строку версии, но это требует дополнительных шагов и обращает внимание на следующие нюансы:
- Используйте двоичный редактор, чтобы отредактировать файл
/usr/sbin/sshd
, заменив строку с версией на желаемую. - Можете также воспользоваться скриптом на Perl, который позволит изменять строку без редактирования вручную.
# VERSION="OpenSSH_9.2" NEW="SSH" perl -0777 -pe 'BEGIN { $version = $ENV{VERSION}; $new = $ENV{NEW} . "\0"; } $pos = index($_, $version, index($_, $version) + 1); substr($_, $pos, length($new), $new) if $pos != -1;' /usr/sbin/sshd > sshd_patched
- Используйте двоичный редактор, чтобы отредактировать файл
Последствия редактирования
-
Проблемы с обновлением: При редактировании бинарного файла могут возникнуть трудности с обновлением OpenSSH через менеджер пакетов. Перед обновлением необходимо восстановить оригинальный файл.
-
Тестирование изменений: Перед внедрением изменений протестируйте работу SSH-сервера, используя команду
telnet localhost 22
для проверки новой строки версии.
Заключение
Итак, ответ на ваш вопрос: да, возможно изменить строку ответа OpenSSH, но это потребует либо изменения исходного кода и его последующей компиляции, либо редактирования бинарного файла. Оба подхода имеют свои преимущества и недостатки, и вам следует выбрать тот, который больше соответствует вашим требованиям безопасности и удобству администрирования.
Если у вас возникнут дополнительные вопросы или потребуется помощь, не стесняйтесь обращаться!