
Wine을 통해 Linux에서 Radmin VPN 실행 — 커스텀 드라이버, TAP 브리지, 패킷 손실 제로
Wine을 통해 Radmin VPN을 Linux에서 실행합니다. VPN 네트워크에 가입하고, 피어를 확인하고, 게임을 플레이하세요 — Windows VM 없이도 가능합니다.
저는 VM보다 쉽기 때문에 이것을 만들지 않았습니다. VM보다 쉽다고 생각했기 때문에 만들었습니다.
AI 지원 코드. 인간과 Claude(Anthropic)가 협력하여 구축했습니다. 드라이버, 훅, 브리지는 Ghidra를 사용한 Radmin VPN의 문서화되지 않은 드라이버 프로토콜에 대한 광범위한 AI 지원 리버스 엔지니어링으로 작성되었습니다. 이것은 작동하지만, 어떤 보장도 없습니다. Famatech와 관련이 없습니다. Radmin VPN은 독점 소프트웨어입니다 — radmin-vpn.com에서 직접 다운로드하세요. 사용에 따른 책임은 본인에게 있습니다.
Radmin VPN의 Windows 서비스는 가상 네트워크 어댑터를 위해 NDIS 미니포트 드라이버와 통신합니다. Wine은 NDIS를 지원하지 않으므로, Linux TAP 장치로 브리지하는 자체 구현으로 드라이버를 대체합니다. 훅 DLL이 Wine 호환성 문제(어댑터 이름 지정, 레지스트리 권한)를 처리합니다. 그 결과 Wine에서 기본적으로 실행되는 완전한 기능의 Radmin VPN 클라이언트가 탄생합니다.
Linux 앱 ← TAP (radminvpn0) ← tap_bridge ← FIFO ← rvpnnetmp.sys (Wine 드라이버) ← RvControlSvc.exe
최신 릴리스에서 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로 직접 지정). 진행 상황이 표시되는 터미널이 열리고, TAP 설정을 위해 sudo 비밀번호 프롬프트가 한 번 표시됩니다.
영구 상태(wineprefix, MAC, 로그)는 ~/.local/share/radmin-vpn-linux/에 저장됩니다.
Radmin이 스스로 종료되나요? 자체 업데이터가 실행 중인 prefix 안에 새 빌드를 설치하고 있습니다. 대신 통제된 방식으로 업그레이드를 수행하세요 — prefix와 Radmin ID가 유지됩니다:
./RadminVPN-Linux-x86_64.AppImage --update그런 다음 Radmin 설정에서 "자동 업데이트"를 꺼서 다시 시도하지 않도록 하세요. 자세한 내용은 Radmin 자체 자동 업데이터를 참조하세요.
i686-w64-mingw32-gcc, x86_64-w64-mingw32-gcc) — 소스 빌드용modprobe tun으로 확인lib.sh의 RADMIN_VERSION 한 곳에 고정되어 있습니다 (현재 2.1.4951.1; 2.0.4899.9도 작동). Radmin VPN 1.4는 지원되지 않습니다 — 등록되고 어댑터가 열리지만 Wine 셰드 아래에서 연결이 완료되지 않아 GUI가 "연결 중..."에서 멈춥니다.sudo pacman -S wine mingw-w64-gcc
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
# https://www.radmin-vpn.com/에서 Radmin VPN 설치 프로그램 다운로드
./run.sh --installer ~/Downloads/Radmin_VPN_*.exe
이후 실행에서는 다음만 하면 됩니다:
./run.sh
Radmin의 GUI는 새 빌드를 다운로드하여 실행 중인 prefix 안에서 설치 프로그램을 실행할 수 있으며,
이로 인해 GUI가 종료되고 실행 중인 서비스에 오류가 발생합니다 (GUI 로그에는 AppData\\Local\\Temp 아래의
설치 프로그램이 표시됨). 두 가지 방어책이 있습니다: 런처가 현재 검증된 빌드를 제공하므로 업데이터가
밀어넣을 것이 없고, 종료된 GUI는 더 이상 터널을 함께 끌어내리지 않습니다 — 한 번 재시작된 후
VPN은 헤드리스로 계속 실행됩니다. 의도적으로 업그레이드하려면 ./run.sh --update를 사용하세요.
이 명령은 먼저 모든 것을 중지합니다. GUI 설정에서 "자동 업데이트"를 끄면 경쟁 조건을 완전히 피할 수 있습니다.
--filter-ui와 --fix-chat는 모두 선택 사항입니다. 필터 UI에는 rvpn_filter_ui
바이너리(make로 빌드)가 필요하고, 채팅 수정에는 patch_qwindows_font.py와 Python 3 인터프리터가 필요합니다.
두 개의 추가 런처가 로컬 데스크톱 없이 Radmin VPN을 실행합니다 — VPS 또는 데이터센터 호스트용입니다. 둘 다 run.sh와 정확히 동일하게 설치 및 구성됩니다 (동일한 wineprefix, 동일한 --installer 첫 실행 흐름, 동일한 TAP 브리지); GUI에 도달하는 방식만 다릅니다.
run_datacenter.sh — 브라우저를 통한 GUI가상 디스플레이(Xvfb)에서 실제 Radmin GUI를 실행하고 VNC + noVNC를 통해 제공하므로, 브라우저에서 네트워크를 구성한 후 계속 실행할 수 있습니다.
sudo apt install -y xvfb x11vnc websockify novnc # 또는: make install-datacenter-deps
./run_datacenter.sh --installer ~/Downloads/Radmin_VPN_*.exe
기본적으로 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와 함께 전달하세요 — 그렇지 않으면 웹 포트에 도달하는 모든 사람이 인증되지 않은 루트 권한 데스크톱에 접속하게 됩니다. 스크립트는 비밀번호 없이 공개 바인딩 시 큰 경고를 출력합니다.
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 — 훅 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 — Radmin의 실제 NDIS 드라이버 설치 프로그램을 대체하는 no-op 스텁 (이슈 #12)build/tap_bridge — 네이티브 Linux TAP 브리지build/rvpn_dnsfix.so — 네이티브 LD_PRELOAD 셰드, 서비스에만 사전 로드됨build/rvpn_reuseport.so — 네이티브 LD_PRELOAD 셰드, wineserver에 사전 로드됨build/rvpn_filter_ui — 선택적 GTK4 패킷 필터 UI (--filter-ui)make
./packaging/build-appimage.sh # → packaging/dist/RadminVPN-Linux-x86_64.AppImage
첫 실행 시 Kron4ek Wine-Staging amd64-wow64 빌드(~100MB)와 appimagetool을 다운로드하고, 둘 다 packaging/dist/에 캐시합니다. curl과 ImageMagick(convert)이 필요합니다.
run.sh가 하는 일/VERYSILENT), 실제 NDIS 드라이버 제거(Wine과 호환되지 않음), 사용자 지정 드라이버 등록wineprefix는 ./wineprefix/(소스 실행) 또는 ~/.local/share/radmin-vpn-linux/wineprefix/(AppImage)에 저장됩니다. 영구 MAC 주소는 첫 실행 시 생성되어 wineprefix에 저장됩니다.
GUI가 "어댑터 대기 중"에서 멈춤: 드라이버가 로드되지 않고 있습니다. /tmp/radmin_driver.log가 존재하고 내용이 있는지 확인하세요. 비어 있으면 드라이버 서비스 등록이 누락된 것일 수 있습니다 — wineprefix를 삭제하고 다시 실행하세요.
등록되었지만 "준비" 상태가 되지 않음: 서비스가 Registered as #…에 도달하고 거기서 멈춥니다. 두 가지 알려진 원인이 있으며, 둘 다 시간 초과 시 출력되는 진단 블록에서 보고됩니다. (a) 자체 라우팅 정책이 있는 투명 프록시 또는 터널(sing-box, clash/mihomo, v2ray 등)이 아웃바운드 연결을 가로채는 경우 — 이러한 스택은 TCP 핸드셰이크에 로컬로 응답하므로 소켓은 ESTABLISHED로 읽히지만 아무것도 중계되지 않습니다. 해당 경로에서 26.0.0.0/8을 제외하고, 직접 도달할 수 있다면 *.radminte.com도 제외하세요. (b) 개인 주소의 역방향 조회를 블랙홀 처리하는 해석기(172.17.0.1의 docker0이 일반적인 트리거). rvpn_dnsfix.so가 이를 처리하지만 64비트 셰드입니다: old-wow64로 빌드된 시스템 Wine은 이를 무시합니다. 해결 방법 — 주소에 대한 줄을 /etc/hosts에 추가하거나 contrib/run-in-netns.sh를 사용하세요 (서비스를 "준비" 상태로 만들지만 VPN을 네임스페이스 안에 유지합니다: 호스트 애플리케이션은 26.0.0.0/8에 도달할 수 없으며, 헤더의 경고를 읽으세요).
Radmin 실행 후 다른 Wine 앱이 깨짐 (unimplemented function ndis.sys.NdisInitializeReadWriteLock): 1.0.0까지의 버전은 Wine의 winemenubuilder.exe가 실행되도록 허용했으며, 이는 호스트의 Windows 파일 연결(.exe, .msi, .lnk, .reg, .chm, …)을 우리 prefix에서 열도록 다시 작성합니다. 그러면 다른 Windows 프로그램이 Radmin prefix 안에서 시작되고, Radmin의 실제 NDIS 미니포트(RvNetMP60)가 여전히 등록되어 있으면 모든 프로그램이 해당 ndis 스텁에서 중단됩니다. 1.0.1은 모든 곳에서 winemenubuilder를 비활성화하고, Radmin prefix에 대해 작성된 항목을 제거하며, system.reg에서 RvNetMP60을 오프라인으로 제거합니다 — 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): 1.1.0보다 오래된 빌드의 Radmin 2.1입니다. 서비스 로그는 피어 연결 직전까지 정상으로 보이다가 해당 코드로 반복 실패하고 마지막에 node offline으로 포기합니다. 두 가지 독립적인 Wine 격차가 있으며, 둘 다 1.1.0에서 수정되었고 둘 다 위의 rvpn_reuseport.so 및 adapter_hook.dll 행에서 설명되었습니다: Wine은 TCP SO_REUSEADDR에 대한 Unix 수준 옵션을 설정하지 않으므로 2.1의 포트 재사용 NAT 트래버설이 모든 피어 연결에서 WSAEACCES를 얻습니다; 그리고 Wine의 advapi32에는 네 개의 perflib 내보내기가 누락되어 있어 2.1은 피어 핸드셰이크로 null 페이로드를 보냅니다. 코드 자체에는 정보가 없다는 점에 유의하세요 — 오류 계단식의 끝에서 발생하는 일반적인 포기이므로 하위 시스템을 읽어내려고 하지 마세요. 해결책은 이 프로젝트를 1.1.0으로 업데이트하는 것입니다; Radmin 쪽에서는 변경할 것이 없습니다.
서비스가 즉시 종료됨: /tmp/radmin_service.log에서 Wine 오류를 확인하세요. 일반적인 원인: 다른 Wine 버전의 오래된 wineprefix. ./wineprefix/를 삭제하고 다시 실행하세요.
피어 하나로 0% 패킷 손실, 여러 피어로 높은 손실: 이것이 원래 버그였습니다 — 드라이버의 MAC 기반 프레임 라우팅으로 수정되었습니다. 최신 빌드를 사용하고 있는지 확인하세요.
첫 ping이 느림 (~1초): 최신 버전은 드라이버가 보는 모든 IP 패킷에 대해 MAC 주소를 캐시합니다. 대상 IP가 드라이버 실행 중에 패킷을 하나 이상 보냈다면 MAC이 이미 캐시되어 ARP 지연이 없습니다. 완전히 조용한 피어(패킷을 보낸 적이 없는)만 초기 ARP 해석이 필요하며, 이는 약 1초가 추가됩니다.
LAN 게임이 다른 피어를 볼 수 없음 / "자동 검색"이 깨짐: 대부분의 LAN 게임은 브로드캐스트 프로브(UDP to 255.255.255.255) 또는 멀티캐스트(224.0.0.0/4)로 서로를 검색합니다. Windows에서는 Radmin TAP 드라이버가 해당 흐름에 대한 기본 인터페이스로 자신을 광고합니다; 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
부작용: 물리적 LAN의 mDNS / Bonjour / SSDP(Chromecast, AirPrint, Sonos, 스마트 TV 등)는 VPN이 켜져 있는 동안 VPN을 통해 전달됩니다. 로컬 LAN 검색과 Radmin을 병렬로 사용해야 한다면 --no-broadcast-routes로 실행하세요:
./run.sh --no-broadcast-routes
경로는 TAP 장치에 범위가 지정되므로 run.sh가 종료 시 장치를 내릴 때 자동으로 제거됩니다.
/tmp/의 공유 FIFO)26.0.0.0/8 온링크 경로는 실행 중 시스템 전체에 영향을 줍니다 (종료 시 정리됨)255.255.255.255/32) 및 멀티캐스트(224.0.0.0/4) 경로는 VPN으로 전달됩니다 — 로컬 LAN mDNS / SSDP를 병렬로 사용해야 한다면 --no-broadcast-routes로 비활성화하세요Wine 버그 우회. RegSetKeySecurity 훅은 서비스가 SYSTEM SID(S-1-5-18)를 받지 못하는 알려진 Wine 제한을 우회합니다. 이는 향후 Wine 릴리스에서 업스트림으로 수정될 수 있습니다.
리버스 엔지니어링 및 Wine 셰드: @baptisterajaut.
src/rvpn_dnsfix.c와 contrib/run-in-netns.sh의 원본을 작성했습니다.GPL-3.0. LICENSE를 참조하세요.
정신적으로 이 코드는 퍼블릭 도메인입니다 — 원하는 대로 사용하세요. GPL은 법적 안전망으로 여기에 있습니다: 상호운용성을 위한 리버스 엔지니어링을 명시적으로 보호하며, 이것이 이 프로젝트가 하는 일입니다. 이중 안전장치입니다.
Radmin VPN은 Famatech Corp.의 독점 소프트웨어입니다. 이 프로젝트는 상호운용성 도구만 제공합니다 — Famatech 코드는 포함되거나 배포되지 않습니다.
| 플래그 | 설명 |
|---|
--installer <path> | Radmin_VPN_*.exe 설치 프로그램 경로 (첫 실행 시에만). |
--no-ui | Radmin GUI를 실행하지 않고 서비스만 실행. |
--update | Radmin을 고정된 버전으로 제자리에서 업그레이드. prefix를 유지하므로 Famatech에 등록된 RID가 유지됩니다. |
--no-broadcast-routes | 브로드캐스트/멀티캐스트 → TAP 경로를 추가하지 않음. |
--filter-ui | 선택적 GTK4 패킷 필터 UI 실행 (기본적으로 꺼짐). |
--fix-chat | Qt의 qwindows.dll을 패치하여 Wine에서 채팅 창 충돌 수정 (기본적으로 꺼짐). |
| 플래그 | 기본값 | 설명 |
|---|
--vnc-port <n> | 5900 | x11vnc 서버 포트. |
--web-port <n> | 6080 | noVNC 웹 엔드포인트 포트. |
--vnc-password <pw> | (없음) | VNC / 웹 세션 비밀번호. |
--web-bind <addr> | 127.0.0.1 | noVNC가 수신하는 주소. |
| 구성 요소 | 설명 |
|---|
rvpnnetmp.sys | Wine 커널 드라이버. Radmin NDIS 미니포트를 에뮬레이션합니다. IOCTL(VERSION, STATUS, SETUP, PEERMAC), TLV 프레임 인코딩/디코딩, 중첩 I/O용 IRP 큐, 다중 피어 지원을 위한 MAC 기반 프레임 라우팅을 처리합니다. |
adapter_hook.dll | RvControlSvc.exe와 함께 로드되는 동반 DLL. IAT 훅: TAP 어댑터 이름을 Radmin이 기대하는 이름으로 변경, 서비스에 SYSTEM SID가 없는 Wine SCM 버그를 우회하기 위해 RegSetKeySecurity를 no-op 처리, Wine의 advapi32가 내보내지 않는 네 개의 Perf{Increment,Decrement}ULong{,Long}CounterValue 조회에 응답. 마지막 것은 미용상의 문제가 아닙니다: Radmin 2.1은 일곱 개의 perflib 진입점을 전부 아니면 전무 방식의 계단식으로 해석한 다음, 결과적인 피어별 카운터 객체를 피어 핸드셰이크의 페이로드로 전달합니다 — 따라서 네 개의 누락된 원격 측정 내보내기가 전체 데이터 경로를 무너뜨립니다 (이슈 #24, docs/wine-perflib.md). |
tap_bridge | 네이티브 Linux 바이너리. TAP 장치와 Wine 드라이버가 읽고 쓰는 명명된 파이프(FIFO) 사이에서 이더넷 프레임을 중계합니다. |
netsh.exe / netsh64.exe | Wine의 netsh 스텁을 대체합니다 (SysWOW64의 32비트, System32의 64비트). Windows netsh interface ip 명령을 파일 기반 릴레이를 통해 Linux ip addr/ip link 명령으로 변환하고, 주소가 루트 릴레이에 도달하기 전에 검증합니다. |
rvpn_launcher.exe | CreateRemoteThread + LoadLibrary를 통해 adapter_hook.dll을 Radmin 서비스 프로세스에 주입합니다. |
drvinst.exe | Radmin의 실제 NDIS 드라이버 설치 프로그램을 대체하는 no-op 스텁. Radmin은 런타임에 이를 실행하여 NetMP60_1_1_64.sys를 로드하는데, 이는 NdisInitializeReadWriteLock을 통해 Wine 11.x를 중단시킵니다 (이슈 #12); 우리 드라이버가 이미 해당 어댑터를 대체하므로 실제 드라이버는 절대 로드되어서는 안 됩니다. |
rvpn_dnsfix.so | 네이티브 LD_PRELOAD 셰드, 서비스 실행에만 주입됩니다. glibc 계층에서 개인 IPv4/IPv6의 역방향 DNS(getnameinfo/gethostbyaddr)를 단락시킵니다. Radmin은 수집한 모든 로컬 후보 주소를 PTR 해석합니다; 해석기가 RFC1918 PTR 쿼리를 블랙홀 처리하는 호스트에서는 수 분 동안 멈추고 서비스가 등록되지만 준비 상태가 되지 않습니다 (이슈 #16). 조회는 Wine의 Unix 쪽에서 발행되므로 adapter_hook.dll 내부의 어떤 훅도 도달할 수 없습니다. |
rvpn_reuseport.so | 네이티브 LD_PRELOAD 셰드, wineserver에 사전 로드됩니다 (서비스가 아님 — Unix 소켓은 wineserver에 속함). 생성 시 모든 TCP 소켓에 SO_REUSEPORT를 설정합니다. Radmin 2.1은 TCP 포트 재사용 NAT 트래버설을 수행합니다: 리스너를 uplink:PORT에 바인딩하고 해당 매핑을 광고한 다음, 아웃바운드 피어 소켓을 SO_REUSEADDR로 동일한 로컬 포트에 바인딩합니다 — Windows에서는 허용됩니다. Wine은 해당 요청을 TCP에 대한 Unix 수준 옵션으로 변환하지 않으므로(server/sock.c, SO_REUSEPORT는 __APPLE__ 전용으로 컴파일됨), 커널이 두 번째 바인딩을 거부하고 클라이언트는 모든 피어 연결에서 WSAEACCES를 봅니다 (이슈 #24). Wineserver 자체의 충돌 기록은 계속 실행되므로 Windows가 거부할 바인딩은 여전히 거부됩니다. |
rvpn_filter_ui | 브리지를 통과하는 패킷을 검사하고 필터링하는 선택적 GTK4 UI. 기본적으로 꺼져 있으며 --filter-ui로 실행합니다. |