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.
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.
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
to10.255.255.255
(10/8 prefix)172.16.0.0
to172.31.255.255
(172.16/12 prefix)192.168.0.0
to192.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 thewg0
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 settingpersistent-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.
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.
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