
radmin-vpn-linux v1.0.0-rc9
Esegui Radmin VPN su Linux tramite Wine — driver personalizzato, bridge TAP, zero perdita di pacchetti
Radmin VPN per Linux
Esegui Radmin VPN su Linux tramite Wine. Unisciti a reti VPN, vedi i peer, gioca — tutto senza una VM Windows.
Non l'ho creato perché fosse più facile di una VM. L'ho creato perché pensavo fosse più facile di una VM.
Codice assistito dall'IA. Sviluppato in collaborazione tra un umano e Claude (Anthropic). Il driver, gli hook e il bridge sono stati scritti con un esteso reverse engineering assistito dall'IA del protocollo driver non documentato di Radmin VPN usando Ghidra. Funziona, ma senza garanzie. Non affiliato a Famatech. Radmin VPN è proprietario — scaricalo tu stesso da radmin-vpn.com. Usalo a tuo rischio.
Come funziona
Il servizio Windows di Radmin VPN comunica con un driver miniport NDIS per la sua scheda di rete virtuale. Wine non supporta NDIS, quindi sostituiamo il driver con una nostra implementazione che fa da bridge verso un dispositivo TAP Linux. Una DLL di hook gestisce i problemi di compatibilità con Wine (nomi degli adapter, permessi del registro). Il risultato è un client Radmin VPN completamente funzionante che gira nativamente sotto Wine.
App Linux ← TAP (radminvpn0) ← tap_bridge ← FIFO ← rvpnnetmp.sys (driver Wine) ← RvControlSvc.exe
Avvio rapido (AppImage, consigliato)
Prendi RadminVPN-Linux-x86_64.AppImage dall'ultima release. Niente da installare — Wine è incluso.
Release candidate (es.
v1.0.0-rc1) sono pubblicate come pre-release di GitHub. Il linklatestsopra punta sempre alla build stabile più recente, quindi le pre-release non appariranno lì — prendile dall'elenco completo delle release.
chmod +x RadminVPN-Linux-x86_64.AppImage
./RadminVPN-Linux-x86_64.AppImage
Al primo avvio scarica il programma di installazione di Radmin VPN contro cui è validato (oppure passa il tuo con --installer). Si apre un terminale con l'avanzamento e serve una richiesta di password sudo per la configurazione TAP.
Lo stato persistente (wineprefix, MAC, log) vive in ~/.local/share/radmin-vpn-linux/.
Radmin si chiude da solo? Il suo aggiornatore sta installando una build più recente all'interno del prefix in esecuzione. Fai l'aggiornamento in modo controllato invece — mantiene il tuo prefix e il tuo ID Radmin:
./RadminVPN-Linux-x86_64.AppImage --updatePoi disattiva "Aggiornamenti automatici" nelle impostazioni di Radmin così smette di provarci. Dettagli in L'aggiornatore automatico di Radmin.
Prerequisiti (build da sorgente / non-AppImage)
- Wine >= 11.0 (testato su Wine 11.5 Arch Linux e su Wine 11.6 Ubuntu 24.04)
- mingw-w64 cross-compilatori (
i686-w64-mingw32-gcc,x86_64-w64-mingw32-gcc) — per compilare da sorgente - iconv (glibc) — per il parsing dei log del servizio
- sudo — per la creazione del dispositivo TAP e il routing
- Supporto kernel TUN/TAP — di solito integrato, verifica con
modprobe tun - Programma di installazione di Radmin VPN — scaricato automaticamente se assente. La versione contro cui questo progetto è validato è fissata in un unico punto,
RADMIN_VERSIONinlib.sh(attualmente 2.1.4951.1; anche 2.0.4899.9 funziona). Radmin VPN 1.4 non è supportato — si registra e apre l'adapter ma non finisce mai la connessione sotto lo shim Wine, lasciando la GUI bloccata su "Connessione...".
Arch Linux
sudo pacman -S wine mingw-w64-gcc
Ubuntu/Debian
sudo apt install wine64 wine32 gcc-mingw-w64
Avvio rapido da sorgente
git clone https://github.com/baptisterajaut/radmin-vpn-linux.git
cd radmin-vpn-linux
# Opzione A: scarica i binari precompilati dalle 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/
# Opzione B: compila da sorgente
make
# Scarica il programma di installazione di Radmin VPN da https://www.radmin-vpn.com/
./run.sh --installer ~/Downloads/Radmin_VPN_*.exe
Alle esecuzioni successive, basta:
./run.sh
Flag da riga di comando
| Flag | Descrizione |
|---|---|
--installer <path> | Percorso del programma di installazione Radmin_VPN_*.exe (solo al primo avvio). |
--no-ui | Esegue il servizio senza avviare la GUI di Radmin. |
--update | Aggiorna Radmin alla versione fissata sul posto. Mantiene il prefix, quindi l'RID registrato con Famatech sopravvive. |
--no-broadcast-routes | Non aggiunge le route broadcast/multicast → TAP. |
--filter-ui | Avvia l'interfaccia GTK4 opzionale per il filtraggio dei pacchetti (disattivata di default). |
--fix-chat | Applica una patch a qwindows.dll di Qt per correggere il crash della finestra chat sotto Wine (disattivato di default). |
L'aggiornatore automatico di Radmin
La GUI di Radmin può scaricare una build più recente ed eseguire il suo programma di installazione dentro il prefix attivo,
il che uccide la GUI e fa fallire il servizio in esecuzione (il log della GUI mostra poi un programma di installazione
sotto AppData\\Local\\Temp). Due difese: il launcher fornisce la build validata corrente così l'aggiornatore non ha nulla da spingere, e una GUI che muore non si porta più dietro il tunnel — viene riavviata una volta, poi la VPN continua a girare headless. Per aggiornare
deliberatamente, usa ./run.sh --update, che prima ferma tutto. Disattivare
"Aggiornamenti automatici" nelle impostazioni della GUI evita del tutto la corsa.
Sia --filter-ui che --fix-chat sono opzionali. L'interfaccia di filtro richiede il binario rvpn_filter_ui
(compilato da make); la correzione chat richiede patch_qwindows_font.py e un interprete Python 3.
Modalità headless / server
Due launcher aggiuntivi eseguono Radmin VPN senza desktop locale — per un VPS o un host in datacenter. Entrambi installano e configurano esattamente come run.sh (stesso wineprefix, stesso flusso --installer al primo avvio, stesso bridge TAP); differiscono solo su come si raggiunge la GUI.
run_datacenter.sh — GUI tramite browser
Esegue la vera GUI di Radmin su un display virtuale (Xvfb) e la serve tramite VNC + noVNC, così puoi configurare le tue reti da un browser e poi lasciarla in esecuzione.
sudo apt install -y xvfb x11vnc websockify novnc # oppure: make install-datacenter-deps
./run_datacenter.sh --installer ~/Downloads/Radmin_VPN_*.exe
| Flag | Default | Descrizione |
|---|---|---|
--vnc-port <n> | 5900 | Porta per il server x11vnc. |
--web-port <n> | 6080 | Porta per l'endpoint web noVNC. |
--vnc-password <pw> | (nessuna) | Password per la sessione VNC / web. |
--web-bind <addr> | 127.0.0.1 | Indirizzo su cui noVNC ascolta. |
Di default noVNC si lega a 127.0.0.1, quindi è raggiungibile solo tramite tunnel SSH:
ssh -L 6080:localhost:6080 your-vps # poi apri http://localhost:6080/vnc.html
Per esporlo pubblicamente, passa --web-bind 0.0.0.0 insieme a --vnc-password — altrimenti chiunque raggiunga la porta web finisce su un desktop non autenticato e con privilegi di root. Lo script stampa un avviso ben visibile se ti leghi pubblicamente senza password.
run_vps.sh — solo servizio, GUID fisso
Avvia il servizio headless con un GUID TAP hardcoded (niente WMI Wine richiesto) e nessuna GUI. Se un enumeratore di rete personalizzato (rv_net_enum.exe, non incluso in questo repo) è presente una directory sopra, viene avviato; altrimenti il servizio gira semplicemente finché non premi Ctrl+C. Solo --installer è accettato.
./run_vps.sh --installer ~/Downloads/Radmin_VPN_*.exe
Compilazione da sorgente
Richiede i cross-compilatori mingw-w64. I binari precompilati sono disponibili dalle Releases (compilati dalla CI su ogni versione taggata) se non vuoi installare mingw.
make # compila tutto in build/
make clean # rimuove gli artefatti di build
Produce:
build/rvpnnetmp.sys— driver kernel Wine (PE a 64 bit)build/adapter_hook.dll— DLL di hook (PE a 32 bit)build/rvpn_launcher.exe— iniettore DLL (PE a 32 bit)build/netsh.exe— sostituto di netsh (PE a 32 bit, installato in SysWOW64)build/netsh64.exe— sostituto di netsh (PE a 64 bit, installato in System32)build/drvinst.exe— stub no-op che sostituisce il vero programma di installazione del driver NDIS di Radmin (issue #12)build/tap_bridge— bridge TAP Linux nativobuild/rvpn_dnsfix.so— shim nativo LD_PRELOAD, precaricato solo nel serviziobuild/rvpn_reuseport.so— shim nativo LD_PRELOAD, precaricato inwineserverbuild/rvpn_filter_ui— interfaccia GTK4 opzionale per il filtraggio dei pacchetti (--filter-ui)
Compilazione dell'AppImage
make
./packaging/build-appimage.sh # → packaging/dist/RadminVPN-Linux-x86_64.AppImage
Scarica la build Wine-Staging amd64-wow64 di Kron4ek (~100 MB) e appimagetool al primo avvio, mettendoli entrambi in cache in packaging/dist/. Richiede curl e ImageMagick (convert).
Cosa fa run.sh
- Primo avvio: installa Radmin VPN tramite Wine (
/VERYSILENT), rimuove il vero driver NDIS (incompatibile con Wine), registra il nostro driver personalizzato - Ogni avvio: crea un dispositivo TAP, avvia il bridge TAP-to-FIFO, configura il registro di Wine (GUID adapter, servizio driver), avvia il servizio e la GUI di Radmin VPN
- All'uscita (Ctrl+C o chiusura GUI): uccide Wine, rimuove il dispositivo TAP, pulisce
Il wineprefix è memorizzato in ./wineprefix/ (esecuzione da sorgente) o ~/.local/share/radmin-vpn-linux/wineprefix/ (AppImage). Un indirizzo MAC persistente viene generato al primo avvio e salvato nel wineprefix.
Architettura
| Componente | Descrizione |
|---|---|
rvpnnetmp.sys | Driver kernel Wine. Emula il miniport NDIS di Radmin. Gestisce IOCTL (VERSION, STATUS, SETUP, PEERMAC), codifica/decodifica frame TLV, coda IRP per I/O overlapped, routing dei frame basato su MAC per il supporto multi-peer. |
adapter_hook.dll | DLL di accompagnamento caricata insieme a RvControlSvc.exe. Hook IAT: rinomina l'adapter TAP per corrispondere al nome atteso da Radmin, rende no-op RegSetKeySecurity per aggirare un bug SCM di Wine dove i servizi non hanno il SID SYSTEM, e risponde alle quattro ricerche Perf{Increment,Decrement}ULong{,Long}CounterValue che advapi32 di Wine non esporta. Quest'ultima non è cosmetica: Radmin 2.1 risolve sette punti di ingresso perflib in una cascata tutto-o-niente, poi passa l'oggetto contatore per-peer risultante come payload dell'handshake tra peer — quindi quattro export di telemetria mancanti abbattono l'intero percorso dati (issue #24, docs/wine-perflib.md). |
tap_bridge | Binario Linux nativo. Inoltra i frame ethernet tra il dispositivo TAP e le named pipe (FIFO) che il driver Wine legge/scrive. |
netsh.exe / netsh64.exe | Sostituisce lo stub netsh di Wine (32 bit in SysWOW64, 64 bit in System32). Traduce i comandi Windows netsh interface ip in comandi Linux ip addr/ip link tramite un relay basato su file, validando l'indirizzo prima che raggiunga il relay di root. |
rvpn_launcher.exe | Inietta adapter_hook.dll nel processo del servizio Radmin tramite CreateRemoteThread + LoadLibrary. |
drvinst.exe | Stub no-op che sostituisce il vero programma di installazione del driver NDIS di Radmin. Radmin lo esegue a runtime per caricare NetMP60_1_1_64.sys, che fa abortire Wine 11.x tramite NdisInitializeReadWriteLock (issue #12); poiché il nostro driver sostituisce già quell'adapter, quello vero non deve mai caricarsi. |
rvpn_dnsfix.so | Shim nativo LD_PRELOAD, iniettato solo nell'avvio del servizio. Cortocircuita il DNS inverso (getnameinfo/gethostbyaddr) degli IPv4/IPv6 privati a livello glibc. Radmin risolve PTR ogni indirizzo candidato locale che raccoglie; su un host il cui resolver buca le query PTR RFC1918 questo si blocca per minuti e il servizio si registra ma non diventa mai pronto (issue #16). La ricerca è emessa dal lato Unix di Wine, fuori dalla portata di qualsiasi hook dentro adapter_hook.dll. |
rvpn_reuseport.so | Shim nativo LD_PRELOAD, precaricato in wineserver (non nel servizio — i socket Unix appartengono a wineserver). Imposta SO_REUSEPORT su ogni socket TCP alla creazione. Radmin 2.1 fa NAT traversal con riuso della porta TCP: lega un listener a uplink:PORT, pubblicizza quella mappatura, poi lega i suoi socket peer in uscita alla stessa porta locale con SO_REUSEADDR, cosa che Windows consente. Wine traduce quella richiesta in nessuna opzione a livello Unix per TCP (server/sock.c, SO_REUSEPORT è compilato solo __APPLE__), quindi il kernel rifiuta il secondo bind e il client vede WSAEACCES su ogni connessione peer (issue #24). La contabilità dei conflitti di wineserver continua comunque a girare, quindi i bind che Windows rifiuterebbe vengono ancora rifiutati. |
rvpn_filter_ui | UI GTK4 opzionale per ispezionare e filtrare i pacchetti che attraversano il bridge. Disattivata di default; avviala con --filter-ui. |
Risoluzione dei problemi
GUI bloccata su "In attesa dell'adapter": il driver non si sta caricando. Verifica che /tmp/radmin_driver.log esista e abbia contenuto. Se è vuoto, la registrazione del servizio driver potrebbe mancare — elimina il wineprefix e riesegui.
Registrato ma mai "pronto": il servizio raggiunge Registered as #… e si ferma lì. Due cause note, entrambe segnalate dal blocco di diagnostica stampato al timeout. (a) Un proxy trasparente o un tunnel con la propria policy di routing (sing-box, clash/mihomo, v2ray…) che intercetta la connessione in uscita — tali stack rispondono all'handshake TCP localmente, quindi il socket legge ESTABLISHED mentre nulla viene inoltrato. Escludi 26.0.0.0/8 dalle sue route, e anche *.radminte.com se puoi raggiungerli direttamente. (b) Un resolver che buca le ricerche inverse degli indirizzi privati (un docker0 su 172.17.0.1 è il trigger usuale). rvpn_dnsfix.so gestisce questo, ma è uno shim a 64 bit: un Wine di sistema compilato come old-wow64 lo ignora. Soluzione alternativa lì — aggiungi una riga per l'indirizzo a /etc/hosts, oppure usa contrib/run-in-netns.sh (che porta il servizio a "pronto" ma tiene la VPN dentro un namespace: le applicazioni host non possono raggiungere 26.0.0.0/8, leggi l'avviso nell'intestazione).
Le tue altre app Wine si sono rotte dopo aver eseguito Radmin (unimplemented function ndis.sys.NdisInitializeReadWriteLock): le versioni fino alla 1.0.0 lasciavano girare winemenubuilder.exe di Wine, che riscrive le associazioni dei file Windows dell'host (.exe, .msi, .lnk, .reg, .chm, …) per aprirli nel nostro prefix. Altri programmi Windows poi partono dentro il prefix Radmin, e se il vero miniport NDIS di Radmin (RvNetMP60) è ancora registrato lì, ognuno di loro abortisce su quello stub ndis. La 1.0.1 disabilita winemenubuilder ovunque, ripulisce le voci che ha scritto per un prefix Radmin e rimuove RvNetMP60 da system.reg offline — basta eseguire la 1.0.1 una volta ed entrambi vengono riparati. Nota che echo $WINEPREFIX non mostra nulla in questa situazione: il dirottamento vive in ~/.local/share/applications/*.desktop, non nel tuo ambiente. Pulizia manuale, se preferisci:
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
Online e nelle tue reti, ma nessun peer si connette mai (error: 0x700000000): questo è Radmin 2.1 su una build precedente alla 1.1.0. Il log del servizio sembra sano fino alle connessioni peer, che poi falliscono in un loop con quel codice e infine si arrendono con node offline. Due lacune indipendenti di Wine, entrambe corrette nella 1.1.0 ed entrambe spiegate sopra nelle righe rvpn_reuseport.so e adapter_hook.dll: Wine non imposta nessuna opzione a livello Unix per un TCP SO_REUSEADDR, quindi il NAT traversal con riuso della porta della 2.1 ottiene WSAEACCES su ogni connessione peer; e advapi32 di Wine manca di quattro export perflib, senza i quali la 2.1 invia un payload nullo come handshake tra peer. Nota che il codice stesso non porta informazioni — è l'arresa generica alla fine della cascata di errori, quindi non cercare di leggere un sottosistema da esso. La soluzione è aggiornare questo progetto alla 1.1.0; nulla deve cambiare dal lato Radmin.
Il servizio muore subito: controlla /tmp/radmin_service.log per errori Wine. Causa comune: vecchio wineprefix da una versione diversa di Wine. Elimina ./wineprefix/ e riesegui.
0% di perdita pacchetti con un peer, perdita alta con molti: questo era il bug originale — corretto dal routing dei frame basato su MAC nel driver. Assicurati di usare l'ultima build.
Il primo ping è lento (~1s): l'ultima versione mette in cache gli indirizzi MAC per ogni pacchetto IP che il driver vede. Se l'IP di destinazione ha inviato almeno un pacchetto mentre il driver era in esecuzione, il MAC è già in cache e non c'è alcun ritardo ARP. Solo i peer completamente silenziosi (quelli che non hanno mai inviato un pacchetto) richiedono la risoluzione ARP iniziale, che aggiunge ~1 secondo.
I giochi LAN non vedono gli altri peer / "auto-discovery" rotta: la maggior parte dei giochi LAN si scoprono a vicenda con sonde broadcast (UDP verso 255.255.255.255) o multicast (224.0.0.0/4). Su Windows il driver TAP di Radmin si pubblicizza come interfaccia preferita per quei flussi; su Linux devi dirlo esplicitamente al kernel. run.sh ora installa due route extra quando la VPN si alza:
ip route append 255.255.255.255/32 dev radminvpn0 metric 0
ip route append 224.0.0.0/4 dev radminvpn0 metric 0
Effetto collaterale: mDNS / Bonjour / SSDP sulla tua LAN fisica (Chromecast, AirPrint, Sonos, smart TV, ...) passeranno attraverso la VPN mentre è attiva. Se ti servono la discovery LAN locale e Radmin in parallelo, esegui con --no-broadcast-routes:
./run.sh --no-broadcast-routes
Le route sono limitate al dispositivo TAP, quindi vengono rimosse automaticamente quando run.sh smonta il dispositivo all'uscita.
Limitazioni note
- Può girare solo un'istanza alla volta (FIFO condivise in
/tmp/) - La route on-link
26.0.0.0/8influenza l'intero sistema mentre è in esecuzione (pulita all'uscita) - Le route broadcast di default (
255.255.255.255/32) e multicast (224.0.0.0/4) sono indirizzate alla VPN — disattivale con--no-broadcast-routesse ti serve mDNS / SSDP della LAN locale in parallelo - Versioni di Wine più vecchie (< 11.0) possono avere un comportamento I/O overlapped diverso che rompe il driver
Note
Soluzione per un bug di Wine. L'hook RegSetKeySecurity aggira una limitazione nota di Wine dove i servizi non ricevono il SID SYSTEM (S-1-5-18). Potrebbe essere corretto a monte in una futura release di Wine.
Crediti
Reverse engineering e shim Wine: @baptisterajaut.
- @ayozetr — ha rintracciato il blocco "si registra ma mai pronto" fino a una
ricerca DNS inversa di un indirizzo privato bucato dal resolver dell'host, l'ha provata con un
repro a libc nudo dopo che quattro teorie sbagliate erano state scartate (inclusa la mia), e ha scritto
l'originale di
src/rvpn_dnsfix.cecontrib/run-in-netns.sh. - @gringoestrangeiro — lavoro sulla stabilità Linux: filtri dei pacchetti, cache ARP, recupero dai crash, modalità headless e datacenter.
- @yuxiaole-bili — ha scoperto che l'SCM di Wine avvia automaticamente una seconda istanza del servizio senza hook che combatte con quella iniettata per l'adapter.
- @D1spell-tech, @Milkiway13 e tutti quelli che hanno incollato un blocco di diagnostica completo — due host indipendenti sono ciò che rende un bug trovabile.
Licenza
GPL-3.0. Vedi LICENSE.
Nello spirito, questo codice è pubblico dominio — fai quello che vuoi con esso. La GPL è qui come rete di sicurezza legale: protegge esplicitamente il reverse engineering per l'interoperabilità, che è ciò che questo progetto fa. Cintura e bretelle.
Radmin VPN è software proprietario di Famatech Corp. Questo progetto fornisce solo strumenti di interoperabilità — nessun codice Famatech è incluso o distribuito.