Skip to content
Author Nejat Hakan
eMail nejat.hakan@outlook.de
PayPal Me https://paypal.me/nejathakan


VPN Server OpenVPN

Introduction to VPNs and OpenVPN

Welcome to the world of self-hosted Virtual Private Networks (VPNs) using OpenVPN. In an era where digital privacy and security are paramount, understanding and implementing your own VPN server is an invaluable skill. This guide aims to provide university-level students with a comprehensive, deep-dive into setting up, configuring, and managing an OpenVPN server, from the foundational basics to advanced, production-ready deployments. We will explore the "why" and "how" with detailed explanations and practical, hands-on workshops.

What is a VPN

A Virtual Private Network, or VPN, is a technology that creates a secure and encrypted connection over a less secure network, such as the public internet. Think of it as a private, encrypted tunnel for your internet traffic. When you connect to a VPN server, your device (computer, smartphone, etc.) establishes a secure link with that server. All your internet traffic is then routed through this tunnel to the VPN server. From the perspective of websites and online services you access, your traffic appears to originate from the VPN server's IP address and location, not your actual IP address and location.

Core Functions of a VPN:

  1. Encryption: This is the cornerstone of VPN security. VPNs use cryptographic protocols to encrypt the data transmitted between your device and the VPN server. This means that even if an attacker (e.g., on the same public Wi-Fi network) manages to intercept your data packets, they will see only scrambled, unreadable ciphertext, not your sensitive information like passwords, browsing history, or financial details. The strength of this encryption depends on the VPN protocol and algorithms used.
  2. Tunneling: This refers to the process of encapsulating your data packets within other packets to create a secure pathway. The original data packet, including its headers (which contain source and destination IP addresses), is wrapped inside an outer packet that is routed between your device and the VPN server. This outer packet protects the inner packet's contents and addressing information from being easily inspected by intermediate network nodes.
  3. IP Address Masking: When you connect through a VPN, your real IP address is hidden. Websites and online services see the IP address of the VPN server you are connected to. This helps in anonymizing your online activities and can also be used to bypass geo-restrictions (accessing content that is only available in certain countries).
  4. Data Integrity: Some VPN protocols also ensure data integrity, meaning they can detect if data has been tampered with during transit. This is usually achieved through cryptographic hashing functions.

Analogy:

Imagine you need to send a valuable, confidential document through a public postal system known for prying eyes.

  • Without a VPN: You send the document on a postcard. Anyone handling it can read its contents. Your sender address (your IP) and recipient address are clearly visible.
  • With a VPN:
    • You place the document (your data) inside a special opaque, locked envelope (encryption).
    • You then put this locked envelope inside another, standard-looking courier package addressed to a secure P.O. Box (the VPN server). The P.O. Box has its own address (VPN server's IP).
    • The courier (internet) delivers this package to the P.O. Box.
    • The P.O. Box (VPN server) unlocks the special envelope, takes out your original document, and then sends it to its final destination from the P.O. Box's address.
    • Replies come back to the P.O. Box, which then puts them in the special locked envelope and sends them back to you through the courier.

This analogy illustrates how a VPN hides your data's content (encryption), your origin (IP masking), and the path it takes (tunneling).

Why Use a VPN

The reasons for using a VPN are diverse and cater to various needs, from individual privacy concerns to corporate security requirements.

  1. Enhanced Privacy:

    • ISP Snooping: Your Internet Service Provider (ISP) can see every website you visit, how long you stay there, and the type of content you consume. In many countries, ISPs are required to log this data and may even sell anonymized browsing habits to advertisers. A VPN encrypts your traffic, making it unreadable to your ISP. They can see you're connected to a VPN server, but not what you're doing through that connection.
    • Government Surveillance: In regions with extensive online surveillance, a VPN can provide a layer of protection against mass data collection by obscuring your online activities.
    • Advertiser Tracking: Advertisers and data brokers build profiles based on your IP address and browsing habits. A VPN helps by masking your real IP and making it harder to track you across different websites.
  2. Improved Security:

    • Public Wi-Fi Protection: Public Wi-Fi networks (in cafes, airports, hotels) are notoriously insecure. Attackers on the same network can easily intercept unencrypted data using techniques like "man-in-the-middle" attacks or packet sniffing. A VPN encrypts all your traffic, securing your connection even on untrusted networks.
    • Protection Against Hacking Attempts: By masking your IP address, a VPN can make it more difficult for attackers to directly target your devices with certain types of attacks (e.g., DDoS, port scanning) as they would target the VPN server instead.
  3. Bypassing Censorship and Geo-Restrictions:

    • Accessing Blocked Content: Some governments or organizations block access to certain websites or online services. A VPN can allow you to bypass these restrictions by routing your traffic through a server located in a country where access is not restricted.
    • Accessing Geo-Restricted Media: Streaming services (like Netflix, BBC iPlayer) often have different content libraries for different regions due to licensing agreements. By connecting to a VPN server in a specific country, you can appear as if you are browsing from that country, potentially unlocking its content library. (Note: This may violate the terms of service of some platforms.)
  4. Secure Remote Access (Corporate Use):

    • Connecting to Company Networks: Businesses use VPNs to allow employees to securely access internal company networks and resources (file servers, intranets, internal applications) when working remotely. This creates a secure, encrypted tunnel from the employee's device directly into the corporate network.
    • Site-to-Site VPNs: Organizations with multiple physical offices can use VPNs to securely connect their entire office networks together over the public internet, effectively creating a single, unified private network.
  5. Safe Torrenting/P2P File Sharing:

    • While P2P file sharing itself is a legitimate technology, it's often associated with copyright infringement. Using a VPN while torrenting can mask your IP address from peers in the torrent swarm and from your ISP, offering a degree of anonymity. However, it's crucial to respect copyright laws.
  6. Avoiding Price Discrimination:

    • Some online retailers, airlines, and booking websites display different prices for the same product or service based on the user's geographical location (derived from their IP address). A VPN can help you shop around by appearing to be from different locations, potentially finding better deals.

Self-hosting your VPN offers additional advantages:

  • Full Control: You control the server, the logs (or lack thereof), and the security configurations. You are not reliant on a third-party VPN provider's policies or security practices.
  • Trust: You know exactly how your data is being handled because you set up the system. With commercial VPNs, you must trust their no-logs claims and security infrastructure.
  • Cost-Effective (Potentially): If you already have a server (e.g., a VPS for other projects, a Raspberry Pi), the software cost for OpenVPN is zero. You only pay for the server/VPS itself and bandwidth.
  • Learning Experience: Setting up and managing your own VPN server is an excellent way to learn about networking, security, Linux administration, and cryptography.

However, self-hosting also means you are responsible for maintenance, security updates, and troubleshooting.

Introduction to OpenVPN

OpenVPN is a robust and highly flexible open-source VPN software that uses a custom security protocol based on SSL/TLS (Secure Sockets Layer/Transport Layer Security). It is widely regarded as one of the most secure and reliable VPN solutions available.

Key Features and Strengths of OpenVPN:

  1. Open Source and Community-Driven:

    • Being open-source means its source code is publicly available for anyone to inspect, audit, and contribute to. This transparency fosters trust and allows security vulnerabilities to be identified and fixed by a global community of developers and security experts.
    • It has undergone multiple independent security audits, which have helped to harden its codebase.
  2. Cross-Platform Compatibility:

    • OpenVPN clients are available for virtually all major operating systems, including Windows, macOS, Linux, Android, iOS, FreeBSD, Solaris, and more. This makes it easy to connect a wide variety of devices to your OpenVPN server.
  3. Strong Security and Encryption:

    • OpenVPN utilizes the OpenSSL library for encryption, providing access to a wide range of cryptographic ciphers (e.g., AES, Blowfish, Camellia) and hash algorithms (e.g., SHA256, SHA512).
    • It supports Perfect Forward Secrecy (PFS) through Diffie-Hellman key exchange, ensuring that even if a server's private key is compromised in the future, past session keys (and thus past communications) cannot be decrypted.
    • It can be configured to use pre-shared static keys or certificate-based public/private key authentication. Certificate-based authentication is the more common and secure method for most deployments.
  4. High Configurability:

    • OpenVPN offers a vast array of configuration options, allowing administrators to fine-tune its behavior to suit specific security and networking requirements. This includes choices of protocol (UDP or TCP), port numbers, encryption algorithms, authentication methods, routing options, and more.
    • It can traverse NAT (Network Address Translation) and firewalls effectively, making it suitable for various network environments.
  5. Tunneling Options:

    • TUN (Network Tunnel): Operates at OSI Layer 3 (Network Layer). It creates a virtual point-to-point IP link. This is the most common mode for OpenVPN and is generally preferred as it's more efficient for routing IP traffic.
    • TAP (Ethernet Tunnel): Operates at OSI Layer 2 (Data Link Layer). It creates a virtual Ethernet adapter, allowing you to tunnel Ethernet frames. This mode is useful for applications that require Layer 2 connectivity, such as bridging networks, running protocols other than IP, or playing LAN games over the VPN. However, it's generally less efficient and can have higher overhead than TUN.
  6. Protocol Choice (UDP vs. TCP):

    • UDP (User Datagram Protocol): OpenVPN generally performs better over UDP. UDP is a connectionless protocol with lower overhead than TCP. It's more resilient to network latency and packet loss as OpenVPN handles its own reliability mechanisms at the application layer. This is the recommended protocol for most use cases.
    • TCP (Transmission Control Protocol): OpenVPN can also run over TCP. TCP is a connection-oriented protocol that provides guaranteed delivery and error checking. While this sounds beneficial, running a tunnel protocol (OpenVPN) that itself handles reliability over another protocol (TCP) that also handles reliability can lead to performance issues, especially on unstable networks (a phenomenon known as "TCP-over-TCP meltdown"). However, TCP might be necessary to bypass restrictive firewalls that only allow traffic on specific TCP ports (like port 443 for HTTPS).
  7. Scalability:

    • While a single OpenVPN instance can handle a moderate number of concurrent users (depending on server hardware and configuration), it can be scaled to support larger deployments through techniques like load balancing across multiple OpenVPN servers.
  8. Extensibility:

    • OpenVPN supports various scripting hooks (e.g., client-connect, client-disconnect, learn-address) that allow administrators to execute custom scripts when certain events occur. This enables automation of tasks like dynamic firewall rule updates, user-specific routing, or integration with external authentication systems.

Despite its strengths, OpenVPN's configuration can be complex for beginners due to its many options. This guide aims to demystify this complexity. Other modern VPN protocols like WireGuard have emerged, often praised for simplicity and speed, but OpenVPN remains a highly trusted, mature, and feature-rich choice, especially for scenarios requiring its specific capabilities or broad compatibility.

OpenVPN Architecture Overview

Understanding the basic components and communication flow of an OpenVPN setup is crucial for effective configuration and troubleshooting.

Key Components:

  1. OpenVPN Server:

    • This is the central machine that listens for incoming connections from OpenVPN clients.
    • It authenticates clients, assigns them virtual IP addresses from a predefined VPN subnet, and routes their traffic.
    • It holds a server certificate, a server private key, and the Certificate Authority (CA) certificate.
    • It uses a configuration file (typically server.conf) to define its behavior.
  2. OpenVPN Clients:

    • These are the devices (laptops, desktops, smartphones) that initiate connections to the OpenVPN server.
    • Each client needs its own unique client certificate and private key (for certificate-based authentication), the CA certificate, and a client configuration file (typically client.ovpn).
    • The client software uses this information to establish a secure, encrypted tunnel with the server.
  3. Certificate Authority (CA):

    • The CA is responsible for creating and signing digital certificates for both the server and the clients.
    • It acts as a trusted third party. The server trusts certificates signed by this CA, and clients trust the server if its certificate is signed by the same CA.
    • The CA has its own master certificate (ca.crt) and a highly sensitive private key (ca.key). The ca.key should be kept extremely secure, preferably offline or on a dedicated, air-gapped machine.
    • Easy-RSA is a common command-line tool used to manage a simple CA for OpenVPN.
  4. Certificates and Keys:

    • CA Certificate (ca.crt): Public certificate of the Certificate Authority. Distributed to both the server and all clients. Used to verify the authenticity of server and client certificates.
    • Server Certificate (server.crt): Public certificate for the OpenVPN server, signed by the CA.
    • Server Private Key (server.key): Secret key corresponding to the server certificate. Kept securely on the server. Must never be shared.
    • Client Certificate (client_name.crt): Public certificate for an individual client, signed by the CA.
    • Client Private Key (client_name.key): Secret key corresponding to the client certificate. Kept securely on the client's device. Must never be shared.
    • Diffie-Hellman Parameters (dh.pem): Used by the server for key exchange to establish Perfect Forward Secrecy (PFS).
    • TLS Authentication Key (ta.key or tls-crypt.key): An optional pre-shared key used for an additional HMAC signature on SSL/TLS handshake packets, providing an extra layer of security against DoS attacks and unauthorized connection attempts.

Basic Connection Flow (using SSL/TLS with certificates):

  1. Client Initiates Connection: The client, using its configuration file (.ovpn), attempts to connect to the OpenVPN server at the specified IP address and port.
  2. TLS Handshake Begins:
    • The client and server initiate an SSL/TLS handshake.
    • (Optional, if tls-auth or tls-crypt is used): The server first checks for a valid HMAC signature on the initial control packets from the client. If invalid, the packet is dropped early, preventing further processing.
  3. Server Authentication:
    • The server presents its server certificate (server.crt) to the client.
    • The client verifies the server certificate using its copy of the CA certificate (ca.crt). It checks if the certificate is signed by the trusted CA, if it's not expired, and if the hostname matches (if configured).
  4. Client Authentication:
    • The client presents its client certificate (client_name.crt) to the server.
    • The server verifies the client certificate using its copy of the CA certificate (ca.crt). It checks if it's signed by the trusted CA and not expired. It also checks against a Certificate Revocation List (CRL) if configured.
  5. Key Exchange:
    • Client and server perform a Diffie-Hellman key exchange (using dh.pem on the server side) to securely generate symmetric session keys. These session keys are unique for each connection and are used to encrypt the actual VPN data. This process provides Perfect Forward Secrecy (PFS).
  6. Tunnel Establishment:
    • Once authentication and key exchange are successful, the encrypted tunnel is established.
    • The server assigns a virtual IP address to the client from its VPN IP pool.
    • The server may also "push" network configuration to the client, such as routes (e.g., route all traffic through the VPN, or route only specific subnets) and DNS server settings.
  7. Data Transfer:
    • All data transmitted between the client and server is now encrypted using the negotiated session keys and algorithms.
    • When the client sends traffic destined for the internet (or other networks accessible via the VPN), it's sent through the tunnel to the OpenVPN server. The server then decrypts it and forwards it to the final destination, using its own IP address as the source (NAT).
    • Traffic from the internet (or other networks) back to the client is received by the server, encrypted, and sent through the tunnel to the client, which then decrypts it.

Network Interfaces:

  • Physical Interface (e.g., eth0): The server's actual network card connected to the internet or local network.
  • TUN/TAP Interface (e.g., tun0): A virtual network interface created by OpenVPN when it starts. This interface represents the VPN tunnel. Traffic entering this interface from the client side is encrypted and sent out the physical interface. Traffic arriving on the physical interface for the VPN is decrypted and passed to the tun0 interface.

This architecture, while detailed, provides a very secure and flexible foundation for VPN services. Understanding these pieces will make the subsequent configuration steps much clearer.

Workshop Understanding VPN Concepts

This workshop is designed to be a thought exercise and research task to solidify your understanding of the foundational concepts discussed. There are no server commands yet; this is about reinforcing theory.

Objective: To ensure you can articulate the core principles of VPNs, their benefits, and the basic role of OpenVPN components.

Tasks:

  1. Define in Your Own Words (150-200 words each):

    • What is a VPN? Focus on encryption, tunneling, and IP masking.
    • Why would an individual want to use a VPN? List at least three distinct reasons with brief explanations.
    • What makes OpenVPN a popular choice for a self-hosted VPN? Highlight at least three key features.
  2. Component Identification:

    • Imagine you are explaining to a non-technical friend how an OpenVPN connection is established. Describe the role of the following in simple terms:
      • Certificate Authority (CA)
      • Server Certificate
      • Client Certificate
      • VPN Server
      • VPN Client
  3. Scenario Analysis: Consider the following scenarios. For each, explain whether a VPN would be beneficial and why:

    • Scenario A: Alice is at a coffee shop using their public Wi-Fi to check her bank balance and pay bills online.
    • Scenario B: Bob lives in Country X where a popular international news website is blocked by the government. He wants to read articles on this site.
    • Scenario C: Carol works for a company and needs to access confidential project files stored on the company's internal server while she is traveling.
    • Scenario D: David is at home using his private, password-protected Wi-Fi network to stream movies from a popular subscription service.
  4. TUN vs. TAP Research:

    • Briefly research the difference between TUN and TAP virtual devices used by OpenVPN.
    • In what specific (even if niche) situation might you choose TAP over TUN?
    • Why is TUN generally recommended for most OpenVPN use cases?

Deliverables:

  • A written document (e.g., a text file or a Word document) containing your answers to the tasks above.

Guidance for Success:

  • Refer back to the explanations provided in the "Introduction to VPNs and OpenVPN" section.
  • Use external resources (reputable websites, academic articles) to supplement your understanding if needed, but ensure your answers are in your own words.
  • Focus on clarity and conciseness in your explanations.
  • For the scenario analysis, think about the core benefits of a VPN (security, privacy, censorship circumvention, remote access) and how they apply.

Self-Reflection Questions (After Completing the Workshop):

  • Do I feel confident explaining what a VPN does to someone unfamiliar with the concept?
  • Can I distinguish between the roles of different certificates in an OpenVPN setup?
  • Do I understand the primary motivations for using a VPN in different contexts?

This foundational knowledge is key. As we move into practical setup, these concepts will be applied directly.

Basic OpenVPN Setup

This section will guide you through the essential steps to get a functional OpenVPN server up and running. We will focus on a common and secure setup using certificate-based authentication on a Linux server.

1. Prerequisites and Server Selection

Before diving into the installation of OpenVPN, it's crucial to prepare your server environment. This involves choosing an appropriate server, setting up the operating system, and performing initial security hardening.

Choosing a Server (VPS, Raspberry Pi, Old PC)

The choice of hardware or virtual machine for your OpenVPN server depends on your budget, technical comfort, expected load (number of concurrent users, bandwidth requirements), and desired level of control.

  1. Virtual Private Server (VPS):

    • Description: A VPS is a virtual machine sold as a service by an internet hosting provider. You get dedicated resources (CPU, RAM, storage, IP address) on a shared physical server.
    • Pros:
      • Reliability & Uptime: Hosted in data centers with redundant power and network connectivity.
      • Scalability: Easy to upgrade resources (CPU, RAM, bandwidth) as your needs grow.
      • Dedicated IP Address: Essential for a VPN server accessible from the internet.
      • Good Network Performance: Data centers usually have high-speed internet connections.
      • Geographic Choice: You can often choose a VPS in a specific country, which can be useful for bypassing geo-restrictions.
    • Cons:
      • Recurring Cost: Monthly or annual fees.
      • Less Control over Hardware: You don't own the physical hardware.
    • Recommendations:
      • Look for providers offering KVM virtualization (more isolation than OpenVZ).
      • Start with a low-spec VPS (e.g., 1 CPU core, 512MB-1GB RAM, 10-20GB SSD storage) for a personal VPN. OpenVPN itself is not very resource-intensive for a few users.
      • Popular providers: DigitalOcean, Linode, Vultr, Hetzner, OVH.
    • Use Case: Ideal for users who want a reliable, internet-accessible VPN server without managing physical hardware, or for those needing an IP in a different geographic location.
  2. Raspberry Pi (or similar Single-Board Computer - SBC):

    • Description: A small, low-cost computer. Newer models (Raspberry Pi 3B+, 4, 5) are capable enough to run an OpenVPN server for personal or small family use.
    • Pros:
      • Low Cost: One-time hardware purchase.
      • Low Power Consumption: Can run 24/7 without significantly impacting electricity bills.
      • Full Control over Hardware: You own the device.
      • Excellent Learning Platform: Great for understanding system setup from scratch.
    • Cons:
      • Limited Resources: CPU and RAM are modest, which can be a bottleneck for many concurrent users or very high-speed connections. Encryption is CPU-intensive.
      • Home Network Challenges:
        • Dynamic IP: Most residential internet connections have dynamic IP addresses. You'll need a Dynamic DNS (DDNS) service to maintain a consistent hostname for your VPN server.
        • Port Forwarding: You'll need to configure port forwarding on your home router to allow incoming OpenVPN connections to reach the Raspberry Pi.
        • Upload Speed: Residential internet often has limited upload speed, which will be the maximum speed for your VPN clients when they are away from home.
      • SD Card Reliability: SD cards can be prone to corruption over time with many read/write cycles. Consider using a high-quality SD card or booting from an external SSD/USB drive if possible.
    • Recommendations:
      • Raspberry Pi 4 or 5 with at least 2GB RAM is recommended for better performance.
      • Use a reliable power supply.
      • Consider a case with cooling (heatsink or fan) if running CPU-intensive tasks for long periods.
    • Use Case: Perfect for hobbyists, home users who want to secure their traffic on public Wi-Fi, or access their home network remotely. Not ideal if you need very high throughput or many users.
  3. Old PC or Dedicated Physical Server:

    • Description: Repurposing an old desktop, laptop, or a dedicated server machine.
    • Pros:
      • Potentially Powerful: Even an older PC can have more CPU power and RAM than a Raspberry Pi or a low-end VPS.
      • Full Control: You own and manage the hardware and software.
      • No Recurring Server Cost (if you own the hardware): Only electricity and internet costs.
    • Cons:
      • Power Consumption: Can be significantly higher than a Raspberry Pi or VPS.
      • Noise and Heat: Depending on the machine.
      • Physical Space: Requires space.
      • Home Network Challenges (same as Raspberry Pi): Dynamic IP, port forwarding, upload speed limitations unless you have a business internet connection with a static IP.
      • Maintenance: You are responsible for hardware maintenance and replacement.
    • Recommendations:
      • Ensure the hardware is reliable.
      • Install a server-focused Linux distribution.
    • Use Case: Suitable if you have spare hardware, need more processing power than an SBC, and are comfortable managing a physical server and your home network configuration.

Resource Considerations for OpenVPN:

  • CPU: Encryption/decryption is CPU-intensive. A faster CPU (especially one with AES-NI hardware acceleration support) will yield better VPN throughput. For a few clients with moderate usage, most modern CPUs will suffice.
  • RAM: OpenVPN itself doesn't use a lot of RAM per connection. 512MB is often enough for the OpenVPN process itself on a dedicated server, but the OS and other services will also require RAM. 1GB or more is a comfortable starting point for a dedicated Linux server.
  • Network Bandwidth: The server's internet connection (especially upload speed for a self-hosted server at home, or total bandwidth for a VPS) will be a major limiting factor for VPN performance.
  • Storage: A minimal Linux server install with OpenVPN doesn't require much disk space (a few GBs). 10-20GB SSD is plenty for the OS and OpenVPN. Logs can grow over time, so monitor disk usage.

For this guide's workshops, we will assume you are working with a Linux server, which could be a VPS or a local machine/VM running Linux.

Operating System Considerations (Linux Focus)

While OpenVPN can run on various operating systems, Linux is a popular choice for servers due to its stability, security, performance, and open-source nature.

Recommended Linux Distributions for an OpenVPN Server:

  1. Debian:

    • Pros: Extremely stable, well-tested, large community, strong security focus, long release cycles. Excellent for servers where stability is paramount. OpenVPN is available in its repositories.
    • Cons: Software packages can sometimes be older than in other distributions due to the focus on stability. However, for OpenVPN, this is usually not an issue as the core protocol is mature.
    • Best for: Users who prioritize stability and long-term support.
  2. Ubuntu Server:

    • Pros: Based on Debian, user-friendly, very large community, extensive documentation, frequent releases with newer software packages. OpenVPN is readily available. LTS (Long Term Support) versions offer 5 years of support.
    • Cons: Non-LTS releases have shorter support cycles. Some users prefer Debian's "purer" approach without Canonical's additions.
    • Best for: Beginners to Linux, users who want newer software versions while still having LTS options, wide hardware compatibility.
  3. CentOS Stream / AlmaLinux / Rocky Linux:

    • Pros: Derived from Red Hat Enterprise Linux (RHEL) sources, known for stability and security in enterprise environments. Long support cycles. OpenVPN is available via EPEL (Extra Packages for Enterprise Linux) repository.
    • Cons: Package management (YUM/DNF) and some configurations differ from Debian/Ubuntu (APT). May have a slightly steeper learning curve for those accustomed to Debian-based systems.
    • Best for: Users familiar with the RHEL ecosystem or those requiring RHEL compatibility.

Key Considerations When Choosing/Setting up the OS:

  • Minimal Installation: When installing the OS, choose a minimal or server installation. Avoid installing a GUI (Graphical User Interface) and unnecessary software, as this reduces the attack surface and saves system resources.
  • 64-bit vs. 32-bit: Always opt for a 64-bit OS if your hardware supports it (most modern hardware does). 64-bit systems can address more memory and often offer better performance for cryptographic operations.
  • Updates: Ensure you have a plan to keep the OS and all installed packages regularly updated to patch security vulnerabilities.

For the workshops in this guide, commands will primarily be shown for Debian/Ubuntu-based systems (using apt package manager). Equivalent commands for RHEL-based systems (using yum or dnf) will be mentioned where appropriate if they differ significantly.

Initial Server Setup and Security Hardening

Once you have chosen your server and installed a minimal Linux distribution, it's critical to perform some initial setup and security hardening steps before installing OpenVPN or any other services.

These steps are crucial for any internet-facing server:

  1. Update Your System:

    • Immediately after the first boot, update all installed packages to their latest versions.
    • Debian/Ubuntu:
      sudo apt update
      sudo apt upgrade -y
      sudo apt dist-upgrade -y # For major version upgrades within a release
      sudo apt autoremove -y   # Remove unused packages
      sudo apt autoclean -y    # Clear downloaded package files
      
    • CentOS/RHEL-based:
      sudo dnf update -y  # Or 'sudo yum update -y' for older CentOS/RHEL
      
    • Consider rebooting if kernel updates were installed: sudo reboot
  2. Create a Non-Root User with Sudo Privileges:

    • Logging in and operating directly as root is risky. A typo can cause serious damage. Create a regular user account and grant it sudo (superuser do) privileges to execute commands as root when needed.
    • Create user (e.g., myadmin):
      sudo adduser myadmin
      
      Follow the prompts to set a strong password and user information.
    • Grant sudo privileges:
      • Debian/Ubuntu:
        sudo usermod -aG sudo myadmin
        
      • CentOS/RHEL-based (add to wheel group):
        sudo usermod -aG wheel myadmin
        
        (On some RHEL systems, you might need to ensure the wheel group has sudo access uncommented in /etc/sudoers).
    • Test: Log out from root and log back in as your new user. Try running a command with sudo, e.g., sudo apt update. You'll be prompted for your user's password, not the root password.
  3. Secure SSH Access:

    • SSH (Secure Shell) is how you'll remotely manage your server.
    • Change Default SSH Port (Optional, Security through Obscurity):
      • Bots frequently scan for SSH on the default port 22. Changing it can reduce log noise and automated attacks. Choose an unassigned port (e.g., between 1024 and 65535, like 2222 or 49188).
      • Edit /etc/ssh/sshd_config:
        sudo nano /etc/ssh/sshd_config
        
        Find #Port 22 and change it to Port YOUR_NEW_PORT_NUMBER (uncomment it).
      • Important: Before restarting SSH, ensure your firewall will allow the new port (see next step).
    • Disable Root Login via SSH:
      • In /etc/ssh/sshd_config, find PermitRootLogin and set it to:
        PermitRootLogin no
        
    • Disable Password Authentication (Use SSH Keys - Highly Recommended):
      • SSH keys are much more secure than passwords.
      • On your local machine (not the server): Generate an SSH key pair if you don't have one:
        ssh-keygen -t rsa -b 4096 -C "your_email@example.com"
        
        (Follow prompts; usually okay to accept defaults. Add a strong passphrase for the key).
      • Copy the public key to your server:
        ssh-copy-id myadmin@YOUR_SERVER_IP_OR_HOSTNAME
        
        (If you changed the SSH port, use: ssh-copy-id -p YOUR_NEW_PORT_NUMBER myadmin@YOUR_SERVER_IP_OR_HOSTNAME) You'll be prompted for myadmin's password one last time.
      • On the server, disable password authentication: In /etc/ssh/sshd_config, find PasswordAuthentication and set it to:
        PasswordAuthentication no
        
        Also, ensure PubkeyAuthentication yes is set (it usually is by default).
    • Restart SSH Service:
      • Debian/Ubuntu:
        sudo systemctl restart ssh
        
      • CentOS/RHEL-based:
        sudo systemctl restart sshd
        
      • CRITICAL: Before logging out, open a new terminal window and try to log in using your new user and SSH key (and new port if changed):
        ssh -p YOUR_NEW_PORT_NUMBER myadmin@YOUR_SERVER_IP_OR_HOSTNAME
        
        If it works, you can safely close your old session. If not, revert changes in /etc/ssh/sshd_config and try again. Do not lock yourself out!
  4. Configure a Basic Firewall (UFW or firewalld):

    • A firewall controls incoming and outgoing network traffic. Only allow necessary services.
    • UFW (Uncomplicated Firewall - common on Debian/Ubuntu):
      • Install (if not already):
        sudo apt install ufw
        
      • Set default policies:
        sudo ufw default deny incoming
        sudo ufw default allow outgoing
        
      • Allow SSH (use your new port if you changed it, otherwise 22):
        sudo ufw allow YOUR_NEW_SSH_PORT_NUMBER/tcp  # e.g., sudo ufw allow 2222/tcp
        # Or if using default port: sudo ufw allow ssh
        
      • Allow OpenVPN port (we'll use UDP port 1194 by default later):
        sudo ufw allow 1194/udp
        
      • Enable UFW:
        sudo ufw enable
        
        (Confirm 'y'. Your current SSH session should remain active).
      • Check status:
        sudo ufw status verbose
        
    • firewalld (common on CentOS/RHEL-based):
      • Usually installed and enabled by default. Check status:
        sudo systemctl status firewalld
        
      • Allow SSH (use your new port if you changed it):
        sudo firewall-cmd --permanent --add-port=YOUR_NEW_SSH_PORT_NUMBER/tcp
        # Or: sudo firewall-cmd --permanent --add-service=ssh (if using default port and service definition exists)
        
      • Allow OpenVPN port (UDP 1194):
        sudo firewall-cmd --permanent --add-port=1194/udp
        # Or create a service definition for OpenVPN for cleaner management later
        
      • Reload firewall to apply changes:
        sudo firewall-cmd --reload
        
      • List active rules:
        sudo firewall-cmd --list-all
        
  5. Install Fail2Ban (Optional but Recommended):

    • Fail2Ban scans log files (e.g., SSH logs) for malicious patterns like repeated failed login attempts and temporarily bans the offending IP addresses by updating firewall rules.
    • Install:
      • Debian/Ubuntu:
        sudo apt install fail2ban
        
      • CentOS/RHEL-based (needs EPEL repository):
        sudo dnf install epel-release  # Or sudo yum install epel-release
        sudo dnf install fail2ban      # Or sudo yum install fail2ban
        
    • Configure for SSH:
      • Copy the default jail configuration to a local configuration file (so updates don't overwrite your changes):
        sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local
        
      • Edit /etc/fail2ban/jail.local with sudo nano /etc/fail2ban/jail.local.
      • Find the [sshd] section. Ensure it's enabled (enabled = true).
      • If you changed your SSH port, update the port line in the [sshd] section:
        [sshd]
        enabled = true
        port    = YOUR_NEW_SSH_PORT_NUMBER
        # other settings...
        
    • Start and enable Fail2Ban:
      sudo systemctl enable fail2ban
      sudo systemctl start fail2ban
      
    • Check status (e.g., for SSH jail):
      sudo fail2ban-client status sshd
      
  6. Set Timezone and Enable NTP:

    • Correct time is important for logs and certificate validity.
    • Set timezone (interactive):
      sudo dpkg-reconfigure tzdata  # Debian/Ubuntu
      sudo timedatectl set-timezone Your/Timezone # e.g., America/New_York (use 'timedatectl list-timezones' to find yours)
      
    • Ensure NTP (Network Time Protocol) client is active for time synchronization:
      • Most modern systems use systemd-timesyncd. Check its status:
        timedatectl status
        
        Look for NTP service: active or System clock synchronized: yes.
      • If not active, you might need to install and enable it or chrony/ntpdate.
        sudo timedatectl set-ntp true # Tries to enable systemd-timesyncd
        

These initial hardening steps significantly improve your server's security posture before you even install OpenVPN.

Workshop Server Preparation

Objective: To set up a secure base Linux server environment ready for OpenVPN installation.

Prerequisites:

  • Access to a newly provisioned VPS, a Raspberry Pi with a fresh OS image, or a virtual machine with a minimal Linux distribution (Debian or Ubuntu recommended for easiest follow-along, but CentOS/AlmaLinux/Rocky is also fine if you adapt package manager commands).
  • Internet connectivity for the server.
  • An SSH client on your local machine (e.g., Terminal on macOS/Linux, PuTTY or Windows Terminal with SSH on Windows).

Instructions:

Perform these steps on your chosen server.

  1. Initial Login:

    • Log in to your server. If it's a VPS, you'll typically log in as root initially using the password provided by your hosting company, or via an SSH key if pre-configured. For a Raspberry Pi, the default user might be pi.
    • Example (VPS as root): ssh root@YOUR_SERVER_IP
  2. System Update:

    • Update all system packages.
      • Debian/Ubuntu:
        apt update
        apt upgrade -y
        # Consider apt dist-upgrade -y and autoremove/autoclean as well
        
      • CentOS/RHEL (as root or with sudo if already configured):
        dnf update -y # or yum update -y
        
    • If a kernel update occurred, it's good practice to reboot: reboot and then log back in.
  3. Create a Non-Root Sudo User:

    • Create a new user (e.g., vpnadmin).
      adduser vpnadmin # If root, or sudo adduser vpnadmin if sudo is already available for current user
      
      Set a strong password.
    • Add this user to the sudo (Debian/Ubuntu) or wheel (CentOS/RHEL) group.
      • Debian/Ubuntu: usermod -aG sudo vpnadmin
      • CentOS/RHEL: usermod -aG wheel vpnadmin
    • Verification: Log out of your current session (exit). Log back in as the new user: ssh vpnadmin@YOUR_SERVER_IP. Try running a privileged command: sudo ls /root. You should be prompted for vpnadmin's password.
  4. Set up SSH Key-Based Authentication (from your local machine):

    • On your local computer:
      • If you don't have an SSH key pair (~/.ssh/id_rsa and ~/.ssh/id_rsa.pub), generate one:
        ssh-keygen -t rsa -b 4096
        
        Accept defaults and set a strong passphrase for your private key.
    • Copy your public key to the server for the vpnadmin user:
      ssh-copy-id vpnadmin@YOUR_SERVER_IP
      
      Enter vpnadmin's password when prompted.
    • Verification: Try logging into your server as vpnadmin without a password (you might be prompted for your SSH key passphrase if you set one):
      ssh vpnadmin@YOUR_SERVER_IP
      
      If successful, key-based authentication is working.
  5. Harden SSH Configuration (on the server, as vpnadmin using sudo):

    • Edit the SSH daemon configuration file:
      sudo nano /etc/ssh/sshd_config
      
    • Make the following changes:
      • PermitRootLogin no
      • PasswordAuthentication no
      • (Optional, but recommended for less log spam) Port 2222 (or another high port number of your choice). Remember this port!
    • Save the file (Ctrl+O, Enter in nano) and exit (Ctrl+X).
    • Crucial: Before restarting SSH, ensure your firewall (next step) will allow the new port if you changed it.
  6. Configure Firewall (UFW for Debian/Ubuntu example):

    • Install UFW if not present: sudo apt install ufw
    • Set default policies:
      sudo ufw default deny incoming
      sudo ufw default allow outgoing
      
    • Allow your chosen SSH port (e.g., 2222, or 22 if you didn't change it):
      sudo ufw allow 2222/tcp  # Replace 2222 with your actual SSH port
      
    • Allow the default OpenVPN port (we'll use this later):
      sudo ufw allow 1194/udp
      
    • Enable UFW:
      sudo ufw enable
      
      Type 'y' and press Enter.
    • Restart SSH daemon (use correct service name for your OS):
      sudo systemctl restart ssh  # or sshd for CentOS/RHEL
      
    • CRITICAL TEST: Open a new terminal window on your local machine. Try to SSH into your server using the new user, new port (if changed), and SSH key:
      ssh -p 2222 vpnadmin@YOUR_SERVER_IP # Replace 2222 if you used a different port
      
      If you cannot connect, DO NOT CLOSE YOUR ORIGINAL SSH SESSION. Revert the SSH port change in /etc/ssh/sshd_config (or firewall rule) in the original session and try again. Only proceed if the new connection is successful.
  7. Install and Configure Fail2Ban (Optional):

    • Install Fail2Ban:
      • Debian/Ubuntu: sudo apt install fail2ban
      • CentOS/RHEL (with EPEL): sudo dnf install epel-release && sudo dnf install fail2ban
    • Copy default config: sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local
    • Edit jail.local: sudo nano /etc/fail2ban/jail.local
    • In the [sshd] section, ensure enabled = true. If you changed your SSH port, update port = YOUR_SSH_PORT.
    • Enable and start Fail2Ban:
      sudo systemctl enable fail2ban
      sudo systemctl start fail2ban
      
  8. Set Timezone:

    • List timezones: timedatectl list-timezones
    • Set your timezone: sudo timedatectl set-timezone Your/Timezone
    • Enable NTP: sudo timedatectl set-ntp true
    • Verify: timedatectl status

Expected Outcome:

  • You have a Linux server updated and secured with a non-root sudo user.
  • SSH access is restricted to key-based authentication, (optionally) on a non-standard port, and root login is disabled.
  • A basic firewall is active, allowing only SSH and the future OpenVPN port.
  • (Optional) Fail2Ban is running to protect SSH from brute-force attacks.
  • The system time is correctly set and synchronized.

Troubleshooting:

  • Locked out of SSH: If you changed the SSH port and restarted SSH before allowing the new port in the firewall, you'll be locked out. You might need to access the server via a console (if VPS) or directly (if physical/VM) to fix the firewall or SSH config. This is why testing in a new terminal is crucial.
  • ssh-copy-id fails: Ensure the server's SSH daemon allows password authentication temporarily for the copy, or that your user vpnadmin has a password set. You can disable password auth after the key is copied.
  • Commands not found: Ensure you typed them correctly. For dnf/yum on Debian/Ubuntu or apt on CentOS/RHEL, use the correct package manager for your distribution.

You now have a solid foundation for installing OpenVPN.

2. Installing OpenVPN

With the server prepared, the next step is to install the OpenVPN software package and Easy-RSA, a utility for managing Public Key Infrastructure (PKI) certificates.

Using Package Managers

Most Linux distributions provide OpenVPN in their standard repositories, making installation straightforward using the system's package manager. Easy-RSA, which we'll use to generate certificates and keys, is often packaged separately or downloaded directly.

For Debian/Ubuntu-based systems (using apt):

OpenVPN is available directly. Easy-RSA is also typically available as a package.

  1. Update Package List: Ensure your package list is up-to-date:

    sudo apt update
    

  2. Install OpenVPN and Easy-RSA:

    sudo apt install openvpn easy-rsa
    
    This command will download and install OpenVPN, Easy-RSA, and any necessary dependencies.

    • openvpn: The core OpenVPN server and client software.
    • easy-rsa: A set of scripts to help manage a CA and generate certificates and keys.

    During the installation, you might be asked to confirm. Press Y and Enter.

For RHEL-based systems (CentOS Stream, AlmaLinux, Rocky Linux, using dnf or yum):

OpenVPN is typically available in the EPEL (Extra Packages for Enterprise Linux) repository. Easy-RSA might also be in EPEL or need to be fetched manually.

  1. Ensure EPEL Repository is Enabled: If you haven't enabled EPEL during server setup (e.g., for Fail2Ban), do so now:

    sudo dnf install epel-release
    # or for older systems: sudo yum install epel-release
    
    Refresh package lists after adding a new repository (dnf does this automatically, yum might need sudo yum clean all && sudo yum makecache).

  2. Install OpenVPN and Easy-RSA:

    sudo dnf install openvpn easy-rsa
    # or for older systems: sudo yum install openvpn easy-rsa
    
    If easy-rsa is not found as a package, we'll cover manual download and setup in the "Generating Certificates and Keys" section. However, it's commonly available.

Alternative Easy-RSA Installation (if not in package manager or you want latest):

If easy-rsa isn't available through your package manager or you prefer the latest version, you can download it directly from GitHub.

  1. Install wget or curl and tar if not present:
    sudo apt install wget tar # Debian/Ubuntu
    sudo dnf install wget tar # RHEL-based
    
  2. Download the latest Easy-RSA release: Go to the Easy-RSA releases page on GitHub (https://github.com/OpenVPN/easy-rsa/releases) and find the latest EasyRSA-*.tgz file. Copy its link.
    # Example for version 3.1.7 (replace with the actual latest version link)
    wget https://github.com/OpenVPN/easy-rsa/releases/download/v3.1.7/EasyRSA-3.1.7.tgz
    
  3. Extract the archive:
    tar -xzf EasyRSA-3.1.7.tgz
    
    This will create a directory like EasyRSA-3.1.7. You can then move this directory to a standard location, for example, /etc/openvpn/easy-rsa.
    sudo mv EasyRSA-3.1.7 /etc/openvpn/easy-rsa
    
    The scripts inside (like easyrsa) would then be run from /etc/openvpn/easy-rsa/easyrsa. This manual method gives you more control over the version but requires manual updates. For simplicity, using the packaged version is recommended if available and reasonably up-to-date.

Verifying Installation

After the installation commands complete without error, you can verify that OpenVPN is installed.

  1. Check OpenVPN version:

    openvpn --version
    
    This should output information about the installed OpenVPN version, including library versions (like OpenSSL, LZO). Example output:
    OpenVPN 2.5.5 x86_64-pc-linux-gnu [SSL (OpenSSL)] [LZO] [LZ4] [EPOLL] [PKCS11] [MH/PKTINFO] [AEAD] built on Mar 22 2022
    library versions: OpenSSL 1.1.1n  15 Mar 2022, LZO 2.10
    ...
    
    The exact version numbers will vary depending on your distribution and when you install it.

  2. Check for Easy-RSA: If installed via package manager, the easyrsa command should be available in your PATH.

    easyrsa
    
    This should display help text or usage information for the easyrsa command. If you installed it manually, you'd navigate to the directory where you extracted it (e.g., /etc/openvpn/easy-rsa) and run ./easyrsa.

    The location of Easy-RSA files when installed from package managers can vary:

    • Debian/Ubuntu: Typically, scripts are in /usr/share/easy-rsa/, and you'd copy them to a working directory like /etc/openvpn/easy-rsa/.
    • RHEL-based: Might also be in /usr/share/easy-rsa/ or /etc/pki/easy-rsa/.

    We will handle the specific setup of the Easy-RSA working directory in the next sub-section.

  3. Check OpenVPN Service Status (Optional at this stage): OpenVPN typically runs as a systemd service. At this point, the service likely won't be active because it requires a configuration file. However, you can check if the service unit file exists.

    sudo systemctl status openvpn@server
    
    You'll likely see it as inactive (dead) or failed because no server.conf is specified or valid yet. This is normal. The openvpn@.service unit is a template that allows running multiple OpenVPN instances, each with its own configuration file (e.g., openvpn@myconfig would look for /etc/openvpn/myconfig.conf).

The successful execution of these commands and checks confirms that OpenVPN and the necessary tools are installed on your system, ready for configuration.

Workshop Installing OpenVPN

Objective: To install OpenVPN and Easy-RSA on your prepared Linux server and verify the installation.

Prerequisites:

  • A Linux server with initial setup and security hardening completed as per the "Workshop Server Preparation."
  • Sudo access for your user (e.g., vpnadmin).
  • Internet connectivity on the server to download packages.

Instructions:

Perform these steps on your server, logged in as your non-root sudo user.

  1. Update Package Information: It's always a good practice to update your package list before installing new software.

    • Debian/Ubuntu:
      sudo apt update
      
    • CentOS/RHEL:
      sudo dnf check-update # DNF does this more automatically, but good to check
      
  2. Install OpenVPN and Easy-RSA:

    • Debian/Ubuntu:
      sudo apt install openvpn easy-rsa -y
      
    • CentOS/RHEL (ensure EPEL is enabled, from previous workshop or check now): If EPEL is not yet installed:
      sudo dnf install epel-release -y
      
      Then install OpenVPN and Easy-RSA:
      sudo dnf install openvpn easy-rsa -y
      
    • Observe the output. The package manager will resolve dependencies and install the software. There should be no errors.
  3. Verify OpenVPN Installation: Check the installed version of OpenVPN:

    openvpn --version
    

    • Record the output. Note the OpenVPN version and the OpenSSL library version. This information can be useful for troubleshooting or looking up specific features/bugs later.
    • Example Output:
      OpenVPN 2.5.1 x86_64-pc-linux-gnu [SSL (OpenSSL)] [LZO] [LZ4] [EPOLL] [PKCS11] [MH/PKTINFO] [AEAD] built on Jul 14 2021
      library versions: OpenSSL 1.1.1k  25 Mar 2021, LZO 2.10
      
  4. Verify Easy-RSA Installation: Check if the easyrsa command is accessible:

    easyrsa
    

    • This should output a list of available easyrsa commands or a help message.
    • If the command is not found, Easy-RSA might not have installed correctly, or its location is not in your system's PATH (less common for package installations).
    • Note the location of Easy-RSA scripts if indicated. On Debian/Ubuntu, they are often in /usr/share/easy-rsa/. We will copy these to a working PKI directory in the next section.
  5. Locate Easy-RSA Directory (Informational): If installed from package manager, Easy-RSA files are usually placed in a shared directory. Let's find it:

    • Debian/Ubuntu:
      ls -ld /usr/share/easy-rsa
      
      You should see the directory listing.
    • CentOS/RHEL: It might be /usr/share/easy-rsa/ or sometimes under /etc/pki/. A common way to find files from a package:
      rpm -ql easy-rsa | grep easyrsa$
      
      This command lists all files installed by the easy-rsa package and filters for the main easyrsa script. Note its path.

Expected Outcome:

  • OpenVPN and Easy-RSA packages are successfully installed on your server.
  • You can successfully execute openvpn --version and easyrsa and see their respective outputs.
  • You have an idea of where the system-wide Easy-RSA scripts are located (e.g., /usr/share/easy-rsa).

Troubleshooting:

  • "Package not found" errors:
    • Ensure your package list is updated (sudo apt update or sudo dnf check-update).
    • For CentOS/RHEL, double-check that the EPEL repository is enabled and accessible.
    • Verify you spelled the package names correctly (openvpn, easy-rsa).
  • easyrsa: command not found:
    • If easy-rsa was reported as installed by the package manager but the command isn't found, it might be installed in a location not in the default PATH for your user. This is rare for standard package installations.
    • You can try sudo find / -name easyrsa to locate the script, but it should typically be in /usr/bin/easyrsa or /usr/sbin/easyrsa (which are in PATH).
    • The main scripts we'll interact with are often in /usr/share/easy-rsa/ (Debian/Ubuntu) or a similar location, which we will copy to a working directory.

With the software installed, we are now ready to create our Public Key Infrastructure (PKI) for secure authentication.

3. Generating Certificates and Keys (Easy-RSA)

A Public Key Infrastructure (PKI) is essential for OpenVPN's certificate-based authentication. It involves a Certificate Authority (CA) that issues and signs digital certificates for the server and each client. Easy-RSA is a command-line tool that simplifies the process of creating and managing this PKI.

Understanding PKI (Public Key Infrastructure)

Before we start generating keys, let's briefly revisit what PKI entails in the context of OpenVPN:

  1. Certificate Authority (CA):

    • The root of trust in your PKI.
    • It has a master key pair: a CA private key (e.g., ca.key) and a CA public certificate (e.g., ca.crt).
    • The CA private key is extremely sensitive. If compromised, your entire VPN's security is compromised, as an attacker could sign their own malicious certificates. It should be kept highly secure, ideally offline or on an air-gapped machine for production environments. For a personal VPN, keeping it on the OpenVPN server with strict permissions is a common compromise, but be aware of the risk.
    • The CA public certificate (ca.crt) is distributed to the OpenVPN server and all clients. It's used to verify that other certificates (server or client) were indeed issued by this trusted CA.
  2. Server Certificate and Key:

    • The OpenVPN server will have its own certificate (e.g., server.crt) and a corresponding private key (e.g., server.key).
    • The server certificate is signed by the CA.
    • When a client connects, the server presents its certificate. The client uses its copy of ca.crt to verify the server's identity.
    • The server's private key (server.key) must be kept secret on the server.
  3. Client Certificates and Keys:

    • Each client that needs to connect to the VPN will have its own unique certificate (e.g., client1.crt, laptop_alice.crt) and a corresponding private key (e.g., client1.key, laptop_alice.key).
    • Client certificates are also signed by the CA.
    • When a client connects, it presents its certificate to the server. The server uses its copy of ca.crt to verify the client's identity.
    • The client's private key must be kept secret on the client's device.
  4. Certificate Revocation List (CRL):

    • A list maintained by the CA that identifies certificates that are no longer valid (e.g., if a client's key is compromised or an employee leaves).
    • The OpenVPN server can be configured to check this CRL to deny access to clients whose certificates have been revoked.

Why PKI?

PKI provides strong authentication.

  • The server knows it's talking to a legitimate client because the client has a certificate signed by the CA the server trusts.
  • The client knows it's talking to the legitimate server because the server has a certificate signed by the CA the client trusts. This mutual authentication is much more secure than just passwords.

Setting up Easy-RSA

Easy-RSA scripts, typically installed from your package manager, provide a convenient way to perform CA operations. The general workflow is to create a dedicated directory for your PKI, copy the Easy-RSA scripts into it (or use them from their system path), initialize the PKI, and then build the CA, server, and client credentials.

Steps:

  1. Create a PKI Directory: It's best practice to manage your PKI in a directory separate from the main OpenVPN configuration, often within /etc/openvpn/.

    sudo mkdir /etc/openvpn/easy-rsa
    sudo chown $USER:$USER /etc/openvpn/easy-rsa # Temporarily own it for easier operations
    cd /etc/openvpn/easy-rsa
    
    We change ownership temporarily so we don't have to type sudo for every easyrsa command. We'll fix permissions later. Security Note: For a highly secure CA, this directory (especially pki/private/ca.key) should ideally be on an offline machine, and only the necessary public certificates and CRL copied to the OpenVPN server. For a personal VPN, managing it on the server itself is common, but ensure directory permissions are strict.

  2. Copy Easy-RSA Scripts (if needed): If your easyrsa command is globally available (check by typing easyrsa), you might not need to copy scripts. However, many guides recommend creating a clean working environment. The location of stock Easy-RSA scripts varies:

    • Debian/Ubuntu: Often in /usr/share/easy-rsa/.
    • RHEL/CentOS: Could be /usr/share/easy-rsa/ or similar.

    If you need to copy them (common practice):

    # Ensure you are in /etc/openvpn/easy-rsa
    cp -R /usr/share/easy-rsa/* .
    
    This copies all files and directories from the system's Easy-RSA share into your current working directory (/etc/openvpn/easy-rsa). If easyrsa is a direct command, this step might be simplified or skipped, and you'd just run easyrsa init-pki directly. This guide will assume you are running easyrsa from within the /etc/openvpn/easy-rsa directory structure. Make the main easyrsa script executable if needed:
    chmod +x easyrsa
    
    You would then run commands like ./easyrsa <command>. If easyrsa is in your PATH from the package install, you can just type easyrsa <command>. We'll use ./easyrsa to be explicit assuming we copied scripts.

  3. Initialize the PKI: This command creates the basic directory structure for your PKI (like pki/, pki/private/, pki/issued/, etc.) within your Easy-RSA working directory.

    # Ensure you are in /etc/openvpn/easy-rsa
    ./easyrsa init-pki
    
    This creates a pki subdirectory. All your keys and certificates will be stored here.

  4. Configure CA Variables (Optional but Recommended): Easy-RSA uses a configuration file named vars (or vars.example which you copy to vars) to set default values for certificate fields like country, organization, email, and key expiry. This saves you from typing them repeatedly.

    • If there's a vars.example file, copy it to vars:
      cp vars.example vars
      
      If no vars.example, you can create vars from scratch or proceed without it (Easy-RSA will prompt for values or use defaults).
    • Edit the vars file:
      nano vars
      
    • Look for and modify lines like these (uncomment them by removing the # if present):
      #set_var EASYRSA_REQ_COUNTRY    "US"
      #set_var EASYRSA_REQ_PROVINCE   "California"
      #set_var EASYRSA_REQ_CITY       "San Francisco"
      #set_var EASYRSA_REQ_ORG        "Copyleft Certificate Co"
      #set_var EASYRSA_REQ_EMAIL      "me@example.net"
      #set_var EASYRSA_REQ_OU         "My Organizational Unit"
      #set_var EASYRSA_KEY_SIZE       2048  # Consider 4096 for CA and server keys for higher security
      #set_var EASYRSA_ALGO           rsa
      #set_var EASYRSA_CA_EXPIRE      3650  # Days (10 years for CA)
      #set_var EASYRSA_CERT_EXPIRE    1080  # Days (approx 3 years for server/client certs)
      #set_var EASYRSA_CRL_DAYS       180   # Days for CRL validity
      
    • Important settings:
      • EASYRSA_KEY_SIZE: Default is often 2048 bits for RSA keys. For the CA key and server key, 4096 is recommended for stronger security, though it incurs a slight performance overhead. Client keys can remain 2048.
      • EASYRSA_ALGO: rsa is common. ec (elliptic curve) is also an option for more modern setups, offering similar security with smaller key sizes. For broadest compatibility, rsa is safer.
      • EASYRSA_CA_EXPIRE: How long the CA certificate itself is valid (e.g., 10 years).
      • EASYRSA_CERT_EXPIRE: Default validity for server and client certificates (e.g., 1-3 years). Shorter is generally better for security, but means more frequent renewal.
      • Fill in EASYRSA_REQ_COUNTRY, EASYRSA_REQ_PROVINCE, etc., with your desired information. This is mostly for identification within the certificate; it doesn't have major functional impact for OpenVPN.
    • Save and close the vars file. These settings will be used when you generate certificates.

Generating CA, Server, and Client Certificates/Keys

Now we'll use Easy-RSA commands to create the actual cryptographic materials.

  1. Build the Certificate Authority (CA): This command creates the CA certificate (ca.crt) and the CA private key (ca.key).

    # Ensure you are in /etc/openvpn/easy-rsa
    ./easyrsa build-ca
    

    • You will be prompted for a PEM pass phrase for the CA key. This is a crucial password that encrypts your ca.key file on disk. Choose a very strong, unique password and store it securely (e.g., in a password manager). You will need this password to sign server/client certificates or generate a CRL.
    • You'll then be asked for the Common Name (CN) for your CA. This can be anything descriptive, e.g., "MyOpenVPN-CA" or your domain name. The values from the vars file will be used as defaults for other fields (Country, Org, etc.).
    • Output:
      • pki/ca.crt (CA public certificate)
      • pki/private/ca.key (CA private key, encrypted with the PEM pass phrase you set)
  2. Generate Server Certificate and Key: This creates a certificate and private key for the OpenVPN server.

    # Syntax: ./easyrsa build-server-full <filename_base> [nopass]
    ./easyrsa build-server-full server nopass
    

    • server: This will be the base filename for the server's files (e.g., server.crt, server.key). "server" is a conventional name.
    • nopass: This option generates an unencrypted private key for the server (pki/private/server.key). This is highly recommended for servers because if the key is encrypted, you would need to enter the passphrase every time the OpenVPN service starts, which is impractical for unattended reboots. Server security relies on file permissions and overall system security to protect this unencrypted key.
    • You will be prompted to enter the CA's PEM pass phrase (the one you set in the previous step) to authorize signing the server certificate.
    • The Common Name (CN) for the server certificate is important. By default, it will be "server". Some client configurations might verify this. It's good practice for it to be unique.
    • Output:
      • pki/issued/server.crt (Server public certificate, signed by CA)
      • pki/private/server.key (Server private key, unencrypted)
      • pki/reqs/server.req (Certificate Signing Request - intermediate file, can be ignored for this process)
  3. Generate Client Certificate and Key: Repeat this process for each client device that will connect to the VPN. Each client needs its own unique certificate and key.

    # Syntax: ./easyrsa build-client-full <client_filename_base> [nopass]
    # For a client named 'client1'
    ./easyrsa build-client-full client1 nopass
    

    • client1: Replace with a descriptive name for the client (e.g., my_laptop, alices_phone). This name will also be the Common Name (CN) in the certificate, which can be useful for identifying clients on the server.
    • nopass: This option generates an unencrypted private key for the client (pki/private/client1.key). This is generally convenient for clients so they don't have to type a key passphrase on every connection. If extra security is needed for the client key at rest on the client device, you can omit nopass, and the user will be prompted for a passphrase when OpenVPN uses the key. For most setups, nopass is fine, and security relies on the client device's overall security.
    • You will again be prompted for the CA's PEM pass phrase to sign the client certificate.
    • Output (for client1):
      • pki/issued/client1.crt (Client public certificate, signed by CA)
      • pki/private/client1.key (Client private key, unencrypted if nopass was used)
      • pki/reqs/client1.req (Certificate Signing Request)

    Generate more client certs as needed:

    ./easyrsa build-client-full myphone nopass
    ./easyrsa build-client-full worklaptop nopass
    

Generating Diffie-Hellman Parameters

Diffie-Hellman (DH) parameters are used for the key exchange process during the TLS handshake. They enable Perfect Forward Secrecy (PFS), meaning that even if the server's long-term private key is compromised, past session keys (and thus past encrypted traffic) cannot be decrypted.

# Ensure you are in /etc/openvpn/easy-rsa
./easyrsa gen-dh
  • This command will generate a dh.pem file (or dh2048.pem/dh4096.pem depending on Easy-RSA version and vars settings for key size). The default DH parameter size in modern Easy-RSA is often 2048 bits. This process can take a few minutes, especially for larger key sizes (e.g., 4096 bits).
  • If your vars file specified a different EASYRSA_KEY_SIZE (e.g., 4096) for DH, it should use that. If not, it usually defaults to 2048 bits which is generally considered secure. Using 4096-bit DH params offers more security but takes longer to generate and has a slight performance impact on connection setup. For most purposes, 2048-bit DH is sufficient.
  • Output:
    • pki/dh.pem (Diffie-Hellman parameters)

Generating HMAC Key (for TLS Authentication)

OpenVPN can use an additional pre-shared static key for HMAC authentication of TLS control channel packets. This provides an extra layer of security:

  • It helps protect against DoS attacks on the OpenVPN port, as packets without the correct HMAC signature are dropped early.
  • It adds a defense against vulnerabilities that might be discovered in the OpenSSL library.
  • It obfuscates the OpenVPN handshake slightly.

This feature is often referred to as tls-auth (older) or tls-crypt (newer, preferred). tls-crypt encrypts and authenticates the control channel, while tls-auth only authenticates it. We will use tls-crypt as it's generally better.

# This command is an OpenVPN command, not Easy-RSA
# Ensure you are in a directory where you want to save the key, e.g., /etc/openvpn/easy-rsa/pki
# Or directly in /etc/openvpn/ if preferred for server config
cd /etc/openvpn # A good place for server-specific keys like this
sudo openvpn --genkey secret tls-crypt.key
# Or for older tls-auth style:
# sudo openvpn --genkey secret ta.key
  • This command creates a file named tls-crypt.key (or ta.key) containing a 2048-bit pre-shared key.
  • This key needs to be present on both the server and all clients.
  • Output:
    • A file named tls-crypt.key (or ta.key) in the current directory (e.g. /etc/openvpn/tls-crypt.key).

File Locations Summary (within /etc/openvpn/easy-rsa/pki/ by default):

  • CA:
    • ca.crt (Public CA certificate)
    • private/ca.key (Private CA key - KEEP SUPER SECRET AND SECURE)
  • Server:
    • issued/server.crt (Server public certificate)
    • private/server.key (Server private key)
    • dh.pem (Diffie-Hellman parameters)
  • Client (e.g., client1):
    • issued/client1.crt (Client public certificate)
    • private/client1.key (Client private key)
  • TLS Crypt Key (e.g., in /etc/openvpn/):
    • tls-crypt.key (Pre-shared HMAC key)

Important Security Considerations for Keys:

  • The ca.key is the most critical private key. Protect it rigorously.
  • server.key must be protected on the server.
  • Each client.key must be protected on its respective client device.
  • The tls-crypt.key (or ta.key) must be known by the server and all clients but kept secret from others.
  • Set strict file permissions on all private keys. Typically, they should only be readable by the root user or the user OpenVPN runs as.

# Example permission setting after all keys are generated and moved to /etc/openvpn/
sudo chown root:root /etc/openvpn/*.key /etc/openvpn/easy-rsa/pki/private/*.key
sudo chmod 600 /etc/openvpn/*.key /etc/openvpn/easy-rsa/pki/private/*.key
sudo chmod 644 /etc/openvpn/*.crt /etc/openvpn/easy-rsa/pki/*.crt /etc/openvpn/easy-rsa/pki/issued/*.crt /etc/openvpn/dh.pem
# If you moved easy-rsa back to root ownership after using it
sudo chown -R root:root /etc/openvpn/easy-rsa
sudo chmod 700 /etc/openvpn/easy-rsa/pki/private
Adjust owner/group as necessary if you plan to run OpenVPN as a non-root user.

Now you have all the cryptographic material needed to configure your OpenVPN server and clients.

Workshop Certificate Generation with Easy-RSA

Objective: To create a complete set of certificates and keys required for an OpenVPN server and at least one client.

Prerequisites:

  • OpenVPN and Easy-RSA installed on your server (from "Workshop Installing OpenVPN").
  • Sudo access for your user.
  • You are logged into your server as your non-root sudo user (e.g., vpnadmin).

Instructions:

  1. Prepare Easy-RSA Environment:

    • Create the working directory for Easy-RSA and take ownership (temporarily, for ease of use):
      sudo mkdir /etc/openvpn/easy-rsa
      sudo chown $(whoami):$(whoami) /etc/openvpn/easy-rsa # $(whoami) inserts your current username
      cd /etc/openvpn/easy-rsa
      
    • Copy the Easy-RSA scripts into your working directory. (Path might vary slightly, /usr/share/easy-rsa/* is common for Debian/Ubuntu. If easyrsa is directly in PATH, you might technically skip this and just run easyrsa init-pki but copying is good practice for self-contained PKI management).
      cp -R /usr/share/easy-rsa/* .
      chmod +x easyrsa # Make sure the script is executable
      
      If /usr/share/easy-rsa/* doesn't work, find the correct path for your distro (e.g., rpm -ql easy-rsa | grep easyrsa$ on RHEL-based might show content paths).
    • Initialize the PKI structure:
      ./easyrsa init-pki
      
      Verify a pki subdirectory is created.
  2. Configure CA Variables (Optional, but good practice):

    • Copy vars.example to vars (if it exists) or create vars:
      cp vars.example vars # If vars.example exists
      nano vars
      
    • Uncomment and set at least the following variables in vars. Adjust values as you see fit. For key sizes, 4096 is stronger for CA/Server, 2048 is fine for clients.
      # Example settings:
      set_var EASYRSA_REQ_COUNTRY    "US"
      set_var EASYRSA_REQ_PROVINCE   "California"
      set_var EASYRSA_REQ_CITY       "San Francisco"
      set_var EASYRSA_REQ_ORG        "MyVPN Inc"
      set_var EASYRSA_REQ_EMAIL      "admin@myvpn.example.com"
      set_var EASYRSA_REQ_OU         "VPN Department"
      set_var EASYRSA_ALGO           rsa
      set_var EASYRSA_KEY_SIZE       2048 # Default for certs, can be overridden per command
      set_var EASYRSA_CA_EXPIRE      3650 # 10 years for CA
      set_var EASYRSA_CERT_EXPIRE    1080 # 3 years for server/client certs
      
    • Save and close vars.
  3. Build the Certificate Authority (CA):

    ./easyrsa build-ca
    

    • When prompted, enter a strong PEM pass phrase for the CA key. Record this passphrase securely! You'll need it multiple times.
    • Enter a Common Name for your CA (e.g., MyPersonalVPN-CA).
  4. Generate Server Certificate and Key:

    We'll use a 4096-bit key for the server for enhanced security.

    # Temporarily override key size for server if your vars default is lower
    # EASYRSA_KEY_SIZE=4096 ./easyrsa build-server-full server nopass
    # Or if you set EASYRSA_KEY_SIZE to 4096 in vars, then just:
    ./easyrsa build-server-full server nopass
    

    • Enter the CA PEM pass phrase when prompted.
    • Confirm the Common Name (default is "server").
  5. Generate Client Certificate and Key (for one client):

    Let's name the first client client1.

    ./easyrsa build-client-full client1 nopass
    

    • Enter the CA PEM pass phrase when prompted.
    • Confirm the Common Name (default is "client1").
  6. Generate Diffie-Hellman Parameters:

    We'll generate 2048-bit DH parameters, which is a good balance of security and generation time. If you want 4096, be prepared for it to take longer.

    # EASYRSA_KEY_SIZE=2048 ./easyrsa gen-dh  # If your vars default is different
    # Or if vars default is 2048:
    ./easyrsa gen-dh
    
    This might take a few minutes.

  7. Generate TLS Crypt Key:

    This key will be stored directly in /etc/openvpn/ for use by the server configuration.

    sudo openvpn --genkey secret /etc/openvpn/tls-crypt.key
    
    (Note: We use sudo here because /etc/openvpn/ is typically root-owned, and we want the key created there directly with root ownership for security.)

  8. Verify Generated Files:

    List the key files in their expected locations:

    • CA files:
      ls -l pki/ca.crt pki/private/ca.key
      
    • Server files:
      ls -l pki/issued/server.crt pki/private/server.key pki/dh.pem
      
    • Client files:
      ls -l pki/issued/client1.crt pki/private/client1.key
      
    • TLS Crypt key:
      sudo ls -l /etc/openvpn/tls-crypt.key
      
  9. Secure Permissions (Crucial):

    The pki directory, especially pki/private, contains highly sensitive keys.

    • Copy necessary files for the server to /etc/openvpn/:
      sudo cp pki/ca.crt /etc/openvpn/
      sudo cp pki/issued/server.crt /etc/openvpn/
      sudo cp pki/private/server.key /etc/openvpn/
      sudo cp pki/dh.pem /etc/openvpn/
      # The tls-crypt.key is already in /etc/openvpn/
      
    • Set strict permissions for files in /etc/openvpn/:
      sudo chown root:root /etc/openvpn/*.*
      sudo chmod 600 /etc/openvpn/*.key /etc/openvpn/dh.pem # Private keys and DH params
      sudo chmod 644 /etc/openvpn/*.crt # Public certificates can be world-readable
      
    • Secure the Easy-RSA directory itself. After you are done generating keys, you might want to transfer pki/private/ca.key and pki/ca.crt (and the CA passphrase) to an offline storage and remove them from the server, or at least ensure the entire /etc/openvpn/easy-rsa directory is owned by root and not generally accessible.
      cd /etc/openvpn/ # Go up one level
      sudo chown -R root:root easy-rsa
      sudo chmod 700 easy-rsa/pki/private # Ensure private key directory is not world readable/listable
      

Expected Outcome:

  • You have a pki directory within /etc/openvpn/easy-rsa/ containing:
    • ca.crt and private/ca.key (your CA)
    • issued/server.crt and private/server.key (for the OpenVPN server)
    • issued/client1.crt and private/client1.key (for your first client)
    • dh.pem (Diffie-Hellman parameters)
  • You have a tls-crypt.key file in /etc/openvpn/.
  • Copies of ca.crt, server.crt, server.key, dh.pem, and tls-crypt.key are in /etc/openvpn/ with secure permissions, ready for the server configuration.
  • You have securely stored your CA's PEM pass phrase.

Troubleshooting:

  • ./easyrsa: No such file or directory or Command not found: Ensure you are in the /etc/openvpn/easy-rsa directory and that the easyrsa script is present and executable (chmod +x easyrsa). Or, if easyrsa is in your system PATH, just run easyrsa <command>.
  • Permission denied errors: Use sudo for commands that write to system directories (like sudo openvpn --genkey secret /etc/openvpn/tls-crypt.key or copying files to /etc/openvpn/). If easyrsa commands fail due to permissions within the pki dir, ensure your current user owns /etc/openvpn/easy-rsa and its subdirectories while you are working in it. Revert ownership to root afterwards for security.
  • Forgetting CA passphrase: If you forget the CA passphrase, you cannot sign new certificates or generate a CRL. You might have to start the PKI generation over (or restore ca.key and ca.crt from a backup if you have one). This highlights the importance of securely storing the passphrase.

You are now equipped with all the necessary cryptographic components. The next step is to write the OpenVPN server configuration file.

4. Configuring the OpenVPN Server

With certificates and keys generated, it's time to create the OpenVPN server configuration file. This file, conventionally named server.conf, tells the OpenVPN daemon how to operate: which IP address and port to listen on, which encryption ciphers to use, network settings for clients, and paths to the necessary keys and certificates.

We will create a basic but secure server configuration.

Basic server.conf Explained

The OpenVPN server configuration file is typically located in /etc/openvpn/. We will create /etc/openvpn/server.conf. Each line in the configuration file is a directive followed by parameters. Lines starting with # or ; are comments and are ignored.

Here's a sample server.conf with explanations. You'll need to adjust paths or settings based on your setup, especially if you used different filenames for keys/certificates or chose different network parameters.

# /etc/openvpn/server.conf

# --- Basic Server Settings ---
port 1194
proto udp
dev tun

# --- Certificate and Key Files ---
# These paths assume you copied the files directly into /etc/openvpn/
# Adjust if your easy-rsa PKI structure is different and you're linking from there.
ca ca.crt
cert server.crt
key server.key  # This file should be kept secret
dh dh.pem
tls-crypt tls-crypt.key # This file must be generated with --genkey secret and shared with clients

# --- Network Configuration ---
# VPN subnet for clients.
# The server will take 10.8.0.1, clients will be assigned IPs from this range.
server 10.8.0.0 255.255.255.0

# Maintain a record of client <-> virtual IP address mappings in this file.
# If OpenVPN is restarted, previously connected clients will get the same IP address.
ifconfig-pool-persist ipp.txt

# --- Routing ---
# Push routes to the client to allow it to reach
# other private subnets behind the server.
# Example: If your server's LAN is 192.168.1.0/24 and you want clients to reach it:
# push "route 192.168.1.0 255.255.255.0"

# Route all client traffic through the VPN (Full Tunnel).
# This makes the VPN server the default gateway for clients.
push "redirect-gateway def1 bypass-dhcp"

# Provide DNS servers to clients. These can be public DNS or your own.
# Using well-known public DNS servers:
push "dhcp-option DNS 8.8.8.8"   # Google DNS
push "dhcp-option DNS 8.8.4.4"   # Google DNS
# Alternatively, use your ISP's DNS, or your own private DNS resolver.
# push "dhcp-option DNS 1.1.1.1" # Cloudflare DNS

# --- Client Management ---
# Allow multiple clients with the same certificate/key pair to connect.
# Not recommended for security if each user should be unique.
# duplicate-cn

# Allow clients to "see" each other.
# Without this, clients cannot reach other clients connected to the VPN.
client-to-client

# --- Security and Performance ---
# Use a strong cipher. AES-256-GCM is recommended.
# List available ciphers with: openvpn --show-ciphers
cipher AES-256-GCM
auth SHA256 # Authentication digest algorithm for HMAC on data channel. GCM ciphers handle this internally, but good to specify.

# For tls-crypt, we specified the key above. For tls-auth (older), you'd use:
# tls-auth ta.key 0 # This file is secret and shared with clients. '0' for server.

# Keepalive ping to ensure connection stays active and detect dead peers.
# Ping every 10 seconds, assume peer is down if no ping for 120 seconds.
keepalive 10 120

# Enable compression. Not recommended due to VORACLE attack.
# If you must use it, use lz4 and ensure clients also support it.
# comp-lzo # Deprecated and potentially insecure
# compress lz4-v2 # Better option if compression is needed
# push "compress lz4-v2"
# For best security, avoid compression if possible.

# --- User and Group ---
# Drop privileges after initialization.
# User and group must exist on the system.
user nobody
group nogroup # On Debian/Ubuntu, 'nogroup'. On CentOS/RHEL, often 'nobody'.

# --- Logging ---
# Log verbosity (0-9, 3 is usually good for normal operation).
verb 3
# Log file location.
status /var/log/openvpn/openvpn-status.log # Client status
log-append /var/log/openvpn/openvpn.log    # General logs
# Ensure /var/log/openvpn directory exists and is writable by OpenVPN process (or root before dropping privs).

# --- Other Settings ---
# Do not re-read Preshared Keys continuously. Improves performance.
persist-key
# Do not close and reopen TUN/TAP device or run up/down scripts on restart.
persist-tun

# Explicitly exit on fatal errors.
explicit-exit-notify 1

Explanation of Key Directives:

  • port 1194: The port OpenVPN listens on. 1194 is the standard.
  • proto udp: Use UDP protocol. Generally faster for VPNs. tcp is an alternative if UDP is blocked.
  • dev tun: Create a Layer 3 IP tunneling device (named tun0, tun1, etc.). tap is for Layer 2 Ethernet tunneling.
  • ca ca.crt, cert server.crt, key server.key, dh dh.pem: Paths to your CA certificate, server certificate, server private key, and Diffie-Hellman parameters. These files should be in /etc/openvpn/ or provide full paths.
  • tls-crypt tls-crypt.key: Specifies the pre-shared key for encrypting/authenticating control channel packets. Replaces tls-auth for better security.
  • server 10.8.0.0 255.255.255.0: Defines the virtual IP address pool for clients. The server will take the first IP (10.8.0.1). Clients get subsequent IPs. Choose a private IP range that doesn't conflict with your server's LAN or client LANs.
  • ifconfig-pool-persist ipp.txt: Saves client IP assignments so they get the same IP if they reconnect. The ipp.txt file will be created in /etc/openvpn/.
  • push "redirect-gateway def1 bypass-dhcp": This critical directive tells clients to route all their internet traffic through the VPN. This is a "full tunnel" setup.
    • def1: Modifies the client's default route to point to the VPN.
    • bypass-dhcp: Prevents conflicts if the client's local DHCP server tries to set gateway options.
  • push "dhcp-option DNS 8.8.8.8": Pushes DNS server settings to clients. When clients are full-tunneling, their DNS requests should also go through the VPN or to a trusted resolver.
  • client-to-client: Allows clients connected to the VPN to communicate with each other through the VPN server. Remove if you want clients isolated from each other.
  • cipher AES-256-GCM: Specifies the symmetric encryption cipher for the data channel. AES-256-GCM is a strong, modern Authenticated Encryption with Associated Data (AEAD) cipher. It provides both encryption and integrity.
  • auth SHA256: Specifies the HMAC algorithm for data channel packet authentication. When using an AEAD cipher like AES-GCM, this auth directive is less critical for the data channel itself (as GCM handles authentication), but it's still good practice to include it for non-AEAD ciphers and for control channel message digests if not fully handled by TLS.
  • keepalive 10 120: Sends a keepalive ping every 10 seconds. If no response from the other side for 120 seconds, the connection is considered dead. Helps maintain connections through NATs and firewalls.
  • user nobody, group nogroup: Drops OpenVPN's root privileges after initialization, running as a less privileged user for security. nogroup is common on Debian/Ubuntu; use nobody for the group on RHEL/CentOS.
  • persist-key, persist-tun: Prevents re-reading keys and recreating the TUN device on SIGHUP signal (often sent on restart or config reload), which can cause issues.
  • verb 3: Sets log verbosity. 3 is a good default. Higher for debugging, lower for less noise.
  • status /var/log/openvpn/openvpn-status.log: Logs current client connections and statistics.
  • log-append /var/log/openvpn/openvpn.log: Appends general operational logs to this file. Ensure the /var/log/openvpn directory exists and is writable by OpenVPN before it drops privileges, or by root.

Network Configuration (TUN/TAP, IP range)

This was largely covered in the server.conf explanation, but let's elaborate:

  • dev tun vs dev tap:

    • tun (default, recommended): Operates at OSI Layer 3 (IP). Creates a virtual point-to-point IP link. Efficient for routing IP traffic. Your clients will get an IP address from the VPN subnet (e.g., 10.8.0.x) and communicate via IP.
    • tap: Operates at OSI Layer 2 (Ethernet). Creates a virtual Ethernet adapter. Can bridge networks, allowing non-IP protocols or things like DHCP over the VPN. More overhead, more complex to configure correctly (especially bridging with the server's LAN). Use only if you have a specific need for Layer 2 connectivity.
  • server 10.8.0.0 255.255.255.0 (VPN IP Range):

    • This directive configures a /24 subnet (254 usable IPs) for VPN clients.
    • The server will occupy 10.8.0.1.
    • Clients will be assigned IPs from 10.8.0.2 to 10.8.0.254.
    • Crucially, this IP range must not overlap with:
      • The IP range of the LAN your OpenVPN server is on.
      • The IP ranges of the LANs your clients might be connecting from.
      • Common public IP ranges (though this is unlikely to be an issue with private IP ranges like 10.x.x.x, 172.16.x.x-172.31.x.x, 192.168.x.x).
    • If you have a small number of clients, you could use a smaller subnet, e.g., server 10.8.0.0 255.255.255.240 (/28 subnet, 14 usable IPs).

Pushing Routes to Clients

The push directive in server.conf is powerful. It sends configuration options to clients when they connect.

  • push "redirect-gateway def1 bypass-dhcp" (Full Tunnel):

    • This is the most common setup for privacy/security VPNs. It forces all client-generated internet traffic (web browsing, email, etc.) through the VPN tunnel.
    • The client's default gateway is changed to be the VPN server's virtual IP (10.8.0.1 in our example).
    • From the internet's perspective, the client's traffic appears to originate from the OpenVPN server's public IP address.
  • push "route <network> <netmask>" (Split Tunnel - specific routes):

    • If you don't use redirect-gateway, only traffic destined for networks explicitly routed via the VPN will go through it. This is called split tunneling.
    • Example: If your server's physical LAN is 192.168.1.0/24 and you only want clients to access this LAN through the VPN, but let their other internet traffic go directly:
      # In server.conf (do NOT use redirect-gateway def1 with this)
      push "route 192.168.1.0 255.255.255.0"
      
    • Clients would then only send traffic for 192.168.1.x through the VPN. Their regular internet browsing would use their local internet connection. This is common for corporate VPNs where only access to internal resources is needed.

Enabling IP Forwarding

For the OpenVPN server to route traffic from VPN clients (on the tun0 interface, e.g., 10.8.0.0/24) to the internet (via its physical interface, e.g., eth0), IP forwarding (also known as packet forwarding) must be enabled in the server's kernel.

  1. Enable IP Forwarding Temporarily (for testing):

    sudo sysctl -w net.ipv4.ip_forward=1
    
    This enables it until the next reboot.

  2. Enable IP Forwarding Permanently:

    • Edit /etc/sysctl.conf (or a file in /etc/sysctl.d/ like /etc/sysctl.d/99-openvpn-forward.conf):
      sudo nano /etc/sysctl.conf
      # Or: sudo nano /etc/sysctl.d/99-openvpn-forward.conf
      
    • Uncomment or add the following line:
      net.ipv4.ip_forward=1
      
    • Save the file.
    • Apply the change without rebooting:
      sudo sysctl -p /etc/sysctl.conf
      # Or if you used a file in /etc/sysctl.d/:
      # sudo sysctl --system
      

Firewall Configuration (iptables/ufw)

The server's firewall needs to be configured to allow OpenVPN traffic and to NAT (Network Address Translation) traffic from VPN clients to the internet.

1. Allow OpenVPN Traffic:

We already did this in the "Server Preparation" workshop when setting up UFW (or firewalld) by allowing UDP port 1194.

  • UFW: sudo ufw allow 1194/udp (should already be there)
  • firewalld: sudo firewall-cmd --permanent --add-port=1194/udp (or --add-service=openvpn if a service definition exists) then sudo firewall-cmd --reload.

2. Configure NAT:

NAT allows multiple clients on the private VPN subnet (e.g., 10.8.0.0/24) to share the server's single public IP address when accessing the internet. This typically involves adding rules to the nat table in iptables.

  • Find your Public Network Interface: Use ip addr or ifconfig to find the name of your server's primary network interface that connects to the internet (e.g., eth0, ens3, venet0). Let's assume it's eth0.

  • iptables NAT Rule: This rule says: "For traffic coming from the OpenVPN subnet (10.8.0.0/24) and going out the public interface (eth0), change its source IP to be the IP of eth0."

    sudo iptables -t nat -A POSTROUTING -s 10.8.0.0/24 -o eth0 -j MASQUERADE
    
    Replace 10.8.0.0/24 if you used a different VPN subnet and eth0 with your actual public interface.

  • Making iptables Rules Persistent: iptables rules are lost on reboot by default. You need a way to save and restore them.

    • Debian/Ubuntu (using iptables-persistent):
      sudo apt install iptables-persistent
      
      During installation, it will ask if you want to save current IPv4 and IPv6 rules. Say Yes. If you add rules later, save them with:
      sudo netfilter-persistent save
      # or explicitly: sudo iptables-save > /etc/iptables/rules.v4
      
    • CentOS/RHEL (using firewalld for NAT - preferred if firewalld is active): If you're using firewalld, it's better to manage NAT through it. First, find your default zone (usually public for VPS).

      sudo firewall-cmd --get-default-zone
      sudo firewall-cmd --get-active-zones # Note the zone your public interface is in
      
      Assuming your public interface is in the public zone:
      sudo firewall-cmd --permanent --zone=public --add-masquerade
      # Or if your interface (e.g. eth0) is in a different zone (e.g. external)
      # sudo firewall-cmd --permanent --zone=external --add-masquerade
      # You also need to tell firewalld about your OpenVPN source IPs (10.8.0.0/24)
      # and allow forwarding from the tun interface zone to the public zone.
      # Add the tun0 interface (once OpenVPN creates it) to a trusted zone or create a new one.
      # Example: sudo firewall-cmd --permanent --zone=trusted --add-interface=tun0
      # sudo firewall-cmd --permanent --direct --passthrough ipv4 -t nat -A POSTROUTING -s 10.8.0.0/24 -o eth0 -j MASQUERADE
      # This direct rule is often simpler for OpenVPN NAT with firewalld.
      sudo firewall-cmd --reload
      
      Using firewalld for NAT is cleaner if it's your primary firewall. If you're using UFW which is an iptables frontend, you often add iptables NAT rules directly and make them persistent as UFW doesn't directly manage NAT in the same way for these specific POSTROUTING rules.

    • UFW and NAT (Slightly More Complex):

      UFW itself doesn't have a simple command for MASQUERADE. You typically need to modify UFW's configuration files to allow forwarding and add the iptables NAT rule.

      1. Edit /etc/default/ufw:
        sudo nano /etc/default/ufw
        
        Change DEFAULT_FORWARD_POLICY="DROP" to DEFAULT_FORWARD_POLICY="ACCEPT".
      2. Edit /etc/ufw/before.rules:
        sudo nano /etc/ufw/before.rules
        
        Add the following lines at the top, before the *filter section (replace eth0 with your public interface and 10.8.0.0/24 with your VPN subnet):
        # NAT table rules
        *nat
        :POSTROUTING ACCEPT [0:0]
        # Allow traffic from OpenVPN client to eth0 (the internet)
        -A POSTROUTING -s 10.8.0.0/24 -o eth0 -j MASQUERADE
        COMMIT
        
      3. Reload UFW:
        sudo ufw disable
        sudo ufw enable
        

After these network configurations, your server should be ready to route client traffic.

Workshop Basic Server Configuration

Objective: To create the OpenVPN server configuration file, enable IP forwarding, and set up firewall rules for NAT and OpenVPN traffic.

Prerequisites:

  • Server prepared and OpenVPN/Easy-RSA installed.
  • Certificates and keys generated and placed in /etc/openvpn/ (from "Workshop Certificate Generation").
  • Sudo access.

Instructions:

  1. Create OpenVPN Log Directory: The server.conf will specify log files in /var/log/openvpn/. Create this directory:

    sudo mkdir -p /var/log/openvpn
    sudo chown nobody:nogroup /var/log/openvpn # Or nobody:nobody for RHEL-based, adjust if OpenVPN user is different
    

  2. Create server.conf: Using sudo nano /etc/openvpn/server.conf, create the server configuration file. Paste the following content. Read through it and understand each line. Pay attention to comments.

    # /etc/openvpn/server.conf
    # My Basic OpenVPN Server Configuration
    
    # Server Port, Protocol, Device
    port 1194
    proto udp
    dev tun
    
    # Certificates and Keys (ensure these files exist in /etc/openvpn/)
    ca ca.crt
    cert server.crt
    key server.key  # This file should be kept secret
    dh dh.pem
    tls-crypt tls-crypt.key
    
    # VPN Network Subnet
    # Server will be 10.8.0.1, clients get IPs from this range
    server 10.8.0.0 255.255.255.0
    
    # Persistent IP assignments for clients
    ifconfig-pool-persist ipp.txt
    
    # Route all client traffic through VPN
    push "redirect-gateway def1 bypass-dhcp"
    
    # Push DNS servers to clients
    push "dhcp-option DNS 8.8.8.8"
    push "dhcp-option DNS 1.1.1.1" # Cloudflare as secondary
    
    # Enable client-to-client communication (optional)
    client-to-client
    
    # Security: Cipher and Auth
    cipher AES-256-GCM
    auth SHA256 # Used for control channel, GCM provides data channel auth
    
    # Keepalive pings
    keepalive 10 120
    
    # Drop privileges
    user nobody
    group nogroup # Use 'nobody' for group on RHEL/CentOS
    
    # Logging
    verb 3
    status /var/log/openvpn/openvpn-status.log
    log-append /var/log/openvpn/openvpn.log
    # Use 'log /var/log/openvpn/openvpn.log' to overwrite log on restart instead of append
    
    # Persist options
    persist-key
    persist-tun
    
    # Explicit exit notification
    explicit-exit-notify 1
    
    Save and close the file.

  3. Enable IP Forwarding:

    • Edit /etc/sysctl.conf (or create /etc/sysctl.d/99-openvpn.conf):
      sudo nano /etc/sysctl.conf # Or /etc/sysctl.d/99-openvpn.conf
      
    • Add or uncomment:
      net.ipv4.ip_forward=1
      
    • Apply the setting:
      sudo sysctl -p # Or sudo sysctl --system if using /etc/sysctl.d/
      
  4. Configure Firewall for NAT and OpenVPN Port:

    • Identify Public Interface: Run ip -br a or ip addr. Note your main public interface (e.g., eth0, ens3). Let's assume eth0 for the example.
    • UFW Users (Debian/Ubuntu):
      1. Ensure OpenVPN port is allowed (should be from previous workshop):
        sudo ufw status # Check for 1194/udp ALLOW
        # If not there: sudo ufw allow 1194/udp
        
      2. Modify /etc/default/ufw to allow forwarding:
        sudo nano /etc/default/ufw
        
        Change DEFAULT_FORWARD_POLICY="DROP" to DEFAULT_FORWARD_POLICY="ACCEPT". Save.
      3. Add NAT rules to /etc/ufw/before.rules:
        sudo nano /etc/ufw/before.rules
        
        At the top of the file, before *filter, add (replace eth0 if yours is different):
        # START OPENVPN RULES
        # NAT table rules
        *nat
        :POSTROUTING ACCEPT [0:0]
        # Allow traffic from OpenVPN client to eth0 (change eth0 to your interface)
        -A POSTROUTING -s 10.8.0.0/24 -o eth0 -j MASQUERADE
        COMMIT
        # END OPENVPN RULES
        
        Save the file.
      4. Reload UFW:
        sudo ufw disable
        sudo ufw enable
        sudo ufw status # Verify it's active and rules are present
        
    • firewalld Users (CentOS/RHEL):
      1. Ensure OpenVPN port is allowed:
        sudo firewall-cmd --list-ports # Check for 1194/udp
        # If not there: sudo firewall-cmd --permanent --add-port=1194/udp && sudo firewall-cmd --reload
        
      2. Enable masquerading for your public zone (e.g., public or external - check with sudo firewall-cmd --get-active-zones):
        # Example for 'public' zone
        sudo firewall-cmd --permanent --zone=public --add-masquerade
        sudo firewall-cmd --reload
        
        (Note: Some setups might require more specific zone interactions or direct rules for forwarding between tun0's zone and the public zone if tun0 isn't automatically trusted or part of a zone that can forward to public. The simple masquerade on the outgoing zone often works for basic setups.)
  5. Start and Enable OpenVPN Server: OpenVPN services on systemd are often managed as openvpn@config_name.service or openvpn-server@config_name.service. If your config is /etc/openvpn/server.conf, the service name would be openvpn@server.service or openvpn-server@server.service.

    • Find the correct service name template: Look in /lib/systemd/system/ for openvpn@.service or openvpn-server@.service. Let's assume it's openvpn-server@.service (common on newer systems). If your file is server.conf, the instance is server.
      sudo systemctl start openvpn-server@server
      sudo systemctl enable openvpn-server@server
      
      If openvpn-server@server fails, try openvpn@server:
      sudo systemctl start openvpn@server
      sudo systemctl enable openvpn@server
      
    • Check Status:
      sudo systemctl status openvpn-server@server # or openvpn@server
      
      Look for "active (running)". If it failed, check logs:
      sudo journalctl -u openvpn-server@server -e # or openvpn@server
      cat /var/log/openvpn/openvpn.log
      
  6. Verify tun0 Interface: If OpenVPN started successfully, a tun0 interface should exist:

    ip addr show tun0
    
    You should see tun0 with the IP address 10.8.0.1.

Expected Outcome:

  • server.conf is created in /etc/openvpn/.
  • IP forwarding is enabled permanently.
  • Firewall is configured to allow OpenVPN traffic and NAT client traffic.
  • The OpenVPN server process is running successfully.
  • A tun0 interface with IP 10.8.0.1 is active.

Troubleshooting:

  • OpenVPN service fails to start:
    • Check sudo journalctl -u openvpn-server@server -e (or openvpn@server) and /var/log/openvpn/openvpn.log for detailed error messages.
    • Common errors:
      • File not found (for certs, keys, dh.pem, tls-crypt.key): Double-check paths in server.conf and ensure files exist in /etc/openvpn/ with correct names and read permissions for the OpenVPN user (root initially, then nobody).
      • Port already in use: Another service might be using port 1194.
      • Cannot allocate TUN/TAP dev dynamically: Permissions issue or TUN/TAP module not loaded (sudo modprobe tun).
      • Options error: Syntax error in server.conf. OpenVPN logs are usually specific.
  • tun0 interface not created: OpenVPN service likely failed to start. See above.
  • Firewall issues: If clients connect but can't access the internet, NAT or forward policy is likely the problem. Double-check your UFW/firewalld/iptables rules.
    • Use tcpdump on the server (sudo tcpdump -i tun0 -n and sudo tcpdump -i eth0 -n port not 22) to see if traffic is arriving from clients and being NATted out.

With the server configured and running, the next step is to set up a client.

5. Configuring OpenVPN Clients

Once the OpenVPN server is up and running, you need to configure client devices to connect to it. This involves creating a client configuration file (.ovpn file) and securely transferring it, along with the necessary certificates and keys, to each client device.

Creating Client Configuration Files (.ovpn)

A client configuration file (e.g., client1.ovpn) contains directives that tell the OpenVPN client software how to connect to your server. It's similar in format to server.conf but with client-specific options.

A key feature for ease of use is to embed the client's certificate, private key, CA certificate, and TLS crypt key directly within the .ovpn file. This creates a single file that can be easily imported by most OpenVPN client software.

Base Client Configuration Template (base.conf):

It's good practice to create a base template and then populate it with the actual key/certificate content for each client.

Create a file, say ~/client-configs/base.conf (not on the server's /etc/openvpn directly, but in a working directory where you'll generate the .ovpn files).

# Client configuration for MyOpenVPN

client
dev tun
proto udp

# Server IP address and Port
# Replace YOUR_SERVER_IP with your server's actual public IP address or resolvable DNS name
remote YOUR_SERVER_IP 1194

# For Laptops/Mobile devices that may change networks,
# resolve the server hostname freshly on connection attempts.
resolv-retry infinite

# Most clients don't need to bind to a specific local port.
nobind

# Try to preserve some state across restarts.
persist-key
persist-tun

# SSL/TLS parameters - files will be embedded below
# ca ca.crt
# cert client.crt
# key client.key
# tls-crypt tls-crypt.key # Use 'tls-auth ta.key 1' for older tls-auth

# Specify same cipher as server.
cipher AES-256-GCM
auth SHA256

# For tls-crypt, the direction is implicit.
# For tls-auth (older), client needs 'key-direction 1'
# key-direction 1 # Uncomment if using tls-auth ta.key 1

# Set log verbosity
verb 3

# Enable compression if server uses it (and you accepted the risk).
# Ensure this matches server config if used.
# compress lz4-v2

# Remote Cert Type Check (more secure)
# Verifies that the certificate presented by the server
# has the X509v3 Extended Key Usage field set to "TLS Web Server Authentication".
remote-cert-tls server

Explanation of Key Client Directives:

  • client: Specifies that this is a client configuration.
  • dev tun, proto udp: Must match the server configuration.
  • remote YOUR_SERVER_IP 1194: Crucial line. Replace YOUR_SERVER_IP with your OpenVPN server's public IP address or a Dynamic DNS hostname that resolves to it. 1194 is the port.
  • resolv-retry infinite: If the server hostname lookup fails, retry indefinitely. Useful for clients that might lose network connectivity temporarily.
  • nobind: Client doesn't bind to a specific local port.
  • persist-key, persist-tun: Same as on the server, helps maintain state.
  • cipher AES-256-GCM, auth SHA256: Must match the cipher and auth digest settings on the server.
  • remote-cert-tls server: An important security measure. It tells the client to verify that the certificate presented by the server is specifically designated as a "server" certificate in its X.509 extensions. This helps prevent man-in-the-middle attacks where a malicious client (masquerading as a server) tries to intercept connections.

Embedding Keys and Certificates:

To create a self-contained .ovpn file for a specific client (e.g., client1), you'll take the base.conf content and append the actual content of ca.crt, client1.crt, client1.key, and tls-crypt.key wrapped in XML-like tags.

The structure for an embedded file in an .ovpn config is:

<ca>
-----BEGIN CERTIFICATE-----
(Content of ca.crt)
-----END CERTIFICATE-----
</ca>

<cert>
-----BEGIN CERTIFICATE-----
(Content of client1.crt)
-----END CERTIFICATE-----
</cert>

<key>
-----BEGIN PRIVATE KEY-----
(Content of client1.key)
-----END PRIVATE KEY-----
</key>

<tls-crypt>
-----BEGIN OpenVPN Static key V1-----
(Content of tls-crypt.key)
-----END OpenVPN Static key V1-----
</tls-crypt>
(If you were using tls-auth instead of tls-crypt, the section would be <tls-auth>...content of ta.key...</tls-auth> and you'd uncomment key-direction 1 and use tls-auth ta.key 1 instead of tls-crypt tls-crypt.key in the commented out section of base.conf).

Script to Generate .ovpn Files:

Manually copying and pasting these keys is tedious and error-prone. It's better to use a script. Here's an example bash script you can create (e.g., in ~/client-configs/make_config.sh) to automate this. This script assumes it's run from a directory that has base.conf and has access to the Easy-RSA PKI directory.

#!/bin/bash

# Script to generate OpenVPN client .ovpn files with embedded keys/certs

# Check if client name is provided
if [ -z "$1" ]; then
    echo "Usage: $0 <client_name>"
    exit 1
fi

CLIENT_NAME="$1"
BASE_CONFIG_FILE="base.conf" # Assumes base.conf is in the same directory as the script
EASY_RSA_PKI_DIR="/etc/openvpn/easy-rsa/pki" # Path to your Easy-RSA PKI directory
OPENVPN_KEYS_DIR="/etc/openvpn" # Path where server's tls-crypt.key is
OUTPUT_DIR="./ovpn-files" # Directory to save the .ovpn files

# Check if base config exists
if [ ! -f "$BASE_CONFIG_FILE" ]; then
    echo "Error: Base config file '$BASE_CONFIG_FILE' not found."
    exit 1
fi

# Check if required client files exist
if [ ! -f "${EASY_RSA_PKI_DIR}/issued/${CLIENT_NAME}.crt" ]; then
    echo "Error: Client certificate ${EASY_RSA_PKI_DIR}/issued/${CLIENT_NAME}.crt not found."
    echo "Did you generate the client certificate using Easy-RSA?"
    echo "Example: cd /etc/openvpn/easy-rsa && ./easyrsa build-client-full ${CLIENT_NAME} nopass"
    exit 1
fi

if [ ! -f "${EASY_RSA_PKI_DIR}/private/${CLIENT_NAME}.key" ]; then
    echo "Error: Client private key ${EASY_RSA_PKI_DIR}/private/${CLIENT_NAME}.key not found."
    exit 1
fi

if [ ! -f "${EASY_RSA_PKI_DIR}/ca.crt" ]; then
    echo "Error: CA certificate ${EASY_RSA_PKI_DIR}/ca.crt not found."
    exit 1
fi

if [ ! -f "${OPENVPN_KEYS_DIR}/tls-crypt.key" ]; then
    echo "Error: tls-crypt key ${OPENVPN_KEYS_DIR}/tls-crypt.key not found."
    exit 1
fi

# Create output directory if it doesn't exist
mkdir -p "$OUTPUT_DIR"

# Start generating the .ovpn file
cat "${BASE_CONFIG_FILE}" \
    <(echo -e '<ca>') \
    <("${EASY_RSA_PKI_DIR}/ca.crt") \
    <(echo -e '</ca>\n<cert>') \
    <("${EASY_RSA_PKI_DIR}/issued/${CLIENT_NAME}.crt") \
    <(echo -e '</cert>\n<key>') \
    <("${EASY_RSA_PKI_DIR}/private/${CLIENT_NAME}.key") \
    <(echo -e '</key>\n<tls-crypt>') \
    <("${OPENVPN_KEYS_DIR}/tls-crypt.key") \
    <(echo -e '</tls-crypt>') \
    > "${OUTPUT_DIR}/${CLIENT_NAME}.ovpn"

echo "Client configuration generated: ${OUTPUT_DIR}/${CLIENT_NAME}.ovpn"
echo "Remember to replace 'YOUR_SERVER_IP' in the .ovpn file with your actual server IP or hostname!"
chmod 600 "${OUTPUT_DIR}/${CLIENT_NAME}.ovpn" # Secure the output file

How to use the script:

  1. Save the script above as make_config.sh in a directory, e.g., ~/client-configs/.
  2. Create base.conf (as shown previously) in the same ~/client-configs/ directory.
  3. Make the script executable: chmod +x ~/client-configs/make_config.sh.
  4. Run it with the client name (e.g., client1 which you created earlier):
    cd ~/client-configs/
    ./make_config.sh client1
    
  5. This will create ~/client-configs/ovpn-files/client1.ovpn.
  6. IMPORTANT: Open the generated client1.ovpn file and replace YOUR_SERVER_IP with your server's actual public IP address or DNS hostname.

Distributing Client Configuration and Certificates Securely

The generated .ovpn file contains the client's private key and the shared tls-crypt.key. Therefore, it is sensitive and must be transferred to the client device securely. Never email it unencrypted or share it over insecure channels.

Secure Transfer Methods:

  1. SCP (Secure Copy Protocol) / SFTP (SSH File Transfer Protocol):

    • If the client device is a computer (Linux, macOS, Windows with an SCP/SFTP client like WinSCP or FileZilla), you can transfer the file directly from the server or an intermediate machine.
    • From your local machine (if you first SCP'd the .ovpn file from the server to your local machine): scp ~/path/to/client1.ovpn user@client_device_ip:/path/to/destination/
    • From the OpenVPN server directly to a client (less common, usually you pull from server): scp /path/to/client1.ovpn user@client_device_ip:/path/to/destination/
  2. USB Drive (Physically Secure):

    • Copy the .ovpn file to a USB drive.
    • Physically hand the USB drive to the user or connect it to the client device.
    • Ensure the USB drive is kept secure during transit.
  3. Encrypted Archives:

    • Compress the .ovpn file into an encrypted archive (e.g., 7z, ZIP with AES-256 encryption).
    • Share the archive through any means (email, cloud storage).
    • Communicate the decryption password to the user via a separate, secure channel (e.g., phone call, encrypted messaging app like Signal).
  4. Secure Cloud Storage with End-to-End Encryption:

    • Use services like Tresorit, Sync.com, or Proton Drive which offer end-to-end encryption. Upload the file there and share it with the user.
  5. QR Code (for Mobile Clients):

    • Some OpenVPN mobile clients can import configurations by scanning a QR code containing the .ovpn file content.
    • You can generate a QR code from the text content of the .ovpn file. Be cautious with this method as QR codes can be large and screen-scraped if not handled carefully. Use a reputable offline QR code generator.
    • Example tool: qrencode (Linux command-line tool)
      qrencode -t ansiutf8 < client1.ovpn # Displays QR in terminal
      qrencode -o client1.png < client1.ovpn # Saves as PNG image
      
      Display the QR code on a secure screen for the user to scan directly.

Once the .ovpn file is on the client device, it should be stored in a secure location and ideally deleted from any intermediate transfer media (like the USB drive after copying).

Connecting from Different Operating Systems (Windows, Linux, macOS, Android, iOS)

Most operating systems require OpenVPN client software to use the .ovpn configuration file.

  1. Windows:

    • Client Software: The official OpenVPN Community Client ("OpenVPN GUI") from openvpn.net.
    • Installation: Download and install the client.
    • Configuration:
      • Copy the client1.ovpn file to the OpenVPN configuration directory, usually C:\Program Files\OpenVPN\config\ or C:\Users\<YourUser>\OpenVPN\config\ (check client documentation). Administrator rights may be needed to write to the Program Files location.
      • Alternatively, right-click the OpenVPN GUI tray icon, choose "Import file...", and select your .ovpn file.
    • Connection: Right-click the OpenVPN GUI tray icon, select the profile (e.g., client1), and click "Connect."
  2. Linux (Desktop/Command Line):

    • Client Software: The openvpn package itself (often installed as a dependency of NetworkManager's OpenVPN plugin). For graphical environments, NetworkManager with network-manager-openvpn and network-manager-openvpn-gnome (or KDE equivalents) is common.
    • Using NetworkManager (GUI):
      • Go to Network Settings -> VPN -> Add VPN -> Import from file...
      • Select your .ovpn file. It should parse the settings and embedded keys.
      • Save and connect.
    • Using Command Line:
      sudo openvpn --config /path/to/your/client1.ovpn
      
      This will run OpenVPN in the foreground and show logs. Press Ctrl+C to disconnect. For background operation, you'd typically use systemd services or NetworkManager.
  3. macOS:

    • Client Software:
      • Tunnelblick: A popular, free, open-source OpenVPN client for macOS (tunnelblick.net).
      • Viscosity: A commercial OpenVPN client, very polished (sparklabs.com/viscosity/).
      • Official OpenVPN Connect client.
    • Installation: Download and install your chosen client.
    • Configuration (Tunnelblick example):
      • Launch Tunnelblick.
      • Drag and drop your .ovpn file onto the Tunnelblick icon in the menu bar or into its "Configurations" list.
      • It will ask if you want to install the configuration for all users or just the current user.
    • Connection: Click the Tunnelblick icon in the menu bar, select your profile, and click "Connect."
  4. Android:

    • Client Software:
      • OpenVPN for Android (by Arne Schwabe): A highly recommended open-source client available on F-Droid and Google Play Store.
      • OpenVPN Connect (Official): Available on Google Play Store.
    • Installation: Install from your preferred app store.
    • Configuration (OpenVPN for Android example):
      • Transfer the .ovpn file to your Android device (e.g., via SCP, secure cloud storage, USB).
      • Open the "OpenVPN for Android" app.
      • Tap the + icon (or "Import") and choose "Import Profile from SD card" (or similar wording for local storage).
      • Navigate to and select your .ovpn file.
      • Give the profile a name and save.
    • Connection: Tap the profile name to connect.
  5. iOS (iPhone/iPad):

    • Client Software:
      • OpenVPN Connect (Official): Available on the Apple App Store.
    • Installation: Install from the App Store.
    • Configuration:
      • Transfer the .ovpn file to your iOS device. This can be done via:
        • iTunes File Sharing (connect device to computer).
        • Emailing it to yourself (if you accept the risk for this brief transfer) and opening the attachment with OpenVPN Connect.
        • Using AirDrop from a Mac.
        • Using iCloud Drive or other cloud services integrated with the Files app.
      • Open the OpenVPN Connect app.
      • Tap the + icon or look for an "Import Profile" option. If you opened the .ovpn file from another app (like Mail or Files), it might prompt to import directly into OpenVPN Connect.
      • Select "File" and browse to your .ovpn file.
    • Connection: Toggle the switch next to the imported profile to connect.

After connecting, verify your public IP address (e.g., by searching "what is my IP" in a browser) to ensure it shows the OpenVPN server's IP address. Also, test access to resources that should be available via the VPN.

Workshop Client Setup and Connection

Objective: To create a .ovpn client configuration file, securely transfer it to a client device, install OpenVPN client software, and establish a successful VPN connection.

Prerequisites:

  • OpenVPN server configured, running, and accessible from the internet (from "Workshop Basic Server Configuration").
  • At least one client certificate/key pair generated (e.g., client1.crt, client1.key from "Workshop Certificate Generation").
  • Access to a client device (Windows, Linux, macOS, Android, or iOS).
  • Your server's public IP address or DNS hostname.

Instructions:

Part 1: Generate Client .ovpn File (on the server or a machine with access to keys)

  1. Create ~/client-configs directory (if not already done):

    mkdir -p ~/client-configs
    cd ~/client-configs
    

  2. Create base.conf: Create the file ~/client-configs/base.conf with the following content:

    # Client configuration for MyOpenVPN - base.conf
    client
    dev tun
    proto udp
    remote YOUR_SERVER_IP 1194 # <<< IMPORTANT: EDIT THIS LATER
    resolv-retry infinite
    nobind
    persist-key
    persist-tun
    cipher AES-256-GCM
    auth SHA256
    verb 3
    remote-cert-tls server
    # If using tls-auth instead of tls-crypt, add:
    # key-direction 1
    

  3. Create make_config.sh script: Create the file ~/client-configs/make_config.sh with the script content provided in the "Creating Client Configuration Files (.ovpn)" section above. Make it executable:

    chmod +x make_config.sh
    

  4. Generate client1.ovpn: Assuming you created certificates for client1:

    ./make_config.sh client1
    
    This will create ~/client-configs/ovpn-files/client1.ovpn.

  5. Edit client1.ovpn to set Server IP: Open the generated file ~/client-configs/ovpn-files/client1.ovpn with a text editor:

    nano ~/client-configs/ovpn-files/client1.ovpn
    
    Find the line: remote YOUR_SERVER_IP 1194 Replace YOUR_SERVER_IP with your OpenVPN server's actual public IP address or its DNS hostname. Save the file.

Part 2: Transfer and Configure Client Device (Example: Windows PC)

The steps will vary slightly based on the client OS. We'll use Windows with the official OpenVPN GUI as an example. Adapt for your OS using the general guidelines provided earlier.

  1. Securely Transfer client1.ovpn:

    • From your server (or the machine where client1.ovpn was generated), transfer ~/client-configs/ovpn-files/client1.ovpn to your Windows client PC.
    • Method: Use SCP (WinSCP is a good Windows client), SFTP, or a secure USB drive. For this workshop, if the file is on your Linux server and your Windows PC is on a different network, you might SCP it from the server to a local Linux/macOS machine first, then to Windows, or use WinSCP directly from Windows to the server.
    • Example using WinSCP (Windows): Connect to your server with WinSCP, navigate to ~/client-configs/ovpn-files/, and download client1.ovpn to your Windows desktop or a known folder.
  2. Install OpenVPN Client on Windows:

    • Go to https://openvpn.net/community-downloads/.
    • Download the appropriate Windows installer (e.g., "OpenVPN Community Edition GUI for Windows").
    • Run the installer, accepting default options. Ensure the core components and OpenVPN GUI are selected. It might also install a TAP network adapter driver.
  3. Import .ovpn Configuration:

    • Locate the OpenVPN GUI icon in your system tray (it might be hidden; click the arrow to show all tray icons).
    • Right-click the OpenVPN GUI icon.
    • Select "Import file...".
    • Navigate to and select the client1.ovpn file you transferred to your Windows PC.
    • You should see a "File imported successfully" message.
  4. Connect to the VPN:

    • Right-click the OpenVPN GUI icon in the system tray again.
    • You should now see client1 (or whatever name was parsed from the file) in the menu.
    • Hover over client1 and click "Connect."
    • A status window will appear, showing connection logs. If successful, it will turn green and indicate "Connected." The tray icon will also turn green.

Part 3: Verify Connection

  1. Check IP Address:

    • Once connected, open a web browser on the client device.
    • Go to a website like https://www.whatismyip.com or https://icanhazip.com.
    • The IP address displayed should be your OpenVPN server's public IP address, not your client's local ISP IP address.
  2. Check Server Logs (on the OpenVPN server):

    sudo tail -f /var/log/openvpn/openvpn.log
    sudo cat /var/log/openvpn/openvpn-status.log
    
    You should see log entries indicating client1 has connected and is assigned an IP from the 10.8.0.0/24 range. The status log will show connected clients.

Expected Outcome:

  • The client device successfully connects to the OpenVPN server.
  • The client's public IP address, when browsing the internet, is the IP address of the OpenVPN server.
  • The OpenVPN server logs show a successful client connection.

Troubleshooting (Client-Side):

  • "Cannot resolve host" / "Host not found":
    • Double-check the remote YOUR_SERVER_IP 1194 line in client1.ovpn. Ensure YOUR_SERVER_IP is correct and resolvable from the client's network.
    • Ensure your server's firewall (e.g., UFW) is allowing incoming connections on UDP port 1194.
    • If using a VPS, ensure its cloud firewall/security group also allows UDP port 1194.
  • "TLS Error: TLS key negotiation failed to occur" or "AUTH_FAILED":
    • Mismatch in tls-crypt.key: The tls-crypt.key embedded in the client config must be identical to the one on the server (/etc/openvpn/tls-crypt.key). Regenerate the .ovpn if unsure.
    • Certificate issues: CA cert (ca.crt), client cert (client1.crt), or client key (client1.key) mismatch or corruption. Ensure correct files were embedded.
    • Server not reachable/firewall: The client can't even make initial contact.
    • Time Mismatch: Significant time differences between client and server can sometimes cause TLS errors. Ensure both are synced to NTP.
  • "Connection timed out":
    • Server is down or not reachable.
    • Firewall on the server, client, or an intermediate network is blocking UDP port 1194.
  • Connected, but no internet access:
    • IP Forwarding: Ensure net.ipv4.ip_forward=1 is set and applied on the server.
    • NAT/Firewall Rules: The iptables MASQUERADE rule (or firewalld equivalent) on the server is missing or incorrect. Ensure the output interface (-o eth0) and source subnet (-s 10.8.0.0/24) are correct.
    • DNS Issues: The DNS servers pushed by the VPN (push "dhcp-option DNS ...") might not be working or reachable. Try changing to other public DNS servers (like 1.1.1.1, 9.9.9.9) in server.conf, restart OpenVPN server, and reconnect client.
    • Client-side firewall: The client's own firewall might be blocking the VPN's virtual adapter traffic.

This completes the basic OpenVPN setup. You now have a functional VPN server and can connect a client to it, routing all its traffic securely through the server. The next sections will explore how to enhance this setup.