Skip to main content

OpenVPN Setup (Server & Client)

Environment

  • VPN Server

    Field Spec or Version
    CPU QEMU Virtual CPU version 2.5+ (2 Cores)
    RAM 2G
    OS Ubuntu 24.04.1 LTS (Noble Numbat)
    Network interface enp6s18 with static IP 192.168.3.100/24
    DNS 192.168.3.1 (Private DNS Server)
  • VPN Client

    Field Spec or Version
    CPU QEMU Virtual CPU version 2.5+ (2 Cores)
    RAM 2G
    OS Ubuntu 24.04.1 LTS (Noble Numbat)
    Network interface enp6s18 with static IP 192.168.5.100/24
    DNS 192.168.5.1 (Private DNS Server)

Server - Package Installation

apt install -y openvpn

Server - Configuration

  • Copy from sample configuration file

    cp /usr/share/doc/openvpn/examples/sample/config-files/server.conf /etc/openvpn/server/server.conf
    
  • Edit the copied file as following content

    vim /etc/openvpn/server/server.conf
    
    port 1194
    proto tcp
    
    # Use routing mode instead of bridge mode
    dev tun
    
    ca ca.crt
    cert example.fake.crt
    key example.fake.key
    dh dh.pem
    
    topology subnet
    server 192.168.7.0 255.255.255.0
    
    # Add route for subnet on server to connected VPN clients
    # Notice: firewall rule adjustment is required
    push "route 192.168.3.0 255.255.255.0"
    
    # Authenticate the clients by user/pass provided by PAM rather than client certificate
    plugin /usr/lib/openvpn/openvpn-plugin-auth-pam.so login
    verify-client-cert none
    username-as-common-name
    

Server - Certification Generation

  • Download Easy RSA and setup the executable path

    wget 'https://github.com/OpenVPN/easy-rsa/releases/download/v3.2.4/EasyRSA-3.2.4.tgz'
    tar -xvf EasyRSA-3.2.4.tgz
    rm EasyRSA-3.2.4.tgz
    
    mv EasyRSA-3.2.4 ~/Softwares/
    
    echo 'PATH="$PATH:/root/Softwares/EasyRSA-3.2.4"' >> ~/.bashrc
    source ~/.bashrc
    
    # easyrsa should be available now
    which easyrsa
    
  • Generate certificate and key

    cd /etc/openvpn/server
    
    # Init pki
    easyrsa init-pki
    
    # Create CA (to add password protect to it, remove "nopass" argument)
    easyrsa build-ca nopass
    
    easyrsa gen-req example.fake nopass
    
    # This may take several minutes
    easyrsa gen-dh
    
    easyrsa sign-req server example.fake
    
  • Copy dh, ca, certificate and key to the correct path (placed with server.conf)

    cp pki/dh.pem pki/ca.crt pki/issued/example.fake.crt pki/private/example.fake.key .
    

Server - sysctl

  • Allow ip forwarding

    vim /etc/sysctl.conf
    
    net.ipv4.ip_forward=1
    
    sysctl -p /etc/sysctl.conf
    

Server - Firewall rule

  • Allow incoming connections to port 1194 if default policy of chain INPUT is NOT ACCEPT

  • Allow VPN interface and subnet to access other devices inside the server subnet (192.168.3.0/24)

    iptables -A FORWARD -i tun0 -o enp6s18 -s 192.168.7.0/24 -d 192.168.3.0/24 -j ACCEPT
    iptables -A FORWARD -i enp6s18 -o tun0 -m state --state RELATED,ESTABLISHED -j ACCEPT
    iptables -t nat -A POSTROUTING -s 192.168.7.0/24 -o enp6s18 -j MASQUERADE
    
  • Don't forget to save the changes to both firewall configuration file and runtime configuration

    # Save iptables runtime to file
    iptables-save > /etc/iptables/rules.v4
    

Server - Service

  • Edit service template

    vim /usr/lib/systemd/system/openvpn@.service
    
    ExecStart=/usr/sbin/openvpn --daemon ovpn-%i --status /run/openvpn/%i.status 10 --cd /etc/openvpn/server --script-security 2 --config /etc/openvpn/server/%i.conf --writepid /run/openvpn/%i.pid
    
    systemctl daemon-reload
    
  • Enable and start service

    systemctl enable openvpn@server.service
    

Client - Create config and server CA

  • Create client configuration file

    vim client.conf
    
    client
    
    remote 192.168.3.100 1194
    proto tcp
    dev tun
    
    # We only need to provide server CA
    # Make sure cert and key are both commented out
    ca ca.crt
    ;cert example.fake.crt
    ;key example.fake.key
    
    # Verify server CA with local ca.crt
    remote-cert-tls server
    
    # Authenticate the client by user/pass rather than client certificate
    auth-user-pass
    
  • Copy content in example.fake.crt as local file ca.crt