Ruixiang
  • Home
  • Work
  • Projects
  • Wiki
Ruixiang
Ruixiang

Wireguard

Setup Wireguard on AWS

Tested Environment

  • Debian 10.5 on AWS
  • Ubuntu 20.04 on AWS

Install wireguard on server

$ sudo apt-get install wireguard-dkms wireguard-tools linux-headers-$(uname -r)

Note that the package "linux-headers-$(uname -r)" is necessary to run wireguard.

Next we need to enable IP Forwarding. Open "/etc/sysctl.conf" and search for the line "#net.ipv4.ip_forward". Uncomment this line by removing the # at the beginning. It should look like this:

net.ipv4.ip_forward=1

Generate server and client keys

You will need root privilege to manipuate the "/etc/wireguard" directory

$ sudo -i
$ cd /etc/wireguard
$ umask 077
$ wg genkey | tee server_private_key | wg pubkey \> server_public_key

You will need to create a key pair for each client (more deails below, not needed for now)

$ wg genkey | tee <client_private_key_name\> | wg pubkey \> <client_public_key_name\>

Generate server and client keys

You will need root privilege to manipuate the "/etc/wireguard" directory

$ sudo -i
$ cd /etc/wireguard
$ umask 077
$ wg genkey | tee server_private_key | wg pubkey \> server_public_key

You will need to create a key pair for each client (more deails below, not needed for now)

$ wg genkey | tee <client_private_key_name\> | wg pubkey \> <client_public_key_name\>

Create server configuration file

Create a file "/etc/wireguard/wg0.conf" with the following content

[Interface]
Address = 10.200.200.1/24
SaveConfig = true
PostUp = /etc/wireguard/iptable-set.sh
PostDown = /etc/wireguard/iptable-reset.sh
ListenPort = 51820
PrivateKey = <insert server_private_key\>
[Peer]
PublicKey = <insert client_public_key\>
AllowedIPs = 10.200.200.2/32

Note in the above example,

  • "10.200.200.0" range is used for the VPN network. You can change it to other preferred ranges
  • The ListenPort has to be accesible and you will need to add a rule in your Firewall to allow "UDP:<ListenPort>"
  • Two scripts are used to set up or recover the routing table when you bring up or down the VPN network

The setup script:

#!/bin/bash
# Reference:
# [1] https://www.ckn.io/blog/2017/11/14/wireguard-vpn-typical-setup/
# [2] https://www.cyberciti.biz/faq/how-to-set-up-wireguard-firewall-rules-in-linux/
IN_FACE="eth0" # NIC connected to the internet
WG_FACE="wg0" # WG NIC
SUB_NET="10.200.200.0/24" # WG IPv4 sub/net aka CIDR
WG_PORT="51820" # WG udp port
# track VPN connection
/sbin/iptables -A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
/sbin/iptables -A FORWARD -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
# allow incoming VPN traffic on the listening port
/sbin/iptables -A INPUT -p udp -m udp --dport $WG_PORT -m conntrack --ctstate NEW -j ACCEPT
# allow both TCP and UDP recursive DNS traffic
/sbin/iptables -A INPUT -s $SUB_NET -p tcp -m tcp --dport 53 -m conntrack --ctstate NEW -j ACCEPT
/sbin/iptables -A INPUT -s $SUB_NET -p udp -m udp --dport 53 -m conntrack --ctstate NEW -j ACCEPT
# allow forwarding of packets between interfaces
/sbin/iptables -A FORWARD -i $WG_FACE -o $WG_FACE -m conntrack --ctstate NEW -j ACCEPT
/sbin/iptables -A FORWARD -i $IN_FACE -o $WG_FACE -m conntrack --ctstate NEW -j ACCEPT
/sbin/iptables -A FORWARD -i $WG_FACE -o $IN_FACE -m conntrack --ctstate NEW -j ACCEPT
# set up nat
/sbin/iptables -t nat -A POSTROUTING -s $SUB_NET -o $IN_FACE -j MASQUERADE

The recovery script:

#!/bin/bash
IN_FACE="eth0" # NIC connected to the internet
WG_FACE="wg0" # WG NIC
SUB_NET="10.200.200.0/24" # WG IPv4 sub/net aka CIDR
WG_PORT="51820" # WG udp port
# allow incoming VPN traffic on the listening port
/sbin/iptables -D INPUT -p udp -m udp --dport $WG_PORT -m conntrack --ctstate NEW -j ACCEPT
# allow both TCP and UDP recursive DNS traffic
/sbin/iptables -D INPUT -s $SUB_NET -p tcp -m tcp --dport 53 -m conntrack --ctstate NEW -j ACCEPT
/sbin/iptables -D INPUT -s $SUB_NET -p udp -m udp --dport 53 -m conntrack --ctstate NEW -j ACCEPT
# allow forwarding of packets between interfaces
/sbin/iptables -D FORWARD -i $WG_FACE -o $WG_FACE -m conntrack --ctstate NEW -j ACCEPT
/sbin/iptables -D FORWARD -i $IN_FACE -o $WG_FACE -m conntrack --ctstate NEW -j ACCEPT
/sbin/iptables -D FORWARD -i $WG_FACE -o $IN_FACE -m conntrack --ctstate NEW -j ACCEPT
# set up nat
/sbin/iptables -t nat -D POSTROUTING -s $SUB_NET -o $IN_FACE -j MASQUERADE

Configure DNS

Here "ubound" is used to provide DNS

$ apt-get install unbound unbound-host dnsutils

Download the list of root DNS servers

$ curl -o /var/lib/unbound/root.hints https://www.internic.net/domain/named.cache
$ chown -R unbound:unbound /var/lib/unbound
$ cd /etc/unbound/unbound.conf.d
$ nano unbound_srv.conf

Add the following content

server:
num-threads: 4
#Enable logs
verbosity: 1
#list of Root DNS Server
root-hints: "/var/lib/unbound/root.hints"
#Use the root servers key for DNSSEC
#auto-trust-anchor-file: "/var/lib/unbound/root.key"
#Respond to DNS requests on all interfaces
interface: 0.0.0.0
max-udp-size: 3072
#Authorized IPs to access the DNS Server
access-control: 0.0.0.0/0 refuse
access-control: 127.0.0.1 allow
access-control: 10.200.200.0/24 allow
#not allowed to be returned for public internet names
private-address: 10.200.200.0/24
# Hide DNS Server info
hide-identity: yes
hide-version: yes
#Limit DNS Fraud and use DNSSEC
harden-glue: yes
harden-dnssec-stripped: yes
harden-referral-path: yes
#Add an unwanted reply threshold to clean the cache and avoid when possible a DNS Poisoning
unwanted-reply-threshold: 10000000
#Have the validator print validation failures to the log.
val-log-level: 1
#Minimum lifetime of cache entries in seconds
cache-min-ttl: 1800
#Maximum lifetime of cached entries
cache-max-ttl: 14400
prefetch: yes
prefetch-key: yes

Now restart unbound service and enable it to autostart

$ systemctl restart unbound
$ systemctl enable unbound

Create server configuration file

Create a file "/etc/wireguard/wg0.conf" with the following content

[Interface]
Address = 10.200.200.1/24
SaveConfig = true
PostUp = /etc/wireguard/iptable-set.sh
PostDown = /etc/wireguard/iptable-reset.sh
ListenPort = 51820
PrivateKey = <insert server_private_key\>
[Peer]
PublicKey = <insert client_public_key\>
AllowedIPs = 10.200.200.2/32

Note in the above example,

  • "10.200.200.0" range is used for the VPN network. You can change it to other preferred ranges

  • The ListenPort has to be accesible and you will need to add a rule in your Firewall to allow "UDP:<ListenPort>"

  • Two scripts are used to set up or recover the routing table when you bring up or down the VPN network

The setup script:

#!/bin/bash
# Reference:
# [1] https://www.ckn.io/blog/2017/11/14/wireguard-vpn-typical-setup/
# [2] https://www.cyberciti.biz/faq/how-to-set-up-wireguard-firewall-rules-in-linux/
IN_FACE="eth0" # NIC connected to the internet
WG_FACE="wg0" # WG NIC
SUB_NET="10.200.200.0/24" # WG IPv4 sub/net aka CIDR
WG_PORT="51820" # WG udp port
# track VPN connection
/sbin/iptables -A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
/sbin/iptables -A FORWARD -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
# allow incoming VPN traffic on the listening port
/sbin/iptables -A INPUT -p udp -m udp --dport $WG_PORT -m conntrack --ctstate NEW -j ACCEPT
# allow both TCP and UDP recursive DNS traffic
/sbin/iptables -A INPUT -s $SUB_NET -p tcp -m tcp --dport 53 -m conntrack --ctstate NEW -j ACCEPT
/sbin/iptables -A INPUT -s $SUB_NET -p udp -m udp --dport 53 -m conntrack --ctstate NEW -j ACCEPT
# allow forwarding of packets between interfaces
/sbin/iptables -A FORWARD -i $WG_FACE -o $WG_FACE -m conntrack --ctstate NEW -j ACCEPT
/sbin/iptables -A FORWARD -i $IN_FACE -o $WG_FACE -m conntrack --ctstate NEW -j ACCEPT
/sbin/iptables -A FORWARD -i $WG_FACE -o $IN_FACE -m conntrack --ctstate NEW -j ACCEPT
# set up nat
/sbin/iptables -t nat -A POSTROUTING -s $SUB_NET -o $IN_FACE -j MASQUERADE

The recovery script:

#!/bin/bash
IN_FACE="eth0" # NIC connected to the internet
WG_FACE="wg0" # WG NIC
SUB_NET="10.200.200.0/24" # WG IPv4 sub/net aka CIDR
WG_PORT="51820" # WG udp port
# allow incoming VPN traffic on the listening port
/sbin/iptables -D INPUT -p udp -m udp --dport $WG_PORT -m conntrack --ctstate NEW -j ACCEPT
# allow both TCP and UDP recursive DNS traffic
/sbin/iptables -D INPUT -s $SUB_NET -p tcp -m tcp --dport 53 -m conntrack --ctstate NEW -j ACCEPT
/sbin/iptables -D INPUT -s $SUB_NET -p udp -m udp --dport 53 -m conntrack --ctstate NEW -j ACCEPT
# allow forwarding of packets between interfaces
/sbin/iptables -D FORWARD -i $WG_FACE -o $WG_FACE -m conntrack --ctstate NEW -j ACCEPT
/sbin/iptables -D FORWARD -i $IN_FACE -o $WG_FACE -m conntrack --ctstate NEW -j ACCEPT
/sbin/iptables -D FORWARD -i $WG_FACE -o $IN_FACE -m conntrack --ctstate NEW -j ACCEPT
# set up nat
/sbin/iptables -t nat -D POSTROUTING -s $SUB_NET -o $IN_FACE -j MASQUERADE

Configure DNS

Here "ubound" is used to provide DNS

$ apt-get install unbound unbound-host dnsutils

Download the list of root DNS servers

$ curl -o /var/lib/unbound/root.hints https://www.internic.net/domain/named.cache
$ chown -R unbound:unbound /var/lib/unbound
$ cd /etc/unbound/unbound.conf.d
$ nano unbound_srv.conf

Add the following content

server:
num-threads: 4
#Enable logs
verbosity: 1
#list of Root DNS Server
root-hints: "/var/lib/unbound/root.hints"
#Use the root servers key for DNSSEC
#auto-trust-anchor-file: "/var/lib/unbound/root.key"
#Respond to DNS requests on all interfaces
interface: 0.0.0.0
max-udp-size: 3072
#Authorized IPs to access the DNS Server
access-control: 0.0.0.0/0 refuse
access-control: 127.0.0.1 allow
access-control: 10.200.200.0/24 allow
#not allowed to be returned for public internet names
private-address: 10.200.200.0/24
# Hide DNS Server info
hide-identity: yes
hide-version: yes
#Limit DNS Fraud and use DNSSEC
harden-glue: yes
harden-dnssec-stripped: yes
harden-referral-path: yes
#Add an unwanted reply threshold to clean the cache and avoid when possible a DNS Poisoning
unwanted-reply-threshold: 10000000
#Have the validator print validation failures to the log.
val-log-level: 1
#Minimum lifetime of cache entries in seconds
cache-min-ttl: 1800
#Maximum lifetime of cached entries
cache-max-ttl: 14400
prefetch: yes
prefetch-key: yes

Now restart unbound service and enable it to autostart

$ systemctl restart unbound
$ systemctl enable unbound

You may need to disable the default DNS resolver if unbound fails to start with an error message saying port 53 has been binded to another process [8][9][10]

% use netstat to check whether port 53 has been binded
$ netstat -lutnp
% disable systemd-resolved
$ sudo systemctl stop systemd-resolved
$ sudo systemctl disable systemd-resolved

You can test your DNS setup with the following commands and you should expect to see similar results returned

$ nslookup www.google.com. 10.200.200.1
Server: 10.8.6.1
Address: 10.8.6.1#53
Non-authoritative answer:
Name: www.google.com
Address: 74.125.200.99
Name: www.google.com
Address: 74.125.200.106
Name: www.google.com
Address: 74.125.200.103
Name: www.google.com
Address: 74.125.200.105
Name: www.google.com
Address: 74.125.200.104
Name: www.google.com
Address: 74.125.200.147
Name: www.google.com
Address: 2404:6800:4003:c00::68
Name: www.google.com
Address: 2404:6800:4003:c00::67
Name: www.google.com
Address: 2404:6800:4003:c00::63
Name: www.google.com
Address: 2404:6800:4003:c00::93
$ unbound-host -C /etc/unbound/unbound.conf -v ietf.org
[1599212188] libunbound[2097:0] notice: init module 0: validator
[1599212188] libunbound[2097:0] notice: init module 1: iterator
ietf.org has address 4.31.198.44 (secure)
ietf.org has IPv6 address 2001:1900:3001:11::2c (secure)
ietf.org mail is handled by 0 mail.ietf.org. (secure)

Additionally you can use http://dnsleak.com/ to test DNS leakage.

Start wireguard service on server

Now you're ready to start the wireguard service on your server

$ sudo wg-quick up wg0
$ sudo systemctl enable wg-quick@wg0.service

Use the following command to bring down the service

$ sudo wg-quick down wg0

Setup clients

Server side

As mentioned above, you will have create a key pair for each client, for example:

$ wg genkey | tee rdu_acer_private.key | wg pubkey \> rdu_acer_public.key

Register the client on the server

$ wg set wg0 peer <new_client_public_key\> allowed-ips <new_client_vpn_IP\>/32

In the following client setup part, we will assume you've assigned 10.200.200.2/32 to the client rdu-acer.

You need to restart the "wg0" interface to make this change into effect.

Client side

You can either set up the VPN profile on your device manually or from a QR code

Manual setup on Linux

$ sudo apt-get install wireguard-dkms wireguard-tools linux-headers-$(uname -r)

Create the configuration file

$ sudo -i
$ nano /etc/wireguard/wg0-acer.conf
[Interface]
Address = 10.200.200.2/32
PrivateKey = <insert client_private_key\>
DNS = 10.200.200.1
[Peer]
PublicKey = <insert server_public_key\>
Endpoint = <VPN-Server-Public-IP\>:<ListenPort\>
AllowedIPs = 0.0.0.0/0
PersistentKeepalive = 25

Now you can bring up the connection

$ sudo wg-quick up wg0-acer
$ sudo systemctl enable wg-quick@wg0-acer.service

QR code setup on Android

Instead of manually typing in the VPN information on the phone, you can generate a QR code on the server and setup your phone with this QR code.

$ cd /etc/wireguard/
$ nano rdu_acer_qr.conf
[Interface]
Address = 10.200.200.2/32
PrivateKey = client_private_key
DNS = 10.200.200.1
[Peer]
PublicKey = server_public_key
AllowedIPs = 0.0.0.0/0
Endpoint = <VPN-Server-Public-IP\>:<ListenPort\>
PersistentKeepalive = 25

Then generate the QR code:

$ apt install qrencode
$ qrencode -t ansiutf8 < rdu_acer_qr.conf

Now you can scan the QR code on your phone to setup the VPN connection.

Reference:

CAN Bus in LinuxRaspberry Pi

© 2021 Ruixiang. All rights reserved.