VPN and securing access

The RDP port is closed until you open it, and there are two good ways to open it to people who are not on the machine: an SSH tunnel and a WireGuard VPN. This page explains what protects the login, then sets up the VPN.

Security: what protects the login

The login is the account's password inside TLS, with no second factor. Everything else is about making sure only the right people get as far as typing it:

  • The port is closed until you open it, and an address that is not allowed gets nothing, before TLS and before any login. Failed logins are delayed 2 seconds; five in a row refuse every login for a minute. Only members of waydesk-users may log in, never root.
  • Keep the port off the open internet. Use an SSH tunnel for one person, or the VPN below for several. Long random passwords matter, because there is no second factor.
  • Each part has only the rights it needs. The network-facing daemon has none and never sees a user's files; a small root helper checks the password through PAM and starts the session; each session runs as the account itself, in its own systemd slice, with its own limits. The architecture page draws it.
  • A certificate you can verify (waydesk-admin cert local-ca) lets the client check every connection instead of trusting the first one.
  • This is not an audited product. Four internal review passes are written down with what is still open: docs/SECURITY-REVIEW.md, who is assumed hostile in docs/THREAT-MODEL.md, and the access model in docs/ACCESS.md.

Why a VPN

For several people or devices, or anything over the internet, do not publish the RDP port: put it behind a VPN. waydesk-admin vpn makes the WireGuard server side, one client at a time, and a QR code for a phone. The RDP port then listens on the VPN address only, so without a key it does not exist for anyone.

Make the VPN

vpn init installs wireguard-tools if needed, makes the server side on its own interface (waydesk0, UDP 51820, 10.8.0.0/24; change them with --interface, --port, --subnet), makes RDP listen on the VPN address only, starts the daemon after the VPN, and opens the port in ufw if it is on. The endpoint is the name or public address clients will connect to.

$ sudo waydesk-admin vpn init --endpoint vpn.example.com
Open UDP 51820 to the internet in this machine's firewall and in the provider's security group, if there is one.
Done.
Listening on     10.8.0.1:3389  (vpn)
Who may connect   10.8.0.0/24
Signed by        CN=your-server
Fingerprint      6F:E1:32:12:8C:64:71:A3:C0:51:C6:BB:80:37:64:B9:C4:E4:C7:1E:C7:C2:B8:93:E3:48:42:A5:C9:A4:FD:10

Connect: bring the VPN up on the client, then point the RDP client at 10.8.0.1. `waydesk-admin vpn add NAME` makes a client.

The VPN is ready. Add a client with:  sudo waydesk-admin vpn add NAME

Open UDP 51820 in the provider's firewall too (a cloud security group is outside the machine). Do not open 3389: the RDP port exists only inside the tunnel. vpn init refuses to replace an existing configuration without --force (it keeps a backup) and uses an interface name of its own, so a wg0 you made by hand is left alone.

Add a client

One client per device, so that a lost laptop is one entry to remove. Install qrencode first if you want the QR code for a phone:

$ sudo apt install qrencode
$ sudo waydesk-admin vpn add phone
Client phone (10.8.0.2) added. Import this in the WireGuard app (or scan the QR code), then connect the RDP client to 10.8.0.1:

[Interface]
PrivateKey = <the client's private key>
Address = 10.8.0.2/32

[Peer]
PublicKey = <the server's public key>
PresharedKey = <a preshared key, on top of the keys>
Endpoint = vpn.example.com:51820
AllowedIPs = 10.8.0.1/32
PersistentKeepalive = 25

(the QR code of the same configuration follows)

On the phone or laptop, install the WireGuard app, scan the code (or import the text), and switch the tunnel on. AllowedIPs = 10.8.0.1/32 sends only the traffic for the server through the tunnel; the rest of the client's traffic is not touched. Then connect the RDP client to **10.8.0.1**.

The configurations stay in /etc/waydesk/vpn/peers (root only), so vpn show NAME prints one again.

See and remove clients

$ sudo waydesk-admin vpn list
Interface    waydesk0  (10.8.0.1, subnet 10.8.0.0/24, UDP port 51820)
Endpoint     vpn.example.com:51820
State        up

CLIENT               ADDRESS         LAST CONNECTED
phone                10.8.0.2        never
$ sudo waydesk-admin vpn remove phone        # stops its access at once

vpn status shows the same listing. After the phone connects, LAST CONNECTED says when.

What it gives, and what it does not

  • The RDP port is invisible to anyone without a peer key, and the password login only travels inside the tunnel.
  • A peer key is not a login. The account's password is still asked, and the memory and user limits still apply.
  • Everyone with a peer can try passwords for every account, so give peers only to people you would let near the login.
  • There is still no second factor: long, random passwords matter.

VPN or SSH tunnel

WireGuard VPNSSH tunnel
Server setupone commandnone (sshd is usually there)
Many users and devicesyes, a key per devicean SSH account each
Always onyes, in the backgroundonly while the command runs
Long round tripshandles them wellTCP inside TCP stalls
Port exposedUDP 51820TCP 22

The manual way, without waydesk-admin, is in docs/WIREGUARD.md, and the whole access model in docs/ACCESS.md.

This page is a file in the repository: corrections are welcome.