Skip to content

Instantly share code, notes, and snippets.

@dockerlead
Created November 16, 2020 05:04
Show Gist options
  • Save dockerlead/e9f025264b1b2caeba34f5d85fe1e866 to your computer and use it in GitHub Desktop.
Save dockerlead/e9f025264b1b2caeba34f5d85fe1e866 to your computer and use it in GitHub Desktop.
Wireguard on CentOS 7/8

Set Up Your Own WireGuard VPN Server on CentOS

This tutorial is going to show you how to set up your own WireGuard VPN server on CentOS. WireGuard is made specifically for the Linux kernel. It runs inside the Linux kernel and allows you to create fast, modern, and secure VPN tunnel. TL;DR

Prerequisites

This tutorial assumes that the VPN server and VPN client are both running CentOS operating system.

Step 1: Install WireGuard on CentOS Server and Desktop

Log into your CentOS server, then run the following commands to install WireGuard.

# CentOS 8
sudo dnf install elrepo-release epel-release -y
sudo dnf install kmod-wireguard wireguard-tools -y
# CentOS 7
sudo yum install epel-release https://www.elrepo.org/elrepo-release-7.el7.elrepo.noarch.rpm
sudo yum install yum-plugin-elrepo
sudo yum install kmod-wireguard wireguard-tools -y

Then use the same commands to install WireGuard on your local CentOS computer (the VPN client).

Step 2: Generate Public/Private Keypair

Server

sudo mkdir -p /etc/wireguard/
cd /etc/wireguard
wg genkey | sudo tee /etc/wireguard/server_private.key | wg pubkey | sudo tee /etc/wireguard/server_public.key

Client

sudo mkdir -p /etc/wireguard/
cd /etc/wireguard
wg genkey | sudo tee /etc/wireguard/client_private.key | wg pubkey | sudo tee /etc/wireguard/client_public.key

Step 3: Create WireGuard Configuration File

Server

sudo vim /etc/wireguard/wg0.conf

Paste in this content:

[Interface]
Address = 10.10.10.1/24
SaveConfig = true
PrivateKey = private-key-of-your-server
ListenPort = 51820

[Peer]
PublicKey = public-key-of-your-client
AllowedIPs = 10.10.10.2/32

Secure the file like so:

sudo chmod 600 /etc/wireguard/ -R

Client

sudo vim /etc/wireguard/wg-client0.conf

Paste in this content:

[Interface]
Address = 10.10.10.2/24
DNS = 10.10.10.1
PrivateKey = private-key-of-your-client

[Peer]
PublicKey = public-key-of-your-server
AllowedIPs = 0.0.0.0/0 # to allow untunneled traffic, use `0.0.0.0/1, 128.0.0.0/1` instead
Endpoint = public-ip-of-your-server:51820
PersistentKeepalive = 25

Secure the config like so:

sudo chmod 600 /etc/wireguard/ -R

Step 4: Enable IP Forwarding on the Server

sudo vim /etc/sysctl.conf

Add the following line at the end of this file.

net.ipv4.ip_forward = 1
sudo sysctl -p # The -p option will load sysctl settings from /etc/sysctl.conf file. This command will preserve our changes across system reboots.

Step 5: Configure IP Masquerading on the Server

Run the following command to enable IP masquerading in the server firewall.

sudo firewall-cmd --zone=public --permanent --add-masquerade
sudo systemctl reload firewalld

This will hide your VPN network from the outside world. So the Internet can only see your VPN server’s IP, but can’t see your VPN client’s IP, just like your home router hides your private home network.

Step 6: Install a DNS Resolver on the Server

Since we specify the VPN server as the DNS server for client, we need to run a DNS resolver on the VPN server. We can install the bind9 DNS server.

sudo dnf install bind
sudo systemctl start named
sudo systemctl enable named
systemctl status named

Edit the BIND main configuration file /etc/named.conf.

sudo vim /etc/named.conf

In the options clause, you can find the following two lines.

listen-on port 53 { 127.0.0.1; };
listen-on-v6 port 53 { ::1; };

This makes named listen on localhost only. If you want to allow clients in the same network to query domain names, then comment out these two lines. (add double slashes at the beginning of each line)

// listen-on port 53 { 127.0.0.1; };
// listen-on-v6 port 53 { ::1; };

Find the following line.

allow-query { localhost; };

Add the 10.10.10.0/24 network range so that VPN clients can send DNS queries. Note that you need to end each network range with a semicolon.

allow-query { localhost; 10.10.10.0/24; };

Save and close the file. Restart BIND9 for the changes to take effect.

sudo systemctl restart named

Then you need to run the following command to allow VPN clients to connect to port 53.

sudo firewall-cmd --zone=public --permanent --add-rich-rule='rule family="ipv4" source address="10.10.10.0/24" accept'

Step 7: Open WireGuard Port in Firewall

Run the following command to open UDP port 51820 on the server.

