Forwarding WireGuard Connections on Windows
WireGuard generally “just works” out-of-the-box on Windows with a Point-to-Point connection, or as a “Point” in a conventional Point-to-Site connection, or as a “Spoke” in a Hub-and-Spoke connection; and if you want to expose a network service (like a web server) running on such a point or spoke, you can do that by making one or two adjustments to its Windows Defender Firewall.
But if you want to use a Windows machine as the “Hub” in a Hub-and-Spoke connection, or to expose a “Site” in a Point-to-Site or Site-to-Site connection, you need to make further configuration changes to various Windows networking settings. This article will show you how:
Hub Forwarding
Enabling packet forwarding on a WireGuard hub is the simplest kind of forwarding to configure. For example, if you’ve set up WireGuard on a Windows machine like the “Host C” hub in the WireGuard Hub and Spoke Configuration guide:
You can enable packet forwarding by running the following PowerShell Set-NetIPInterface
command as an Administrator on Host C:
PS> Set-NetIPInterface -InterfaceAlias wg0 -Forwarding Enabled
The above command enables both IPv4 and IPv6 forwarding. Alternatively, you could enable each version separately by running the following netsh
commands:
> netsh interface ipv4 set interface wg0 forwarding=enabled > netsh interface ipv6 set interface wg0 forwarding=enabled
Both sets of commands above are the equivalent of turning on the IP forwarding kernel parameters on a Linux machine:
# sysctl -w net.ipv4.conf.wg0.forwarding=1 # sysctl -w net.ipv6.conf.wg0.forwarding=1
To check the current forwarding state of each network interface on a Windows machine, run the following PowerShell command:
PS> Get-NetIPInterface | Select IfIndex,InterfaceAlias,AddressFamily,ConnectionState,Forwarding | Sort-Object -Property IfIndex | Format-Table IfIndex InterfaceAlias AddressFamily ConnectionState Forwarding ------- -------------- ------------- --------------- ---------- 1 Loopback Pseudo-Interface 1 IPv4 Connected Disabled 1 Loopback Pseudo-Interface 1 IPv6 Connected Disabled 7 Ethernet IPv6 Connected Disabled 7 Ethernet IPv4 Connected Disabled 15 wg0 IPv6 Connected Enabled 15 wg0 IPv4 Connected Enabled
Site Gateway
Enabling packet forwarding for a WireGuard site gateway is only a little more complicated than for a hub. You need to run the same commands on the site gateway as on the hub — but for both the WireGuard interface (wg0
) and the site-facing Ethernet adapter (usually named Ethernet
):
PS> Set-NetIPInterface -InterfaceAlias wg0 -Forwarding Enabled PS> Set-NetIPInterface -InterfaceAlias Ethernet -Forwarding Enabled PS> Get-NetIPInterface | Select IfIndex,InterfaceAlias,AddressFamily,ConnectionState,Forwarding | Sort-Object -Property IfIndex | Format-Table IfIndex InterfaceAlias AddressFamily ConnectionState Forwarding ------- -------------- ------------- --------------- ---------- 1 Loopback Pseudo-Interface 1 IPv4 Connected Disabled 1 Loopback Pseudo-Interface 1 IPv6 Connected Disabled 7 Ethernet IPv6 Connected Enabled 7 Ethernet IPv4 Connected Enabled 15 wg0 IPv6 Connected Enabled 15 wg0 IPv4 Connected Enabled
Run these commands on the WireGuard host for both sites in a Site-to-Site connection (eg both “Host α” and “Host β” in the WireGuard Site to Site Configuration guide), or on the site host of a Point-to-Site connection (eg “Host β” in the WireGuard Point to Site With a Site Gateway guide).
Note that you will still have to update the routing tables on the LAN router (or each individual computer you want to expose) at the site in order for traffic from the other computers at the site to actually be routed to the WireGuard site host. For example, in the WireGuard Point to Site With a Site Gateway guide, the WireGuard network is using the 10.0.0.0/24
address block, and the WireGuard site host (Host β) has an address of 192.168.200.2
on the LAN:
So on the LAN router at Site B, you would have to add a route like the following:
# ip route add 10.0.0.0/24 via 192.168.200.2 dev eth1
Point to Site Masquerading
Setting up masquerading (aka Source Network Address Translation or SNAT) on a WireGuard site host for a Point-to-Site connection is only a little more complicated. You simply have to use the New-NetNat
command and specify the address block of source addresses that should be masqueraded.
For example, if you’ve set up WireGuard on a Windows machine to be a site host like “Host β” in the WireGuard Point to Site Configuration guide, 10.0.0.0/24
is the address block of WireGuard addresses that the site host should masquerade to the site LAN:
To enable this, run the following PowerShell command as an Administrator on Host β:
PS> New-NetNat -Name wg0nat -InternalIPInterfaceAddressPrefix 10.0.0.0/24
Unlike with Linux, you do not have to separately enable packet forwarding; Windows will automatically allow forwarding from any source addresses in the specified address block (such as 10.0.0.1
, the WireGuard “Point” in the Point to Site Configuration example), and will automatically rewrite the source address of those forwarded connections to use the address of whatever interface the connection is forwarded out (such as 192.168.200.2
, the LAN address of Host β above).
Run the following PowerShell command to see the current list of SNAT configurations:
PS> Get-NetNat Name : wg0nat ExternalIPInterfaceAddressPrefix : InternalIPInterfaceAddressPrefix : 10.0.0.0/24 IcmpQueryTimeout : 30 TcpEstablishedConnectionTimeout : 1800 TcpTransientConnectionTimeout : 120 TcpFilteringBehavior : AddressDependentFiltering UdpFilteringBehavior : AddressDependentFiltering UdpIdleSessionTimeout : 120 UdpInboundRefresh : False Store : Local Active : True
Note that the wg0nat
name in the above example is completely arbitrary — it doesn’t have to include the WireGuard interface name. It’s relevant only for the purpose of updating or deleting existing SNAT configurations; for example, run the following command to remove the SNAT added above:
PS> Remove-NetNat -Name wg0nat -Confirm:$false
Point to Site Port Forwarding
Enabling port forwarding (aka Destination Network Address Translation or DNAT) on a WireGuard host takes a few more steps. The first step is to determine the original destination address and port that will be used by incoming packets which should be forwarded, and the destination address and port to which those packets should be rewritten.
With the example from the WireGuard Point to Site With Port Forwarding guide, “Host β” should forward incoming TCP port 80 packets from its site LAN, using its LAN address of 192.168.200.2
, to TCP port 80 of WireGuard “Endpoint A”, which has an IP address of 10.0.0.1
on the WireGuard network:
To set up this DNAT, first run the following netsh
command as Administrator on Host β:
> netsh interface portproxy add v4tov4 listenaddress=192.168.200.2 listenport=80 connectaddress=10.0.0.1 connectport=80
For IPv6 addresses, use the v6tov6
subcommand instead of v4tov4
. Unlike with Linux, you do not need to separately enable packet forwarding, and you do not need to separately enable SNAT — connections that match this DNAT rule will automatically be forwarded, and have their source address translated to match the interface out of which they’ll be forwarded (10.0.0.2
in this example).
Next, add a firewall rule on Host β with the New-NetFirewallRule
PowerShell command to allow the incoming connection to be accepted before it is translated:
PS> New-NetFirewallRule ` -Name wg0http ` -DisplayName "HTTP-In wg0" ` -Group "Custom" ` -Enabled True ` -Direction Inbound ` -Action Allow ` -Protocol TCP ` -LocalPort 80
The above firewall rule will allow connections to TCP port 80 from anywhere. You might, however, want add a -RemoteAddress
option to constrain the source machines from which Host β will forward; for example, you might add the following -RemoteAddress 192.168.200.0/24
option to forward connections only from Host β’s own LAN:
PS> New-NetFirewallRule ` -Name wg0http ` -DisplayName "HTTP-In wg0" ` -Group "Custom" ` -Enabled True ` -Direction Inbound ` -Action Allow ` -Protocol TCP ` -LocalPort 80 ` -RemoteAddress 192.168.200.0/24
The combination of the above port-proxy command and firewall rule will allow the example Host β to forward HTTP connections from its site LAN through WireGuard to Endpoint A.
To list the active port-proxies, run the following command:
> netsh interface portproxy show all Listen on ipv4: Connect to ipv4: Address Port Address Port --------------- ---------- --------------- ---------- 192.168.200.2 80 10.0.0.1 80
To delete the port-proxy set up above, run the following command with the listen address and port to delete:
> netsh interface portproxy delete v4tov4 listenaddress=192.168.200.2 listenport=80
And to delete the firewall rule set up above, run the following PowerShell command with the name of the rule to delete:
PS> Remove-NetFirewallRule -Name wg0http