Files
RemoteDesk/transport/hysteria2-agent/README.md
T
曾志威 19a8e03a83
ci / rust (push) Canceled after 0s
ci / web (push) Canceled after 0s
ci / package-preview (push) Canceled after 0s
ci / package-installer (push) Canceled after 0s
ci / linux-agent (push) Canceled after 0s
ci / edge-service (push) Canceled after 0s
ci / coturn-pop (push) Canceled after 0s
ci / package-windows-host (push) Canceled after 0s
Document all-Rust migration and extend native media stack
2026-08-14 14:31:57 +08:00

5.4 KiB

RemoteDesk Hysteria2 transport

This helper uses the official github.com/apernet/hysteria/core/v2 Go server. It exposes only authenticated Hysteria2 QUIC/UDP sessions. The core's TCP proxy hook is deliberately rejected, so the public transport never falls back to TCP or SOCKS5. Authenticated datagrams are delivered to the local Agent UDP endpoint (127.0.0.1:39502 by default).

Build with go build -buildvcs=false -trimpath -ldflags "-s -w" -o remotedesk-hysteria2-agent ./. The certificate and key must be a real TLS pair; do not run without them.

Example:

REMOTEDESK_HYSTERIA2_PASSWORD='change-me' \
REMOTEDESK_HYSTERIA2_CERT=/etc/remotedesk/server.crt \
REMOTEDESK_HYSTERIA2_KEY=/etc/remotedesk/server.key \
./remotedesk-hysteria2-agent --listen 0.0.0.0:39502

The same binary provides the official Hysteria2 client path. It listens on a local UDP socket and forwards datagrams through one authenticated Hysteria2 UDP session:

./remotedesk-hysteria2-agent --mode client --listen 127.0.0.1:39503 \
  --server relay.example:39502 --password 'change-me' \
  --server-name relay.example --agent-udp 127.0.0.1:39502

--insecure is intentionally opt-in and should only be used for a local test certificate. No TCP listener, TCP proxy, or SOCKS5 endpoint is created.

Rust encoded ring bridge

The Windows Agent compatibility encoder can publish H.264 Annex-B access units to its session-bound memory-mapped ring. The Hysteria2 client can consume that ring directly and send RDV1 video datagrams on the same authenticated UDP session:

remotedesk-hysteria2-agent --mode client \
  --listen 127.0.0.1:39503 \
  --server relay.example:39502 --password 'change-me' \
  --server-name relay.example \
  --agent-udp 127.0.0.1:39502 \
  --encoded-ring C:\Users\user\AppData\Local\Temp\remotedesk-session-...ring \
  --ring-stream-id 1 --ring-generation 7

--encoded-ring is optional and is intended for the authenticated session orchestrator, which obtains the path, stream ID, and generation from the Rust control response. The Go consumer validates the ring header and geometry, copies each encoded access unit before releasing the slot, fragments it into RDV1, and drops video on cancellation or transport failure. It never maps or transmits raw BGRA/NV12 surfaces.

For production local orchestration, start the Agent and bridge with the same random 32-byte base64url bootstrap. The Agent removes its inherited copy from the environment after startup, restricts the pipe and ring DACL to the current Windows user, rejects remote pipe clients, and authenticates each connection with a nonce-bound HMAC-SHA256 challenge:

$token = New-Object byte[] 32
[Security.Cryptography.RandomNumberGenerator]::Fill($token)
$env:REMOTEDESK_AGENT_PIPE_TOKEN = [Convert]::ToBase64String($token).TrimEnd('=').Replace('+','-').Replace('/','_')
Start-Process -WindowStyle Hidden remotedesk-windows-agent -ArgumentList 'pipe'

remotedesk-hysteria2-agent --mode client `
  --server relay.example:39502 --password 'change-me' `
  --server-name relay.example --agent-udp 127.0.0.1:39502 `
  --windows-agent-pipe '\\.\pipe\RemoteDesk\windows-agent' `
  --session-id session-1 --ring-fps 120 --ring-stream-id 1
Remove-Item Env:REMOTEDESK_AGENT_PIPE_TOKEN

--windows-agent-control remains available only for a same-machine development bridge. Its address must be a literal loopback IP:

remotedesk-hysteria2-agent --mode client \
  --server relay.example:39502 --password 'change-me' \
  --server-name relay.example --agent-udp 127.0.0.1:39502 \
  --windows-agent-control 127.0.0.1:39501 \
  --session-id session-1 --ring-fps 120 --ring-stream-id 1

The receiver-side Windows viewer binds only loopback UDP, pins the first valid RDV1 source, uses bounded reassembly and a one-frame UI mailbox, and presents H.264 through Media Foundation/D3D11:

remotedesk-windows-agent-viewer --target 10.0.0.20:39501 \
  --session-id session-1 --fps 120 --media-udp 127.0.0.1:39502

RDWF remains the default when --media-udp is absent. The authenticated Named Pipe is the production descriptor path; loopback TCP and manual --encoded-ring are diagnostic/development paths and do not prove descriptor authenticity.

RemoteDesk media datagrams

Packets beginning with RDV1 are RemoteDesk H.264/HEVC/AV1 video fragments. The relay enforces the complete datagram limit (58-byte header plus at most 1200 bytes of payload) and otherwise forwards the bytes without decoding them. Audio and control packets use their own framing and remain opaque to this adapter. A missing video fragment is not retransmitted by this helper; the receiver drops the incomplete access unit after its bounded reassembly timeout.

The transport is an unreliable media path. Input and control traffic must use a separate reliable path in the Agent session protocol; this UDP adapter does not provide ordering or delivery guarantees for those messages.

RemoteDesk Opus packets use RDA1: a 40-byte header followed by one bounded Opus packet (maximum 4 KiB). Valid durations are 10/20/40/60 ms. The adapter validates the framing and forwards the packet without reordering or waiting for video. With an authenticated Windows Agent descriptor it independently drains the Opus mmap ring and sends RDA1 datagrams. The Windows viewer uses a bounded jitter queue plus Opus FEC/PLC and WASAPI playback; audio failure does not stop video or input. Real-device validation and precise shared-QPC drift correction remain release requirements.