OpenVPN Access Server is ready to use OpenVPN server which requires minimal configuration.
The free version allows you to have two clients. If you need more – you can buy additional licenses.
Currently to access our resources such as Jenkins, Nexus etc we are using Allow Rules in AWS Security Groups where each user has its own IP added.
This was not too bad approach while was a small team but as we are growing fast and there are more and more developers/QA – had to find a better solution.
In this post, we will set up an OpenVPN service using OpenVPN Access Server AWS AMI.
After all, everything will look like:
You can find documentation OpenVPN AS documentation
AWS: creating OpenVPN AS service
Find the AMI:
You can add license later so, for now, let’s use its Free version.
Take a t2.micro instance – it will be fair enough at this moment:
Create a new VPC for our VPN:
As we will use VPC peerings – make sure your networks aren’t overlapped.
In the current case – I have Jenkins VPC with the 10.0.4.0/24 CIDR and VPC VPN CIDR – 10.0.9.0/24:
Create a new subnet in this VPC:
Configure new EC2 networking using those VPC and subnet:
Create Internet Gateway (IGW) to access the Internet from your new VPC:
Attach this IGW to your VPC:
Next, have to update a Route Table to be used to route traffic to the 0.0.0.0/0 network (the Internet) via created IGW.
Go to your new subnet, find the Route Table tab, click on it:
Add a new route via IGW:
AWS will suggest you use a Security Group with already predefined set of rules.
As this is such a Proof of Concept – you can leave it as is:
- TCP 22 — SSH access
- TCP 943 — OpenVPN AS admin UI access port
- TCP 443 — OpenVPN AS users UI access port
- UDP 1194 — OpenVPN UDP for VPN clients
In kind of Production setup, you have to limit 943 and 22 by only trusted IPs.
Start the instance, create new RSA key for access:
Create an EIP to use it with your new host:
Source/Destination check disabling
For NAT’s correct work have to disable the Source/Dest check (see post AWS: миграция RTFM 2.5 — настройка NAT на Bastion EC2 как замена NAT Gateway и AWS: миграция RTFM 2.7 — CloudFormation и Ansible — наcтройка NAT):
And we are done with the EC2 now – let’s start configuring our new OpenVPN service.
OpenVPN AS set up
SSH to the host using the openvpnas login:
Read 🙂 the license, accept it:
Initialization and the first configuration
On the first login, OpenVPN AS will start its wizard automatically.
You can run it later using the
For now, you can just answer Yes with default values for everything here:
- Will this be the primary Access Server node? // yes
- Please specify the network interface and IP address to be
used by the Admin Web UI:
(1) all interfaces: 0.0.0.0
(2) eth0: 10.0.9.8
- Please specify the port number for the Admin Web UI.
// yes – 943
- Please specify the TCP port number for the OpenVPN Daemon
// yes – 443
- Should client traffic be routed by default through the VPN?
// no – we will route only traffic to our own resources
- Should client DNS traffic be routed by default through the VPN?
- Use local authentication via internal DB?
- Private subnets detected: [‘10.0.9.0/24’]
Should private subnets be accessible to clients by default?
- Do you wish to login to the Admin UI as “openvpn”?
- > Please specify your OpenVPN-AS license key (or leave blank to specify later):
// leave blank
openvpn user ‘s password:
Now you can open your admin page using EIP created before – https://184.108.40.206:943/admin in this case.
As we didn’t configure a hostnames/URLs – just agree here:
Your connection is not private
Login to the admin page using the openvpn user and password created with
VPN client connection
Go to the user’s UI (no
/admin at the end) – https://220.127.116.11:943/?src=connect:
Click on the Yourself (user-locked profile) and download the
client.ovpn file with settings for your local VPN client:
openvpn on your local PC, here is Arch Linux used:
Start it with the
Now – let’s check some routing.
First, let’s make a request to the CloudFlare – it must be passed via my office’s router/gateway:
Yup, it is.
And now to the OpenVPN host – must go directly:
VPN-tunnel traffic routing
For the testing purposes – let’s add a new EC2 in the same VPC where is our OpenVPN placed:
And let’s check routes again.
During local OpenVPN client start you have to notice a message with new routes to be added in your system:
Wed Feb 20 17:22:56 2019 /usr/bin/ip route add 172.27.224.0/20 metric 101 via 172.27.232.1
Check it – try SSH using Private IP of the new instance:
The next step is to configure VPC-peering and a traffic routing between our workstation, VPN-server, and the Jenkin’s VPC.
Read more about VPC-peering тут>>>,
Create a new VPC peering connection:
Accept its request:
If you’ll try to connect to the Jenkins using its Private IP – this will not work now:
Because there are no routes added between the 10.0.9.0/24 (OpenVPN VPC) and the 10.0.4.0/24 (Jenkins VPC) networks.
So now we have to add two new routes:
- in the Jenkins route table – 10.0.4.0/28 => 10.0.9.0/24 via VPC peering created above
- in the OpenVPN route table – 10.0.4.0/28 => 10.0.9.0/24 via VPC peering created above
Edit the jenkins rtb-9597e6ec | jenkins-dev-route-table table:
Add the new route:
Repeat for the VPN’s route table:
Check from the VPN network:
And from the Jenkins host – back to the VPN’s network to any host:
Remember that Jenkins has its own Security Group – add new Allow rule there.
Check SSH from the VPN’s network:
Go back to your workstation and check how traffic will be routed to the Jenkins host, using its Private IP:
It is passed through the office’s router – and this is absolutely not what we want.
Go to the VPN admin => VPN Settings – https://18.104.22.168:943/admin/vpn_settings:
Add a new NAT-rule for the 10.0.4.0/24 subnet:
Save, press Update Running Server:
Restart local client:
Here is our new route – 10.0.4.0/24 metric 101 via 172.27.232.1.
Check your local routing table:
Check trace again:
Now it went via OpenVPN IP as a gateway.
Check if SSH works via Private IP:
“It works!” (c) 🙂
The last thing to think about is the DNS settings.
As our Jenkins has to be accessible using its Public IP and domain dev.ci.example.com from a few addresses on the Internet and via its Private IP – using VPN connection – need to find a way resolve it to a different IPs.
Check the OpenVPN: DNS and dnsmasq configuration post for details.