EUR
european

EUR

usa

USD

Ex. VAT Ex. VAT 0%

WireGuard Windows setup

This guide explains how to set up a WireGuard VPN tunnel between two Windows machines: a WireGuard server running on a remote Windows host, for example a Windows VPS, and a WireGuard client running on your local Windows computer. Once the tunnel is active, the two machines exchange data over an encrypted private connection, and you can optionally route all of the client's traffic through the server.

The basic setup creates a tunnel between the server and the client. Routing all of the client's internet traffic through the server also requires NAT on the server, see "Configuring NAT on the server for full tunneling".

To keep key generation simple, this guide creates both the server and the client configurations inside one WireGuard application, and then deploys each configuration file to the machine it belongs to. The server configuration runs on the server and the client configuration runs on the client. The server and the client are always separate machines. The same process is used to add any number of additional clients.

Before you start, install the latest version of WireGuard from the WireGuard installation page on both the server and the client, and make sure you have administrator rights on each machine.

The setup in this guide looks like this:

Server (public IP, listening on UDP 51820) Tunnel address 10.0.0.1/24 | | encrypted WireGuard tunnel | Client Tunnel address 10.0.0.2/32

Creating the server configuration

Run C:\Program Files\WireGuard\wireguard.exe, click Add tunnel, and choose Add empty tunnel. WireGuard generates a key pair automatically. The public key shown at the top of the window is the server public key. You will need it later when you configure the client.

Give the tunnel a name and fill in the interface section with the server private key, the port WireGuard will listen on, and the internal address the server will use inside the tunnel.

[Interface] PrivateKey = # private key of the WireGuard server ListenPort = # port that WireGuard will listen on Address = # internal IP address of the WireGuard server, for example 10.0.0.1/24

Use a private subnet for the tunnel network and keep the server and all clients in the same range. A common choice is 10.0.0.1/24 for the server and 10.0.0.2/32, 10.0.0.3/32, and so on for each client. The server uses a /24 prefix so it treats the whole tunnel range as reachable through the WireGuard interface. Each client uses /32, because a client represents a single address rather than a subnet. A client set to /24 would assume the entire range is on its own interface and would not send traffic for other tunnel addresses through the tunnel.

The server configuration does not show the Block untunneled traffic (kill-switch) checkbox. This option appears only in a client configuration that routes all traffic through the tunnel, see "Creating the client configuration".

For an extra layer of security, you can add a pre-shared key to each peer. Generate it once and add the same line to the matching [Peer] section on both the server and the client:

PresharedKey = # pre-shared key, identical on the server and the client

You can generate the key with the wg tool that ships with WireGuard:

"C:\Program Files\WireGuard\wg.exe" genpsk

Creating the client configuration

Click Add tunnel and choose Add empty tunnel a second time, this time for the client. The public key shown for this tunnel is the client public key, which the server needs in order to accept the client.

Fill in the client configuration:

[Interface] PrivateKey = # private key of the WireGuard client Address = # internal IP address of the WireGuard client, for example 10.0.0.2/32 DNS = 1.1.1.1, 1.0.0.1 [Peer] PublicKey = # public key of the WireGuard server AllowedIPs = # 0.0.0.0/0 for a full tunnel, or 10.0.0.0/24 for a split tunnel Endpoint = # public IP address and port of the WireGuard server PersistentKeepalive = 25

The Endpoint must be the real public IP address of the server together with the port set in the server's ListenPort, not the internal tunnel address. For help choosing the AllowedIPs value, see the section "Understanding AllowedIPs" below.

The DNS and PersistentKeepalive lines are optional. DNS sets the DNS servers used while the tunnel is active, which helps avoid name resolution problems after connecting. You can use public resolvers such as 1.1.1.1, 1.0.0.1 or 8.8.8.8, 8.8.4.4, or the DNS server of the VPN network itself. PersistentKeepalive = 25 sends a small packet every 25 seconds and helps keep the connection open when the client is behind NAT.

When the client configuration has a single [Peer] and its AllowedIPs contains 0.0.0.0/0 (or ::/0), the tunnel editor shows the Block untunneled traffic (kill-switch) checkbox below the configuration field. With a split tunnel, for example AllowedIPs = 10.0.0.0/24, the checkbox does not appear at all.

The kill-switch is enabled by default as soon as you enter 0.0.0.0/0. While the tunnel is active, firewall rules allow only traffic that goes through the tunnel, loopback traffic, DHCP, and IPv6 neighbor discovery. Everything else is blocked, including devices on your local network such as printers and NAS. If the DNS line is set, DNS queries are allowed only to the servers listed there.

