README: update roadmap, document Linux+Windows builds, reflect first-packet tunnelUp signal
This commit is contained in:
parent
967539de5d
commit
e03c978d85
1 changed files with 106 additions and 91 deletions
197
README.md
197
README.md
|
|
@ -1,4 +1,4 @@
|
||||||
# 🐉 DragonMoonlight
|
# DragonMoonlight
|
||||||
|
|
||||||
A fork of [moonlight-qt](https://github.com/moonlight-stream/moonlight-qt) with native [DragonRelay](https://forge.wilddragon.net/zgaetano/dragonrelay) integration and an embedded WireGuard client.
|
A fork of [moonlight-qt](https://github.com/moonlight-stream/moonlight-qt) with native [DragonRelay](https://forge.wilddragon.net/zgaetano/dragonrelay) integration and an embedded WireGuard client.
|
||||||
|
|
||||||
|
|
@ -15,8 +15,10 @@ Instead of managing a separate VPN app, DragonMoonlight authenticates against yo
|
||||||
│ ▼ │ │ │
|
│ ▼ │ │ │
|
||||||
│ TunnelManager │ │ wg0 interface │
|
│ TunnelManager │ │ wg0 interface │
|
||||||
│ ├─ boringtun (WireGuard/Rust) │◄═════►│ 10.99.0.1 │
|
│ ├─ boringtun (WireGuard/Rust) │◄═════►│ 10.99.0.1 │
|
||||||
│ └─ utun (macOS, no root*) │ WG │ │
|
│ ├─ utun (macOS, no root*) │ WG │ │
|
||||||
│ │ │ mDNS → Apollo/Artemis hosts │
|
│ ├─ Wintun (Windows, Admin) │ │ Hosts registered by Artemis │
|
||||||
|
│ └─ /dev/net/tun (Linux, CAP) │ │ via /api/host/register │
|
||||||
|
│ │ │ │
|
||||||
│ DragonRelayView.qml │ └──────────────────────────────┘
|
│ DragonRelayView.qml │ └──────────────────────────────┘
|
||||||
│ (host list, stream button) │
|
│ (host list, stream button) │
|
||||||
└─────────────────────────────────┘
|
└─────────────────────────────────┘
|
||||||
|
|
@ -28,92 +30,97 @@ Instead of managing a separate VPN app, DragonMoonlight authenticates against yo
|
||||||
|
|
||||||
```
|
```
|
||||||
app/vpn/
|
app/vpn/
|
||||||
├── boringtun_ffi.h C ABI for the boringtun Rust library
|
├── boringtun_ffi.h C ABI for the boringtun Rust library
|
||||||
├── wireguardconfig.h/.cpp WireGuard .conf parser
|
├── wireguardconfig.h/.cpp WireGuard .conf parser
|
||||||
├── tunnelmanager.h Cross-platform tunnel interface
|
├── tunnelmanager.h Cross-platform tunnel interface
|
||||||
├── tunnelmanager_mac.mm macOS implementation (utun + boringtun)
|
├── tunnelmanager_mac.mm macOS implementation (utun + boringtun)
|
||||||
├── relayclient.h/.cpp HTTP client for the DragonRelay API
|
├── tunnelmanager_win.cpp Windows implementation (Wintun + boringtun)
|
||||||
└── CMakeLists_vpn.cmake Build system additions
|
├── tunnelmanager_linux.cpp Linux implementation (/dev/net/tun + boringtun)
|
||||||
|
├── wintun.h Wintun dynamic loader (Windows)
|
||||||
|
├── relayclient.h/.cpp HTTP client for the DragonRelay API
|
||||||
|
├── dragonrelaybackend.h/.cpp QObject bridge: RelayClient + TunnelManager → QML
|
||||||
|
└── CMakeLists_vpn.cmake Build system additions
|
||||||
|
|
||||||
app/gui/
|
app/gui/
|
||||||
└── DragonRelayView.qml Connect / host-list UI page
|
├── DragonRelayView.qml Connect / host-list UI page
|
||||||
|
└── DragonDisplayPicker.qml Multi-display selection modal
|
||||||
|
|
||||||
|
app/
|
||||||
|
├── DragonMoonlight.manifest Windows UAC manifest (requireAdministrator)
|
||||||
|
├── main.cpp Entry point with QML engine + dragonRelay backend
|
||||||
|
└── assets/ WildDragon logo + qrc
|
||||||
|
|
||||||
scripts/
|
scripts/
|
||||||
└── build-boringtun.sh Compiles boringtun as a static library
|
├── build-boringtun.sh Compiles boringtun for Linux/macOS
|
||||||
|
├── build-boringtun-win.ps1 Compiles boringtun for Windows
|
||||||
|
├── build-installer-mac.sh macOS .dmg + .pkg installer
|
||||||
|
├── build-installer-win.ps1 Windows .exe installer (Inno Setup)
|
||||||
|
└── DragonMoonlight.iss Inno Setup script
|
||||||
|
|
||||||
deps/boringtun/ Created by build-boringtun.sh (git-ignored)
|
package/
|
||||||
|
├── mac/ macOS code-signing entitlements + DMG art
|
||||||
|
└── win/ Windows pre-install elevation/version checks
|
||||||
|
|
||||||
|
deps/boringtun/ Created by build scripts (git-ignored)
|
||||||
```
|
```
|
||||||
|
|
||||||
## Building (macOS)
|
## Building
|
||||||
|
|
||||||
### 1. Prerequisites
|
### macOS
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Xcode Command Line Tools
|
|
||||||
xcode-select --install
|
|
||||||
|
|
||||||
# Homebrew
|
|
||||||
brew install qt@6 cmake rustup
|
brew install qt@6 cmake rustup
|
||||||
|
rustup-init && rustup target add aarch64-apple-darwin x86_64-apple-darwin
|
||||||
|
|
||||||
# Rust toolchain
|
git clone https://forge.wilddragon.net/zgaetano/dragonmoonlight && cd dragonmoonlight
|
||||||
rustup-init
|
git remote add upstream https://github.com/moonlight-stream/moonlight-qt.git
|
||||||
rustup target add aarch64-apple-darwin x86_64-apple-darwin
|
git fetch upstream && git merge upstream/master --allow-unrelated-histories
|
||||||
|
git submodule update --init --recursive
|
||||||
|
|
||||||
|
bash scripts/build-boringtun.sh --universal
|
||||||
|
|
||||||
|
mkdir build && cd build
|
||||||
|
cmake .. -DCMAKE_PREFIX_PATH="$(brew --prefix qt@6)"
|
||||||
|
make -j$(sysctl -n hw.logicalcpu)
|
||||||
```
|
```
|
||||||
|
|
||||||
### 2. Clone upstream moonlight-qt into this repo
|
### Windows
|
||||||
|
|
||||||
This repo holds only the DragonMoonlight additions. You need to merge with upstream:
|
```powershell
|
||||||
|
# Prerequisites: Visual Studio Build Tools 2019+, Rust, CMake, Qt 6, Inno Setup
|
||||||
```bash
|
|
||||||
git clone https://forge.wilddragon.net/zgaetano/dragonmoonlight
|
git clone https://forge.wilddragon.net/zgaetano/dragonmoonlight
|
||||||
cd dragonmoonlight
|
cd dragonmoonlight
|
||||||
|
|
||||||
# Add upstream as a remote and merge
|
|
||||||
git remote add upstream https://github.com/moonlight-stream/moonlight-qt.git
|
git remote add upstream https://github.com/moonlight-stream/moonlight-qt.git
|
||||||
git fetch upstream
|
git fetch upstream
|
||||||
git merge upstream/master --allow-unrelated-histories
|
git merge upstream/master --allow-unrelated-histories
|
||||||
git submodule update --init --recursive
|
git submodule update --init --recursive
|
||||||
|
|
||||||
|
pwsh scripts/build-boringtun-win.ps1
|
||||||
|
|
||||||
|
cmake -B build -A x64 -DCMAKE_BUILD_TYPE=Release
|
||||||
|
cmake --build build --config Release
|
||||||
|
|
||||||
|
# Optional: build the .exe installer
|
||||||
|
pwsh scripts/build-installer-win.ps1
|
||||||
```
|
```
|
||||||
|
|
||||||
### 3. Build boringtun
|
`wintun.dll` (x64) must sit next to `DragonMoonlight.exe` at run time. The
|
||||||
|
installer script downloads it automatically; for ad-hoc builds, fetch it from
|
||||||
|
<https://www.wintun.net> and copy it to the build output directory.
|
||||||
|
|
||||||
|
### Linux
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
bash scripts/build-boringtun.sh --universal
|
sudo apt install qt6-base-dev qt6-declarative-dev qml6-module-qtquick \
|
||||||
# Produces: deps/boringtun/libboringtun.a (universal arm64+x86_64)
|
cmake build-essential libcurl4-openssl-dev rustup
|
||||||
```
|
|
||||||
|
|
||||||
### 4. Integrate the VPN CMake snippet
|
bash scripts/build-boringtun.sh
|
||||||
|
|
||||||
In moonlight-qt's root `CMakeLists.txt`, add **after** the main target is defined:
|
cmake -B build -DCMAKE_BUILD_TYPE=Release
|
||||||
|
cmake --build build -j
|
||||||
|
|
||||||
```cmake
|
# Grant net-admin so the binary can open /dev/net/tun without being root:
|
||||||
include(app/vpn/CMakeLists_vpn.cmake)
|
sudo setcap cap_net_admin+ep ./build/dragonmoonlight
|
||||||
```
|
|
||||||
|
|
||||||
### 5. Register DragonRelayBackend with QML
|
|
||||||
|
|
||||||
In `app/main.cpp` (or wherever the QML engine is set up), add:
|
|
||||||
|
|
||||||
```cpp
|
|
||||||
#include "dragonrelaybackend.h" // thin QObject wrapping RelayClient + TunnelManager
|
|
||||||
|
|
||||||
// Before engine.load():
|
|
||||||
DragonRelayBackend relayBackend;
|
|
||||||
engine.rootContext()->setContextProperty("dragonRelay", &relayBackend);
|
|
||||||
```
|
|
||||||
|
|
||||||
`DragonRelayBackend` is the next class to write — it wires `RelayClient` ↔ `TunnelManager` ↔ QML.
|
|
||||||
|
|
||||||
### 6. Add the view to the navigation stack
|
|
||||||
|
|
||||||
In `app/gui/main.qml` or the computer browser stack, push `DragonRelayView` alongside the normal `PcView`.
|
|
||||||
|
|
||||||
### 7. Build
|
|
||||||
|
|
||||||
```bash
|
|
||||||
mkdir build && cd build
|
|
||||||
cmake .. -DCMAKE_PREFIX_PATH="$(brew --prefix qt@6)"
|
|
||||||
make -j$(sysctl -n hw.logicalcpu)
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## How it works (connection flow)
|
## How it works (connection flow)
|
||||||
|
|
@ -128,21 +135,23 @@ RelayClient.login(url, user, pass)
|
||||||
RelayClient.provisionVPN(deviceName)
|
RelayClient.provisionVPN(deviceName)
|
||||||
│ POST /api/vpn/peer → {id, conf}
|
│ POST /api/vpn/peer → {id, conf}
|
||||||
▼
|
▼
|
||||||
WireGuardConfig.fromConf(conf)
|
WireGuardConfig::fromConf(conf)
|
||||||
│
|
│
|
||||||
▼
|
▼
|
||||||
TunnelManager.start(cfg)
|
TunnelManager.start(cfg) (mac/win/linux platform impl)
|
||||||
├─ new_tunnel() via boringtun FFI
|
├─ new_tunnel() via boringtun FFI
|
||||||
├─ openUtun() → utunN fd (no root)
|
├─ Open utun/Wintun/tun device
|
||||||
├─ UDP socket → server endpoint
|
├─ UDP socket → server endpoint
|
||||||
├─ configureInterface() → osascript admin dialog (once per session)
|
├─ configureInterface() → routes
|
||||||
│ ifconfig + route add for 10.99.0.0/24
|
|
||||||
└─ I/O threads (tunToUdp, udpToTun, ticker)
|
└─ I/O threads (tunToUdp, udpToTun, ticker)
|
||||||
│
|
│
|
||||||
▼
|
▼
|
||||||
WireGuard handshake completes
|
WireGuard handshake completes
|
||||||
│
|
│
|
||||||
▼
|
▼
|
||||||
|
udpToTunThread emits tunnelUp() on first decrypted packet
|
||||||
|
│
|
||||||
|
▼
|
||||||
RelayClient.fetchHosts() → GET /api/hosts
|
RelayClient.fetchHosts() → GET /api/hosts
|
||||||
│
|
│
|
||||||
▼
|
▼
|
||||||
|
|
@ -152,38 +161,44 @@ TunnelManager.start(cfg)
|
||||||
│
|
│
|
||||||
▼
|
▼
|
||||||
dragonRelay.streamHost(ip, "Desktop")
|
dragonRelay.streamHost(ip, "Desktop")
|
||||||
(launches Moonlight streaming session)
|
(launches Moonlight streaming session via QProcess)
|
||||||
```
|
```
|
||||||
|
|
||||||
## Privilege model
|
## Privilege model
|
||||||
|
|
||||||
| Operation | Root / Admin? |
|
| Operation | macOS | Windows | Linux |
|
||||||
|---|---|
|
|-----------|-------|---------|-------|
|
||||||
| Open utun device | No |
|
| Open TUN device | none | Admin (Wintun driver) | `CAP_NET_ADMIN` |
|
||||||
| `ifconfig utunN <ip> up` | Yes — one-time macOS auth dialog |
|
| Configure address + routes | one osascript dialog | none (IP Helper API) | `CAP_NET_ADMIN` |
|
||||||
| `route add -net 10.99.0.0/24 -interface utunN` | Yes — same dialog, batched |
|
| Streaming (RTSP/UDP) | none | none | none |
|
||||||
| Streaming (RTSP/UDP to Apollo host) | No |
|
|
||||||
|
|
||||||
The admin dialog appears once when the VPN first connects. Subsequent reconnects in the same session reuse the saved original-gateway and only need the dialog again if the interface was torn down.
|
The macOS dialog appears once when the VPN first connects; subsequent reconnects
|
||||||
|
in the same session reuse the saved original-gateway and only need the dialog
|
||||||
|
again if the interface was torn down.
|
||||||
|
|
||||||
**Production path:** Replace the `osascript` approach with a signed, sandboxed SMJobBless privileged helper or a NetworkExtension PacketTunnelProvider entitlement (requires Apple developer approval).
|
**Production path (macOS):** Replace the `osascript` approach with a signed,
|
||||||
|
sandboxed SMJobBless privileged helper or a NetworkExtension PacketTunnelProvider
|
||||||
## DragonRelayBackend (next step)
|
entitlement (requires Apple developer approval).
|
||||||
|
|
||||||
The QML view is wired to a `dragonRelay` context property. The next file to write is `app/vpn/dragonrelaybackend.h/.cpp` — a `QObject` that:
|
|
||||||
|
|
||||||
- Owns `RelayClient` and `TunnelManager`
|
|
||||||
- Exposes `Q_PROPERTY` values (`status`, `statusText`, `hosts`) to QML
|
|
||||||
- Has `Q_INVOKABLE` methods: `connectRelay()`, `disconnectRelay()`, `streamHost()`
|
|
||||||
- Translates `RelayClient` and `TunnelManager` signals into QML-visible state changes
|
|
||||||
|
|
||||||
## Roadmap
|
## Roadmap
|
||||||
|
|
||||||
- [ ] `DragonRelayBackend` C++ ↔ QML bridge
|
- [x] `DragonRelayBackend` C++ ↔ QML bridge
|
||||||
- [ ] Integrate `DragonRelayView` into upstream `PcView.qml` navigation
|
- [x] `DragonRelayView` is the navigation entry point exposed to QML
|
||||||
- [ ] Windows support (`tunnelmanager_win.cpp` using Wintun)
|
- [x] Windows support (`tunnelmanager_win.cpp` using Wintun)
|
||||||
- [ ] Linux support (`tunnelmanager_linux.cpp` using kernel WireGuard)
|
- [x] Linux support (`tunnelmanager_linux.cpp` using boringtun userspace + `/dev/net/tun`)
|
||||||
|
- [x] `tunnelUp()` signal from first received packet (with 1500 ms fallback)
|
||||||
|
- [x] Multi-monitor / display selection (Sunshine API integration via DragonDisplayPicker)
|
||||||
- [ ] Replace `osascript` with SMJobBless privileged helper on macOS
|
- [ ] Replace `osascript` with SMJobBless privileged helper on macOS
|
||||||
- [ ] Replace plain-text password storage with system keychain (QKeychain)
|
- [ ] Replace plain-text password storage with system keychain (QKeychain)
|
||||||
- [ ] `connected()` signal from first received packet rather than a fixed timer
|
- [ ] Auto-reconnect on network change
|
||||||
- [ ] Multi-monitor / display selection (Sunshine API integration)
|
|
||||||
|
## Notes for upstream maintainers
|
||||||
|
|
||||||
|
- `app/main.cpp` is the entry point; it instantiates a `DragonRelayBackend` and
|
||||||
|
registers it as the `dragonRelay` context property before loading `main.qml`.
|
||||||
|
- All Dragon-specific files live under `app/vpn/`, `app/gui/Dragon*`, and
|
||||||
|
`scripts/`. Upstream `app/main.qml` is unmodified — DragonRelayView is loaded
|
||||||
|
on demand by user action in the existing PcView navigation stack.
|
||||||
|
- The boringtun FFI header is identical to the one used by Artemis; both
|
||||||
|
projects link the same boringtun build artifact and the FFI surface must
|
||||||
|
stay in lock-step.
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue