{"id":621,"date":"2025-03-10T11:42:29","date_gmt":"2025-03-10T11:42:29","guid":{"rendered":"https:\/\/blog.ngocha.biz\/?p=621"},"modified":"2025-03-10T11:42:29","modified_gmt":"2025-03-10T11:42:29","slug":"setup-openvpn-server-in-ec2","status":"publish","type":"post","link":"https:\/\/blog.ngocha.biz\/?p=621","title":{"rendered":"Setup OpenVPN Server In EC2 For Secure AWS Access"},"content":{"rendered":"<p>In this blog, you will learn to Setup OpenVPN Server in EC2 instance.<\/p>\n<p>By the end of this guide, you will:<\/p>\n<ul>\n<li>Have a fully working OpenVPN server<\/li>\n<li>Validate the connection from your workstation to the OpenVPN server<\/li>\n<li>Set up split tunneling to separate internet traffic from AWS access<\/li>\n<li>Test application access to private subnets using SSH and HTTP connections<\/li>\n<\/ul>\n<div class=\"kg-card kg-callout-card kg-callout-card-blue\">\n<div class=\"kg-callout-emoji\">\ud83d\udca1<\/div>\n<div class=\"kg-callout-text\">Enterprise usually have Site to Site VPN configured for this use case. AWS also offers other client to site VPN solutions like <a href=\"https:\/\/devopscube.com\/aws-client-vpn\/\" rel=\"noreferrer\"><b><strong style=\"white-space: pre-wrap;\">AWS Client VPN<\/strong><\/b><\/a> but it becomes expensive with more users. checkout <a href=\"https:\/\/devopscube.com\/aws-vpc-design\/#private-subnet-access\" rel=\"noreferrer\">AWS Private Subnet section<\/a> in VPC design blog to know more.<\/p>\n<p>So if you are looking for a simple poor mans solution, a custom client to server VPN solution like OpenVPN can help. <\/p><\/div>\n<\/div>\n<h2 id=\"openvpn-server-types\">OpenVPN Server Types<\/h2>\n<p>There are two types of OpenVPN implemention.<\/p>\n<ol>\n<li><strong>OpenVPN Community Edition (CE):<\/strong> This is the free, open-source version of OpenVPN. It requires manual setup and configuration using command-line tools. Also, it does not have a UI for configuration. However, there is a <a href=\"https:\/\/github.com\/d3vilh\/openvpn-ui?ref=devopscube.com\" rel=\"noreferrer\">open source project<\/a> that provides UI for community edition.<\/li>\n<li><strong>Self-hosted Access Server(AS): <\/strong>This is a commercial product from OpenVPN, that is built upon the open source version.\n<ol>\n<li>It offers only two free users and you can use it free forever. For more users, you can checkout the <a href=\"https:\/\/openvpn.net\/pricing\/?ref=devopscube.com\" rel=\"noreferrer\">pricing here.<\/a><\/li>\n<li>It provides user-friendly web-based GUI for easier management and configuration.<\/li>\n<li>It also supports multiple authentication methods such as LDAP, SAML etc.<\/li>\n<\/ol>\n<\/li>\n<li>OpenVPN CloudConnexa: This is the cloud offering of the OpenVPN.\n<ol>\n<li>It provides a user friendly approach for the configuration with the networks and applications.<\/li>\n<li>It has integrated security features like contentent filtering and IDS\/IPS (Intrusion Detection Systetem and Intrusion Prevention System) to protect from the cyber attacks.<\/li>\n<li>Highly scalable approach for growing projects, for more information, refer to this <a href=\"https:\/\/openvpn.net\/cloud-vpn\/?ref=devopscube.com\" rel=\"noreferrer\">offical documentation.<\/a><\/li>\n<\/ol>\n<\/li>\n<\/ol>\n<p>In short, the Community Edition is ideal for someone looking for a free VPN setup that supports multiple users.<\/p>\n<p>Access Server is for organizations looking for an easier setup process and additional management features.<\/p>\n<div class=\"kg-card kg-callout-card kg-callout-card-blue\">\n<div class=\"kg-callout-emoji\">\ud83d\udccc<\/div>\n<div class=\"kg-callout-text\"><b><strong style=\"white-space: pre-wrap;\">Important Note: <\/strong><\/b>This blog is based on the OpenVPN Community Edition setup.<\/div>\n<\/div>\n<h2 id=\"setup-prerequisites\">Setup Prerequisites<\/h2>\n<ol>\n<li>Public subnets for the OpenVPN server <\/li>\n<li>Private subnets with NAT attached &#8211; Only for testing the workloads via VPN (Optional)<\/li>\n<li>OpenVPN client in the local machine to establish the authentication between the client and the VPN server<\/li>\n<\/ol>\n<h2 id=\"architecture-openvpn-workflow\">Architecture &amp; OpenVPN Workflow<\/h2>\n<p>The OpenVPN server will help to access the other AWS private resources securely.<\/p>\n<p>The OpenVPN server will create a secure HTTP tunnel over the Internet between the AWS network and our local machine so we can securely access the private AWS resources from the local machine.<\/p>\n<p>The below is the workflow of the OpenVPN server and the access to the private AWS resource.<\/p>\n<figure class=\"kg-card kg-image-card kg-width-wide\"><img decoding=\"async\" src=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/03\/openvpn-ec2-server-access-1.png\" class=\"kg-image\" alt=\"the workflow diagram of the openvpn server in the ec2 instance\" loading=\"lazy\" width=\"1920\" height=\"1080\" srcset=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w600\/2025\/03\/openvpn-ec2-server-access-1.png 600w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w1000\/2025\/03\/openvpn-ec2-server-access-1.png 1000w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w1600\/2025\/03\/openvpn-ec2-server-access-1.png 1600w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/03\/openvpn-ec2-server-access-1.png 1920w\" sizes=\"auto, (min-width: 1200px) 1200px\"><\/figure>\n<ol>\n<li>The OpenVPN server will generate the client certificate and key for the authentication.<\/li>\n<li>Once the user gets the credentials and the OpenVPN client configuration file, that user can authenticate with the OpenVPN server with the help of the OpenVPN client application (Client app should be available on the local machine).<\/li>\n<li>After authentication, a secure encrypted tunnel will be created between the client machine and the OpenVPN server.<\/li>\n<li>During this process, the VPN server will assign a virtual IP to the user&#8217;s machine for the remote communication and traffic will reach the VPN server over the 1194 port.<\/li>\n<li>The VPN server will route the traffic from the user to the <a href=\"https:\/\/devopscube.com\/terraform-aws-vpc\/\" rel=\"noreferrer noopener\">AWS VPC<\/a> (Private subnets).<\/li>\n<li>VPC will route the traffic to a particular destination based on the security group&#8217;s rules.<\/li>\n<\/ol>\n<h2 id=\"how-to-setup-openvpn-server-in-ec2\">How to Setup OpenVPN Server in EC2?<\/h2>\n<p>The steps below explain the OpenVPN server setup on an EC2 instance.<\/p>\n<h3 id=\"step-1-create-a-virtual-private-network\">Step 1: Create a Virtual Private Network<\/h3>\n<p>We need at least one private and a public subnet in the VPC to demonstrate this setup.<\/p>\n<p>The <strong>public subnet<\/strong> should be attached to the <strong>Internet Gateway<\/strong> for the inbound and outbound communication ( This is for the VPN Server).<\/p>\n<p>The <strong>private subnet<\/strong> has to be attached to the <strong>NAT Gateway<\/strong> to get the outbound internet access ( This is not mandatory, only for the testing purposes).<\/p>\n<p>I already have a VPC setup. If you want to see the creation of the VPC, you can refer to this <a href=\"https:\/\/devopscube.com\/aws-ssm\/\">blog<\/a>.<\/p>\n<figure class=\"kg-card kg-image-card\"><img decoding=\"async\" src=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/03\/image-79-4.png\" class=\"kg-image\" alt=\"The vpc creation resource map of the VPC dashboard\" loading=\"lazy\" width=\"1862\" height=\"704\" srcset=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w600\/2025\/03\/image-79-4.png 600w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w1000\/2025\/03\/image-79-4.png 1000w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w1600\/2025\/03\/image-79-4.png 1600w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/03\/image-79-4.png 1862w\" sizes=\"auto, (min-width: 720px) 720px\"><\/figure>\n<h3 id=\"step-2-create-an-ec2-instance-for-the-openvpn\">Step 2: Create an EC2 instance for the OpenVPN<\/h3>\n<p>To create an <strong>OpenVPN server<\/strong>, we need to use the <strong>public subnet<\/strong>, because it needs inbound and outbound internet access.<\/p>\n<p>I am choosing an<strong> Amazon Linux 2 AMI, t2-micro<\/strong> instance for this.<\/p>\n<blockquote><p>Note: Currently we are using the Amazon Linux 2, so the installation steps might differ in other distros.<\/p><\/blockquote>\n<p>Navigate to the EC2 console and click <code>Launch instances<\/code> button.<\/p>\n<figure class=\"kg-card kg-image-card\"><img decoding=\"async\" src=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/03\/image-80-6.png\" class=\"kg-image\" alt=\"ec2 instance creation page and the ec2 dashboard\" loading=\"lazy\" width=\"1177\" height=\"371\" srcset=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w600\/2025\/03\/image-80-6.png 600w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w1000\/2025\/03\/image-80-6.png 1000w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/03\/image-80-6.png 1177w\" sizes=\"auto, (min-width: 720px) 720px\"><\/figure>\n<p>Give a name for the instance and select Amazon Linux as well as the AMI.<\/p>\n<figure class=\"kg-card kg-image-card\"><img decoding=\"async\" src=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/03\/image-81-4.png\" class=\"kg-image\" alt=\"giving name and selection os and type for the instance creation\" loading=\"lazy\" width=\"1155\" height=\"775\" srcset=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w600\/2025\/03\/image-81-4.png 600w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w1000\/2025\/03\/image-81-4.png 1000w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/03\/image-81-4.png 1155w\" sizes=\"auto, (min-width: 720px) 720px\"><\/figure>\n<p>Select an instance type. I am choosing t2.micro, but you can choose any. If you already have a key pair, select it or create a new one.<\/p>\n<figure class=\"kg-card kg-image-card\"><img decoding=\"async\" src=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/03\/image-82-5.png\" class=\"kg-image\" alt=\"choosing instance type and keypair for the ec2 instance\" loading=\"lazy\" width=\"1041\" height=\"467\" srcset=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w600\/2025\/03\/image-82-5.png 600w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w1000\/2025\/03\/image-82-5.png 1000w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/03\/image-82-5.png 1041w\" sizes=\"auto, (min-width: 720px) 720px\"><\/figure>\n<p>Select the VPC you have created, select the public subnet, enable public IP to access the server, and select the default security group, or you can create a new one for the OpenVPN server.<\/p>\n<figure class=\"kg-card kg-image-card\"><img decoding=\"async\" src=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/03\/image-83-3.png\" class=\"kg-image\" alt=\"network settings section to select the vpc, subnet and security groups configuration\" loading=\"lazy\" width=\"1011\" height=\"626\" srcset=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w600\/2025\/03\/image-83-3.png 600w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w1000\/2025\/03\/image-83-3.png 1000w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/03\/image-83-3.png 1011w\" sizes=\"auto, (min-width: 720px) 720px\"><\/figure>\n<p>For now, I am using the default configuration for the rest of the settings, but you can modify it if you want.<\/p>\n<figure class=\"kg-card kg-image-card\"><img decoding=\"async\" src=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/03\/image-84-4.png\" class=\"kg-image\" alt=\"lauching instance after all the configuration provided\" loading=\"lazy\" width=\"1103\" height=\"567\" srcset=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w600\/2025\/03\/image-84-4.png 600w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w1000\/2025\/03\/image-84-4.png 1000w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/03\/image-84-4.png 1103w\" sizes=\"auto, (min-width: 720px) 720px\"><\/figure>\n<h3 id=\"step-3-update-security-group-rules\">Step 3: Update Security Group Rules<\/h3>\n<p>We have attached the default security group to this server, but need to know what protocols need to be enabled for the incoming traffic.<\/p>\n<p>Navigate to the attached security group.<\/p>\n<figure class=\"kg-card kg-image-card\"><img decoding=\"async\" src=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/03\/image-88-4.png\" class=\"kg-image\" alt=\"selecting the default security group of the ec2 instance to modifiy the rules\" loading=\"lazy\" width=\"1156\" height=\"655\" srcset=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w600\/2025\/03\/image-88-4.png 600w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w1000\/2025\/03\/image-88-4.png 1000w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/03\/image-88-4.png 1156w\" sizes=\"auto, (min-width: 720px) 720px\"><\/figure>\n<p>Clicking the security group will open a new page, there you need to click the <code>Edit inbound rules<\/code> button to add or remove rules.<\/p>\n<figure class=\"kg-card kg-image-card\"><img decoding=\"async\" src=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/03\/image-89-3.png\" class=\"kg-image\" alt=\"the security group page to modify the inbound rules to the server\" loading=\"lazy\" width=\"1166\" height=\"619\" srcset=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w600\/2025\/03\/image-89-3.png 600w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w1000\/2025\/03\/image-89-3.png 1000w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/03\/image-89-3.png 1166w\" sizes=\"auto, (min-width: 720px) 720px\"><\/figure>\n<p>I will add a rule for <strong>SSH<\/strong>, then we can access this EC2 instance, and add a custom UDP port for the OpenVPN, which is <code>1194<\/code>.<\/p>\n<p>I am adding one more port, which is 9090, to demonstrate a private AWS resource access, so that is optional.<\/p>\n<figure class=\"kg-card kg-image-card\"><img decoding=\"async\" src=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/03\/image-91-4.png\" class=\"kg-image\" alt=\"the added rules list inthe security group\" loading=\"lazy\" width=\"1268\" height=\"680\" srcset=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w600\/2025\/03\/image-91-4.png 600w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w1000\/2025\/03\/image-91-4.png 1000w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/03\/image-91-4.png 1268w\" sizes=\"auto, (min-width: 720px) 720px\"><\/figure>\n<p>Once the security group rules are properly added, we can access the instance.<\/p>\n<h3 id=\"step-4-access-the-openvpn-ec2-instance\">Step 4: Access the OpenVPN EC2 Instance<\/h3>\n<p>The instance will take a few minutes to prepare. Once the health checks are completed and the state is running, we can log in to the shell.<\/p>\n<figure class=\"kg-card kg-image-card\"><img decoding=\"async\" src=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/03\/image-85-4.png\" class=\"kg-image\" alt=\"the status of the openvpn ec2 server\" loading=\"lazy\" width=\"1166\" height=\"381\" srcset=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w600\/2025\/03\/image-85-4.png 600w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w1000\/2025\/03\/image-85-4.png 1000w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/03\/image-85-4.png 1166w\" sizes=\"auto, (min-width: 720px) 720px\"><\/figure>\n<p>If you click the <strong>instance ID<\/strong>, you can see the option to connect and note down the server&#8217;s public IP for the upcoming configuration.<\/p>\n<figure class=\"kg-card kg-image-card\"><img decoding=\"async\" src=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/03\/image-86-5.png\" class=\"kg-image\" alt=\"the server connection methods\" loading=\"lazy\" width=\"980\" height=\"450\" srcset=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w600\/2025\/03\/image-86-5.png 600w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/03\/image-86-5.png 980w\" sizes=\"auto, (min-width: 720px) 720px\"><\/figure>\n<p>You can use the <code>EC2 Instance Connect<\/code> method to connect the server, or can use the SSH method with the key from the local machine.<\/p>\n<figure class=\"kg-card kg-image-card\"><img decoding=\"async\" src=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/03\/image-87-4.png\" class=\"kg-image\" alt=\"\" loading=\"lazy\" width=\"1169\" height=\"754\" srcset=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w600\/2025\/03\/image-87-4.png 600w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w1000\/2025\/03\/image-87-4.png 1000w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/03\/image-87-4.png 1169w\" sizes=\"auto, (min-width: 720px) 720px\"><\/figure>\n<p>To access from the local machine, use the following command.<\/p>\n<pre><code>ssh -i &lt;KEY&gt; ec2-user@&lt;PUBLIC_IP&gt;<\/code><\/pre>\n<h2 id=\"setting-up-openvpn-in-amazon-linux-ec2-instance\">Setting up OpenVPN in Amazon Linux EC2 Instance<\/h2>\n<p>Follow the below steps to install the OpenVPN server on an EC2 instance.<\/p>\n<h3 id=\"step-1-install-openvpn-and-easyrsa\">Step 1: Install OpenVPN and EasyRSA<\/h3>\n<p>Enable the EPEL repository for the additional software packages.<\/p>\n<pre><code>sudo amazon-linux-extras enable epel<\/code><\/pre>\n<p>Install EPEL release package, OpenVPN and Easy-RSA<\/p>\n<pre><code>sudo yum install -y epel-release\nsudo yum install -y openvpn easy-rsa<\/code><\/pre>\n<h3 id=\"step-2-configure-openvpn\">Step 2: Configure OpenVPN<\/h3>\n<p>Initialize the Easy-RSA and generate certificates<\/p>\n<p>Easy-RSA is a tool for creating certificates for various use cases. It provides a framework with necessary components for generating certificates.<\/p>\n<pre><code>cd \/etc\/openvpn\nsudo mkdir easy-rsa\ncd easy-rsa<\/code><\/pre>\n<p>Download the Easy-RSA package from the GitHub and extract it<\/p>\n<pre><code>sudo wget -O easy-rsa.tar.gz https:\/\/github.com\/OpenVPN\/easy-rsa\/releases\/download\/v3.2.2\/EasyRSA-3.2.2.tgz\nsudo tar -xvf easy-rsa.tar.gz\ncd EasyRSA-3.2.2<\/code><\/pre>\n<p>Initialize the Public Key Infrastructure (PKI)<\/p>\n<pre><code>sudo .\/easyrsa init-pki<\/code><\/pre>\n<figure class=\"kg-card kg-image-card\"><img decoding=\"async\" src=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/03\/image-92-4.png\" class=\"kg-image\" alt=\"the initialization of the easy-rsa public key infrastructure \n\" loading=\"lazy\" width=\"1599\" height=\"800\" srcset=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w600\/2025\/03\/image-92-4.png 600w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w1000\/2025\/03\/image-92-4.png 1000w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/03\/image-92-4.png 1599w\" sizes=\"auto, (min-width: 720px) 720px\"><\/figure>\n<p>Create a Certificate Authority (CA)<\/p>\n<p>The Certificate Authority is a trusted entity that is capable of issuing and managing certificates.<\/p>\n<pre><code>sudo .\/easyrsa build-ca<\/code><\/pre>\n<p>You will be prompted to give the <strong>passphrase<\/strong>, which is actually a password, and also will be asked to provide a common name; you can give any name.<\/p>\n<figure class=\"kg-card kg-image-card\"><img decoding=\"async\" src=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/03\/image-93-4.png\" class=\"kg-image\" alt=\"setting up passphrase for the ca and common name\" loading=\"lazy\" width=\"1031\" height=\"860\" srcset=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w600\/2025\/03\/image-93-4.png 600w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w1000\/2025\/03\/image-93-4.png 1000w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/03\/image-93-4.png 1031w\" sizes=\"auto, (min-width: 720px) 720px\"><\/figure>\n<p>Create a request for a server key<\/p>\n<pre><code>sudo .\/easyrsa gen-req server nopass<\/code><\/pre>\n<p>Will prompt to provide a common name, you can just press <code>enter<\/code> or provide a hostname like <code>dev.techiescamp.com<\/code><\/p>\n<figure class=\"kg-card kg-image-card\"><img decoding=\"async\" src=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/03\/image-94-3.png\" class=\"kg-image\" alt=\"requesting server key and providing host name\" loading=\"lazy\" width=\"1725\" height=\"861\" srcset=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w600\/2025\/03\/image-94-3.png 600w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w1000\/2025\/03\/image-94-3.png 1000w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w1600\/2025\/03\/image-94-3.png 1600w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/03\/image-94-3.png 1725w\" sizes=\"auto, (min-width: 720px) 720px\"><\/figure>\n<p>To sign the server certificate request, use the following command.<\/p>\n<pre><code>sudo .\/easyrsa sign-req server server<\/code><\/pre>\n<p>Will prompt for <code>yes<\/code> and needs to provide the CA passphrase<\/p>\n<figure class=\"kg-card kg-image-card\"><img decoding=\"async\" src=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/03\/image-95-3.png\" class=\"kg-image\" alt=\"the singing information and the validity of the server certificates \" loading=\"lazy\" width=\"734\" height=\"867\" srcset=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w600\/2025\/03\/image-95-3.png 600w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/03\/image-95-3.png 734w\" sizes=\"auto, (min-width: 720px) 720px\"><\/figure>\n<p>The output will give the validity and other related information.<\/p>\n<p>Generate the Diffie-Hellman (DH)  key exchange file<\/p>\n<p>The Diffie-Hellman protocol secures communication protocols such as <a href=\"https:\/\/devopscube.com\/configure-ingress-tls-kubernetes\/\" rel=\"noreferrer noopener\">SSL\/TLS<\/a>, SSH, and IPsec.<\/p>\n<pre><code>sudo .\/easyrsa gen-dh<\/code><\/pre>\n<figure class=\"kg-card kg-image-card\"><img decoding=\"async\" src=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/03\/image-96-5.png\" class=\"kg-image\" alt=\"diffie Hellman exchange key creation output\" loading=\"lazy\" width=\"1605\" height=\"741\" srcset=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w600\/2025\/03\/image-96-5.png 600w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w1000\/2025\/03\/image-96-5.png 1000w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w1600\/2025\/03\/image-96-5.png 1600w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/03\/image-96-5.png 1605w\" sizes=\"auto, (min-width: 720px) 720px\"><\/figure>\n<h3 id=\"step-3-configure-openvpn-server\">Step 3: Configure OpenVPN Server<\/h3>\n<p>Create a configuration file for the OpenVPN server<\/p>\n<pre><code>sudo vim \/etc\/openvpn\/server.conf<\/code><\/pre>\n<p>Add the following configurations<\/p>\n<pre><code>port 1194\nproto udp\ndev tun\nca \/etc\/openvpn\/easy-rsa\/EasyRSA-3.2.2\/pki\/ca.crt\ncert \/etc\/openvpn\/easy-rsa\/EasyRSA-3.2.2\/pki\/issued\/server.crt\nkey \/etc\/openvpn\/easy-rsa\/EasyRSA-3.2.2\/pki\/private\/server.key\ndh \/etc\/openvpn\/easy-rsa\/EasyRSA-3.2.2\/pki\/dh.pem\nserver 10.8.0.0 255.255.255.0\nkeepalive 10 120\npersist-key\npersist-tun\nstatus \/var\/log\/openvpn-status.log\nverb 3\npush \"route 10.0.4.0 255.255.255.0\"  <\/code><\/pre>\n<p>Port <code>1194<\/code>, is the default listening port of the OpenVPN and UDP is the protocol, which is faster than the TCP protocol.<\/p>\n<p><code>dev tun<\/code> &#8211;&gt; Indicating that the OpenVPN to use tunnel device, (Layer 3 IP based tunneling)<\/p>\n<p><code>ca \/etc\/openvpn\/easy-rsa\/EasyRSA-3.2.2\/pki\/ca.crt<\/code> &#8211;&gt;  Certificate Authority certificate<\/p>\n<p><code>cert \/etc\/openvpn\/easy-rsa\/EasyRSA-3.2.2\/pki\/issued\/server.crt<\/code> &#8211;&gt; Server&#8217;s SSL certificate<\/p>\n<p><code>key \/etc\/openvpn\/easy-rsa\/EasyRSA-3.2.2\/pki\/private\/server.key<\/code> &#8211;&gt; The private key of the server certificate<\/p>\n<p><code>dh \/etc\/openvpn\/easy-rsa\/EasyRSA-3.2.2\/pki\/dh.pem<\/code> &#8211;&gt; Diffie-Hellman exchange key<\/p>\n<p><code>server 10.8.0.0 255.255.255.0<\/code> &#8211;&gt; Virtual IP for the VPN clients<\/p>\n<p><code>keepalive 10 120<\/code> &#8211;&gt; Sends ping request for each 10 seconds to ensure that connection is active and if there is no response in 120 seconds, it will restart the server.<\/p>\n<p><code>persist-key<\/code> &#8211;&gt; This will avoid reloading the private key each time the OpenVPN server restarts.<\/p>\n<p><code>persist-tun<\/code> &#8211;&gt; Keep the tunnel persistently.<\/p>\n<p><code>status \/var\/log\/openvpn-status.log<\/code> &#8211;&gt; Stores the OpenVPN logs in the specific path.<\/p>\n<p><code>verb 3<\/code> &#8211;&gt; The verbosity level for the logs.<\/p>\n<p><code>push \"route 10.0.4.0 255.255.255.0\"<\/code> &#8211;&gt; Route to connect the VPN clients and <code>10.0.4.0<\/code> is the private network the clients can securely access.<\/p>\n<p>Enable and start the OpenVPN service<\/p>\n<pre><code>sudo systemctl enable openvpn@server\nsudo systemctl start openvpn@server<\/code><\/pre>\n<p>To check the OpenVPN service status.<\/p>\n<pre><code>sudo systemctl status openvpn@server<\/code><\/pre>\n<figure class=\"kg-card kg-image-card\"><img decoding=\"async\" src=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/03\/image-18-5.png\" class=\"kg-image\" alt=\"the openvpn service status output\" loading=\"lazy\" width=\"1711\" height=\"863\" srcset=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w600\/2025\/03\/image-18-5.png 600w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w1000\/2025\/03\/image-18-5.png 1000w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w1600\/2025\/03\/image-18-5.png 1600w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/03\/image-18-5.png 1711w\" sizes=\"auto, (min-width: 720px) 720px\"><\/figure>\n<h3 id=\"step-4-enable-split-tunnel-nat-for-internet-access\">Step 4: Enable Split Tunnel (NAT) for Internet Access<\/h3>\n<p>Now, if you establish the VPN connection from the local machine, you can only access the particular AWS private network.<\/p>\n<p>This is quite secure because all the traffic will go through the secured VPN tunnel, which is called the full-tunnel method.<\/p>\n<p>But the problem is that we can&#8217;t access anything besides the AWS private network, even Google.<\/p>\n<p>So, we need only the secure connection for the AWS network, but we also need to use the other networks. This method is called split tunnel.<\/p>\n<p>For that we need to enable NAT.<\/p>\n<p>To allow the clients to access the internet,<\/p>\n<pre><code>sudo sysctl -w net.ipv4.ip_forward=1\nsudo iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE<\/code><\/pre>\n<p>To make the configuration persistent<\/p>\n<pre><code>echo \"net.ipv4.ip_forward = 1\" | sudo tee -a \/etc\/sysctl.conf\nsudo iptables-save | sudo tee \/etc\/iptables\/rules.v4<\/code><\/pre>\n<p>Restart the OpenVPN service.<\/p>\n<pre><code>sudo systemctl restart openvpn@server<\/code><\/pre>\n<p>The OpenVPN Server setup is completed.<\/p>\n<h2 id=\"generate-a-client-key\">Generate a client key<\/h2>\n<p>Next step is to create the client key for a user. This is required to authenticate from the VPN client with the sever for a specific user.<\/p>\n<p>Navigate to the <code>EasyRSA-3.2.2<\/code> directory.<\/p>\n<pre><code>\/etc\/openvpn\/easy-rsa\/EasyRSA-3.2.2<\/code><\/pre>\n<p>Generate a client key without password.<\/p>\n<pre><code>sudo .\/easyrsa gen-req client nopass<\/code><\/pre>\n<p>This will prompt you to give a client name. It will create the <code>client.req<\/code> and <code>client.key<\/code> files.<\/p>\n<figure class=\"kg-card kg-image-card\"><img decoding=\"async\" src=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/03\/image-24-6.png\" class=\"kg-image\" alt=\"output of generating the client key for the openvpn access\" loading=\"lazy\" width=\"1400\" height=\"857\" srcset=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w600\/2025\/03\/image-24-6.png 600w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w1000\/2025\/03\/image-24-6.png 1000w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/03\/image-24-6.png 1400w\" sizes=\"auto, (min-width: 720px) 720px\"><\/figure>\n<p>Sign the client certificate request using the OpenVPN CA.<\/p>\n<pre><code>sudo .\/easyrsa sign-req client client<\/code><\/pre>\n<p>This will prompt you to type <code>yes<\/code>. Also you need to provide a passphrase. It will create the client certificates.<\/p>\n<figure class=\"kg-card kg-image-card\"><img decoding=\"async\" src=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/03\/image-25-5.png\" class=\"kg-image\" alt=\"the signing output of the client certificate\" loading=\"lazy\" width=\"731\" height=\"865\" srcset=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w600\/2025\/03\/image-25-5.png 600w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/03\/image-25-5.png 731w\" sizes=\"auto, (min-width: 720px) 720px\"><\/figure>\n<h2 id=\"move-certificates-to-local-workstation\">Move Certificates to Local Workstation<\/h2>\n<p>Now that we have the certificates generated, we need to copy it to our local workstation for validation.<\/p>\n<p>You can find the <strong>certs and key<\/strong> in the following locations.<\/p>\n<ol>\n<li><code>\/etc\/openvpn\/easy-rsa\/EasyRSA-3.2.2\/pki\/ca.crt<\/code><\/li>\n<li><code>\/etc\/openvpn\/easy-rsa\/EasyRSA-3.2.2\/pki\/issued\/client.crt<\/code><\/li>\n<li><code>\/etc\/openvpn\/easy-rsa\/EasyRSA-3.2.2\/pki\/private\/client.key<\/code><\/li>\n<\/ol>\n<p>Use <code>cat<\/code> command to manually copy and paste. <\/p>\n<p>Or you use <code>scp<\/code> to directly copy from the <strong>OpenVPN server to the local machine<\/strong> via SSH.<\/p>\n<p>Once you have the files copied, move on to the next step.<\/p>\n<h2 id=\"generate-a-vpn-client-configuration-file\">Generate a VPN Client Configuration File<\/h2>\n<p>Once the above files are present in the local machine, we need to create a OpenVPN Client configuration file.<\/p>\n<p>Make sure all files are in the same directory.<\/p>\n<pre><code>vim client.ovpn<\/code><\/pre>\n<p>Add the following configurations in the file.<\/p>\n<pre><code>client\ndev tun\nproto udp\nremote 34.209.222.65 1194\nresolv-retry infinite\nnobind\npersist-key\npersist-tun\nca ca.crt\ncert client.crt\nkey client.key\nroute 10.0.4.0 255.255.255.0<\/code><\/pre>\n<p>Here <strong><code>34.209.222.65<\/code><\/strong> is the OpenVPN Server&#8217;s public IP so replace it with yours. <\/p>\n<p>Add <code>redirect-gateway def1<\/code> to route all traffic through the VPN, this might affect the regular internet access. <\/p>\n<p>Now you should have the following files in your local workstation.<\/p>\n<figure class=\"kg-card kg-image-card\"><img decoding=\"async\" src=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/03\/image-97-5.png\" class=\"kg-image\" alt=\"the openvpn client files such as ca, client certificate and key and copenvpn configuration file\" loading=\"lazy\" width=\"1304\" height=\"652\" srcset=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w600\/2025\/03\/image-97-5.png 600w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w1000\/2025\/03\/image-97-5.png 1000w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/03\/image-97-5.png 1304w\" sizes=\"auto, (min-width: 720px) 720px\"><\/figure>\n<h2 id=\"install-configure-openvpn-client\">Install &amp; Configure OpenVPN Client<\/h2>\n<p>Now that we have the necessary certs and config files for client authentication, we can configure the OpenVPN client application.<\/p>\n<p>First, need to install the OpenVPN client.<\/p>\n<p>You can follow this <a href=\"https:\/\/openvpn.net\/client\/?ref=devopscube.com\" rel=\"noreferrer\">official&nbsp;downloads page<\/a>&nbsp;to download the client based on your platform.<\/p>\n<p>After the installation, if you open the client, you can see a <code>+<\/code> button to add a configuration.<\/p>\n<figure class=\"kg-card kg-image-card\"><img decoding=\"async\" src=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/03\/image-27-5.png\" class=\"kg-image\" alt=\"OpenVPN client dashboard\" loading=\"lazy\" width=\"400\" height=\"685\"><\/figure>\n<p>On the next step, you need to upload the <code>.ovpn<\/code> file that we have configured earlier.<\/p>\n<figure class=\"kg-card kg-image-card\"><img decoding=\"async\" src=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/03\/image-28-5.png\" class=\"kg-image\" alt=\"openvpn client dashboard to update the openvpn configuration file\" loading=\"lazy\" width=\"400\" height=\"685\"><\/figure>\n<p>Once you uploaded the OpenVPN Configuration file, you can see a <code>connect<\/code> button to establish the connection<\/p>\n<figure class=\"kg-card kg-image-card\"><img decoding=\"async\" src=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/03\/image-29-5.png\" class=\"kg-image\" alt=\"the connection of the openvpn client\" loading=\"lazy\" width=\"400\" height=\"685\"><\/figure>\n<p>Once the connection is successfully established, we can see the green mark on the radio button.<\/p>\n<figure class=\"kg-card kg-image-card\"><img decoding=\"async\" src=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/03\/image-30-4.png\" class=\"kg-image\" alt=\"the openvpn client successful connection indication\" loading=\"lazy\" width=\"400\" height=\"685\"><\/figure>\n<\/p>\n<h2 id=\"vpn-validation-using-private-ec2-instance\">VPN Validation Using Private ec2 Instance<\/h2>\n<p>Now, we need to check whether we can access the private AWS resources.<\/p>\n<p>For that, I am creating an EC2 instance within private subnet and deploying a Prometheus application inside it.<\/p>\n<p>I am choosing Amazon Linux as AMI.<\/p>\n<figure class=\"kg-card kg-image-card\"><img decoding=\"async\" src=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/03\/image-19-5.png\" class=\"kg-image\" alt=\"creating an ec2 instance for the prometheus server\" loading=\"lazy\" width=\"981\" height=\"761\" srcset=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w600\/2025\/03\/image-19-5.png 600w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/03\/image-19-5.png 981w\" sizes=\"auto, (min-width: 720px) 720px\"><\/figure>\n<p>Select the keypair and choose the VPC and private Subnet.<\/p>\n<figure class=\"kg-card kg-image-card\"><img decoding=\"async\" src=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/03\/image-20-7.png\" class=\"kg-image\" alt=\"selecting the keypair and vpc as well as the subnets.\" loading=\"lazy\" width=\"982\" height=\"702\" srcset=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w600\/2025\/03\/image-20-7.png 600w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/03\/image-20-7.png 982w\" sizes=\"auto, (min-width: 720px) 720px\"><\/figure>\n<p>Wait until the state and status are ready and note down the private IP of the server.<\/p>\n<figure class=\"kg-card kg-image-card\"><img decoding=\"async\" src=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/03\/image-21-4.png\" class=\"kg-image\" alt=\"checking the status of the private server and noting down the private ip address\" loading=\"lazy\" width=\"1262\" height=\"538\" srcset=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w600\/2025\/03\/image-21-4.png 600w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w1000\/2025\/03\/image-21-4.png 1000w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/03\/image-21-4.png 1262w\" sizes=\"auto, (min-width: 720px) 720px\"><\/figure>\n<p>Now, I am getting in the private server through SSH from the VPN Server, because the VPN server is public and on the same network as the private server.<\/p>\n<p>We can also SSH to the private server from the local machine as well because the VPN connection is established between local workstation and the VPC network.<\/p>\n<figure class=\"kg-card kg-image-card\"><img decoding=\"async\" src=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/03\/image-22-7.png\" class=\"kg-image\" alt=\"the public key to ssh the private server\" loading=\"lazy\" width=\"1868\" height=\"855\" srcset=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w600\/2025\/03\/image-22-7.png 600w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w1000\/2025\/03\/image-22-7.png 1000w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w1600\/2025\/03\/image-22-7.png 1600w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/03\/image-22-7.png 1868w\" sizes=\"auto, (min-width: 720px) 720px\"><\/figure>\n<p>Copy the keypair to the VPN server and change the permission.<\/p>\n<pre><code>sudo chmod 400 techiescamp.pem<\/code><\/pre>\n<p>To SSH to the private server, use the following command.<\/p>\n<pre><code>sudo ssh -i techiescamp.pem ec2-user@&lt;PRIVATE_SERVER_IP&gt;<\/code><\/pre>\n<figure class=\"kg-card kg-image-card\"><img decoding=\"async\" src=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/03\/image-23-5.png\" class=\"kg-image\" alt=\"the successful authentication of the private server\" loading=\"lazy\" width=\"1535\" height=\"863\" srcset=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w600\/2025\/03\/image-23-5.png 600w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w1000\/2025\/03\/image-23-5.png 1000w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/03\/image-23-5.png 1535w\" sizes=\"auto, (min-width: 720px) 720px\"><\/figure>\n<div class=\"kg-card kg-callout-card kg-callout-card-blue\">\n<div class=\"kg-callout-emoji\">\ud83d\udca1<\/div>\n<div class=\"kg-callout-text\"><b><strong style=\"white-space: pre-wrap;\">Important Note:<\/strong><\/b> If we enable <a href=\"https:\/\/devopscube.com\/aws-ssm\/\" rel=\"noreferrer noopener\">AWS SSM<\/a>, we can connect to the server without using SSH, otherwise, we can access the shell only from another public server of the same network with the key pair.<\/div>\n<\/div>\n<h2 id=\"deploy-application-in-private-ec2-instance\">Deploy Application in Private ec2 Instance<\/h2>\n<p>We are installing Prometheus on a private server to demonstrate access from a local machine but you can try with any application even a simpe nginx server also enough for the testing. <\/p>\n<p>You can follow this <a href=\"https:\/\/devopscube.com\/install-configure-prometheus-linux\/\">blog<\/a> for the Prometheus installation.<\/p>\n<p>Now, we can try to access the Prometheus dashboard from our local machine with its private IP securely.<\/p>\n<figure class=\"kg-card kg-image-card\"><img decoding=\"async\" src=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/03\/image-31-4.png\" class=\"kg-image\" alt=\"the access output of the prometheus dashboard\" loading=\"lazy\" width=\"1069\" height=\"508\" srcset=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w600\/2025\/03\/image-31-4.png 600w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w1000\/2025\/03\/image-31-4.png 1000w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/03\/image-31-4.png 1069w\" sizes=\"auto, (min-width: 720px) 720px\"><\/figure>\n<h2 id=\"conclusion\">Conclusion<\/h2>\n<p>This blog mainly covers setting up the OpenVPN server on the EC2 instance and accessing private AWS resources.<\/p>\n<p>There is a managed service available in AWS, AWS Client VPN Endpoint. We don&#8217;t need a server to deploy for the OpenVPN, and it will automatically scale based on the user connection.<\/p>\n<p>If you want to see the AWS Client VPN Endpoint setup, refer to this <a href=\"https:\/\/devopscube.com\/aws-client-vpn\/\">blog<\/a>.<\/p>\n<p>The next blog will cover access to the AWS EKS private cluster resources.<\/p>\n<hr>\n<p><strong>Ngu\u1ed3n:<\/strong> <a href=\"https:\/\/devopscube.com\/setup-openvpn-server-in-ec2\/\" target=\"_blank\" rel=\"noopener noreferrer\">Setup OpenVPN Server In EC2 For Secure AWS Access \u2014 DevOpsCube<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Source: https:\/\/devopscube.com\/setup-openvpn-server-in-ec2\/<\/p>\n","protected":false},"author":1,"featured_media":622,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-621","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-devops"],"_links":{"self":[{"href":"https:\/\/blog.ngocha.biz\/index.php?rest_route=\/wp\/v2\/posts\/621","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blog.ngocha.biz\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.ngocha.biz\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.ngocha.biz\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.ngocha.biz\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=621"}],"version-history":[{"count":0,"href":"https:\/\/blog.ngocha.biz\/index.php?rest_route=\/wp\/v2\/posts\/621\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/blog.ngocha.biz\/index.php?rest_route=\/wp\/v2\/media\/622"}],"wp:attachment":[{"href":"https:\/\/blog.ngocha.biz\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=621"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.ngocha.biz\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=621"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.ngocha.biz\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=621"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}