WireGuard Remote Access: Fedora ↔︎ Windows

A concise guide for setting up WireGuard VPN to remotely access a Fedora machine from Windows, with SSH locked to the tunnel for security.

Overview


Part 1: Fedora Server Setup

1.1 Install WireGuard

sudo dnf install wireguard-tools -y

The kernel module is built into modern Fedora — no extra packages needed.

1.2 Generate server keys

cd /etc/wireguard
sudo sh -c 'umask 077; wg genkey | tee server_private.key | wg pubkey > server_public.key'

View them:

sudo cat /etc/wireguard/server_private.key
sudo cat /etc/wireguard/server_public.key

1.3 Create server config

Create /etc/wireguard/wg0.conf:

[Interface]
Address = 10.10.10.1/24
ListenPort = 51820
PrivateKey = <paste server_private.key contents>

[Peer]
PublicKey = <Windows client public key — fill in after Part 2>
AllowedIPs = 10.10.10.2/32

Set permissions:

sudo chmod 600 /etc/wireguard/wg0.conf

1.4 Configure firewall

Find your active zone first:

sudo firewall-cmd --get-active-zones

Typical active zone is FedoraWorkstation (desktop) or FedoraServer. Add WireGuard port to that zone and bind wg0 to the trusted zone:

# Replace <active-zone> with whatever --get-active-zones returns
sudo firewall-cmd --permanent --zone=<active-zone> --add-port=51820/udp
sudo firewall-cmd --permanent --zone=trusted --add-interface=wg0
sudo firewall-cmd --reload

1.5 Start and enable the tunnel

sudo systemctl enable --now wg-quick@wg0

1.6 Router port forward

On your home router, forward UDP 51820 to the Fedora box's LAN IP.

Find the Fedora LAN IP:

ip -4 addr show | grep inet

Find your public IP (what to put in Windows Endpoint):

curl -4 ifconfig.me

⚠️ CGNAT check: if curl -4 ifconfig.me doesn't match your router's WAN IP, you're behind CGNAT and port forwarding won't work. Use Tailscale instead.


Part 2: Windows Client Setup

2.1 Install WireGuard

Download from wireguard.com/install and install.

2.2 Create empty tunnel

Open WireGuard → Add Tunnel → Add empty tunnel...

A keypair is auto-generated. Copy the public key shown at the top — you'll paste it into the Fedora config.

2.3 Fill in the config

Replace the dialog contents with:

[Interface]
PrivateKey = <leave the auto-generated one>
Address = 10.10.10.2/32
DNS = 1.1.1.1

[Peer]
PublicKey = <Fedora server's public key>
Endpoint = <your-public-ip-or-ddns>:51820
AllowedIPs = 10.10.10.0/24
PersistentKeepalive = 25

Name the tunnel (e.g. fedora-home) and save.

2.4 Paste Windows public key into Fedora config

Back on Fedora:

sudo nano /etc/wireguard/wg0.conf

Replace the <Windows client public key> placeholder with the actual key from Windows, then restart:

sudo systemctl restart wg-quick@wg0

2.5 Activate on Windows

In the WireGuard GUI, click Activate. Status should flip to "Active" within seconds.


Part 3: Verification & Sanity Checks

3.1 Check WireGuard is running (Fedora)

sudo systemctl status wg-quick@wg0
sudo wg show
ip -brief addr | grep wg0

Expected: service active, wg0 interface with 10.10.10.1/24, listening port 51820.

3.2 Verify keys match on both sides

Server public key (Fedora):

sudo wg show wg0 public-key

This must equal the [Peer] PublicKey in your Windows config.

Check peer public key Fedora expects:

sudo wg show wg0 | grep peer

This must equal the Public key shown in the Windows WireGuard GUI.

Validate key lengths (should all be 44 chars ending in =):

sudo grep -E "PrivateKey|PublicKey" /etc/wireguard/wg0.conf | awk '{print $3, "length:", length($3)}'

3.3 Sanity-check config file

sudo cat /etc/wireguard/wg0.conf
sudo ls -la /etc/wireguard/

Config should have both [Interface] and [Peer] blocks with no placeholder text. Permissions should be -rw------- (600), owned by root.

Validate config parses correctly:

sudo wg-quick strip wg0

Prints clean config if valid, errors if not.

3.4 Verify firewall state

sudo firewall-cmd --get-active-zones
sudo firewall-cmd --zone=<active-zone> --list-all
sudo firewall-cmd --zone=trusted --list-all

Active zone should have 51820/udp in ports. Trusted zone should have wg0 in interfaces with target: ACCEPT.

3.5 Confirm port is listening

sudo ss -ulnp | grep 51820

Should show something bound to *:51820.

3.6 Test handshake live

On Fedora, run tcpdump to watch packets. First identify your WAN-facing interface:

ip route | grep default

Note the dev <name> — that's your WAN interface. Then:

sudo tcpdump -i any -n udp port 51820

(-i any captures on all interfaces, easiest for troubleshooting.)

Then click Activate on Windows (from outside your LAN — use phone hotspot). You should see both incoming and outgoing packets within a second.

Interpreting tcpdump output:

3.7 Confirm handshake completed

After activating Windows tunnel:

sudo wg show

Look for:

3.8 Test connectivity

From Windows PowerShell with tunnel active:

ping 10.10.10.1
ssh <user>@10.10.10.1

Once SSH works through the tunnel, remove it from public exposure.

4.1 Remove SSH from active zone

sudo firewall-cmd --permanent --zone=<active-zone> --remove-service=ssh
sudo firewall-cmd --reload

4.2 Verify SSH still works via tunnel

From Windows (tunnel active):

ssh <user>@10.10.10.1

Should still work — wg0 is in the trusted zone which allows all traffic.

4.3 Verify SSH blocked from LAN

From any other LAN device:

ssh <user>@<fedora-lan-ip>

Should time out or be refused.

4.4 Optional: Key-only SSH auth

Generate an Ed25519 key on Windows:

ssh-keygen -t ed25519
ssh-copy-id <user>@10.10.10.1

Then disable password auth on Fedora — edit /etc/ssh/sshd_config:

PasswordAuthentication no
PermitRootLogin no

Reload:

sudo systemctl reload sshd

Part 5: Troubleshooting Quick Reference

No handshake (bytes sent but not received)

  1. Check tcpdump on Fedora — are packets arriving?
  2. If no: router port forward, stale endpoint IP, or CGNAT
  3. If yes but no response: firewall or key mismatch

Endpoint IP changed (dynamic home IP)

curl -4 ifconfig.me

Update the Windows config's Endpoint = line with the new value.

Tunnel shows active but ping fails

Check wg0 is in trusted zone:

sudo firewall-cmd --zone=trusted --list-interfaces

If missing:

sudo firewall-cmd --permanent --zone=trusted --add-interface=wg0
sudo firewall-cmd --reload

Service fails to start

sudo journalctl -u wg-quick@wg0 -n 50 --no-pager

Common causes:

Verify after reboot

sudo systemctl is-enabled wg-quick@wg0   # should say: enabled
sudo wg show
ip -brief addr | grep wg0

Final Expected State

Fedora firewall

<active-zone> (default, active)
  interfaces: <your-wan-interface>
  services: dhcpv6-client
  ports: 51820/udp
  masquerade: no

trusted (active)
  interfaces: wg0
  target: ACCEPT

What you can do now


Data Usage Reference (over tunnel)

Activity Data/hour
SSH (terminal) 1-10 MB
X11 forwarding (single GUI app) 20-100 MB
RDP, tuned for low bandwidth 100-200 MB
RDP, defaults 200-500 MB
RDP with video 1-5 GB (avoid)

Use SSH for most things, RDP only when GUI is necessary.