Installing OpenVPN on CentOS Stream 9: Enterprise-Grade Security with SELinux

CentOS tutorial - IT technology blog
CentOS tutorial - IT technology blog

Introduction: Why Choose CentOS Stream 9 and OpenVPN?

Since CentOS 7 officially “retired,” I have spent six months testing VPNs for a remote team of 50 on the CentOS Stream 9 platform. The real-world results are impressive: the system maintains 99.9% uptime, consumes less than 200MB of RAM at idle, and is perfectly compatible with the latest security patches, which you can manage by configuring automatic security updates.

Setting up a VPN for a production environment involves more than just installing packages, similar to the other 10 essential post-installation steps for server hardening. You need to pay close attention to certificate authentication, firewall management, and SELinux configuration. Most administrators tend to disable SELinux to avoid trouble. However, I recommend against this. This article will guide you on how to configure OpenVPN and SELinux to “live together happily.”

Quick Start: Install OpenVPN in 5 Minutes

If you need an emergency backup VPN server, community scripts are the best choice, though installing WireGuard VPN is often preferred for its superior speed. Angristan’s script currently has over 20k stars on GitHub, making it highly reputable and clean.

curl -O https://raw.githubusercontent.com/angristan/openvpn-install/master/openvpn-install.sh
chmod +x openvpn-install.sh
sudo ./openvpn-install.sh

The script will automatically prompt for the IP, protocol (choose UDP), and DNS. It handles the entire Easy-RSA process and exports the .ovpn file for the client. For deeper enterprise customization, let’s dive into the manual steps below.

Step 1: Environment Preparation and Package Installation

CentOS Stream 9 does not include OpenVPN by default. You need to enable the EPEL (Extra Packages for Enterprise Linux) repository before installation. Without this step, the installation command will certainly return a No package available error.

sudo dnf install epel-release -y
sudo dnf update -y
sudo dnf install openvpn easy-rsa -y

Step 2: Initialize PKI with Easy-RSA

OpenVPN uses digital certificates instead of traditional passwords to enhance security. We will use Easy-RSA to create a private Certificate Authority (CA). I usually store this directory at /etc/openvpn/easy-rsa for centralized management.

mkdir -p /etc/openvpn/easy-rsa
cp -r /usr/share/easy-rsa/3/* /etc/openvpn/easy-rsa/
cd /etc/openvpn/easy-rsa

./easyrsa init-pki
./easyrsa build-ca nopass

Next, generate the Server certificate and Diffie-Hellman parameters. Note: The gen-dh process may take a few minutes depending on your CPU performance.

./easyrsa gen-req server nopass
./easyrsa sign-req server server
./easyrsa gen-dh
openvpn --genkey --secret ta.key

The ta.key (TLS-Auth) file provides an additional layer of protection. It allows the server to immediately reject unauthorized packets, effectively countering DoS attacks, much like installing Fail2ban for brute-force protection.

Step 3: Configure OpenVPN Server

Move the critical certificate files into the OpenVPN execution directory:

cp pki/ca.crt pki/issued/server.crt pki/private/server.key pki/dh.pem ta.key /etc/openvpn/server/

Create the configuration file /etc/openvpn/server/server.conf. Here, I use AES-256-GCM encryption. This is a modern encryption standard that offers faster processing on CPUs supporting the AES-NI instruction set.

port 1194
proto udp
dev tun
ca ca.crt
cert server.crt
key server.key
dh dh.pem
auth SHA512
tls-auth ta.key 0
topology subnet
server 10.8.0.0 255.255.255.0
push "redirect-gateway def1 bypass-dhcp"
push "dhcp-option DNS 8.8.8.8"
keepalive 10 120
cipher AES-256-GCM
user nobody
group nobody
persist-key
persist-tun
verb 3

Step 4: Network and Firewall Configuration

To allow clients to access the internet via the VPN, you must enable IP Forwarding. I once wasted an entire morning because I forgot this line when migrating from CentOS 7 to version 9.

echo 'net.ipv4.ip_forward = 1' | sudo tee -a /etc/sysctl.d/99-openvpn.conf
sudo sysctl -p /etc/sysctl.d/99-openvpn.conf

Next, open port 1194 and enable NAT (Masquerade) on Firewalld:

sudo firewall-cmd --permanent --add-port=1194/udp
sudo firewall-cmd --permanent --add-masquerade
sudo firewall-cmd --reload

Step 5: Handling SELinux – Don’t Disable It, Understand It!

If you start OpenVPN immediately, you will encounter a Permission denied error. Instead of using the risky setenforce 0, assign the correct context labels to the configuration files. This only takes 10 seconds but makes your server much more secure.

sudo chcon -R -t openvpn_etc_t /etc/openvpn/server/
sudo restorecon -Rv /etc/openvpn/server/

Start and Verify

Enable the service to start with the system:

sudo systemctl enable --now openvpn-server@server

Use the command systemctl status openvpn-server@server to check. If you see the active (running) status in green, your server is ready to serve.

Real-World Field Experience

1. Prioritize UDP over TCP

TCP in a VPN often causes “TCP Meltdown.” When packet loss occurs, speeds drop drastically due to overlapping retransmission mechanisms. With UDP, latency is significantly lower, making it suitable for both online meetings and remote work.

2. Strict Client Certificate Management

Never share a single certificate among multiple people. When an employee leaves, you can revoke their specific certificate without disrupting the connection for the entire company.

3. Real-Time Log Monitoring

All connection issues can be found in /etc/openvpn/server/openvpn-status.log. When a client reports an error, check this log first, or consider centralized logging with Rsyslog for easier troubleshooting across multiple nodes.

CentOS Stream 9 and OpenVPN are a powerful duo for enterprises. With just a little attention to SELinux, you will have a high-level secure VPN system with zero licensing costs.

Share: