Deploys private OpenVPN servers quickly around the world via Amazon AWS EC2.
Based on the kylemanna/docker-openvpn docker container and inspired by brasey/deploy-docker-openvpn.
This project will deploy one (or more) t3.nano
private VPN servers around the world to securely route your desktop,
laptop, router or mobile traffic. The tools in this package will help you configure a private, secure docker container
with an OpenVPN environment that you can easily deploy to any number of Amazon AWS
regions around the world with just a few lines of configuration, at any time. Using
Terraform you can easily setup or destroy your OpenVPN deployments in seconds.
The goal is to create a OpenVPN certificate authority (CA) on your local machine via EasyRSA. This CA will generate a server certificate for use in OpenVPN servers that you can deploy via AWS, and generate client certificates for any machines you want to connect to those OpenVPN servers.
We will then use Terraform to deploy a docker container with the kylemanna/docker-openvpn image to a minimal Amazon AWS EC2 server to one or more AWS regions. Terraform will also update Amazon Route 53 DNS entries pointing to your deployed server(s).
You can then use the .ovpn
profiles generated by the CA on your local machine to connect to your OpenVPN servers
across the globe!
First, you will need have Docker installed on your local machine:
Next, we'll create a Docker volume on the local machine to host the CA files.
Then, we will use the kylemanna/docker-openvpn docker image to generate a OpenVPN certificate authority (CA) with a CA root key. This CA will be responsible for generating certificates for all of your servers and clients. You won't deploy this container directly to the outside world -- it will be solely responsible for generating server certificates for your OpenVPN servers and client certificates for each of your clients, with the CA root key. These files will live in the Docker volume we created.
This is a modified process of the kylemanna/docker-openvpn Quick Start
guide where we use the local machine to generate the CA root key and
only put the CA certificate
on the deployed OpenVPN servers. The files required for the OpenVPN servers will be generated into
files/openvpn-server.tar.gz
.
-
Configure a few environment variables.
Replace
vpn.myhost.com
with the Amazon Route 53 DNS entry you want your clients to connect to.Linux/Mac:
# Set this to the VPN server name OVPN_SERVER="vpn.myhost.com" OVPN_DATA="ovpn-data"
Windows:
REM Set this to the VPN server name set OVPN_SERVER=vpn.myhost.com set OVPN_DATA=ovpn-data
-
Create a Docker volume
Linux/Mac:
docker volume create --name $OVPN_DATA
Windows:
docker volume create --name %OVPN_DATA%
-
Next, we'll generate the OpenVPN configuration into the
$OVPN_DATA
voume:Linux/Mac:
# Generates OpenVPN configs docker run -v $OVPN_DATA:/etc/openvpn --rm kylemanna/openvpn ovpn_genconfig -u udp://$OVPN_SERVER
Windows:
REM Generates OpenVPN configs docker run -v %OVPN_DATA%:/etc/openvpn --rm kylemanna/openvpn ovpn_genconfig -u udp://%OVPN_SERVER%
-
We'll use EasyRSA to build the CA root key, certificate and other files used by the server.
Linux/Mac:
# Initialize the EasyRSA PKI docker run -v $OVPN_DATA:/etc/openvpn --rm -it kylemanna/openvpn ovpn_initpki
Windows:
REM Initialize the EasyRSA PKI docker run -v %OVPN_DATA%:/etc/openvpn --rm -it kylemanna/openvpn ovpn_initpki
-
Finally, we'll call
ovpn_copy_server_files
which will copy out the minimal files required for the OpenVPN server intofiles/openvpn-server.tar.gz
.Linux/Mac:
# Generates the minimal OpenVPN files necessary for clients to connect to into /etc/openvpn/server docker run --net=none --rm -t -i -v $OVPN_DATA:/etc/openvpn kylemanna/openvpn ovpn_copy_server_files # Package the files up into an archive docker run -v $OVPN_DATA:/etc/openvpn --rm kylemanna/openvpn tar -cvz -C /etc/openvpn/server . > files/openvpn-server.tar.gz
Windows:
REM Generates the minimal OpenVPN files necessary for clients to connect to into /etc/openvpn/server docker run --net=none --rm -t -i -v %OVPN_DATA%:/etc/openvpn kylemanna/openvpn ovpn_copy_server_files REM Package the files up into an archive docker run -v %OVPN_DATA%:/etc/openvpn --rm kylemanna/openvpn tar -cvz -C /etc/openvpn/server . > files/openvpn-server.tar.gz
Now we're all set to generate client certificates and deploy our servers.
For each client you want to allow to connect to your OpenVPN instances, we will use
EasyRSA to generate client certificates and the ovpn_getclient
script
to build .ovpn
files that can be used by OpenVPN client software.
The client certificates will end up in $OVPN_DATA/pki/issued/
and the .ovpn
profiles will be written out to the local
machine.
Linux/Mac:
CLIENTNAME=myclient
docker run -v $OVPN_DATA:/etc/openvpn --rm -it kylemanna/openvpn easyrsa build-client-full $CLIENTNAME nopass
docker run -v $OVPN_DATA:/etc/openvpn --rm kylemanna/openvpn ovpn_getclient $CLIENTNAME > $CLIENTNAME.ovpn
Windows:
set CLIENTNAME=myclient
docker run -v %OVPN_DATA%:/etc/openvpn --rm -it kylemanna/openvpn easyrsa build-client-full %CLIENTNAME% nopass
docker run -v %OVPN_DATA%:/etc/openvpn --rm kylemanna/openvpn ovpn_getclient %CLIENTNAME% > %CLIENTNAME%.ovpn
Note if you're going to be deploying multiple VPN instances you'll want to modify the .ovpn
to edit the remote
DNS entry.
Once the server has been configured and you have generated keys for your clients, you are ready to deploy OpenVPN servers to AWS.
We will be using Terraform to easy prepare and deploy OpenVPN servers across the globe.
They will be initialized using the certificates generated via ovpn_copy_server_files
and in the
files/openvpn-server.tar.gz
package.
Terraform uses configuration files to know how to configure each OpenVPN deployment. The base configuration is in
terraform.tfvars
, and each deployment has its own config-[deployment].tfvars
file. For example, you could deploy
OpenVPN servers to multiple AWS regions.
First, we'll need to configure Amazon AWS:
-
Create an IAM user that will be responsible for deploying the EC2 instances and for modifying the Route 53 domain entries.
When you create the IAM user, you will be given a AWS Access Key and a AWS Secret Key that you will use later.
You will need to attach some permissions to this user. You may be able to attach finer-grained policies, but these should be sufficient:
AmazonEC2FullAccess
AmazonRoute53DomainsFullAccess
AmazonRoute53ReadOnlyAccess
AmazonSSMFullAccess
-
Create (or use an existing) Amazon Route 53 Hosted Zone (root domain) that will host the DNS record you want updated when you deploy a server.
Note the Hosted Zone ID.
-
Generate (or use an existing) Private Key pair that you will use to connect (via SSH) to EC2 instances.
The easiest way to do this is via the EC2 console. Click on Key Pairs and Create Key Pair. You wil lbe given a
.pem
file with your private keys.If you already have a Private Key, you will need to make sure it's listed in the EC2 Key Pairs console for every zone that you want to deploy OpenVPN servers to.
If you're deploying to more than one AWS zone, you will use Import Key Pair to import your
.pem
to other zones.
Next, we'll need to edit a couple configuration files.
-
terraform.tfvars
You can use the
terraform.tfvars.sample
file to get you started. Copy it toterraform.tfvars
:aws_access_key = "" aws_secret_key = "" host_route_53_zone_id = "" instance_type = "t3.nano" ssh_key = "mykey.pem" ssh_key_name = "" ssh_user_name = "ec2-user"
aws_access_key
is your AWS Access Keyaws_secret_key
is your AWS Secret Keyhost_route_53_zone_id
is the Hosted Zone ID you will be updating for$OVPN_SERVER
instance_type
can be the AWS EC2 instance type you want to use. At the time of writing,t3.nano
is the cheapest instance type.ssh_key
is the location of the.pem
file you createdssh_key_name
is the name of Key Pair Name in EC2ssh_user_name
is the user name used to connect to your EC2 instance.ec2-user
should probably be used.
-
Create
config-[deployment].tfvars
for each deployment (e.g. zone) you want to deploy to.You can use the
config-main.tfvars.sample
file to get you started. For example, copy it toconfig-us-east.tfvars
:host_name = "vpn.myhost.com" region = "us-east-2" base_image = "ami-31c7f654"
host_name
is the DNS name of this deploymentregion
is the AWS region you want to deploy tobase_image
is your AMI you want to use for that region. This package assumes Amazon Linux 2.
-
Initialize Terraform:
terraform init
-
Create Terraform Workspaces for each deployment:
For example, if you want to deploy to
us-east
,us-west
andde
:terraform workspace new us-east terraform workspace new us-west terraform workspace new de
Now you're ready to deploy! The Terraform scripts will do the following:
- Configures a VPC, Internet Gateway, Routes and Subnet for this region (required if you're using
t3.nano
) - Creates a Security Group (firewall), open to incoming SSH (22) and OpenVPN (1194)
- Launches an EC2 instance
- Once it's ready, it uploads the files in
files/
:openvpn-server.tar.gz
package that has the OpenVPN server certificatedocker-openvpn@data.service
to ensure the OpenVPN runs after reboots
- Runs
scripts/configure_node.sh
to:- Update the packages on the machine
- Install Docker
- Install
docker-openvpn
as a service - Create a docker volume for
/etc/openvpn
and extractopenvpn-server.tar.gz
into it - Start the
docker-openvpn
service
- Once it's ready, it uploads the files in
To deploy to a region, you simply need to switch to that workspace, then run terraform apply
with
the -var-file config-[deployment].tfvars
set:
terraform workspace select us-east
terraform plan -var-file config-us-east.tfvars
terraform apply -var-file config-us-east.tfvars
terraform workspace select us-west
terraform plan -var-file config-us-west.tfvars
terraform apply -var-file config-us-west.tfvars
terraform workspace select de
terraform plan -var-file config-de.tfvars
terraform apply -var-file config-de.tfvars
You can destroy (stop) a deployment via:
terraform workspace select us-east
terraform destroy -var-file config-us-east.tfvars
- 2018-04-24: Initial version
- 2018-11-08: Changed to
t3.nano
; Updatedconfigure_node.sh
for latest Amazon Linux 2 AMI