I run a small lab in my office that talks to a few EC2 instances in eu-west-1, and until last month the connection was a constant source of friction. SSH keys scp’d to the wrong host, a curl request that needed to come from the office network, an RDS database I did not want exposed to the public internet. A site-to-site VPN, which puts the office LAN and the AWS VPC on the same private network, is the cleanest fix, and OpenVPN Access Server from the AWS Marketplace is the fastest way to get there. The setup is a Saturday afternoon, not a week.
This is the recipe I landed on, distilled into the steps that actually matter. Most how-tos cover every AWS dialog box, and most of that is not the hard part. The hard part is the routing and the NAT.
The shape of what you are building
A site-to-site VPN (a permanent, always-on encrypted tunnel between two networks) is different from the client VPN most people think of first. A client VPN is a single laptop connecting to a corporate network over the internet. A site-to-site VPN is two networks connected to each other, with the VPN concentrator (the server that terminates VPN tunnels) acting as a gateway between them. Once it is up, every device on network A can talk to every device on network B as if they were on the same LAN.
The pieces you need are an AWS VPC (Virtual Private Cloud, a logically isolated network you define inside AWS) with a CIDR block (a range of IP addresses written in slash notation, like 10.0.0.0/16) that does not overlap your office network, an EC2 instance running OpenVPN Access Server, IP forwarding and NAT (Network Address Translation, the mechanism that rewrites the source IP of packets leaving a network so replies can find their way back) configured on the EC2 instance, and a Linux box on the office side that runs the OpenVPN client.
The OpenVPN Access Server AMI from the AWS Marketplace is the easiest way to get the server side. The pay-as-you-go pricing starts at zero for the 2-connection tier, which is enough for a lab. The license scales with concurrent connections, not bandwidth.
The order that actually works
The order AWS presents in its wizards is not the order you should do the work in. Do this in the order below, because each step depends on the previous one and most of the friction is in the routing, not the deployment.
- Create the VPC first. A new VPC with a /16 CIDR block, two subnets (one public, one private), a route table, and an internet gateway. AWS will create all of this from the “VPC and more” wizard. Pick a CIDR that does not overlap your office network. 10.0.0.0/16 is the conventional choice and what I use, but anything in the 10.0.0.0/8, 172.16.0.0/12, or 192.168.0.0/16 private ranges works. The non-overlap is the load-bearing part.
- Launch the OpenVPN Access Server from the Marketplace. Subscribe to the OpenVPN listing, create an OpenVPN account, choose the region close to you, and launch a stack into the VPC you just created. Pick t4g.small for a lab. Generate an SSH key pair in EC2 first if you do not already have one, and save the .pem file somewhere you will not lose it.
- Configure the security group. Open inbound TCP 22 (SSH), TCP 443 (HTTPS for the client UI), TCP 943 (admin UI), and UDP 1194 (the OpenVPN tunnel). Delete any other ports the AMI exposes by default. The fewer open ports, the fewer surprises later.
- Enable IP forwarding on the EC2 instance. SSH in and run
sudo sysctl -w net.ipv4.ip_forward=1. Verify withcat /proc/sys/net/ipv4/ip_forward. Then make it permanent in/etc/sysctl.confby uncommenting thenet.ipv4.ip_forward=1line and runningsudo sysctl -p. The OpenVPN server has to forward packets between its two interfaces, and this is the kernel-level switch that allows it. - Configure NAT. Run
sudo iptables -t nat -A POSTROUTING -o ens5 -j MASQUERADE. Theens5is the EC2 instance’s network interface. The MASQUERADE rule rewrites the source IP of packets leaving through that interface so that AWS-side resources can reply. Install iptables-persistent and runsudo netfilter-persistent saveso the rule survives a reboot. - Configure Access Server routing. In the Access Server admin UI, go to Access Controls > Global Access Rules and add your VPC CIDR (10.0.0.0/16 in my case) with the “Route” action. Then go to InterClient Communication and allow user-to-user connections. Without these two settings, the tunnel comes up but no traffic flows.
- Generate a user-locked client profile. Users > Connection Profiles > New Connection Profile > User-locked. Download the .ovpn file. This is what your office-side OpenVPN client will use to connect.
- Install the OpenVPN client on the office-side box.
sudo apt install openvpnon Debian/Ubuntu. Copy the .ovpn file to /etc/openvpn/ or just runsudo openvpn --config profile-userlocked.ovpnfrom your Downloads directory to test. - Add the office LAN to the Access Server routing. This is the step most tutorials bury. In Access Controls > Global Access Rules, add your office network (192.168.1.0/24 in my case). Without this, the AWS side can reach the OpenVPN client, but it cannot reach the rest of your office LAN. With it, the two networks behave as one.
- Verify. From the office side,
ping 10.0.0.x(a host in your AWS VPC). From the AWS side,ping 192.168.1.x(a host on your office LAN). If both directions work, the site-to-site VPN is up.
The two security group rules that matter
Most of the security group work is obvious. The two that are not, in my experience, are the OpenVPN tunnel port and the admin UI port.
UDP 1194 is the OpenVPN tunnel itself. If you forget to open it, the client connects, gets an IP address, and then nothing works. The error is unhelpful. Open the port, restart the client, and the issue goes away.
TCP 943 is the admin UI. It also serves the client web UI at https://your-vpn-host:943. If you do not open it, you cannot get to the admin panel from outside the VPC. The Access Server logs you in at this port by default.
A common mistake is opening TCP 443 and TCP 943 to the entire internet. That is fine for a lab. For anything sensitive, scope the source to your office IP range or a bastion host. The OpenVPN documentation covers the production-grade setup, and it is worth the hour if the VPN is going to host anything beyond a homelab.
What I would tell past me
If I could send a message back to the version of me that started the setup, I would say four things.
- Do the CIDR check first. If your VPC CIDR overlaps your office network, the routing does not work and the error message is cryptic. Pick a non-overlapping CIDR before you start the wizard, and write it down.
- The MASQUERADE rule is the load-bearing piece. IP forwarding alone does not get you a working tunnel. The MASQUERADE rule on the EC2 instance’s egress interface is what makes AWS-side resources able to reply to office-side traffic. If traffic flows in one direction but not the other, this is almost always the cause.
- Add the office LAN to the Access Server routing before you troubleshoot. Most “the tunnel is up but nothing works” diagnoses are this rule missing. It is a five-second fix once you know it exists, and a 45-minute troubleshooting session if you do not.
- The OpenVPN client UI is the fastest test, not the ping. When something does not work, the OpenVPN client logs the error in plain English. A
ping 10.0.0.xis a good second test, but the client UI tells you whether the tunnel itself came up. If the tunnel is up and the ping fails, it is a routing problem. If the tunnel is down, the client UI tells you why.
Trade-offs
A site-to-site VPN on OpenVPN Access Server is the right tool for a small lab, a homelab, or a single office talking to a single VPC. The setup is a Saturday afternoon and the operational cost is essentially zero. The OpenVPN admin UI gives you a per-user audit log, and the AMI keeps itself updated through the standard Ubuntu apt cycle.
The cost is operational. You are now running a VPN server that needs to be patched, monitored, and backed up. The iptables rules need to survive the next instance reboot, the Access Server license needs renewing annually, and the EC2 instance will need a larger size if you add more concurrent connections. None of this is hard, but it is work that the cloud-vendor-managed alternatives do for you. AWS Site-to-Site VPN with a virtual customer gateway, for example, costs more per hour but eliminates the instance management.
In our case, the OpenVPN setup is the right call for a homelab and a single office. The cost is in the tens of dollars a month and the operational work is a few hours a year. For a 50-person company with five VPCs, the AWS-managed option is the right call, and the math changes.
The migration to the AWS-managed option is a non-event. You tear down the OpenVPN instance, configure the virtual customer gateway on your office router, and provision the Site-to-Site VPN connection in the VPC console. The configuration is mostly the same, and the routing tables on your office router do not need to change.
If you are running a homelab or a single office and you want site-to-site, the OpenVPN Access Server Marketplace AMI is the right starting point. The setup is documented well, the steps above cover the load-bearing parts, and the operational cost is small. For anything larger, the AWS-managed option is the answer, and the OpenVPN route is the wrong tool.
Bottom line
A site-to-site VPN is the right way to connect an office LAN to an AWS VPC, and the OpenVPN Access Server Marketplace AMI is the fastest way to get there. The setup is mostly a routing exercise, and the routing exercise is mostly about not overlapping your CIDRs and not forgetting the MASQUERADE rule.
Bottom line: if you are running a homelab or a small office, the OpenVPN setup above is a Saturday afternoon. The VPC + AMI + IP forwarding + MASQUERADE + Access Server routing is the whole thing, and each step is in the AWS and OpenVPN docs. For larger deployments, look at the AWS-managed option, but that is a different cost conversation.