RDP via Home-Gateway (Option B)
Alternative: Option A — Create an L4 gateway route directly.
What it is
An RDP route in the Admin UI gets a new access mode:
Via Home Gateway. When you choose it:
- The connection is routed through a Home Gateway container into the home network (the Windows machine needs no port forwarding on the home router and no WG peer of its own).
- GateControl automatically creates an L4 TCP route behind the
scenes that tunnels
public port → gateway → LAN RDP port. - All RDP convenience features (credential vault, resolution, clipboard, audio, NLA, sharing, WoL, maintenance windows, …) remain available.
- The generated
.rdpfile uses the public address + listen port instead of the LAN IP.
Difference from MS RD-Gateway
The RDP route historically has fields for "Gateway host" / "Gateway port" — those are for the Microsoft RD-Gateway (TSGateway), i.e. the Windows role service that tunnels RDP over HTTPS. That is a standalone Microsoft product, not part of GateControl.
The new "Via Home Gateway" is the GateControl way. Both can be combined (e.g. Home Gateway to the LAN edge, then an MS-RDG there tunneling RDP to the final host); the UI separates both sections clearly.
Prerequisites
- Home Gateway peer created in the Admin UI and heartbeating
- Pro license (both RDP feature + Home Gateway routing)
- RDP enabled on the target device
Creating — the wizard
Remote Desktop → New RDP Route opens a 6-step wizard:
| Step | Contents |
|---|---|
| 1 — Connection | Name, description, host (LAN IP), RDP port, access mode, depending on mode: external hostname/port or Home Gateway peer + listen port, plus (optional) Microsoft RD-Gateway configuration |
| 2 — Authentication | Credential mode (none / user_only / full), domain, username, password |
| 3 — Display + Resources | Resolution (fullscreen/fixed/dynamic), color depth, multi-monitor, redirects (clipboard/printer/drives/USB/smart card), audio |
| 4 — Network + Session | Network profile, bandwidth limit, NLA, disable wallpaper/themes/animations, session timeout, remote app, start program, admin session |
| 5 — WoL + access control + tags | Wake-on-LAN, maintenance window, health check, credential rotation, tags, notes |
| 6 — Access + review | Which users see the route + summary of all fields before saving |
The wizard uses the same form state as the classic flat edit — the edit button on an existing route also opens the wizard with all fields pre-filled.
What you pick in the wizard for Home Gateway routing
Step 1 — Connection:
- Host: the LAN IP of the Windows machine, e.g.
192.168.2.100. (Not the public address — the gateway needs to route into the LAN.) - Port:
3389(the RDP port on the target device) - Access mode:
Via Home Gateway - Home Gateway: your registered gateway peer (dropdown only shows peers configured as a gateway)
- Public listen port: the port under which the session is reachable
externally. Default: same as the RDP port (3389). Pick a different
one if 3389 is already in use on the server — e.g.
13389. - Microsoft RD-Gateway fields: leave empty, unless you really have an MS-RDG server behind the RDP target.
Data flow (identical to Option A)
RDP client ── TCP SYN ──▶ Server (VPS)
│
│ Caddy Layer-4 plugin
│ (auto-generated L4 route)
│ forward → gateway-peer-IP : listen_port
▼
Gateway container (home)
│
│ TcpProxyManager : listen_port
│ forward → host : port (from RDP route)
▼
Windows machine (RDP server)
Under the hood, this is exactly the same network setup as
Option A — the only difference: the L4 route is created
automatically and hidden. It appears in the routes table with
route_type=l4, target_kind=gateway, and description "auto-created
for RDP route …". It is automatically kept in sync on delete / toggle /
access-mode change of the RDP route — no orphans possible.
Edit cases
Switch access mode to gateway
- Save the wizard → the L4 route is newly created, the ID is stored in
rdp_routes.gateway_l4_route_id.
Switch access mode away from gateway
- Save → the L4 route is removed, the pointer is set to
NULL.
Change listen port, switch LAN host, etc.
- Update → the L4 route is updated in place (dual-bind overlap in the gateway TcpProxyManager provides zero downtime on port change).
Delete RDP route
- Cascade → L4 route is removed first, then the RDP route. No orphan.
Disable RDP route (toggle)
- The L4 route is disabled as well → the public listen port closes immediately. User feedback: "the machine is off the network."
Client side
From the Admin UI you can download a .rdp file per RDP route that is
already filled with the public address + listen port. The user clicks
it → mstsc.exe opens with all settings from the route (resolution,
redirects, color depth, domain prefix on the username, etc.).
Security
- Credentials are stored AES-256-GCM encrypted in the DB
(
encrypted_username/encrypted_password). - The server only decrypts them when generating the
.rdpfile or on an explicit credential request via API. - The L4 route forwards pure TCP — the RDP-internal encryption (NLA / TLS 1.2+) remains untouched. The tunnel is additionally WG-encrypted, giving double crypto on the public-to-gateway hop.
- No GateControl component decrypts the RDP stream at any point.
Interplay with other access modes
You can give an RDP route only one access mode. gateway is
exclusive — switching to it automatically discards peer forwarding
info (internal) or port forwarding info (external). If you want a
fallback route in parallel, create two RDP routes (one with
internal, one with gateway).
Relevant files
Server
src/services/rdp.js—VALID_ACCESS_MODES+_syncLinkedL4Route(), cascade delete, toggle syncsrc/routes/api/rdp.js— license gate before create/updatesrc/services/license.js—COMMUNITY_FALLBACKentrysrc/db/migrations.js— migration 38 (rdp_routes_gateway_link)- UI wizard:
public/js/rdp.js(step navigation, review, gateway peer dropdown),templates/pro/pages/rdp.njk(wizard-step attributes + new Home Gateway section)
Tests
tests/rdp_gateway.test.js— 5 scenarios (create + L4 link, cascade delete, access-mode change, validation, toggle sync)
Troubleshooting
On save: "Feature not available in your plan"
You are missing the Pro license for Home Gateway RDP routing. Upgrade
or use Option A (L4 gateway route directly) — that one only requires
gateway_tcp_routing, not the RDP-specific feature flag.
On save: "Linked L4 gateway route could not be created"
The listen port collides with another L4 route or a blocked port (e.g. 3389 already used by another RDP route). Pick a different listen port in the wizard (e.g. 13389).
RDP client connects but only shows a black screen
- NLA conflict. Under "Network & Behavior" in the wizard, make sure NLA matches the target server (old servers: off, new: on).
- Multi-monitor on old servers can also hang — try disabling it.
Client gets "Gateway timeout"
- Home Gateway in the Admin UI: status check — is the gateway online?
- WG tunnel on the server:
wg show wg0 | grep handshake— the line for the gateway peer should be < 2 minutes old. - If in doubt, run
docker restart gatecontrol-gatewayon the gateway — the TcpProxyManager then comes up with a fresh route map.
I want to change the L4 listen port afterwards
In the RDP route wizard, step 1, adjust "Public listen port" and save. The L4 route is updated in place, and the gateway container migrates to the new port with a dual-bind overlap (10 s both ports open). Existing RDP sessions are not killed.