FICUSONLINE F9E
VPN Connection by WireGuard(AWS: EC2 or Lightsail)
WireGuard itself is not server software, but VPN (Virtual Private Network) software that establishes peer-to-peer connections between terminals.
Takanobu FuseAdministrator

11 min read

3 years ago

Cloud / Server

Build a VPN server with WireGuard on AWS (EC2 or Lightsail).

WireGuard itself is not server software, but VPN (Virtual Private Network) software that establishes peer-to-peer connections between terminals. The software installed on both side of server and client is the same, and each runs as a peer (client) or server by defining the configuration file. Compared to conventional VPN servers such as OpenVPN, it is more secure, lighter, and has a very stable connection.

It is easy to understand that the relationship between the server and the peer (client) in the VPN corresponds to the relationship between the home router and the PC in the home.

Wireguard Concept

The advantages of introducing WireGuard are as follows.

  • Access to sites limited to users from Japan to overseas by specifying the region of the server (viewing programs provided by media sites in each country, etc.)
  • Access to a home server that is not assigned a global IP (by reverse proxy)

Reference

WireGuard: fast, modern, secure VPN tunnel

How To Set Up WireGuard on Ubuntu 20.04 | DigitalOcean

Getting Started with WireGuard

Docker WireGuard

GitHub - linuxserver/docker-wireguard


0. Prerequisite

As a preliminary preparation, prepare an instance (EC2 or Lightsail) by AWS on the server side. Make sure you have an SSH connection to your instance. The recommended service is Lightsail. Even if you select a 3.5 USD Linux instance as a VPN server by WireGuard, the upper limit of the data transfer amount is set to 1 TB, the memory is 512 MB, and the disk capacity is 20 GB, which are sufficient specifications.

Lightsail Instance


1. Install WireGuard

The installation procedure is the same on both the server side and the client side. Install the same software on the server side and the peer (client) side.

$ sudo apt update
$ sudo apt install wireguard

After installation, create a private and public key from WireGuard's "wg genkey" and "wg pubkey" commands. The umask command imposes owner-only restrictions on access to these files and directories created within the shell. This setting is reset at the end of the shell.

$ umask 077

Create Private Key

Create the private key by "wg genkey" command and save it as private.key.

$ wg genkey | sudo tee /etc/wireguard/private.key

Create Public Key

Create the public key by "wg pubkey" command from the private key created from the above, and save it as the public.key.

$ sudo cat /etc/wireguard/private.key | wg pubkey | sudo tee /etc/wireguard/public.key

2. Define Local IP

Defines the IP range and type (IP4, IP6, or both) of the VPN network used by WireGuard. This time, only IP4 is defined, and 10.8.0.0/24 is selected from the following addresses that are typically used as local IPs.

  • 10.0.0.0 to 10.255.255.255 (10/8 prefix)
  • 172.16.0.0 to 172.31.255.255 (172.16/12 prefix)
  • 192.168.0.0 to 192.168.255.255 (192.168/16 prefix)

3. IP Forwarding on The Server

Set IP forwarding to connect to the Internet from the network interface wg0 by WireGuard via the server network interface eth0.

$ sudo nano /etc/sysctl.conf

Comment out the following section and set it to 1.

sysctl.conf

net.ipv4.ip_forward=1

The above settings will be adopted.

$ sudo sysctl -p
output
net.ipv4.ip_forward = 1

Use the following command to check the network interface.

$ ip route list default

Output
default via 203.0.113.1 dev eth0 proto static

In this case, the interface connected to the Internet is eth0.


4. Create Configuration File

Create configuration files on the server side and peer (client) side respectively. The name of the network interface is wg0, which is the name of the configuration file without the extension.

Configuration File on The Server

As necessary information,

  • Contents in the private.key file created on the server side
  • Contents in the public.key file created on the peer (client) side
  • Local IP (range) assigned to the server side: 10.8.0.1/24
  • Accepted IP (range) on the peer (client) side: 10.8.0.2/32
  • Specify the default 51820 for the port. Note) Open this port (in) on the AWS instance.
$ sudo nano /etc/wireguard/wg0.conf

wg0.conf

[Interface]
Address = 10.8.0.1/24
SaveConfig = true
PostUp = iptables -t nat -I POSTROUTING -o eth0 -j MASQUERADE
PreDown = iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE
ListenPort = 51820
PrivateKey = server_private_key

[Peer]
PublicKey = peer_client_public_key
AllowedIPs = 10.8.0.2/32
  • iptables -t nat -I POSTROUTING -o eth0 -j MASQUERADE - This rule configures masquerading, and rewrites IPv4 traffic that comes in on the wg0 VPN interface to make it appear like it originates directly from the WireGuard Server’s public IPv4 address.
  • SaveConfig saves the connection peer information at the end.

Configuration File on The Peer(Client)

