Skip to main content

Crosscloud VPN with WireGuard

Learn to establish secure VPN connections across cloud environments using WireGuard, including detailed setups for site-to-site tunnels and VPN gateways with NAT on Equinix Metal, enhancing cross-platform security and connectivity.

Crosscloud VPN with WireGuard

WireGuard is an open source solution for creating encrypted VPNs. Compared to other existing VPN protocols, WireGuard offers greater reliability, updated encryption, simpler configuration, quicker handshake and faster speeds. This article provides two basic WireGuard use cases and the steps to setup the WireGuard VPN in Equinix Metal's facilities.

Use Case 1: Tunnel between servers at different locations

For this use case, you'll set up a site-to-site WireGuard VPN tunnel between two Equinix Metal servers located at different Equinix Metal facilities. The following diagram illustrates a server at our EWR1 facility and another server at our SJC1 facility, along with their IP addresses:

server-ip

Step 1: Install WireGuard

The first thing to do is install WireGuard on both Equinix Metal servers (using Ubuntu 18.04 LTS in this example). Type the following commands on each server:

apt-get update
apt-get install software-properties-common -y
add-apt-repository ppa:wireguard/wireguard -y
apt-get install -y wireguard wireguard-dkms wireguard-tools linux-headers-$(uname -r)

After the successful installation, the /etc/wireguard directory will be created for both servers.

Step 2: Generate public and private keys

Use the wg genkey command to generate the public and private keys for both servers:

cd /etc/wireguard
umask 077
wg genkey | tee privatekey | wg pubkey > publickey

The keys will be located at /etc/wireguard/ under the file names of privatekey and publickey

Step 3: Setup WireGuard interfaces at the first site

To create an interface at the first location, EWR1 in this case, create a file called /etc/wireguard/wg0.conf on the EWR1 server and add the following content:

[Interface]
PrivateKey = EWR1 server’s privatekey strings
Address = 192.168.1.1
ListenPort = 51820
[Peer]
PublicKey = SJC1 server’s publickey strings
AllowedIPs = 10.168.1.1
Endpoint = 139.178.68.53:51820

We're using 192.168.1.1 as a private IP address for the EWR1 server’s VPN tunnel. Make sure not to use the private IP blocks that are assigned to your project at EWR1, such as 10.99.x.x/25.

We're also using 10.168.1.1 as a private IP address for the SJC1 server’s VPN tunnel. Make sure not to use the private IP blocks that are assigned to your project at SJC1, such as 10.88.x.x/25.

139.178.68.53 is the SJC1 server’s public IP in this example.

51820 is a random chosen UDP port number.

Step 4: Setup WireGuard Interfaces at the second site

To create an interface at the first location, SJC1 in this case, create a file called /etc/wireguard/wg0.conf on the SJC1 server side and add the following content:

[Interface]
PrivateKey = SJC1 server’s privatekey strings
Address = 10.168.1.1
ListenPort = 51820
[Peer]
PublicKey = EWR1 server’s publickey strings
AllowedIPs = 192.168.1.1
Endpoint = 147.75.72.241:51820

This works because 147.75.72.241 is the EWR1 server’s public IP. 51820 is the UDP port number, which has to match the port number used for the EWR1 server.

Step 5: Enable and Start WireGuard

On each server, enable and start WireGuard with the following commands:

sudo systemctl enable wg-quick@wg0
sudo systemctl start wg-quick@wg0

Once that's done, use the sudo wg command to double-check wg0.conf configuration.

Step 6: Test the VPN

Test the connection from each end, by having the EWR1 server ping SJC1 server, then vice versa:

ewr1-server # ping 10.168.1.1
PING 10.168.1.1 (10.168.1.1) 56(84) bytes of data.
64 bytes from 10.168.1.1: icmp_seq=1 ttl=64 time=144 ms
64 bytes from 10.168.1.1: icmp_seq=2 ttl=64 time=71.3 ms
^C
sjc1-server # ping 192.168.1.1
PING 192.168.1.1 (192.168.1.1) 56(84) bytes of data.
64 bytes from 192.168.1.1: icmp_seq=1 ttl=64 time=72.6 ms
64 bytes from 192.168.1.1: icmp_seq=2 ttl=64 time=71.3 ms
^C

Use Case 2: Set up a WireGuard VPN and NAT gateway

The following diagram illustrates that one server (node 1) at our EWR1 facility serves as a VPN and NAT gateway (internet accessible) and is also on a VLAN (VLAN ID: 1092). Two more servers (node 2, node 3) are on the same VLAN (1092) but have no direct internet access. Another server at our SJC1 facility serves as another VPN gateway.

All traffic between node 2 or 3 in EWR1 and SJC1 server are forwarded via node 1 in EWR1 through the WireGuard VPN tunnel between the SJC1 server and EWR1’s node 1.

vpn-example

Step 1: Install WireGuard

As in the previous use case, the first thing to do is install WireGuard on both servers acting as VPN gateways (using Ubuntu 18.04 LTS in this example). Type the following commands on each server:

apt-get update
apt-get install software-properties-common -y
add-apt-repository ppa:wireguard/wireguard -y
apt-get install -y wireguard wireguard-dkms wireguard-tools linux-headers-$(uname -r)

After the successful installation, the /etc/wireguard directory will be created for both servers.

Step 2: Generate public and private keys

Use the wg genkey command to generate the public and private keys for SJC1 and EWR1 node 1:

cd /etc/wireguard
umask 077
wg genkey | tee privatekey | wg pubkey > publickey

The keys will be located at /etc/wireguard/ under the file names of privatekey and publickey

Step 3: Set up WireGuard interfaces for node 1

Create a file called /etc/wireguard/wg0.conf on the EWR1 node 1 server and add the following content:

[Interface]
PrivateKey = EWR1 node1 server’s privatekey strings
Address = 192.168.1.1
PostUp = iptables -A FORWARD -i wg0 -j ACCEPT; iptables -t nat -A POSTROUTING -o bond0 -j MASQUERADE
PostDown = iptables -D FORWARD -i wg0 -j ACCEPT; iptables -t nat -D POSTROUTING -o bond0 -j MASQUERADE
ListenPort = 51820
[Peer]
PublicKey = SJC1 server’s publickey strings
AllowedIPs = 10.168.1.1
Endpoint = 139.178.68.53:51820

The PostUp line enables NAT between the server's public interface (bond0) and the wg0 interface when the wg0 interface is up. Similarly, the PostDown line disables the NAT when wg0 interface is down.

Step 4 - Setup WireGuard interfaces for the second server

Create a file called /etc/wireguard/wg0.conf on the SJC1 server side and add the following content:

[Interface]
PrivateKey = SJC1 server’s privatekey strings
Address = 10.168.1.1
ListenPort = 51820
[Peer]
PublicKey = EWR1 server’s publickey strings
AllowedIPs = 192.168.1.1
Endpoint = 147.75.72.241:51820

As in the first use case, make sure you use the correct IP address for the endpoints, and ensure that both servers are listening on the same port number.

Step 5: Set up the routing for node 1 of EWR1

Issue the following commands at EWR1 node 1 to enable IPv4 and IPv6 routing, so that it can forward packets for node 2 and node 3:

echo "net.ipv4.ip_forward = 1
net.ipv6.conf.all.forwarding = 1" > /etc/sysctl.d/wg.conf
sysctl --system

Step 6: Set up VLAN at EWR1

Follow the Equinix Metal guide “layer 2 configuration” to setup the following:

  1. Create a VLAN at EWR1.
  2. Node 1 is in hybrid mode: eth0 is on bond0 (internet accessible) but eth1 is on layer 2 (on the VLAN 1092 in this example).
  3. Node 2 and 3 are in layer 2 mode (on the same VLAN as node 1).

Step 7: Test the VPN and NAT gateway

To test the VPN and the NAT gateway, ensure that all the servers can see the servers they're supposed to.

Check both ends of the VPN tunnel first. From EWR1 node 1, ping the SJC1 server, and vice versa. Check the connectivity of the VLAN. From Node 2, ping EWR1 node 1 and vice versa. Then do the same from Node 3. Finally, check the full connectivity. From Node 2, ping SJC1, and vice versa. Then do the same from Node 3.

Conclusion

These configurations work just fine across different cloud providers. For example, you can follow the same steps to set up a WireGuard VPN between AWS and Equinix Metal. In addition to the two use cases provided in this article, there are many other use cases for WireGuard. For example, kilo uses WireGuard to create a mesh between the different nodes in a Kubernetes cluster.

Last updated

07 September, 2024

Category

Tagged

Technical