WireGuard Point to Site With Port Forwarding
Usually when you connect a remote endpoint to a local site, you want the endpoint to be able to access some resources (like a web app or a mail server) at the local site, and don’t need to allow hosts at the site to be able to initiate connections to the remote endpoint. But sometimes you want the reverse — for the hosts at the local site to be able to access a service (like a web app or database) on the remote endpoint.
This article will cover exactly how to do that: we’ll set up a remote endpoint as one WireGuard peer, and connect it to a second WireGuard peer at a local site; and forward a port on the second WireGuard peer with DNAT (Destination Network Address Translation) to allow other hosts at the local site to access the remote endpoint through this WireGuard tunnel.
This is the reverse of the way a WireGuard Point to Site Topology is usually used, but the WireGuard configuration for it is similar to the standard Point to Site Configuration — just with a few different firewall rules to enable port forwarding.
In the example scenario for this article, we’ll have the remote endpoint running a web server on port 80, as well as running WireGuard on port 51821. I’ll call this endpoint “Endpoint A”. We’ll have another host running WireGuard at our local site on port 51822, which I’ll call “Host β”, in “Site B”. And we’ll have an end-user workstation on the LAN (Local Area Network) at Site B, which I’ll call “Endpoint B”. This endpoint is not running WireGuard, but we still want it to be able to connect to the web server on Endpoint A.
The Internet is between Endpoint A and Site B. Endpoint A is behind NAT (Network Address Translation) and a firewall that allows only established connections through. Site B is also behind NAT and a firewall, but its NAT + firewall allows port 51822 from the Internet to be forwarded on to Host β.
The diagram below illustrates this scenario:
By connecting Endpoint A and Host β in a WireGuard VPN (Virtual Private Network), Endpoint B will be able to access Endpoint A as if the web server on Endpoint A was running on Host β instead. Host β has an IP address of 192.168.200.2
within Site B, so a user using Endpoint B will be able to access the web server on Endpoint A simply by navigating to http://192.168.200.2
in her web browser.
Take note of the IP addresses shown in the above diagram: In this scenario, Endpoint A’s IP address, from the perspective of the Internet, is 198.51.100.1
, but from the perspective of its own LAN (Site A), it’s 192.168.1.11
; and from the perspective of the WireGuard VPN that we’ll build, it’s 10.0.0.1
. Endpoint B is not accessible from the Internet; but on its own LAN (Site B), its IP address is 192.168.200.22
.
Host β’s IP address, from the perspective of the Internet, is 203.0.113.2
, but from the perspective of its own LAN (Site B), it’s 192.168.200.2
; and from the perspective of the WireGuard VPN we’ll build, it’s 10.0.0.2
. And from the perspective of Endpoint B (or any other endpoints in Site B), Endpoint A’s packets will appear to come from Host β — so from the perspective of Endpoint B, Endpoint A’s IP address will be the same as the IP address for Host β in the Site B LAN: 192.168.200.2
.
These are the steps we’ll follow for this scenario:
Install WireGuard
Install WireGuard on both Endpoint A and Host β by following the installation instructions for the appropriate platform on the WireGuard Installation page. You can verify that you’ve installed WireGuard successfully by running wg help
on both hosts.
Generate WireGuard Keys
Next, generate two WireGuard keys, one for Endpoint A, and one for Host β. A WireGuard key (also known as a “key pair”) is composed of two parts, the “private key” (also known as the “secret key”), and the “public key”. The magic of this kind of crypto (known as “public-key cryptography”) is that it’s trivial to compute the public key if you know the private key, but practically impossible to compute the private key if all you know is the public key.
While you don’t have to generate the keys on the hosts, generating a host’s key on the host itself often is the best way to keep its private key secure — that way the private key never leaves the host. If you generate your keys outside of the host, be very careful with the private keys, as WireGuard’s security depends entirely on keeping the private keys a secret.
Run the following commands to generate a new key pair for Endpoint A:
$ wg genkey > endpoint-a.key
$ wg pubkey < endpoint-a.key > endpoint-a.pub
And similar commands to generate a new key pair for Host β:
$ wg genkey > host-b.key
$ wg pubkey < host-b.key > host-b.pub
This will generate four files: endpoint-a.key
, endpoint-a.pub
, host-b.key
, and host-b.pub
. The *.key
files contain the private keys, and the *.pub
files contain the public keys. The content of each will be 44 characters of Base64-encoded text:
$ cat endpoint-a.key
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEE=
$ cat endpoint-a.pub
/TOE4TKtAqVsePRVR+5AA43HkAK5DSntkOCO7nYq5xU=
$ cat host-b.key
ABBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBFA=
$ cat host-b.pub
fE/wdxzl0klVp/IR8UcaoGUMjqaWi3jAd7KzHKFS6Ds=
You don’t actually need to keep these files around — the content of each will be used in the WireGuard configuration files we build for Endpoint A and Host β in the next sections. The private key for a host goes in the host’s own configuration file; and its public key goes in the configuration file of every other host you want to connect it to. Each end of a connection must be pre-configured with the other end’s public key in order for WireGuard to establish the connection.
Configure WireGuard on Endpoint A
Now let’s configure Endpoint A (the remote web server). On Endpoint A, create a new file at /etc/wireguard/wg0.conf
with the following content:
# /etc/wireguard/wg0.conf
# local settings for Endpoint A
[Interface]
PrivateKey = AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEE=
Address = 10.0.0.1/32
ListenPort = 51821
# remote settings for Host β
[Peer]
PublicKey = fE/wdxzl0klVp/IR8UcaoGUMjqaWi3jAd7KzHKFS6Ds=
Endpoint = 203.0.113.2:51822
AllowedIPs = 192.168.200.0/24
PersistentKeepalive = 25
Set the file’s owner to root
, and its permissions to 600
(owner can read+write; everyone else is denied access — the file contains the endpoint’s private key, which must be kept secret).
Let’s go through the configuration, setting-by-setting:
- Interface.PrivateKey
-
This is Endpoint A’s private key — replace this value with the actual private key you generated for Endpoint A. This value is secret, and this is the only place where it should live.
- Interface.Address
-
This is Endpoint A’s IP address inside the WireGuard VPN we’re building — replace this value with a suitable value for your network. You can use any address you want for this, but the address should be within the “Private-Use” IPv4 or “Unique-Local” IPv6 address space (like
10.0.0.0/8
— see RFC 6890 for all available address blocks), and should not collide with any other private subnets to which the endpoint itself or any of its peers can connect.With a Point to Site topology, this setting in Endpoint A’s configuration file should match exactly the
Peer.AllowedIPs
setting in Host β’s configuration file (discussed in the next section).This setting isn’t used by WireGuard directly — it’s only used by the
wg-quick
helper service when it sets up a virtual network interface for WireGuard. In order for network packets to be routed correctly to and from this endpoint when they’re outside of the WireGuard tunnel, they need to use the IP address you set here.While you can configure multiple IP addresses for this setting, unless you have a special use-case, you should just use a single IP address (in the form of a
/32
block with an IPv4 address, or a/64
block with an IPv6 address). - Interface.ListenPort
-
This is Endpoint A’s WireGuard port. Endpoint A must be able to receive UDP traffic for established connections on this port from the Internet (or wherever the traffic of the other WireGuard peers with which it will communicate comes from).
If you omit this setting, WireGuard will select a new random, unused port in the in the operating system’s ephemeral port range (which may range from
1024
to65535
, depending on operating system) every time it starts up. - Peer.PublicKey
-
This is Host β’s public key — replace this value with the actual public key you generated for Host β. This value is not secret; however, it is a globally-unique identifier for Host β.
- Peer.Endpoint
-
This is Host β’s publicly-facing IP address (and port) — the IP address and port Endpoint A will use to connect over the Internet to Host β to set up the WireGuard tunnel. Replace this value with the actual IP address that you would normally use to connect to Host β from Endpoint A (and suffix it with the actual WireGuard port you’ll use for Host β).
Host β must be able to accept new UDP connections from the Internet at this address and port; and Endpoint A must be able to send UDP traffic over the Internet to it at this address and port.
- Peer.AllowedIPs
-
This is Site B’s subnet block — replace this value with the actual block of IP addresses Site B uses. If Host β can route to multiple subnets within Site B, you can specify each block of IP addresses separated by commas (like
192.168.200.0/24,192.168.202.64/26,192.0.2.48/28
) for this setting, or you can just specify this setting multiple times, one for each CIDR (Classless Inter-Domain Routing) block. - Peer.PersistentKeepalive
-
This is a number of seconds between keepalive packets. The default is
0
, which turns off keepalive packets.If you set this to a positive integer N, WireGuard will send a small keepalive packet to Host β when the WireGuard interface on Endpoint A starts up, and again after every N seconds. This will open up any stateful firewalls between Endpoint A and Host β that accept only established connections in Endpoint A’s direction.
We need this in our example scenario, which has firewalls in front of Endpoint A that accept inbound traffic only for established connections, to allow Host β to initiate new connections to Endpoint A when it forwards HTTP requests from Endpoint B.
Configure WireGuard on Host B
Now let’s configure Host β (the local site side of the connection). On Host β, create a new file at /etc/wireguard/wg0.conf
with the following content:
# /etc/wireguard/wg0.conf
# local settings for Host β
[Interface]
PrivateKey = ABBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBFA=
Address = 10.0.0.2/32
ListenPort = 51822
# remote settings for Endpoint A
[Peer]
PublicKey = /TOE4TKtAqVsePRVR+5AA43HkAK5DSntkOCO7nYq5xU=
AllowedIPs = 10.0.0.1/32
Set the file’s owner to root
, and its permissions to 600
(owner can read+write; everyone else is denied access — the file contains the host’s private key, which must be kept secret).
Let’s go through the configuration, setting-by-setting:
- Interface.PrivateKey
-
This is Host β’s private key — replace this value with the actual private key you generated for Host β. This value is secret, and this is the only place where it should live.
- Interface.Address
-
This is Host β’s IP address inside the WireGuard VPN we’re building — replace this value with a suitable value for your network. You can use any address you want for this, but the address should be within the “Private-Use” IPv4 or “Unique-Local” IPv6 address space (like
10.0.0.0/8
— see RFC 6890 for all available address blocks), and should not collide with any other private subnets to which the endpoint itself or any of its peers can connect.This setting isn’t used by WireGuard directly — it’s only used by the
wg-quick
helper service when it sets up a virtual network interface for WireGuard. In order for network packets to be routed correctly to and from this host when they’re outside of the WireGuard tunnel, they need to use the IP address you set here.In a Point to Site topology, this setting on the site’s WireGuard host isn’t very important — typically you want route packets through the site’s WireGuard host (and on to other endpoints in the site), not to the host itself. So you just need to make sure you pick an IP address that isn’t going to collide with any other IP addresses the host can route to.
While you can configure multiple IP addresses for this setting, unless you have a special use-case, you should just use a single IP address (in the form of a
/32
block with an IPv4 address, or a/64
block with an IPv6 address). - Interface.ListenPort
-
This is Host β’s WireGuard port. Host β must be able to receive UDP traffic for new connections on this port from the Internet (or wherever the traffic of the other WireGuard peers with which it will communicate comes from).
With a Point to Site topology, this setting in Host β’s configuration file should be the same as the port in the
Peer.Endpoint
setting of Endpoint A’s configuration file (discussed in the section above). - Peer.PublicKey
-
This is Endpoint A’s public key — replace this value with the actual public key you generated for Endpoint A. This value is not secret; however, it is a globally-unique identifier for Endpoint A.
- Peer.AllowedIPs
-
This is Endpoint A’s IP address inside the WireGuard VPN we’re building — replace this value with a suitable value for your network. You can use any address you want for this, but the address should be within the “Private-Use” IPv4 or “Unique-Local” IPv6 address space (like
10.0.0.0/8
— see RFC 6890 for all available address blocks), and should not collide with any other private subnets to which the endpoint itself or any of its peers can connect.With a Point to Site topology, this setting in Host β’s configuration file should match exactly the
Interface.Address
setting in Endpoint A’s configuration file (discussed in the section above).While you can configure multiple IP addresses for this setting, unless you have a special use-case, with a Point to Site topology you should just use a single IP address (in the form of a
/32
block with an IPv4 address, or a/64
block with an IPv6 address).
Alternate Endpoint Configuration
You will notice that we omitted the Peer.Endpoint
setting from Host β’s configuration file, even though we used it in Endpoint A’s configuration file. In this example, because Endpoint A is configured with Host β’s endpoint address — and to send keepalive packets to Host β every 25 seconds — we don’t need to configure Host β with Endpoint A’s endpoint address. WireGuard will figure out Endpoint A’s address automatically when it receives the first keepalive packet from Endpoint A.
In cases where your remote endpoint has a static IP address — and its firewall allows new connections on its WireGuard port — you can reverse these settings, and include a Peer.Endpoint
setting on the site side, while omitting it from the point side. You can also omit the Peer.PersistentKeepalive
from either side. If we did that in this example, this is what Endpoint A’s wg0.conf
would look like:
# /etc/wireguard/wg0.conf
# local settings for Endpoint A
[Interface]
PrivateKey = AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEE=
Address = 10.0.0.1/32
ListenPort = 51821
# remote settings for Host β
[Peer]
PublicKey = fE/wdxzl0klVp/IR8UcaoGUMjqaWi3jAd7KzHKFS6Ds=
AllowedIPs = 192.168.200.0/24
And this is what Host β’s wg0.conf
file would look like:
# /etc/wireguard/wg0.conf
# local settings for Host β
[Interface]
PrivateKey = ABBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBFA=
Address = 10.0.0.2/32
ListenPort = 51822
# remote settings for Endpoint A
[Peer]
PublicKey = /TOE4TKtAqVsePRVR+5AA43HkAK5DSntkOCO7nYq5xU=
Endpoint = 198.51.100.1:51821
AllowedIPs = 10.0.0.1/32
Configure Routing on Host B
Assuming Host β is a Linux host, we need to configure two things on it:
-
Turn on packet forwarding
-
Set up port forwarding with
iptables
If you don’t have iptables
installed on the host, install it now with your package manager (like sudo apt install iptables
or sudo yum install iptables
etc).
While there are other ways to set these two things up, the simplest way is to add PreUp
commands for them in the [Interface]
section of our WireGuard config file — wg-quick
will execute these for us automatically when it starts the WireGuard interface up (and execute the PostDown
commands when it shuts the interface down).
So update the /etc/wireguard/wg0.conf
file on Host β to add the following Interface.PreUp
and Interface.PostDown
settings:
# /etc/wireguard/wg0.conf
# local settings for Host β
[Interface]
PrivateKey = ABBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBFA=
Address = 10.0.0.2/32
ListenPort = 51822
# packet forwarding
PreUp = sysctl -w net.ipv4.ip_forward=1
# port forwarding
PreUp = iptables -t nat -A PREROUTING -d 192.168.200.2 -p tcp --dport 80 -j DNAT --to-destination 10.0.0.1
PostDown = iptables -t nat -D PREROUTING -d 192.168.200.2 -p tcp --dport 80 -j DNAT --to-destination 10.0.0.1
# remote settings for Endpoint A
[Peer]
PublicKey = /TOE4TKtAqVsePRVR+5AA43HkAK5DSntkOCO7nYq5xU=
AllowedIPs = 10.0.0.1/32
If you’re using IPv6 addresses for your WireGuard VPN, replace net.ipv4.ip_forward
with net.ipv6.conf.all.forwarding
, and iptables
with ip6tables
.
The first PreUp
setting above makes sure that packet forwarding is turned on (this setting is global for the Linux kernel’s networking subsystem). The second PreUp
setting configures iptables
to forward packets sent to port 80
on Host β’s LAN address (192.168.200.2
) over to port 80
on Endpoint A (10.0.0.1
). Because we’re using Endpoint A’s WireGuard address as their new destination, these packets will be forwarded through the WireGuard tunnel between Host β and Endpoint A.
Note that we can forward packets to a different destination port by including the different port in the --to-destination
value. For example, if we wanted to forward port 80
on Host β to port 8080
on Endpoint A, we’d do it like this:
PreUp = iptables -t nat -A PREROUTING -d 192.168.200.2 -p tcp --dport 80 -j DNAT --to-destination 10.0.0.1:8080
The PostDown
command deletes the iptables
rule when wg-quick
brings the interface down. If you change the iptables
rule in the PreUp
command, make sure you make the corresponding change to the rule in the PostDown
command (the two commands should be identical, except the PreUp
command uses the -A
flag, for --append
, whereas the PostDown
command uses the -D
flag, for --delete
).
Start Up WireGuard
On both Endpoint A and Host β, start the wg-quick
service. On Linux with systemd, run the following commands:
$ sudo systemctl enable wg-quick@wg0.service
$ sudo systemctl start wg-quick@wg0.service
On systems without systemd, run this command instead:
$ sudo wg-quick up /etc/wireguard/wg0.conf
Either way, starting up the wg-quick
service will set up a WireGuard network interface named wg0
on the host, and configure some routing rules to route packets destined for any IP address listed in the Peer.AllowedIPs
setting(s) of the /etc/wireguard/wg0.conf
file to go out the wg0
interface.
Note that the name wg0
is just the standard convention for your first WireGuard interface. You can create as many WireGuard interfaces as you like, and name them however you like. For example, you could create another configuration file named /etc/wireguard/mytunnel.conf
, and start it up with the command wg-quick up /etc/wireguard/mytunnel.conf
; this would create a new WireGuard interface named mytunnel
.
But for now, if you ran wg-quick up
directly, you’ll see output like the following:
$ sudo wg-quick up /etc/wireguard/wg0.conf
[#] ip link add wg0 type wireguard
[#] wg setconf wg0 /dev/fd/63
[#] ip -4 address add 10.0.0.1/32 dev wg0
[#] ip link set mtu 1420 up dev wg0
[#] ip -4 route add 10.0.0.2/32 dev wg0
This output shows the routing rules that wg-quick
set up for you automatically.
If you ran systemctl start
instead, you can see the same output by running the journalctl
tool, like so:
$ journalctl -u wg-quick@wg0.service
systemd[1]: Starting WireGuard via wg-quick(8) for wg0...
wg-quick[271288]: [#] ip link add wg0 type wireguard
wg-quick[271288]: [#] wg setconf wg0 /dev/fd/63
wg-quick[271288]: [#] ip -4 route add 10.0.0.1/32 dev wg0
wg-quick[271288]: [#] ip link set mtu 1420 up dev wg0
wg-quick[271288]: [#] ip -4 address add 10.0.0.2/32 dev wg0
systemd[1]: Started WireGuard via wg-quick(8) for wg0.
Test Out the Tunnel
On Endpoint A, if you haven’t already, start up the web server on port 80. On Endpoint B, use curl
(or any other browser) to request a page from Endpoint A:
$ curl 192.168.200.2
If you see any HTML output from this, your WireGuard tunnel works!
Basic Troubleshooting
If curl
hangs, or you see an error like like Connection refused
or No route to host
, you may have neglected to turn on packet forwarding for Host β. Run this command on Host β to double check:
$ sysctl net.ipv4.ip_forward
net.ipv4.ip_forward = 0
Or, if you’re using IPv6 addresses, run the IPv6 variant:
$ sysctl net.ipv6.conf.all.forwarding
net.ipv6.conf.all.forwarding = 0
If the result is 0
, you need to turn on packet forwarding (see the Configure Routing on Host B section above). If the result is 1
, packet forwarding is on.
The next thing to check is to make sure Host β is performing port forwarding for Endpoint A. Run this command on Host β to list out all your iptables
tables rules:
$ sudo iptables-save -c
If you don’t have any iptables
rules in place, the result will be blank. What you should see instead is something like this:
$ sudo iptables-save -c
# Generated ...
*nat
:PREROUTING ACCEPT [0:0]
:INPUT ACCEPT [0:0]
:OUTPUT ACCEPT [12:123]
:POSTROUTING ACCEPT [34:567]
[21:432] -A PREROUTING -d 192.168.200.2/32 -p tcp -m tcp --dport 80 -j DNAT --to-destination 10.0.0.1
COMMIT
# Completed ...
In particular, you should see this rule under the *nat
table:
[21:432] -A PREROUTING -d 192.168.200.2/32 -p tcp -m tcp --dport 80 -j DNAT --to-destination 10.0.0.1
If you don’t have this rule, Host β isn’t going to be able to forward HTTP requests from Endpoint B to Endpoint A. Try following the Configure Routing on Host B section above to set up port forwarding.
The numbers in brackets (like [21:432]
) are the packet and byte count processed by each rule. If you see [0:0]
for the DNAT rule, it means no packets have matched it. If that’s the case, you likely have some other firewall rules or network configuration blocking packets sent to port 80 on Host β.
Otherwise, try running sudo wg
on both Endpoint A and Host β, to see if the WireGuard interface on both is up and configured as you expect.
On Host β, you’ll probably see output like this:
$ sudo wg
interface: wg0
public key: fE/wdxzl0klVp/IR8UcaoGUMjqaWi3jAd7KzHKFS6Ds=
private key: (hidden)
listening port: 51822
peer: /TOE4TKtAqVsePRVR+5AA43HkAK5DSntkOCO7nYq5xU=
allowed ips: 10.0.0.1/32
If Endpoint A had successfully connected, this display would include a “latest handshake” field for the peer, as well as a “transfer” field indicating some data had been received. The above output indicates that Endpoint A has not successfully connected yet.
On Endpoint A, you’ll probably see output like this:
$ sudo wg
interface: wg0
public key: /TOE4TKtAqVsePRVR+5AA43HkAK5DSntkOCO7nYq5xU=
private key: (hidden)
listening port: 51821
peer: fE/wdxzl0klVp/IR8UcaoGUMjqaWi3jAd7KzHKFS6Ds=
endpoint: 203.0.113.2:51822
allowed ips: 192.168.200.0/24
transfer: 0 B received, 123 B sent
persistent keepalive: every 25 seconds
If the “transfer” field indicates some data has been sent to Host β, but none has been received (as it does above), it likely means packets are being blocked or misdirected somewhere between Endpoint A and Host β. If this is the case for you, you need to fiddle with your firewalls or other network configuration until they allow Endpoint A to send UDP packets to Host β via the IP address and port configured in Endpoint A’s Peer.Endpoint
setting (in this example, it’s 203.0.113.2:51822
).
Extra: Configure Firewall on Host B
As long as Site B is not configured to use Host β as a gateway, the only traffic that will be routed successfully between Site B and our WireGuard network will be packets sent to and responding from Endpoint A’s port 80. But as an extra security measure, you may want to add some additional firewall rules to Host β to prevent traffic from your WireGuard network from accessing any services on Host β itself (and if you add additional WireGuard peers to Host β’s network, to prevent those peers from connecting to one another through Host β).
Here are a few simple iptables
rules that you can use to reject WireGuard traffic from accessing local services on Host β itself, and to reject any forwarded WireGuard traffic from being used to make new connections to anything other than port 80 of Endpoint A. First, bring down the WireGuard interface on Host β with wg-quick
or systemctl
:
$ sudo wg-quick down /etc/wireguard/wg0.conf
$ # or alternately:
$ sudo systemctl stop wg-quick@wg0.service
Then edit the /etc/wireguard/wg0.conf
file to add several new Interface.PreUp
and Interface.PostDown
settings, like the following:
# /etc/wireguard/wg0.conf
# local settings for Host β
[Interface]
PrivateKey = ABBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBFA=
Address = 10.0.0.2/32
ListenPort = 51822
# packet forwarding
PreUp = sysctl -w net.ipv4.ip_forward=1
# port forwarding
PreUp = iptables -t nat -A PREROUTING -d 192.168.200.2 -p tcp --dport 80 -j DNAT --to-destination 10.0.0.1
PostDown = iptables -t nat -D PREROUTING -d 192.168.200.2 -p tcp --dport 80 -j DNAT --to-destination 10.0.0.1
# firewall local host from wg peers
PreUp = iptables -A INPUT -i wg0 -j REJECT
PreUp = iptables -A OUTPUT -o wg0 -j REJECT
PostDown = iptables -D INPUT -i wg0 -j REJECT
PostDown = iptables -D OUTPUT -o wg0 -j REJECT
# firewall other hosts from wg peers
PreUp = iptables -A FORWARD -i wg0 -m state --state ESTABLISHED,RELATED -j ACCEPT
PreUp = iptables -A FORWARD -i wg0 -m state --state NEW -d 10.0.0.1 -p tcp --dport 80 -j ACCEPT
PreUp = iptables -A FORWARD -i wg0 -j REJECT
PostDown = iptables -D FORWARD -i wg0 -m state --state ESTABLISHED,RELATED -j ACCEPT
PostDown = iptables -D FORWARD -i wg0 -m state --state NEW -d 10.0.0.1 -p tcp --dport 80 -j ACCEPT
PostDown = iptables -D FORWARD -i wg0 -j REJECT
# remote settings for Endpoint A
[Peer]
PublicKey = /TOE4TKtAqVsePRVR+5AA43HkAK5DSntkOCO7nYq5xU=
AllowedIPs = 10.0.0.1/32
Then bring the interface back up again with wg-quick
or systemctl
:
$ sudo wg-quick up /etc/wireguard/wg0.conf
$ # or alternately:
$ sudo systemctl start wg-quick@wg0.service
The first set of the new PreUp
firewall commands will prevent any WireGuard peers from connecting directly to services on Host β (and vice versa):
PreUp = iptables -A INPUT -i wg0 -j REJECT
PreUp = iptables -A OUTPUT -o wg0 -j REJECT
The second set of PreUp
firewall commands will prevent Host β from forwarding any connections to and from its WireGuard peers, other than connections related to Endpoint A’s port 80:
PreUp = iptables -A FORWARD -i wg0 -m state --state ESTABLISHED,RELATED -j ACCEPT
PreUp = iptables -A FORWARD -i wg0 -m state --state NEW -d 10.0.0.1 -p tcp --dport 80 -j ACCEPT
PreUp = iptables -A FORWARD -i wg0 -j REJECT
For a guide to setting up a more complicated iptables
firewall, check out the “Point to Site” section of the WireGuard Access Control With Iptables article.
To use UFW to set up a firewall similar to the firewall described in this article, see the “Extra: Port Forwarding on Host β” section of the How to Use WireGuard with UFW guide; to use firewalld, see the “Extra: Port Forwarding on Host β” section of the How to Use WireGuard with Firewalld guide; or to use nftables, see the “Point to Site With Port Forwarding” section of the How to Use WireGuard With Nftables guide.