WireGuard Tunnel: Difference between revisions

Jump to navigation Jump to search
no edit summary
m (small note)
No edit summary
This guide will instruct you on how to set up a WireGuard tunnel between a server machine and one or more clients. This establishes a secure tunnel between the machines (connecting them as if they were on the same LAN), and can further be used to route traffic and forward ports.
WIP
 
These instructions are specifically tailored to Linux machines.
Welcome to the official guide on setting up a WireGuard Tunnel. This is useful if you do not want to directly port forward to the internet (e.g. using your own IP to host UserVMs).
 
These instructions are specifically tailored to Linux machines, with nftables.
 
== Prerequisites ==
You'll need:
*A server machine that haswill host the IP address you want to use forWireGuard hostingendpoint
*At least one client machine.
*Basic knowledge of how computers and Linux systems work.
 
== PreparationSetting up the tunnel ==
 
For the purposes of this guide, we are calling our tunnel <code>wg0</code>. If you would like to use a different name, make sure to substitute <code>wg0</code> with the interface name of your choice in all commands and config files.
 
We will be using <code>10.0.32.0/24</code> as our WireGuard subnet for the purposes of this guide.
 
=== Install Dependencies ===
First up, make sure you have wireguard-tools and nftables installed on both your server machine, and your client machines.
{{code|lang=bash|<nowiki>
$ sudo pacman --needed --noconfirm -Sy wireguard-tools nftables # Arch
$ sudo apt-get install -y wireguard-tools nftables # Debian
</nowiki>
}}
 
=== EnableGenerating IPthe ForwardingKeys ===
Now, we need to generate a public and private key for each system that will be in the tunnel. You can use these commands on each computer, as root:
This is only necessary on the server machine, unless you will be hosting UserVMs. In that case, you might want to enable it on your client as well.
 
{{code|lang=bash|<nowiki>
As root, do the following.
$ sudo -i
{{code|<nowiki>
# mkdir -p /etc/wireguard/keys/wg0 # Create a directory for the keys
# sysctl -w net.ipv4.ip_forward=1
</nowiki>
}}
 
To make your changes persistent, you will need to edit your sysctl conf file(s).
On Ubuntu, you can find ipv4 forwarding commented out in <code>/etc/sysctl.conf</code>
 
== Setting Up The Tunnel ==
 
=== Key Setup ===
Now we can begin the actual setup.
 
On your server machine AND your client machine, as root, do the following steps separately.
{{code|lang=bash|
# mkdir -p /etc/wireguard/keys/wg0
# cd /etc/wireguard/keys/wg
# umask 077 # Temporarily set the default permissions for all files to rwx------
# umask 077
# wg genkey</nowiki> > <nowiki>private.key # Generate the private key
# wg pubkey</nowiki> < <nowiki>private.key</nowiki> > <nowiki>public.key # Derive the public key from the private key
}}
 
# cat private.key
=== Server wg0.conf ===
/ExampleServerPrivateKey=
For demonstration purposes, we will be using <code>10.0.32.0/24</code> as our subnet. The server will have <code>10.0.32.1</code> assigned on the wg0 interface.
# cat public.key
/ExampleServerPublicKey=
</nowiki>}}
 
=== Configuring the tunnel (Server) ===
Create <code>/etc/wireguard/wg0.conf</code> and put the following in it.
On your server machine, create <code>/etc/wireguard/wg0.conf</code> and put the following in it.
 
{{code|lang=ini|
[Interface]
<nowiki>PrivateKey = </nowiki> <pastePaste serveryour private.key from the SERVER> <nowiki>
Address = 10.0.32.1/32
ListenPort = 51820
</nowiki>
}}
This will assign your WireGuard server with the IP <code>10.0.32.1</code> on the WireGuard tunnel, and listen on UDP port <code>51820</code>
 
Next, add the clients. In the server's wg0.conf, add the following for each client:
You can use <code>cat private.key</code> and copy the output of this command to paste in the key.
 
 
For every client you will connect, you also want to add this. For demonstration purposes, our first client will have <code>10.0.32.2</code> assigned.
{{code|lang=ini|
[Peer]
<nowiki>PublicKey =</nowiki> <pastePaste client'sthe PUBLIC public.key from the CLIENT>
<nowiki>AllowedIPs = 10.0.32.2/32</nowiki>
}}
Repeat for each client, making sure to give each client a different ip address.
 
This will give the specified client an IP address of <code>10.0.32.2</code> on the WireGuard tunnel. Make sure you increment this for each client and use the correct public keys.
=== Bringing Your WireGuard Server Up ===
Now that we have configured our server, we can start the WireGuard service.
Run the following as root to start the WireGuard service on a systemd machine.
{{code|lang=bash|
# systemctl enable --now wg-quick@wg0
}}
 
Here is an example of a completed server wg0.conf:
Run <code># journalctl -xeu wg-quick@wg0</code> to make sure that WireGuard started properly.
 
