In 2020, I spent a lot of time setting up a small homelab. While it started with a single Raspberry PI 4B, they are now 5 along with multiple HP servers running dozens of containers and VMs.

As I am running a bare metal Kubernetes cluster, I wanted to go even further and connect my home network to one of my AWS VPCs to have an offsite node. I ended up removing the node as I wasn't actually using it, but connecting your homelab to the cloud can have several advantages:

  • Backup your data through a secure connection
  • Replicate your application and DBs to have an active-passive failover setup
  • Deploy a Kubernetes node outside of your home network

And more! Through this guide, we will establish a secure OpenVPN connection between AWS and our local network. I will provide instructions using the AWS console as the AWS configuration is pretty simple, but don't hesitate to use Terraform or Cloudformation if you are an IaC lover 🙂

⚠️While this solution is cost-effective and free tier eligible, keep in mind that when you use AWS, you pay for the traffic that leaves your VPC – inbound traffic being free. Depending on what purpose you will use this tunnel for, it can quickly become expensive.

Requirements

  • An AWS account with a VPC deployed
  • Terraform 0.14.X – optional

Deploying the OpenVPN Server

AWS has many different options when it comes to Network-to-Amazon connectivity, but none of them apply to our deployment. As we can use a T2 micro to be free tier eligible, using EC2 will be the most cost-effective option and using the premium features of other services like AWS Managed VPN would be overkill.

To access our AWS environment, we will connect to an OpenVPN access server deployed to a single EC2 instance in one of our public subnets. This is called a Software Site-to-Site VPN solution.

Starting the OpenVPN instance:

  • Open the Amazon EC2 console at https://console.aws.amazon.com/ec2/.
  • From the console dashboard, choose Launch Instance.
  • Type Openvpn in the search bar, go to the AWS Marketplace and select the first image. Make sure you pick the free one and not the premium images that allow connectivity to more than two devices – our router being the only device needed.
  • In Instance Type, pick t2.micro to be free tier eligible.
  • In Configure Instances, make sure that you choose the right VPC, with a public subnet attached. Auto-assign Public IP will need to be enabled (default). The rest is optional.
  • In Tags, you can add custom tags to identify your instance more easily. For instance Name=OpenVPN.
  • In Configure Security Group, you can either choose to create a new security group based on the recommended settings, or select an existing one. Make sure that the right ports are open to allow ingress traffic (TCP 22, 443, 943, 945 and UDP 1194) to your home public IP only. As we are only connecting our home network to AWS, we do not have to allow access from the internet.
  • You can then Review and Launch your instance. You will need to SSH into the instance to configure OpenVPN, so make sure you choose an existing key pair, or download a new one.

Make sure that your instance state is running and it has a public IP. In order to make it static, don't forget to associate an Elastic IP  (EC2 > Network & Security > Elastic IPs).

⚠️ We must stop source / destination checks to allow traffic flowing through the OpenVPN instance when the source or destination is not itself. To do so, you can go to EC2, click on the OpenVPN instance and click on Actions > Network > Change source / destination check and check the Stop box.

Configuring OpenVPN

If your EC2 instance is running and you have the ssh key downloaded locally, you should be able to ssh into the instance using the openvpnas user and the instance public IP.

ssh openvpnas@{instance_public_ip} -i ./openvpn.pem

Once you're connected to the instance, the standard openvpn installation will begin. You can leave everything by default and press ENTER to each statement. Once done, we can then define a new password for the admin user:

openvpnas@ip-10-0-102-180:~$ sudo passwd openvpn
Enter new UNIX password: 
Retype new UNIX password: 
passwd: password updated successfully

You can then access the admin web UI on port 943, using the newly created password: https://{instance_public_ip}:943/admin

Once logged in, you can find a lot of useful information about the current OpenVPN server details. Feel free to look around.

In order to connect our router to this VPN server, we will create a new user specifically allocated to our device. Head to User Management > User Permissions.

Note that this user needs:

  • Auto-login enabled, to maintain the connection
  • A password
  • Routing as access control, and it needs the AWS network range that will be accessed. In my case, it's the entire VPC (10.0.0.0/16). All server-side private subnets needs to be enabled.
  • VPN gateway to be enabled, allowing access from your home network CIDR range (192.168.178.0/24 in my case).

Don't forget to Save Settings and Update Running Server to save your changes.

You can then head to https://{instance_public_ip}:943, and login as the newly created user. This will allow us to download the autologin profile .ovpn file.

Configuring your Home Router

Unfortunately, this step depends on what router you have. I currently own an EdgeRouter X running EdgeOS, so I will detail the process using this hardware. If you have a different router, I am sure this won't be difficult to find how to do it online.

  • First, we need to copy the .ovpn file to the router
scp ./openvpn.ovpn ubnt@{router_ip}:/config
  • Once in the EdgeOS web portal, start the CLI and enter configure mode
ubnt@ubnt:~$ configure
[edit]
  • You can now create a new virtual interface vtun0 that will connect to our OpenVPN server using the erx credentials. Don't forget to commit and save your changes.
ubnt@ubnt# set interfaces openvpn vtun0 mode client                     
[edit]
ubnt@ubnt# set interfaces openvpn vtun0 config-file /config/openvpn.ovpn
[edit]   
ubnt@ubnt# commit
[edit]
ubnt@ubnt# save
Saving configuration to '/config/config.boot'...   
Done
[edit] 

If the tunnel is established, you will see the new interface status as connected.

Validating and Going Further

If you want to check that your VPN connection is fully functional, you can try to ping your OpenVPN instance using its private IP.

$ ping 10.0.102.180           
PING 10.0.102.180 (10.0.102.180) 56(84) bytes of data.
64 bytes from 10.0.102.180: icmp_seq=1 ttl=63 time=23.6 ms
64 bytes from 10.0.102.180: icmp_seq=2 ttl=63 time=22.9 ms
64 bytes from 10.0.102.180: icmp_seq=3 ttl=63 time=27.6 m

It's working! However, our current setup is not enough to connect to a different EC2 instance deployed in our VPC and the other way around.

  • To allow connectivity from a home device to an EC2 instance that is not the OpenVPN server

Make sure that the security group attached to the instance allow traffic from your home CIDR range – in my case 192.168.178.0/24.

Save your changes and try pinging one of your instances from a home device.

  • To allow connectivity from an EC2 instance that is not the OpenVPN server to a home device

All the traffic between an instance to your home network will flow through the OpenVPN gateway, therefore it also has to be allowed at the VPN level. Make sure that the security group attached to the OpenVPN instance allows traffic from the EC2 instance, in my case 10.0.101.75/32.

A new route also has to be added to the route table that is attached to the subnet where the instance is deployed. This route will target the VPN server for all traffic going to our home CIDR range.

Once you have identified which route table to update, VPC > Route Tables > Actions > Edit Route Table. Destination is the local CIDR range and target is the OpenVPN instance.

Save your changes and try pinging one of your home devices from the instance.

Congratulations! You now have a fully functional OpenVPN secured connection between your home network and your AWS VPC.

Drop a comment if you have any questions/issues!