Connect AWS and GCP (or any cloud) with ZeroTier VPN

ZeroTier is a mesh VPN provided as a service by the company that created it, ZeroTier. The license they use for the software (both the client and server-side controllers) is mostly open source using a slightly modified BSD license. You can get started for free, connect up to 25 nodes to your VPN and there’s no charge for traffic that traverses the VPN.

Today we are going to connect an AWS EC2 instance and a Compute Instance in Google Cloud.

Why ZeroTier and not IPsec?

There are many open-source and 100% free VPN technologies – IPsec, OpenVPN, WireGuard, to name just a few. Every situation is different and I would recommend a careful evaluation of the circumstances before making a decision, as no technology is the “best” for all things. But here’s the reasons why I really like ZeroTier for some use-cases:

  • It’s really, REALLY easy to set up.
  • You don’t need public IP’s on anything to get it working (really!)
  • You don’t need port forwarding
  • Connections between nodes are direct (not relayed by ZeroTier servers)
  • No limits on traffic or performance
  • Supports broadcast, multicast and routing protocols
  • You can get support and submit tickets. This is a must for many business/enterprise use cases.

The reason you don’t need public IP’s is because ZeroTier’s hosted controllers will handle UDP hole-punching for you. Without that you’d need to host your own controller on a public IP.

I should mention – I’m NOT affiliated with ZeroTier or getting any kickbacks from them. I just like their VPN.

Topology

“EC2” and “GCP Compute” are just different names for VM’s that you can rent from AWS and Google, we’ll assume you can spin one up. We’re not going to cover how to construct anything else in these public clouds, and assume you have built a functioning VPC and have outbound internet access of some sort, either through a public IP or a NAT gateway/instance. Our VPN will have a virtual network of 172.18.0.0/24. We’ll jump straight into setting up ZeroTier. I have created an AWS EC2 and a GCP Compute Instance:

AWS EC2 Instance
GCP Compute Instance

The EC2 instance is running Amazon Linux, while the GCP instance is running Debian.

ZeroTier service setup

You can sign up for free at https://my.zerotier.com. Once you’ve done that, login and create a network:

ZeroTier Networks Page

We now have a private network with an ID of 8bd5124fd6c0c590. For a node to join this network, they need to know the ID and be authorized (also done here in the GUI) to access it once they’ve joined.

We’ll set up a route of 172.18.0.0/24 and just 2 auto-assigned IP’s of 172.18.0.1 and 172.18.0.2 (172.18.0.3 won’t be included).

That’s it for now – we’ll come back here to authorize the two nodes once they’ve joined.

ZeroTier installation

There are a few ways to install, but there’s a nice convenience script one-liner if you’re ok with downloading a script from the internet and running it with permissions:

curl -s https://install.zerotier.com | sudo bash

We should see some output at the end of the installation like this:

Installed:
  zerotier-one.x86_64 0:1.10.1-1.el6                                            

Complete!

*** Enabling and starting ZeroTier service...
zerotier-one.service is not a native service, redirecting to /sbin/chkconfig.
Executing /sbin/chkconfig zerotier-one on

*** Waiting for identity generation...

*** Success! You are ZeroTier address [ 0edf4ce5bb ].

[ec2-user@ip-172-31-85-153 ~]$ 

Now that ZeroTier is installed, join the network we created with this command:

sudo zerotier-cli join 8bd5124fd6c0c590
----

200 join OK

Back in the “members” section of our network in the ZeroTier GUI, we should see that two nodes have joined, but have yet to be authorized:

Just check the box on the left to authorize them.

We should be up and running at this point.

Test and verify

Before we ping, let’s first verify the IP address has indeed been assigned with a simple ip route command on both nodes.

Terminal sessions side-by-side for the EC2 and Compute Instance

We can see here that both instances have the right IP addresses of 172.18.0.1 and 172.18.0.2. We should also be able to verify that the zerotier-one service is running:

sudo systemctl status zerotier-one
zerotier-one systemd service

And finally, let’s ping:

Ping results along with tcpdump capture

While running the ping from the EC2 instance, I did a live tcpdump capture on the GCP Compute Instance to show packets were indeed making it across the VPN.

For another test, I’ve install the web server nginx on the GCP instance and used curl from the EC2 to test it:

Testing nginx with curl

There are no filters on the ZeroTier interfaces, even though the EC2’s security group is very restrictive, only allowing SSH traffic. There is a similar firewall rule in GCP:

EC2 Security Group
GCP Firewall

If the AWS and GCP traffic filters could see the ZeroTier internal tunnel traffic, they would block it. But since it’s encrypted and considered “outbound”, traffic is allowed in both directions. This is made possible by the ZeroTier controllers facilitating UDP hole-punching to make all traffic, regardless of it’s properties inside the VPN tunnel, appear to be “outbound” and part of a single flow.

Cool, right?