Clearing the checkbox does not just switch off a setting. The editor rewrites AllowedIPs: 0.0.0.0/0 becomes 0.0.0.0/1, 128.0.0.0/1, and ::/0 becomes ::/1, 8000::/1. All internet traffic still goes through the tunnel, but the blocking firewall rules are not created. Selecting the checkbox again restores 0.0.0.0/0.

Copy the keys and the Endpoint very carefully. A mistyped key or a wrong Endpoint is the most common reason a tunnel fails to connect.

Adding the client to the server

Open the server configuration again and add a [Peer] section for the client, using the client public key from the previous step.

[Peer] PublicKey = # public key of the WireGuard client AllowedIPs = # internal IP address of the client

In the server configuration, AllowedIPs has two roles. It tells the server which tunnel address belongs to this client, and it acts as a routing list: any packet addressed to those ranges is encrypted and sent to this peer. For a single client this is its tunnel address, for example 10.0.0.2/32. If the client should also make a local network reachable through the tunnel, add that subnet here as well, for example 10.0.0.2/32, 192.168.1.0/24. Repeat this step for every additional client.

Configuring the Windows Firewall on the server

The server must accept incoming WireGuard traffic on its UDP port. Open Windows Defender Firewall with Advanced Security, select Inbound Rules, and click New Rule. Choose Port and click Next. Select UDP, enter the WireGuard port, for example 51820, and click Next. If you use more than one port, list the ports separated by commas, for example 51820, 51821. Select Allow the connection and click Next. Select the profiles the rule applies to. If the server is hosted in a datacenter, the Public profile is usually sufficient, otherwise leave the Domain, Private, and Public profiles selected. Click Next, give the rule a clear name such as WireGuard UDP 51820, and click Finish.

This inbound rule is only needed on the server, because the server is the side that receives incoming connections. On a VPS, also make sure your hosting provider allows inbound UDP traffic on this port at the network level, not only in the Windows Firewall.

Exporting and deploying the configurations

When both configurations are ready, click Export all tunnels to zip, choose a location, and save.

Open the archive to find the configuration files for all tunnels. Place the server configuration on the server and give each client its own configuration file. If the machine holds many tunnels, you can also export a single tunnel from its context menu. Exporting to a zip file is convenient when both tunnels were created on the same machine, as in this guide. If you create each configuration directly on its own host, exporting is not required and you can copy the configuration file across by hand.

On the server, select the server configuration and click Activate.

On the client, click Add Tunnel, select the client configuration file, and open it.

Then click Activate.

The first client is now configured. Add further clients the same way: create a new empty tunnel for each client, and add a matching [Peer] section with that client's public key and tunnel address to the server configuration, as described in "Adding the client to the server".

Warning

If you configure WireGuard on a remote server over an RDP session, read the section "Understanding AllowedIPs" before you activate a tunnel that routes all traffic. A configuration with AllowedIPs = 0.0.0.0/0 can redirect the server's own traffic into the tunnel and drop your RDP connection.

Verifying the connection

After you activate the tunnel, Windows may show the WireGuard adapter as "No network access" or "No Internet access" in the Network and Sharing Center. This is expected behaviour, because Windows does not treat VPN tunnel adapters as standard internet connections, and it does not affect the tunnel. Windows decides this status with its connectivity check, which probes specific Microsoft URLs, so the warning can also appear if those probes are blocked or not resolved by your DNS, even when the tunnel works.

To confirm that the tunnel works, check its status in the WireGuard client. An active tunnel shows the Active status together with data transfer counters. If the counters increase, the tunnel is passing traffic.

On the server you can also confirm that WireGuard is listening on its UDP port while the tunnel is active:

netstat -ano | findstr 51820

In PowerShell the equivalent is:

Get-NetUDPEndpoint -LocalPort 51820

Replace 51820 with your WireGuard port. If nothing is returned, the tunnel is not active or the port differs from the one set in the server configuration.

Next, open Command Prompt and ping the server's internal tunnel address:

ping 10.0.0.1

Replace 10.0.0.1 with the actual internal IP you set for the server. If the server replies, traffic is passing through the tunnel. If there is no reply, check the handshake first: Windows Firewall on Windows Server blocks incoming ping by default, so a missing reply does not always mean that the tunnel is down.

If the client uses AllowedIPs = 0.0.0.0/0, you can also confirm that traffic is routed through the tunnel:

tracert 8.8.8.8

The first hop should be the internal IP address of the WireGuard server.

Checking the WireGuard handshake

The handshake is the most useful indicator when diagnosing a WireGuard connection. In the WireGuard application, open the tunnel and watch the Latest handshake field. On a working tunnel the handshake appears within seconds of activation and then updates periodically while data is transferred. If the tunnel is idle, some time can pass between handshakes, so a short gap is normal. If the field stays empty, the peers cannot reach each other, which usually points to a wrong Endpoint, a closed UDP port, or mismatched keys.

You can also check the handshake from the command line with the wg tool that ships with WireGuard:

wg show

The output lists each peer together with its latest handshake time and its transfer counters.

Understanding AllowedIPs

The AllowedIPs value in the client configuration decides which traffic is sent through the tunnel. In short, on the client AllowedIPs sets which packets are sent into the tunnel, while on the server it sets which packets are accepted from a given client and where they are routed.

A value of 0.0.0.0/0 routes all traffic through the tunnel, including ordinary internet browsing. Use it when you want full traffic protection. For this traffic to reach the internet, the server must translate it. See "Configuring NAT on the server for full tunneling" below.

A value such as 10.0.0.0/24 routes only the internal network traffic through the tunnel, while ordinary internet traffic keeps using the normal connection. Use it when you only need to reach specific resources on the remote network.

You can list several subnets separated by commas, for example 10.0.0.0/24, 192.168.1.0/24.

Tip

The Block untunneled traffic (kill-switch) option in the tunnel editor takes full effect with AllowedIPs = 0.0.0.0/0. It blocks anything that would travel outside the tunnel, which also blocks the local network. If you need access to printers or other LAN devices, leave the kill-switch disabled.

Warning

Setting AllowedIPs = 0.0.0.0/0 sends every connection through the tunnel. If you apply this on a remote server that you manage over RDP, the RDP session can drop the moment the tunnel becomes active, because the server's traffic is rerouted. On a server reached over RDP, route only the subnets you need, and test with a narrow AllowedIPs value before you switch to 0.0.0.0/0.

Accessing the local network while the tunnel is active

With a split tunnel, for example AllowedIPs = 10.0.0.0/24, the local network keeps working as usual and nothing needs to change. The steps below apply to a full tunnel.

The simplest option is to clear the Block untunneled traffic (kill-switch) checkbox in the client tunnel editor. The editor replaces 0.0.0.0/0 with 0.0.0.0/1, 128.0.0.0/1. Your local subnet, for example 192.168.1.0/24, has a more specific route through the physical adapter, so Windows sends LAN traffic directly to the local network, while internet traffic still goes through the tunnel. The trade-off is that nothing blocks traffic if the tunnel drops.

If you want to be sure that LAN traffic never enters the tunnel, exclude the local range from AllowedIPs explicitly. For example, the following value covers every IPv4 address except 192.168.0.0/16:

AllowedIPs = 0.0.0.0/1, 128.0.0.0/2, 192.0.0.0/9, 192.128.0.0/11, 192.160.0.0/13, 192.169.0.0/16, 192.170.0.0/15, 192.172.0.0/14, 192.176.0.0/12, 192.192.0.0/10, 193.0.0.0/8, 194.0.0.0/7, 196.0.0.0/6, 200.0.0.0/5, 208.0.0.0/4, 224.0.0.0/3

If your local network uses a different range, such as 10.x.x.x or 172.16.x.x, calculate the list for that range with an AllowedIPs calculator, and make sure the tunnel subnet is still included. Because this value has no /0 route, the kill-switch is not available with it.

Info Avoid using the same subnet for the tunnel and the local network. If your home network is 10.0.0.0/24, choose another tunnel range, for example 10.8.0.0/24.

To reach a network behind the server, for example an office LAN 192.168.10.0/24, the server needs no extra entry, because it already has a route to its own LAN. On the client, add it to AllowedIPs in the [Peer] section, for example AllowedIPs = 10.0.0.0/24, 192.168.10.0/24. The server must also forward and translate this traffic, see "Configuring NAT on the server for full tunneling". Devices in that LAN reply to the server's LAN address, so NAT on the server is the easiest way to make replies return through the tunnel.

Configuring NAT on the server for full tunneling

If clients use AllowedIPs = 0.0.0.0/0 and you want their traffic to actually reach the internet through the server, the server must translate the internal WireGuard addresses to its own external address. On Windows this is done with the New-NetNat command, not with the PostUp and PostDown scripts used on Linux.

Open PowerShell as an administrator on the server and run the following, using the tunnel subnet you assigned to the server:

New-NetNat -Name WireGuardNAT -InternalIPInterfaceAddressPrefix 10.0.0.0/24

Replace 10.0.0.0/24 with your tunnel subnet, and make sure the prefix covers every client address you assign. A client outside this range, for example 10.0.1.2, would not be matched by this rule. You can review the active rules at any time:

Get-NetNat

To remove the NAT rule later, run:

Remove-NetNat -Name WireGuardNAT

If clients connect and the handshake succeeds but their internet traffic still does not pass through the server, enable IP forwarding on the interfaces involved in routing and test again. The exact form depends on the Windows version, for example:

Set-NetIPInterface -InterfaceAlias "Ethernet" -Forwarding Enabled

Apply it to the external interface that carries internet traffic and to the WireGuard interface, using their real names from Get-NetIPInterface.

Info

New-NetNat requires Windows 10, Windows 11, or Windows Server 2016 and later, and on some systems it needs the Hyper-V feature to be enabled even if you do not otherwise use Hyper-V. On some VPS plans Hyper-V cannot be enabled, which blocks this method. Whether New-NetNat alone is enough or IP forwarding must also be enabled can depend on the Windows version, so confirm this on your server when full tunneling does not work

Troubleshooting

The tunnel is active but there is no connection to the server. Check that the WireGuard UDP port, for example 51820, is open in the firewall on the server. Confirm that the public keys are copied correctly between the server and client configurations. Make sure the Endpoint in the client configuration points to the real public IP address of the server, not the internal tunnel address.

DNS does not work after connecting. Add a DNS server to the client interface section:

[Interface] PrivateKey = ... Address = ... DNS = 1.1.1.1, 1.0.0.1

The packet counters do not increase. The tunnel is not passing data. Check that AllowedIPs is set correctly on both sides, that the internal WireGuard addresses do not clash with the existing local network, and that the ListenPort is not already used by another application.

The kill-switch checkbox does not clear. The editor rewrites AllowedIPs only when it can read the whole configuration. Check that the [Peer] section contains a valid public key copied from the server and that every setting is on its own line, then try again.

You need more detail to diagnose a problem. Open the tunnel in the WireGuard application and look at the Log tab, which records handshakes, errors, and connection events as they happen. You can export the log from there if you need to share it.

Auto-start WireGuard after a server restart

To keep the tunnel running across reboots, install it as a Windows service. When a tunnel is installed as a service, it starts automatically after a reboot. Open Command Prompt or PowerShell as an administrator and run the following, using the path to your server configuration file:

wireguard /installtunnelservice "C:\Program Files\WireGuard\wg_server.conf"

Run this command only once, not at every startup. Activating the tunnel from the WireGuard application normally installs the same service, so in many cases activating it once is enough. To remove the service later, use the tunnel name, which is the configuration file name without the .conf extension.

wireguard /uninstalltunnelservice wg_server

To restart the service, for example after editing the configuration, run the uninstall command followed by the install command again.

Info

Because the tunnel runs as a service, a separate Task Scheduler task is not needed.

Reboot the server and confirm that the tunnel starts on its own.

VAT

  • Other

    Ex. VAT

    0%
  • austria

    Austria

    20%
  • Belgium

    Belgium

    21%
  • Bulgaria

    Bulgaria

    20%
  • Croatia

    Croatia

    25%
  • Cyprus

    Cyprus

    19%
  • Czech Republic

    Czech Republic

    21%
  • Denmark

    Denmark

    25%
  • Estonia

    Estonia

    22%
  • France

    France

    20%
  • Finland

    Finland

    24%
  • Germany

    Germany

    19%
  • Greece

    Greece

    24%
  • Hungary

    Hungary

    27%
  • Ireland

    Ireland

    23%
  • Italy

    Italy

    22%
  • Latvia

    Latvia

    21%
  • Lithuania

    Lithuania

    21%
  • Luxembourg

    Luxembourg

    17%
  • Malta

    Malta

    18%
  • Netherlands

    Netherlands

    21%
  • Poland

    Poland

    23%
  • Portugal

    Portugal

    23%
  • Romania

    Romania

    19%
  • Slovakia

    Slovakia

    20%
  • Slovenia

    Slovenia

    22%
  • Spain

    Spain

    21%
  • Sweden

    Sweden

    25%
  • USA

    USA

    0%
european
states
  • kingdom
  • germany
  • Español
  • French
  • Hrvatska
  • Italiano
  • Poland
  • Slovenski
  • ukraine
  • Türkçe
  • Русский
  • Other
  • Austria
  • Belgium
  • Bulgaria
  • Croatia
  • Cyprus
  • Czech Republic
  • Denmark
  • Estonia
  • Finland
  • France
  • Germany
  • Greece
  • Hungary
  • Ireland
  • Italy
  • Latvia
  • Lithuania
  • Luxembourg
  • Malta
  • Netherlands
  • Poland
  • Portugal
  • Romania
  • Slovakia
  • Slovenia
  • Spain
  • Sweden
  • USA