As necessary information,

  • Contents in the private.key file created on the peer(client) side
  • Contents in the public.key file created on the server side
  • Server-side global IP: Port: instance_global_IP: 51820
  • Local IP (range) assigned to the peer (client) side: 10.8.0.2/24
$ sudo nano /etc/wireguard/wg0.conf

wg0.conf

[Interface]
Address = 10.8.0.2/24
PrivateKey = peer_client_private_key

#optional below
#PostUp = ip rule add table 200 from 192.168.1.xxx
#PostUp = ip route add table 200 default via 192.168.1.1
#PreDown = ip route delete table 200 default via 192.168.1.1
#PreDown = ip rule delete table 200 from 192.168.1.xxx
#DNS = 1.1.1.1

[Peer]
PublicKey = server_public_key
AllowedIPs = 0.0.0.0/0
Endpoint = instance_global_IP:51820
PersistentKeepalive = 25

Specify 0.0.0.0/0 for Allowed IPs to use the server as a gateway to the Internet.

Note) #For details on optional parts, please refer the below.

How To Set Up WireGuard on Ubuntu 20.04 | DigitalOcean

If you set DNS option, need to install resolvconf.

$ sudo apt install resolvconf

About "PersistentKeepalive = ", please see the below:

Quick Start - WireGuard

NAT and Firewall Traversal Persistence

By default, WireGuard tries to be as silent as possible when not being used; it is not a chatty protocol. For the most part, it only transmits data when a peer wishes to send packets. When it’s not being asked to send packets, it stops sending packets until it is asked again. In the majority of configurations, this works well. However, when a peer is behind NAT or a firewall, it might wish to be able to receive incoming packets even when it is not sending any packets. Because NAT and stateful firewalls keep track of “connections”, if a peer behind NAT or a firewall wishes to receive incoming packets, he must keep the NAT/firewall mapping valid, by periodically sending keepalive packets. This is called persistent keepalives. When this option is enabled, a keepalive packet is sent to the server endpoint once every interval seconds. A sensible interval that works with a wide variety of firewalls is 25 seconds. Setting it to 0 turns the feature off, which is the default, since most users will not need this, and it makes WireGuard slightly more chatty. This feature may be specified by adding the PersistentKeepalive = field to a peer in the configuration file, or setting persistent-keepalive at the command line. If you don’t need this feature, don’t enable it. But if you’re behind NAT or a firewall and you want to receive incoming connections long after network traffic has gone silent, this option will keep the “connection” open in the eyes of NAT.


5. Start VPN Server

First, start the server side. Enable and then start the WireGuard system daemon.

$ sudo systemctl enable [email protected]
$ sudo systemctl start [email protected]

Check Status

$ sudo systemctl status [email protected]
 
Output
● [email protected] - WireGuard via wg-quick(8) for wg0
     Loaded: loaded (/lib/systemd/system/[email protected]; enabled; vendor preset: enabled)
     Active: active (exited) since Wed 2021-08-25 15:24:14 UTC; 5s ago
       Docs: man:wg-quick(8)
             man:wg(8)
             https://www.wireguard.com/
             https://www.wireguard.com/quickstart/
             https://git.zx2c4.com/wireguard-tools/about/src/man/wg-quick.8
             https://git.zx2c4.com/wireguard-tools/about/src/man/wg.8
    Process: 3245 ExecStart=/usr/bin/wg-quick up wg0 (code=exited, status=0/SUCCESS)
   Main PID: 3245 (code=exited, status=0/SUCCESS)