{{code|lang=ini|<nowiki>
=== Client wg0.conf ===
[Interface]
Now, on your client(s), create <code>/etc/wireguard/wg0.conf</code> as well and put the following in. For demonstration purposes, we are using <code>10.0.32.2</code> once more.
PrivateKey = /ExampleServerPrivateKey=
Address = 10.0.32.1/32
ListenPort = 51820
 
[Peer]
PublicKey = /ExampleClientPublicKey1=
AllowedIPs = 10.0.32.2/32
 
[Peer]
PublicKey = /ExampleClientPublicKey2=
AllowedIPs = 10.0.32.3/32
 
[Peer]
PublicKey = /ExampleClientPublicKey3=
AllowedIPs = 10.0.32.4/32
</nowiki>}}
 
=== Configuring the tunnel (Client) ===
Now, on your client(s), create <code>/etc/wireguard/wg0.conf</code> as well and put the following in
{{code|lang=ini|
[Interface]
<nowiki>PrivateKey =</nowiki> (paste<Paste client'syour PRIVATE private.key) from THIS CLIENT>
<nowiki>Address = 10.0.32.2/24</nowiki>
 
<nowiki>[Peer]
PublicKey =</nowiki> (paste<Paste server'sthe PUBLIC public.key) from the SERVER>
<nowiki>AllowedIPs = 10.0.32.0/24
Endpoint =</nowiki> <Your server's IP ipaddress>:51820
}}
 
Make SURE to use the correct combination of IP address and private key defined in a <code>[Peer]</code> section in the server configuration.
Once this is done, start the WireGuard service on the client as well.
 
If everything is set up properly, you should be able to ping 10.0.32.1 on the client machine.
=== Bringing Your WireGuard Tunnel Up ===
Now that we have configured our server and clients, we can start the tunnel. The following command will start the tunnel, and configure it to be started on every boot. Run it on your server and all your clients.
 
{{code|lang=bash|
#sudo systemctl enable --now wg-quick@wg0
}}
If the connection isn't properly established, you should check if you have properly opened port 51820 on the server. This port is UDP.
 
After pinging 10.0.32.1, you should also doRun <code>#sudo systemctl status wg show-quick@wg0</code> to make sure the handshakethat isWireGuard successfullystarted establishedproperly.
 
=== TrafficTest Routingthe connection ===
 
Assuming everything started correctly, each machine should now have a <code>wg0</code> interface with the correct IP assigned to it. Test the connection from one of the clients with ping:
=== Server nftables Configuration ===
Now that we have successfully established a link between the WireGuard server and our client, it is time to set up nftables on the server.
 
{{code|lang=bash|<nowiki>
We must note first, however, that eth0 in the code snippet below is the interface that is connected to the internet on the server. This may be different between systems, so change it to match.
$ ping 10.0.32.1
To get internet access working on the client before we route all traffic through the server, we must add this to nftables on the server.
PING 10.0.32.1 (10.0.32.1) 56(84) bytes of data.
{{code|lang=ini|
64 bytes from 10.0.32.1: icmp_seq=1 ttl=64 time=1.99 ms
64 bytes from 10.0.32.1: icmp_seq=2 ttl=64 time=1.81 ms
64 bytes from 10.0.32.1: icmp_seq=3 ttl=64 time=1.76 ms
(...)
</nowiki>}}
 
If all went well, congratulations! You now have a secure tunnel between your server and all of your WireGuard clients. Continue reading for how to configure it to your liking
table inet nat {
chain postrouting {
type nat hook postrouting priority srcnat; policy accept;
meta iifname wg0 meta oifname eth0 snat ip to <server ip here>
}
}
 
== Routing traffic ==
You may want to set up your WireGuard server as a router, so that all outbound traffic from one or more of your clients goes through the server (the common definition of a VPN). This is very easy to do.
 
=== Enable IP Forwarding ===
First, we enable IP forwarding on the server machine. This instructs the Linux kernel that when it receives a packet from one of your clients destined to the internet, it should route that packet to its destination.
 
Run the following command to enable IP forwarding in the sysctl configuration:
{{code|lang=bash|<nowiki>
echo 'net.ipv4.ip_forward = 1' | sudo tee /etc/sysctl.d/router.conf
sudo sysctl --system
</nowiki>
}}
 
=== Configuring SNAT ===
The following is an example of what <code>/etc/nftables.conf</code> could look like as a result.
With IP forwarding enabled, the next step is to set an SNAT rule. This instructs the server that when it routes a packet from your client to the internet, it should also replace the source IP address (the client's internal WireGuard IP) with its own public IP. This can be accomplished through the NFTables firewall.
{{code|lang=ini|
#!/usr/sbin/nft -f
 
First, get the name of the server's internet-facing network interface, and it's public IP address. For example, we will use <code>eth0</code> as the interface.
flush ruleset
 
Now, open <code>/etc/nftables.conf</code> and configure as follows:
table inet filter {
{{code|lang=ini|
chain input {
type filter hook input priority filter;
}
chain forward {
type filter hook forward priority filter;
}
chain output {
type filter hook output priority filter;
}
}
 
table inet nat {
chain postrouting {
type nat hook postrouting priority srcnat; policy accept;
meta iifname wg0 meta oifname eth0 snat ip to <Enter server's public IP ipaddress here>
}
}
 
}}
 
Reload the NFTables configuration:
=== Final Client Changes ===
At this point, you are encouraged to test via the client whether you can reach the internet.
If you can afford to lose internet on the client, you can change <code>AllowedIPs</code> in <code>/etc/wireguard/wg0.conf</code> to <code>0.0.0.0/0</code>.
 
{{code|lang=bash|
An example is provided of what this should look like afterward.
sudo nft -f /etc/nftables.conf
}}
 
Depending on distro and prior configuration, you may already have a <code>table inet nat</code> block, and possibly a <code>chain postrouting</code> inside it. In this case, merge the above configuration with your own. Otherwise, paste the above snippet into the bottom of the file.
{{code|lang=ini|
 
<nowiki>
=== Configure the client route ===
 
Now, all you need to do is configure WireGuard on the client to route all traffic through the server. You do this by configuring the <code>[Peer]</code> section on the client to have an <code>AllowedIPs</code> value of <code>0.0.0.0/0</code>. For example:
 
{{code|lang=ini|<nowiki>
[Interface]
PrivateKey = client private key/ExampleClientPrivateKey1=
Address = 10.0.32.2/24
 
[Peer]
PublicKey = server public key/ExampleServerPublicKey=
AllowedIPs = 0.0.0.0/0
Endpoint = server ip:51820 </nowiki>
</nowiki>}}
 
Restart the WireGuard tunnel on the client:
 
{{code|lang=bash|
sudo systemctl restart wg-quick@wg0
}}
 
If all went well, all traffic on the client should now be routed through the server:
If this does in fact work, then you have successfully completed your WireGuard tunnel.
 
{{code|<nowiki>
== Extras ==
$ curl ipinfo.io/what-is-my-ip
While by this point you may have already set up the tunnel, there are some things you might want to add on to the setup. For example, you might want to pass through ports from your client to the server.
{
"ip": "143.244.47.86",
"hostname": "unn-143-244-47-86.datapacket.com",
"city": "Weehawken",
"region": "New Jersey",
"country": "US",
"loc": "40.7696,-74.0204",
"org": "AS212238 Datacamp Limited",
"postal": "07086",
"timezone": "America/New_York",
"readme": "https://ipinfo.io/missingauth"
}
</nowiki>}}
 
== Port Forwarding ==
You may want to forward ports on your server's public IP to the guest. This is very easy to do. We will update the server's NFTables configuration to set a DNAT rule. The following example will forward TCP ports 80 and 443 to the client at <code>10.0.32.2</code>.
{{code|lang=ini|
 
=== Port Forwarding ===
This is what the nftables rule would look like for forwarding a port from a specified client machine to the internet. This is done on the server machine.
For this example, we are using port <code>6004</code> (Standard CVM server port) and <code>10.0.32.2</code> which is our client machine.
{{code|lang=bash|
table inet nat {
chain prerouting {
type nat hook prerouting priority dstnat; policy accept;
meta iifname eth0 tcp dport 6004{ 80, 443 } dnat ip to 10.0.32.2
}
}
 
}}
 
Make sure to change <code>eth0</code> to your server's public interface if it differs. Note that this rule goes into the <code>prerouting</code> chain, NOT the previously used <code>postrouting</code> chain.
This is what the nat table should look like in the end. Your result may be different depending on your setup.
 
Note the new prerouting chain before the postrouting chain.
Reload the NFTables configuration:
 
{{code|lang=bash|
sudo nft -f /etc/nftables.conf
table inet nat {
chain prerouting {
type nat hook prerouting priority dstnat; policy accept;
meta iifname eth0 tcp dport 6004 dnat ip to 10.0.32.2
}
 
chain postrouting {
type nat hook postrouting priority srcnat; policy accept;
meta iifname wg0 meta oifname eth0 snat ip to SERVERIPHERE
}
}
}}
 
If all went well, connections to ports 80 and 443 on the server's public IP should now be forwarded to the HTTP server running on the client at <code>10.0.32.2</code>.
You can test if the port forward is working by running <code>netcat -l -p 6004</code> on the client that you forwarded the port from. If the port forward is working properly, <code>netcat SERVERIPHERE 6004</code> should allow you to send messages back and forth from both machines.
 
You can also test this by setting up a UserVM on your client with the [[UserVM Handbook]].
 
=== WIP ===
I don't really have much else here, feel free to contribute to this page.

Navigation menu