sudo firewall-cmd --permanent --add-port=51820/udp
sudo systemctl reload firewalld

Step 8: Start WireGuard

Server

Run the following command on the server to start WireGuard.

sudo wg-quick up /etc/wireguard/wg0.conf

To stop it, run

sudo wg-quick down /etc/wireguard/wg0.conf

You can also use systemd service to start WireGuard.

sudo systemctl start [email protected]

If the start failed, you should check the log to find out what’s wrong.

sudo journalctl -eu [email protected]

Enable auto-start at system boot time with the following command.

sudo systemctl enable [email protected]

Now WireGuard server is ready to accept client connections.

Client

Start WireGuard.

sudo systemctl start [email protected]

Enable auto-start at system boot time.

sudo systemctl enable [email protected]

By default, all traffic on the VPN client will be routed through the VPN server. Sometimes you may want to route only a specific type of traffic, based on the transport layer protocol and the destination port. This is known as policy routing. Policy routing is configured on the client computer, and we need to stop the VPN connection first.

sudo systemctl stop [email protected]

Then edit the client configuration file.

sudo nano /etc/wireguard/wg-client0.conf

For example, if you add the following 3 lines in the [interface] section, then WireGuard will create a routing table named “1234” and add the ip rule into the routing table. In this example, traffic will be routed through VPN server only when TCP is used as the transport layer protocol and the destination port is 25, i.e, when the client computer sends emails.

Table = 1234
PostUp = ip rule add ipproto tcp dport 25 table 1234
PreDown = ip rule delete ipproto tcp dport 25 table 1234

Save and close the file. Then start WireGuard client again.

sudo systemctl start [email protected]

VPN Kill Switch

By default, your computer can access the Internet via the normal gateway when the VPN connection is disrupted. You may want to enable the kill switch feature, which prevents the flow of unencrypted packets through non-WireGuard interfaces. Stop the WireGuard client process.

sudo systemctl stop [email protected]

Edit the client configuration file.

sudo nano /etc/wireguard/wg-client0.conf

Add the following two lines in the [interface] section.

PostUp = iptables -I OUTPUT ! -o %i -m mark ! --mark $(wg show %i fwmark) -m addrtype ! --dst-type LOCAL -j REJECT
PreDown = iptables -D OUTPUT ! -o %i -m mark ! --mark $(wg show %i fwmark) -m addrtype ! --dst-type LOCAL -j REJECT

Like this:

[Interface]
Address = 10.10.10.2/24
DNS = 10.10.10.1
PrivateKey = cOFA+x5UvHF+a3xJ6enLatG+DoE3I5PhMgKrMKkUyXI=
PostUp = iptables -I OUTPUT ! -o %i -m mark ! --mark $(wg show %i fwmark) -m addrtype ! --dst-type LOCAL -j REJECT
PreDown = iptables -D OUTPUT ! -o %i -m mark ! --mark $(wg show %i fwmark) -m addrtype ! --dst-type LOCAL -j REJECT

[Peer]
PublicKey = RaoAdsIEIwgV9DHNSubxWVG+nZ1GP/c3OU6A/efBJ0I=
AllowedIPs = 0.0.0.0/0
Endpoint = 12.34.56.78:51820
PersistentKeepalive = 25

Save and close the file. Then start the WireGuard client.

sudo systemctl start [email protected]

That's it. Happy networking!

@riccardo1991
Copy link

A little remark that made me waste some time.

Before step 5: if for some reason you have to install firewalld because it's missing from your system and you currently connect via ssh on a different port rather than 22, be sure to move back to port 22 in /etc/ssh/sshd_config.
By default ssh is enabled as a service on firewalld, but it's just a "wrapper" to the standard port 22. So activating firewalld without switching back to the standard port is gonna lock you out.

@Pirxster
Copy link

Pirxster commented Jan 8, 2023

I followed the manual and everything works perfectly, except for DNS resolution.

The settings for BIND 9.2 seem to be different, and the entries listen-on port 53 { 127.0.0.1; };
listen-on-v6 port 53 { ::1; }; don't exist in the BIND 9.2 config file.

Yes, it is quite possibly a RTFM case, but I would rather hope to find the shortcut instead of hours and hours study, trial and failure.

I would therefore be infinitely grateful, if you could update the a.m. settings for BIND 9.2.

Thank you!

@truebest
Copy link

truebest commented Aug 4, 2023

[#] ip link add wg0 type wireguard
[#] wg setconf wg0 /dev/fd/63
[#] ip -4 address add 10.10.10.0/24 dev wg0
[#] ip link set mtu 1450 up dev wg0
[#] iptables -I OUTPUT ! -o wg0 -m mark ! --mark $(wg show wg0 fwmark) -m addrtype ! --dst-type LOCAL -j REJECT
iptables v1.8.8 (nf_tables): mark: bad integer value for option "--mark", or out of range.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment