Каждый раз, когда я с кем-то делюсь очередной успешной покупкой ретрокомпьютера, мне задают один и тот же вопрос: «А что ты с ним будешь делать?» С одной стороны, практическое применение очевидно — старые игры или софт запускать. Но вот с современными приложениями будут проблемы.

Мне же по роду деятельности постоянно приходится работать с удаленными серверами по SSH, и именно под это дело я порой использую старые машины. Но если SSH-соединение из условного Windows XP не вызывает каких-либо проблем, то с более старыми ОС все сложнее. Ну а если вам попался совсем «старичок», в котором есть MS-DOS и больше ничего, — неужели он уже не подойдет на роль SSH-клиента?

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


1998 год. В протоколе SSH была найдена фундаментальная слабость: CRC-32 попросту не давал криптографической стойкости, чтобы обеспечивать целостность зашифрованных данных. В итоге злоумышленники получили возможность при определенных условиях выполнять атаку типа Packet Injection — модифицировать любой пакет в потоке. Как только уязвимость стала известна широкому кругу лиц, системные администраторы стали думать, как с этим бороться.

Сначала «дыру» закрывали «костылями». Сам протокол не модифицировали, а просто добавили детектор, который искал признаки подмены данных в пакете и принудительно разрывать соединение. Казалось бы, хорошее решение, но в коде этого защитного механизма была отдельная критичная уязвимость Integer Overflow — целочисленное переполнение. В итоге злоумышленник мог выполнить произвольный код как на сервере, так и на клиенте.

Все это стало крышкой гроба для первой версии SSH. В качестве долгосрочного решения безальтернативно рекомендовалось перейти на SSH2, который архитектурно был лишен большинства проблем предшественника. Так, например, вместо CRC-32 применялся MAC/HMAC, что закрывало класс атак в виде незаметной модификации пакетов, характерный для SSH1. 

В 2000 году еще многие компьютеры вполне себе работали на MS-DOS. Сложилась любопытная ситуация: Telnet давно устарел, а когда сообщество доросло до SSH1 — он уже был скомпрометирован. Именно в это время венгерский программист Даниэль Надь (Daniel Nagy) решил, что DOS-юзерам надо дать возможность использовать более безопасный SSH2.

SSH2DOS by Daniel Nagy (2000–2006)

Реализация SSH-клиента под MS-DOS — комплексная задача, которую можно условно разделить на четыре компонента, призванных взаимодействовать и дополнять друг друга:

  1. Криптографическая часть — обмен ключами, шифрование.

  2. TCP/IP-стек — MS-DOS никогда не рассматривалась как сетевая ОС, так что ядро ничего не знает о сети.

  3. Компрессия нужна для экономии трафика на медленных каналах. Когда сидишь на модемном соединении — крайне полезная штука.

  4. Эмуляция терминала — для SSH-сессии надо уметь эмулировать терминалы, вроде DEC VT100/VT102.

Написать такое в одиночку можно, но Даниэль не стал изобретать велосипед, а обратился к нескольким отдельным проектам, чтобы позаимствовать у них исходный код. Криптография и протокольная часть была взята у PuTTY версии 0.52, распространяющегося по лицензии MIT. Логично, что написать обертку над PuTTY будет проще, чем пытаться реализовать с нуля.

DOS-сеть — это почти как контейнеризация до появления контейнеризации. Общего сетевого стека нет, а любая программа жила в собственной сетевой песочнице — что реализуешь, то и будет. Условному DOS-разработчику надо было знать, что такое ARP, в то время как Windows-программисту было достаточно написать connect(). Так что для SSH2DOS был выбран существующий стек Waterloo TCP, написанный Эриком Энгельке (Erick Engelke) в Университете Ватерлоо (Онтарио, Канада).

WATTCP был портирован на 32-битную архитектуру Гисле Ванемом (Gisle Vanem) и получил название WATT-32. Вышла удобная библиотека для внедрения сетевых функций в DOS и Windows-NT приложения. Да, это не полноценное ядро TCP/IP, однако и этих возможностей с лихвой хватало для решения большинства задач. Вместо того чтобы дергать сетевую карту, напрямую применялся иной подход — через пакетный драйвер (читай register-based RPC). 

Олды помнят, что последний ставился на программное прерывание INT 0x60, а далее любой TCP/IP-стек, которому нужно было поговорить с сетью — туда же в INT 0x60 засылал команды. Это намеренная абстракция, чтобы драйвер ничего не знал ни про IP-адреса, ни про ARP, ни даже про TCP. Ему дозволялся только «сырой» Ethernet L2, а программист мог реализовать любой протокол поверх — хоть IPX, хоть AppleTalk.

Что же до компрессии, то тут был взят код библиотеки сжатия ZLIB. Собиралась она отдельно для реального и защищенного режимов работы MS-DOS, позволяя реализовать соответствующую опцию в SSH-сессии. Эмулятор терминала также не был написан с нуля — модуль VT100/VT102/xterm был позаимствован из CVT100 — часть проекта Kermit, разработанного в стенах Колумбийского университета.

Таким образом, задачей Даниэля было собрать все эти разрозненные куски чужого кода, одновременно преодолевая существенные ограничения DOS. В этом ему помог компилятор OpenWatcom C/C++. Да, тот самый, наследник коммерческого Watcom, на котором собирались легендарные игры всех времен и народов — Doom и Quake. В те годы было хорошим тоном билдить отдельные исполняемые файлы для реального режима и защищенного. 

Поэтому в комплекте SSH2DOS был удвоенный набор бинарей. Наличие SFTP, SCP и TELNET в данном случае заслуга исключительно PuTTY:

  • SSH2D386.EXE

  • SSH2DOS.EXE

  • SFTP386.EXE

  • SFTPDOS.EXE

  • SCP2D386.EXE

  • SCP2DOS.EXE

  • TEL386.EXE

  • TELNET.EXE

Таким образом, приложение могло работать на древнем Tandy в реальном режиме и значительно более современном на то время Pentium в защищенном. Даниэль продолжал работу над программой до 2006 года, а затем фактически перестал коммитить. Тем не менее формально проект до сих пор активен. Код можно скачать на SourceForge.

SSH2DOS by AnttiTakala (2021)

Запас прочности оригинального SSH2DOS полностью закончился к 2020 году. К тому времени любой OpenSSH-сервер перестал разговаривать на устаревших шифрах. Если вам позарез надо было подключиться, то приходилось вручную ослаблять криптографию на каждом сервере через sshd_config. Понятное дело, что такой вариант — большая глупость и обречен на забвение.

Горячий финский парень Antti Takala, посмотрел на проблему под другим углом. Вместо ослабления защиты он решил форкнуть проект и поднять клиент до того уровня, который современный sshd-демон принимает по умолчанию. Здесь как раз свою роль сыграло то, что приложение было построено на криптографических возможностях PuTTY. В итоге удалось выполнить апгрейд, не затрагивая саму архитектуру.

Изменений было ровно три, каждое из которых влияло на критическую точку «рукопожатия» в протоколе SSH2:

  1. Обмен ключами. Вместо diffie-hellman-group1-sha1 была применена 2048-битная MODP группа diffie-hellman-group14-sha256. Не идеальный, но приемлемый вариант. Однако это влекло за собой примерно в четыре раза больше вычислений, что на древнем 386-м процессоре уже было ощутимо.

  2. Проверка подлинности. Несмотря на то что HMAC-SHA-1 на 2020 год оставался криптографически живым, индустрия от него избавилась, заменив на HMAC-SHA-256. На тот момент он стал предпочтительным для любого современного sshd. Объем вычислений также возрос, механизм работал примерно в два раза медленнее, если говорить о 386-м.

  3. Симметричный шифр. В 2008 году исследователи обнаружили, что AES-128-CBC (Cipher Block Chaining) подвержен атаке — CCA (Chosen-Ciphertext Attack), а именно подвиду — Padding Oracle. Так что в современном SSH его заменили на AES-128-CTR, в котором нет той же CBC-специфической поверхности атаки.

Antti использовал тот же подход, не пытаясь написать криптографию с нуля или подтягивая из современных библиотек. Вместо этого он просто скопировал недостающие части из исходников PuTTY 0.70. Выбор был неслучаен — это последняя версия до серьезного рефакторинга слоя криптографии. Следовательно, новые шифры можно «подружить», не затрагивая Event Loop и SSH state machine. 

Разумеется, практическая реализация далека до идеала. Нормально работала только аутентификация по паролю, а эфемерные ключи Диффи — Хеллмана генерировались стандартным предсказуемым rand() из libc. Теоретически эта была дыра в безопасности, но на практике вы бы вряд ли пошли настраивать продакшен-сервер в 2020 году через DOS-машину. Все остальное было пересобрано в оригинальном виде, включая SCP-, SFTP- и Telnet-клиенты. Правда, тестировались только SSH и SCP.

В практическом смысле форк давал возможность подключиться из коробки к любой версии Ubuntu, включая 20.04.2 LTS, однако работать это все стало значительно медленнее. От момента запроса до получения приглашения ввести пароль могло пройти с десяток секунд. Ну а теперь этот форк и вовсе непригоден для работы с актуальными версиями sshd. 

SSH2DOS by Toyoyo (2026)

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

Большая часть работы была заключена в два коммита: 42f788c (ed25519) и 8077e47 (curve25519-sha256). Список предлагаемых host-key-алгоритмов был изменен с ssh-rsa на ssh-ed25519,ssh-rsa соответственно. Кроме того, теперь там реально делается проверка подписи — правда, только для ed25519. Раньше клиент вычислял хеш, но никогда с подписью его не сверял. Сейчас же в коде есть полноценный verify.

Любопытно, что если соединение идет по RSA, то клиент просто принимает подпись на веру — исторически так было еще со времен оригинала. Генератор случайных чисел трогать тоже не стал — он продолжает быть криптографически небезопасным. А это значит, что SSH2DOS хорошо подходит для работы в защищенной сети или чисто под ретроцели. Однако если вы собрались администрировать из MS-DOS свой боевой сервер, то учтите, что сессию теоретически можно расшифровать. 

Seed ограничен 32 битами и предсказуемо связан со временем запуска соединения — следовательно, пространство поиска можно перебрать довольно быстро. В общем, современный SSH2DOS — это только для работы в доверенной сети и ретроэкспериментов.

Как развернуть

Чтобы наглядно продемонстрировать SSH2DOS by Toyoyo, я воспользовался эмулятором PCem. Это один из самых полезных инструментов в арсенале любителя ретро. Прежде всего я создал виртуальную машину, выбрав сетевым адаптером Novell NE2000. PCem будет функционировать в режиме SLiRP, обеспечивая NAT до внешней сети.

Первым делом надо перекинуть в систему пакетный драйвер NE2000 — взять можно с Old-DOS. Это обычный COM-файл, который я закинул в IMA-образ флоппи-диска (делается за пару кликов в UltraISO). Затем примонтировал его в систему и скопировал драйвер в корень диска C. Вызов запихнул в AUTOEXEC.BAT:

Содержимое AUTOEXEC.BAT
Содержимое AUTOEXEC.BAT

По сути, это запуск COM-файла с программным INT 0x60, аппаратным IRQ 3 и базовым I/O-портом 0x300. Таким образом, сетевая карта займет 32-байтное окно с этого адреса (0x300 — 0x31F) — дефолт для NE2000 и совместимых. После перезагрузки пакетный драйвер успешно подгрузился.

Консоль при запуске системы
Консоль при запуске системы

Хорошо видно то, о чем говорилось выше: драйвер работает исключительно на L2 и ничего не знает об IP-адресе. Копируем SSH2DOS.EXE в любую удобную директорию (например, C:\SSH2DOS) и рядом надо создать конфиг c именем WATTCP.CFG для сетевого стека WATT-32:

Конфигурация сети
Конфигурация сети

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

  • bootp = 0

  • dhcp = 0

  • domainlist = “”

  • gratuitous_arp = 0

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

C:\> SSH2DOS\SSH2DOS.EXE <username> <host>

Вводите пароль и сессия устанавливается:

Поднятая SSH-сессия через SSH2DOS by Toyoyo
Поднятая SSH-сессия через SSH2DOS by Toyoyo

Подводим итоги

SSH2DOS — пример того, как одна идея прошла уже через две реинкарнации и продолжает жить среди любителей старой техники. Это приложение не просто дает возможность управлять современными серверами по SSH2, но и позволяет это делать фактически с любого компьютера на 386-м процессоре. Да, это не будет быстро, однако сам факт того, что вы можете экспериментировать с современным железом, используя какой-нибудь красивый раритетный ноутбук на MS-DOS, уже заслуживает внимания.

Кроме того, советую заглянуть к Toyoyo на GitHub — там я уже заприметил любопытную реализацию PuTTY 0.83 для Windows 3.11 и выше — уверен, штука не менее эпическая и полезная для всех фанатов ретрокомпьютинга. Ну а на этой позитивной ноте я с вами прощаюсь и желаю отличного дня.