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

    dsf

    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