
radmin-vpn-linux v1.1.0
Запуск Radmin VPN на Linux через Wine — собственный драйвер, TAP-мост, нулевая потеря пакетов
Radmin VPN для Linux
Запуск Radmin VPN на Linux через Wine. Подключайтесь к VPN-сетям, просматривайте пиров, играйте в игры — всё без Windows-виртуальной машины.
Я сделал это не потому, что это проще, чем виртуальная машина. Я сделал это, потому что думал, что это проще, чем виртуальная машина.
Код, созданный с помощью ИИ. Разработан совместно человеком и Claude (Anthropic). Драйвер, хуки и мост были написаны с использованием обширной обратной разработки с помощью ИИ недокументированного протокола драйвера Radmin VPN с использованием Ghidra. Это работает, но без каких-либо гарантий. Не связано с Famatech. Radmin VPN является проприетарным ПО — скачайте его самостоятельно с radmin-vpn.com. Используйте на свой страх и риск.
Как это работает
Служба Windows Radmin VPN взаимодействует с NDIS-минипорт-драйвером для своего виртуального сетевого адаптера. Wine не поддерживает NDIS, поэтому мы заменяем драйвер нашей собственной реализацией, которая связывается с Linux TAP-устройством. Hook-DLL обрабатывает проблемы совместимости с Wine (именование адаптера, права реестра). В результате получается полностью функциональный клиент Radmin VPN, работающий нативно под Wine.
Linux app ← TAP (radminvpn0) ← tap_bridge ← FIFO ← rvpnnetmp.sys (Wine driver) ← RvControlSvc.exe
Быстрый старт (AppImage, рекомендуется)
Загрузите RadminVPN-Linux-x86_64.AppImage из последнего релиза. Ничего устанавливать не нужно — Wine уже включён.
Кандидаты в релизы (например,
v1.0.0-rc1) публикуются как GitHub предварительные релизы. Ссылкаlatestвыше всегда указывает на новейшую стабильную сборку, поэтому предварительные релизы там не появятся — загружайте их из полного списка релизов.
chmod +x RadminVPN-Linux-x86_64.AppImage
./RadminVPN-Linux-x86_64.AppImage
При первом запуске загружается установщик Radmin VPN, с которым проект проверен (или укажите свой с помощью --installer). Откроется терминал с прогрессом, и потребуется один запрос пароля sudo для настройки TAP.
Постоянное состояние (wineprefix, MAC, журналы) хранится в ~/.local/share/radmin-vpn-linux/.
Radmin закрывается сам по себе? Его собственный обновлятор устанавливает новую сборку внутри работающего префикса. Выполните обновление контролируемым способом — это сохранит ваш префикс и ваш Radmin ID:
./RadminVPN-Linux-x86_64.AppImage --updateЗатем отключите «Автоматические обновления» в настройках Radmin, чтобы он перестал пытаться. Подробности в собственном автообновлении Radmin.
Предварительные требования (сборка из исходников / не-AppImage)
- Wine >= 11.0 (протестировано на Wine 11.5 Arch Linux и Wine 11.6 Ubuntu 24.04)
- mingw-w64 кросс-компиляторы (
i686-w64-mingw32-gcc,x86_64-w64-mingw32-gcc) — для сборки из исходников - iconv (glibc) — для разбора журналов службы
- sudo доступ — для создания TAP-устройства и маршрутизации
- Поддержка TUN/TAP в ядре — обычно встроена, проверьте с помощью
modprobe tun - Установщик Radmin VPN — загружается автоматически, если отсутствует. Версия, с которой проверен этот проект, зафиксирована в одном месте,
RADMIN_VERSIONвlib.sh(в настоящее время 2.1.4951.1; 2.0.4899.9 также работает). Radmin VPN 1.4 не поддерживается — он регистрируется и открывает адаптер, но так и не завершает подключение под Wine-прокладкой, оставляя GUI зависшим на «Подключение...».
Arch Linux
sudo pacman -S wine mingw-w64-gcc
Ubuntu/Debian
sudo apt install wine64 wine32 gcc-mingw-w64
Быстрый старт из исходников
git clone https://github.com/baptisterajaut/radmin-vpn-linux.git
cd radmin-vpn-linux
# Вариант A: загрузить готовые бинарники из GitHub Releases
mkdir -p build
TAG=$(curl -sI https://github.com/baptisterajaut/radmin-vpn-linux/releases/latest | grep -i location | grep -oP 'v[\d.]+')
curl -sL "https://github.com/baptisterajaut/radmin-vpn-linux/releases/download/${TAG}/radmin-vpn-linux-${TAG}.tar.gz" \
| tar xz -C build/
# Вариант B: собрать из исходников
make
# Загрузите установщик Radmin VPN с https://www.radmin-vpn.com/
./run.sh --installer ~/Downloads/Radmin_VPN_*.exe
При последующих запусках просто:
./run.sh
Параметры командной строки
| Флаг | Описание |
|---|---|
--installer <path> | Путь к установщику Radmin_VPN_*.exe (только при первом запуске). |
--no-ui | Запуск службы без запуска GUI Radmin. |
--update | Обновление Radmin до зафиксированной версии на месте. Сохраняет префикс, поэтому RID, зарегистрированный в Famatech, сохраняется. |
--no-broadcast-routes | Не добавлять маршруты broadcast/multicast → TAP. |
--filter-ui | Запуск дополнительного GTK4 интерфейса фильтрации пакетов (по умолчанию выключен). |
--fix-chat | Патч qwindows.dll из Qt для исправления сбоя окна чата под Wine (по умолчанию выключен). |
Собственное автообновление Radmin
GUI Radmin может загрузить новую сборку и запустить её установщик внутри живого префикса,
что убивает GUI и вызывает сбой работающей службы (журнал GUI затем показывает установщик
в AppData\\Local\\Temp). Две защиты: лаунчер поставляет текущую проверенную
сборку, поэтому обновлятору нечего устанавливать, а GUI, который умирает, больше не тянет за собой
туннель — он перезапускается один раз, затем VPN продолжает работать в фоновом режиме. Для намеренного
обновления используйте ./run.sh --update, который сначала останавливает всё. Отключение
«Автоматических обновлений» в настройках GUI полностью исключает гонку.
Оба параметра --filter-ui и --fix-chat являются опциональными. Интерфейсу фильтрации нужен бинарник rvpn_filter_ui
(собирается командой make); исправление чата требует patch_qwindows_font.py и интерпретатор Python 3.
Режимы без графического интерфейса / серверные режимы
Два дополнительных лаунчера запускают Radmin VPN без локального рабочего стола — для VPS или хостинга в дата-центре. Оба устанавливаются и настраиваются точно так же, как run.sh (тот же wineprefix, тот же процесс первого запуска с --installer, тот же TAP-мост); они отличаются только способом доступа к GUI.
run_datacenter.sh — GUI через браузер
Запускает настоящий GUI Radmin на виртуальном дисплее (Xvfb) и предоставляет к нему доступ через VNC + noVNC, так что вы можете настроить свои сети из браузера, а затем оставить его работать.
sudo apt install -y xvfb x11vnc websockify novnc # или: make install-datacenter-deps
./run_datacenter.sh --installer ~/Downloads/Radmin_VPN_*.exe
| Флаг | По умолчанию | Описание |
|---|---|---|
--vnc-port <n> | 5900 | Порт для сервера x11vnc. |
--web-port <n> | 6080 | Порт для веб-интерфейса noVNC. |
--vnc-password <pw> | (нет) | Пароль для сеанса VNC / веб-интерфейса. |
--web-bind <addr> | 127.0.0.1 | Адрес, на котором слушает noVNC. |
По умолчанию noVNC привязан к 127.0.0.1, поэтому доступ к нему возможен только через SSH-туннель:
ssh -L 6080:localhost:6080 your-vps # затем откройте http://localhost:6080/vnc.html
Чтобы открыть публичный доступ, передайте --web-bind 0.0.0.0 вместе с --vnc-password — в противном случае любой, кто получит доступ к веб-порту, попадёт на неаутентифицированный рабочий стол с правами root. Скрипт выводит громкое предупреждение, если вы открываете публичный доступ без пароля.
run_vps.sh — только служба, фиксированный GUID
Запускает службу без графического интерфейса с жёстко заданным TAP GUID (без Wine WMI) и вообще без GUI. Если пользовательский перечислитель сетей (rv_net_enum.exe, не поставляется в этом репозитории) присутствует на одну директорию выше, он запускается; в противном случае служба просто работает, пока вы не нажмёте Ctrl+C. Принимается только --installer.
./run_vps.sh --installer ~/Downloads/Radmin_VPN_*.exe
Сборка из исходников
Требуются кросс-компиляторы mingw-w64. Готовые бинарники доступны в Releases (собираются CI для каждой тегированной версии), если вы не хотите устанавливать mingw.
make # собрать всё в build/
make clean # удалить артефакты сборки
Результат:
build/rvpnnetmp.sys— драйвер ядра Wine (64-битный PE)build/adapter_hook.dll— Hook-DLL (32-битный PE)build/rvpn_launcher.exe— инжектор DLL (32-битный PE)build/netsh.exe— замена netsh (32-битный PE, устанавливается в SysWOW64)build/netsh64.exe— замена netsh (64-битный PE, устанавливается в System32)build/drvinst.exe— заглушка no-op, заменяющая реальный установщик NDIS-драйвера Radmin (issue #12)build/tap_bridge— нативный Linux TAP-мостbuild/rvpn_dnsfix.so— нативная LD_PRELOAD-прокладка, предзагружается только в службуbuild/rvpn_reuseport.so— нативная LD_PRELOAD-прокладка, предзагружается вwineserverbuild/rvpn_filter_ui— дополнительный GTK4 интерфейс фильтрации пакетов (--filter-ui)
Сборка AppImage
make
./packaging/build-appimage.sh # → packaging/dist/RadminVPN-Linux-x86_64.AppImage
При первом запуске загружает сборку Kron4ek Wine-Staging amd64-wow64 (~100 МБ) и appimagetool, кэширует обе в packaging/dist/. Требуются curl и ImageMagick (convert).
Что делает run.sh
- Первый запуск: устанавливает Radmin VPN через Wine (
/VERYSILENT), удаляет реальный NDIS-драйвер (несовместим с Wine), регистрирует наш пользовательский драйвер - Каждый запуск: создаёт TAP-устройство, запускает мост TAP-to-FIFO, настраивает реестр Wine (GUID адаптера, служба драйвера), запускает службу и GUI Radmin VPN
- При выходе (Ctrl+C или закрытие GUI): убивает Wine, удаляет TAP-устройство, выполняет очистку
Wineprefix хранится в ./wineprefix/ (запуск из исходников) или ~/.local/share/radmin-vpn-linux/wineprefix/ (AppImage). Постоянный MAC-адрес генерируется при первом запуске и сохраняется в wineprefix.
Архитектура
| Компонент | Описание |
|---|---|
rvpnnetmp.sys | Драйвер ядра Wine. Эмулирует NDIS-минипорт Radmin. Обрабатывает IOCTL (VERSION, STATUS, SETUP, PEERMAC), кодирование/декодирование TLV-кадров, очередь IRP для перекрытого ввода-вывода, маршрутизацию кадров на основе MAC для поддержки нескольких пиров. |
adapter_hook.dll | Компаньон-DLL, загружаемая вместе с RvControlSvc.exe. IAT-хуки: переименовывает TAP-адаптер в ожидаемое Radmin имя, превращает RegSetKeySecurity в no-op для обхода бага SCM в Wine, где службам не хватает SYSTEM SID, и отвечает на четыре запроса Perf{Increment,Decrement}ULong{,Long}CounterValue, которые Wine advapi32 не экспортирует. Последнее не косметическое: Radmin 2.1 разрешает семь точек входа perflib в одном каскаде «всё или ничего», затем передаёт полученный объект счётчика на пира как полезную нагрузку рукопожатия пира — поэтому четыре отсутствующих телеметрических экспорта разрушают весь путь данных (issue #24, docs/wine-perflib.md). |
tap_bridge | Нативный Linux-бинарник. Передаёт ethernet-кадры между TAP-устройством и именованными каналами (FIFO), которые читает/пишет Wine-драйвер. |
netsh.exe / netsh64.exe | Заменяет заглушку netsh в Wine (32-битную в SysWOW64, 64-битную в System32). Преобразует Windows-команды netsh interface ip в Linux-команды ip addr/ip link через файловый ретранслятор, проверяя адрес до того, как он достигнет корневого ретранслятора. |
rvpn_launcher.exe | Инжектирует adapter_hook.dll в процесс службы Radmin через CreateRemoteThread + LoadLibrary. |
drvinst.exe | Заглушка no-op, заменяющая реальный установщик NDIS-драйвера Radmin. Radmin запускает его во время выполнения для загрузки NetMP60_1_1_64.sys, который прерывает Wine 11.x через NdisInitializeReadWriteLock (issue #12); поскольку наш драйвер уже заменяет этот адаптер, реальный никогда не должен загружаться. |
rvpn_dnsfix.so | Нативная LD_PRELOAD-прокладка, инжектируется только при запуске службы. Замыкает обратный DNS (getnameinfo/gethostbyaddr) для частных IPv4/IPv6 на уровне glibc. Radmin выполняет PTR-разрешение для каждого собранного локального адреса-кандидата; на хосте, чей резолвер блокирует PTR-запросы RFC1918, это зависает на минуты, и служба регистрируется, но никогда не становится готовой (issue #16). Запрос выполняется Unix-стороной Wine, вне досягаемости любых хуков внутри adapter_hook.dll. |
rvpn_reuseport.so | Нативная LD_PRELOAD-прокладка, предзагружается в wineserver (не в службу — Unix-сокеты принадлежат wineserver). Устанавливает SO_REUSEPORT на каждом TCP-сокете при создании. Radmin 2.1 выполняет NAT-траверс с повторным использованием TCP-портов: он привязывает слушатель к uplink:PORT, рекламирует это сопоставление, затем привязывает свои исходящие пир-сокеты к тому же локальному порту с SO_REUSEADDR, что разрешено в Windows. Wine преобразует этот запрос в отсутствие Unix-уровневой опции для TCP (server/sock.c, SO_REUSEPORT компилируется только для __APPLE__), поэтому ядро отказывает во второй привязке, и клиент видит WSAEACCES при каждом подключении к пиру (issue #24). Собственный учёт конфликтов wineserver всё ещё работает, поэтому привязки, которые Windows отказала бы, по-прежнему отклоняются. |
rvpn_filter_ui | Дополнительный GTK4-интерфейс для просмотра и фильтрации пакетов, пересекающих мост. По умолчанию выключен; запускается с --filter-ui. |
Устранение неполадок
GUI завис на «Ожидание адаптера»: драйвер не загружается. Проверьте, что /tmp/radmin_driver.log существует и содержит данные. Если пусто, регистрация службы драйвера может отсутствовать — удалите wineprefix и запустите заново.
Зарегистрирован, но никогда не «готов»: служба достигает состояния Registered as #… и останавливается. Две известные причины, обе указаны в диагностическом блоке, выводимом по таймауту. (a) Прозрачный прокси или туннель с собственной политикой маршрутизации (sing-box, clash/mihomo, v2ray…), перехватывающий исходящее соединение — такие стеки отвечают на TCP-рукопожатие локально, поэтому сокет читает ESTABLISHED, пока ничего не ретранслируется. Исключите 26.0.0.0/8 из его маршрутов, а также *.radminte.com, если можете достичь их напрямую. (b) Резолвер, который блокирует обратные запросы частных адресов (обычный триггер — docker0 на 172.17.0.1). rvpn_dnsfix.so обрабатывает это, но это 64-битная прокладка: системный Wine, собранный как old-wow64, игнорирует её. Обходной путь — добавьте строку для адреса в /etc/hosts или используйте contrib/run-in-netns.sh (который доводит службу до состояния «готов», но держит VPN внутри namespace: хост-приложения не могут достичь 26.0.0.0/8, прочитайте предупреждение в его заголовке).
Ваши другие Wine-приложения сломались после запуска Radmin (unimplemented function ndis.sys.NdisInitializeReadWriteLock): версии до 1.0.0 позволяли запускаться winemenubuilder.exe из Wine, который переписывает файловые ассоциации Windows на хосте (.exe, .msi, .lnk, .reg, .chm, …), чтобы они открывались в нашем префиксе. Другие Windows-программы затем запускаются внутри префикса Radmin, и если реальный NDIS-минипорт Radmin (RvNetMP60) всё ещё зарегистрирован там, каждая из них прерывается на этой ndis-заглушке. Версия 1.0.1 отключает winemenubuilder везде, очищает записи, которые он создал для префикса Radmin, и удаляет RvNetMP60 из system.reg в автономном режиме — просто запустите 1.0.1 один раз, и оба будут исправлены. Обратите внимание, что echo $WINEPREFIX в этой ситуации ничего не показывает: захват живёт в ~/.local/share/applications/*.desktop, а не в вашем окружении. Ручная очистка, если предпочитаете:
grep -rl 'WINEPREFIX=[^"]*radmin' ~/.local/share/applications --include='*.desktop' | xargs -r rm
rm -rf ~/.local/share/applications/wine/Programs/"Radmin VPN"
update-desktop-database ~/.local/share/applications
В сети и в своих сетях, но ни один пир никогда не подключается (error: 0x700000000): это Radmin 2.1 на сборке старше 1.1.0. Журнал службы выглядит здоровым вплоть до подключений к пирам, которые затем завершаются с ошибкой в цикле с этим кодом и в итоге сдаются с node offline. Два независимых пробела Wine, оба исправлены в 1.1.0 и оба объяснены выше в строках rvpn_reuseport.so и adapter_hook.dll: Wine не устанавливает Unix-уровневую опцию для TCP SO_REUSEADDR, поэтому NAT-траверс с повторным использованием портов в 2.1 получает WSAEACCES при каждом подключении к пиру; и в Wine advapi32 отсутствуют четыре perflib-экспорта, без которых 2.1 отправляет нулевую полезную нагрузку как рукопожатие пира. Обратите внимание, что сам код не несёт информации — это общий отказ в конце каскада ошибок, поэтому не пытайтесь вычитать из него подсистему. Исправление — обновить этот проект до 1.1.0; на стороне Radmin ничего менять не нужно.
Служба умирает сразу: проверьте /tmp/radmin_service.log на ошибки Wine. Частая причина: старый wineprefix от другой версии Wine. Удалите ./wineprefix/ и запустите заново.
0% потери пакетов с одним пиром, высокая потеря со многими: это была исходная ошибка — исправлена маршрутизацией кадров на основе MAC в драйвере. Убедитесь, что используете последнюю сборку.
Первый ping медленный (~1с): последняя версия кэширует MAC-адреса для каждого IP-пакета, который видит драйвер. Если целевой IP отправил хотя бы один пакет, пока драйвер работал, MAC уже кэширован, и задержка ARP нулевая. Только полностью молчаливые пиры (те, кто никогда не отправлял пакет) требуют начального ARP-разрешения, что добавляет ~1 секунду.
LAN-игры не видят других пиров / «автообнаружение» сломано: большинство LAN-игр обнаруживают друг друга с помощью broadcast-зондов (UDP на 255.255.255.255) или multicast (224.0.0.0/4). В Windows TAP-драйвер Radmin рекламирует себя как предпочтительный интерфейс для этих потоков; в Linux нужно явно указать ядру. run.sh теперь устанавливает два дополнительных маршрута при подъёме VPN:
ip route append 255.255.255.255/32 dev radminvpn0 metric 0
ip route append 224.0.0.0/4 dev radminvpn0 metric 0
Побочный эффект: mDNS / Bonjour / SSDP в вашей физической LAN (Chromecast, AirPrint, Sonos, умные ТВ, ...) будут проходить через VPN, пока он активен. Если вам нужны локальное LAN-обнаружение и Radmin параллельно, запускайте с --no-broadcast-routes:
./run.sh --no-broadcast-routes
Маршруты привязаны к TAP-устройству, поэтому они автоматически удаляются, когда run.sh завершает работу устройства при выходе.
Известные ограничения
- Одновременно может работать только один экземпляр (общие FIFO в
/tmp/) - Маршрут on-link
26.0.0.0/8влияет на всю систему, пока работает (очищается при выходе) - Маршруты по умолчанию для broadcast (
255.255.255.255/32) и multicast (224.0.0.0/4) направляются в VPN — отключите с помощью--no-broadcast-routes, если нужны локальные mDNS / SSDP в LAN параллельно - Старые версии Wine (< 11.0) могут иметь другое поведение перекрытого ввода-вывода, которое ломает драйвер
Примечания
Обход бага Wine. Хук RegSetKeySecurity обходит известное ограничение Wine, где службы не получают SYSTEM SID (S-1-5-18). Это может быть исправлено в апстриме в будущем релизе Wine.
Благодарности
Обратная разработка и Wine-прокладка: @baptisterajaut.
- @ayozetr — отследил зависание «регистрируется, но никогда не готов» до
обратного DNS-запроса частного адреса, блокируемого резолвером хоста, доказал это с помощью
воспроизведения на голой libc после того, как четыре неверные теории были отброшены (включая мою), и написал
оригинал
src/rvpn_dnsfix.cиcontrib/run-in-netns.sh. - @gringoestrangeiro — работа над стабильностью Linux: фильтры пакетов, ARP-кэш, восстановление после сбоев, режимы без графического интерфейса и для дата-центра.
- @yuxiaole-bili — обнаружил, что SCM в Wine автоматически запускает второй, не-хукнутый экземпляр службы, который борется с инжектированным за адаптер.
- @D1spell-tech, @Milkiway13 и все, кто вставил полный диагностический блок — два независимых хоста — вот что делает баг находимым.
Лицензия
GPL-3.0. См. LICENSE.
По духу этот код является общественным достоянием — делайте с ним что хотите. GPL здесь как юридическая страховка: она явно защищает обратную разработку для совместимости, что и делает этот проект. Ремень и подтяжки.
Radmin VPN — проприетарное ПО компании Famatech Corp. Этот проект предоставляет только инструменты совместимости — код Famatech не включён и не распространяется.