January 24, 2021 - Patrick Kerwood
In this how-to I'll create a WireGuard VPN exit node, which is NAT'ing connections for clients. I will give an example on using both iptables and firewalld and how to forward ports to a WireGuard client.
Create a VPS some where in the world. For this example I'll be using Digital Ocean (opens new window).
WireGuard has a fantastic support for different platforms. In this how-to I will be using CentOS 7 for the server, but have a look at https://www.wireguard.com/install/ (opens new window) for installing on a different platform.
epel-release and the ELRepo (opens new window) repository.
yum install epel-release https://www.elrepo.org/elrepo-release-7.el7.elrepo.noarch.rpm
yum install yum-plugin-elrepo
yum install kmod-wireguard wireguard-tools
Create a directory for the WireGuard configuration files, if it does not exist.
mkdir -p /etc/wireguard
Create keys for the server. Files
wg_public.key will be saved to the
wg genkey | tee /etc/wireguard/wg_private.key | wg pubkey | tee /etc/wireguard/wg_public.key
Create a configuration file for the WireGuard interface at
/etc/wireguard/wg0.conf. Add the content of the
wg_private.key file. The
Address property is the IP address of the VPN network. The server will get the IP address of
[Interface] Address = 10.99.0.1/24 SaveConfig = true ListenPort = 51820 PrivateKey = <wg_private.key>
Enable masquerade and open port
51820 for WireGuard and reload firewalld.
firewall-cmd --permanent --zone public --add-masquerade firewall-cmd --permanent --zone public --add-port=51820/udp firewall-cmd --reload
A lot of other guides will tell you to set
net.ipv4.ip_forward=1. This is not nessacary when using firewalld. The
--add-masquerade option will do this for you.
Enable IPv4 forwarding and make sysctl apply the changes.
echo "net.ipv4.ip_forward = 1" >> /etc/sysctl.conf && sysctl -p
Enable masquerade and open port
51820 for WireGuard. Replace
<public interface> with your servers public interface.
iptables -t nat -A POSTROUTING -o <public interface> -j MASQUERADE iptables -I INPUT 1 -p udp --dport 51820 -j ACCEPT
Remember to make your iptables rules persistant upon reboot. How you do that is out of this scope, but have a look at
Add below lines to your
[Interface] PostUp = iptables -A FORWARD -i wg0 -j ACCEPT PostDown = iptables -D FORWARD -i wg0 -j ACCEPT ...
Bring the WireGuard interface up.
$ wg-quick up wg0 [#] ip link add wg0 type wireguard [#] wg setconf wg0 /dev/fd/63 [#] ip -4 address add 10.99.0.1/24 dev wg0 [#] ip link set mtu 1420 up dev wg0 [#] firewall-cmd --zone internal --add-interface wg0 success
Verify the interface.
$ wg interface: wg0 public key: EgmmIi/UC6F/VlDU37/QpBO1zilROKPS2gLYdudgJFY= private key: (hidden) listening port: 51820
Enable the interface to start on boot.
systemctl enable wg-quick@wg0
Setting up the client is almost the same procedure as setting up the server. Install WireGuard on your client, generate the private and public keys in the
/etc/wireguard directory. Create the
wg0.conf with below content.
[Interface] Address = 10.99.0.2/24 SaveConfig = true PrivateKey = <wg_private.key> [Peer] PublicKey = <server public key> Endpoint = <server ip>:51820 AllowedIPs = 0.0.0.0/0
[Peer] section is the configuration for connecting to the server. The
AllowedIPs property is not only an IP filter, but also the subnets that is going to be routed through the VPN. The value
0.0.0.0/0 tells the client to route all traffic through the VPN.
No specific firewall configuration is needed.
Start the interface.
wg-quick up wg0
If you specified
AllowdIPs, you will lose any SSH connections to the client. Go through the next step and setup the client on the server before activating the interface. To test your connection, you could run
wg-quick up wg0 && sleep 30 && wg-quick down wg0 and see where it goes.
At this point, both the server and client is configured. The last step is to add the client to the server configuration. You can add the
[Peer] section to the server configuration manually or run below command on the server.
wg set wg0 peer <client public key> allowed-ips 10.99.0.2
Because we have the
SaveConfig = true option in the server configuration, WireGuard will save the running config to
wg0.conf, when bringing down the interface. A
[Peer] section will be added for each of your peers.
You can forward connections on a giving port, from the server to a WireGuard client. Below exampels shows how to forward HTTP and HTTPS to the client we setup.
On the server, enable masquerade on the internal interface and forward the ports you want.
firewall-cmd --permanent --zone internal --add-masquerade firewall-cmd --permanent --zone public --add-forward-port=port=443:proto=tcp:toport=443:toaddr=10.99.0.2 firewall-cmd --permanent --zone public --add-forward-port=port=80:proto=tcp:toport=80:toaddr=10.99.0.2 firewall-cmd --reload
Add below lines to the to the
[Interface] section. This will add/remove the
wg0 interface on the internal zone on interface up/down. Remember to bring the interface down before editing
wg0.conf or WireGuard will overwrite your changes.
[Interface] PostUp = firewall-cmd --zone internal --add-interface wg0 PostDown = firewall-cmd --zone internal --remove-interface wg0 ...
On the server, enable masquerade on the
wg0 interface and forward the ports you want.
iptables -t nat -A POSTROUTING -o wg0 -j MASQUERADE iptables -t nat -A PREROUTING -i <public interface> -p tcp --dport 80 -j DNAT --to-destination 10.99.0.2 iptables -t nat -A PREROUTING -i <public interface> -p tcp --dport 443 -j DNAT --to-destination 10.99.0.2