Aug 25 15:24:14 wg0 wg-quick[3245]: [#] wg setconf wg0 /dev/fd/63
Aug 25 15:24:14 wg0 wg-quick[3245]: [#] ip -4 address add 10.8.0.1/24 dev wg0
Aug 25 15:24:14 wg0 wg-quick[3245]: [#] ip -6 address add fd0d:86fa:c3bc::1/64 dev wg0
Aug 25 15:24:14 wg0 wg-quick[3245]: [#] ip link set mtu 1420 up dev wg0
Aug 25 15:24:14 wg0 wg-quick[3245]: [#] ufw route allow in on wg0 out on eth0
Aug 25 15:24:14 wg0 wg-quick[3279]: Rule added
Aug 25 15:24:14 wg0 wg-quick[3279]: Rule added (v6)
Aug 25 15:24:14 wg0 wg-quick[3245]: [#] iptables -t nat -I POSTROUTING -o eth0 -j MASQUERADE
Aug 25 15:24:14 wg0 wg-quick[3245]: [#] ip6tables -t nat -I POSTROUTING -o eth0 -j MASQUERADE
Aug 25 15:24:14 wg0 systemd[1]: Finished WireGuard via wg-quick(8) for wg0.

Stop

$ sudo systemctl stop [email protected]

Check the connection status

You can check which client you are connected to and the amount of packets.

$ sudo wg
 
Output
interface: wg0
 public key: U9uE2kb/nrrzsEU58GD3pKFU3TLYDMCbetIsnV8eeFE=
 private key: (hidden)
 listening port: 51820

peer: PeURxj4Q75RaVhBKkRTpNsBPiPSGb5oQijgJsTa29hg=
 allowed ips: 10.8.0.2/32, fd0d:86fa:c3bc::/128

6. Connection to The Server from The Peer(Client)

Connect while the server is running.

Connect

$ sudo wg-quick up wg0
Output
[#] ip link add wg0 type wireguard
[#] wg setconf wg0 /dev/fd/63
[#] ip -4 address add 10.8.0.2/24 dev wg0
[#] ip -6 address add fd0d:86fa:c3bc::2/64 dev wg0
[#] ip link set mtu 1420 up dev wg0
[#] resolvconf -a tun.wg0 -m 0 -x
[#] wg set wg0 fwmark 51820
[#] ip -6 route add ::/0 dev wg0 table 51820
[#] ip -6 rule add not fwmark 51820 table 51820
[#] ip -6 rule add table main suppress_prefixlength 0
[#] ip6tables-restore -n
[#] ip -4 route add 0.0.0.0/0 dev wg0 table 51820
[#] ip -4 rule add not fwmark 51820 table 51820
[#] ip -4 rule add table main suppress_prefixlength 0
[#] sysctl -q net.ipv4.conf.all.src_valid_mark=1
[#] iptables-restore -n

Stop

$ sudo wg-quick down wg0

Check the connection status

$ sudo wg
 
Output
interface: wg0
 public key: PeURxj4Q75RaVhBKkRTpNsBPiPSGb5oQijgJsTa29hg=
 private key: (hidden)
 listening port: 49338
 fwmark: 0xca6c

peer: U9uE2kb/nrrzsEU58GD3pKFU3TLYDMCbetIsnV8eeFE=
 endpoint: 203.0.113.1:51820
 allowed ips: 10.8.0.0/24, fd0d:86fa:c3bc::/64
 latest handshake: 1 second ago
 transfer: 6.50 KiB received, 15.41 KiB sent

Use the following curl command to check whether the IP of the peer (client) has been changed to the public IP of the server.

$ curl https://ipinfo.io/ip

7. Multiple Peers Connection

To connect multiple peers (clients), install WireGuard, create a private and public key, and describe the server information in the configuration file wg0.conf in the newly connected peer 2 as well as peer 1.

Wireguard Multi Concept 1

Peer2 IP Address:10.8.0.3

Peer2: wg0.conf

[Interface]
Address = 10.8.0.3/24
PrivateKey = peer2_client2_private_key

#optional below
#PostUp = ip rule add table 200 from 192.168.1.xxx
#PostUp = ip route add table 200 default via 192.168.1.1
#PreDown = ip rule delete table 200 from 192.168.1.xxx
#PreDown = ip route delete table 200 default via 192.168.1.1
#DNS = 1.1.1.1

[Peer]
PublicKey = server_public_key
AllowedIPs = 0.0.0.0/0
Endpoint = instance_global_IP:51820
PersistentKeepalive = 25

Add the newly added peer 2 information to the server-side configuration file wg0.conf.

Server: wg0.conf

[Interface]
Address = 10.8.0.1/24
SaveConfig = true
PostUp = iptables -t nat -I POSTROUTING -o eth0 -j MASQUERADE
PreDown = iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE
ListenPort = 51820
PrivateKey = server_private_key

[Peer]
PublicKey = peer_client_public_key
AllowedIPs = 10.8.0.2/32

[Peer]
PublicKey = peer2_client2_public_key
AllowedIPs = 10.8.0.3/32

After restart WireGuard on the Server Side,

$ sudo systemctl restart [email protected]

Run WireGuard on the Peer 2.

$ sudo wg-quick up wg0

The contents of this blog will also be posted on the forum, and supplements and corrections will be followed on the forum same topic.

https://forum.ficusonline.com/t/topic/436

Added at 2021/12/28 : Reprinted additional content in the forum


Examples of Using WireGuard

By using the WireGuard network, it is possible to operate a server (multi-domain) with a fixed IP (AWS instance) even on a host machine to which a global IP is not assigned.


Method 1: Deply a proxy server on the VPN server

Deploy the Nginx proxy server on the instance used as the VPN server and specify the port number of Peer2: 10.0.8.3 for each domain.

Wireguard Web Proxy


Method 2: Apply iptables port forwarding rules(Recommended)

Add iptables port forwarding rules on the VPN Server.

$ sudo iptables -t nat -A PREROUTING -p tcp -i eth0 --dport 443 -j DNAT --to-destination 10.8.0.3:443
$ sudo iptables -A FORWARD -p tcp -d 10.8.0.3 --dport 443 -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT

Note) The lower part of the above command is required when the firewall is set.

Deploy the Proxy Sever on Peer2

Wireguard Web Iptables