OpenVPN clients

Chapter 6 — OpenVPN Clients

The server is running and the .ovpn profile is ready. This chapter covers connecting from three environments: Linux via the command line and NetworkManager, Windows via the official GUI client, and a close look at the .ovpn file itself so you can customise it with confidence.

Linux — Command Line

🐧
Linux — openvpn CLI
Works on any distro · runs in foreground or as a systemd service
linux client — connect with openvpn
# install the client philip@laptop:~$ sudo apt install -y openvpn # connect — runs in foreground, Ctrl+C to disconnect philip@laptop:~$ sudo openvpn --config client1.ovpn ... Initialization Sequence Completed ← tunnel is up when you see this # connect in background (daemon mode) philip@laptop:~$ sudo openvpn --config client1.ovpn --daemon --log /var/log/openvpn-client.log # verify the tunnel interface exists philip@laptop:~$ ip addr show tun0 4: tun0: <POINTOPOINT,MULTICAST,NOARP,UP,LOWER_UP> mtu 1500 inet 10.8.0.2/24 brd 10.8.0.255 scope global tun0 # confirm all traffic routes through the VPN philip@laptop:~$ curl ifconfig.me 203.0.113.42 ← your server's public IP # disconnect (daemon mode) philip@laptop:~$ sudo pkill openvpn

Running as a systemd service (always-on client)

linux client — systemd service
# copy the profile to /etc/openvpn/client/ philip@laptop:~$ sudo cp client1.ovpn /etc/openvpn/client/client1.conf # the service name is derived from the filename: client1.conf → openvpn-client@client1 philip@laptop:~$ sudo systemctl enable --now openvpn-client@client1 philip@laptop:~$ sudo systemctl status openvpn-client@client1 ● openvpn-client@client1.service - OpenVPN tunnel for client1 Active: active (running) # view live connection log philip@laptop:~$ sudo journalctl -u openvpn-client@client1 -f

NetworkManager GUI integration

linux — import .ovpn into NetworkManager
# install the NetworkManager OpenVPN plugin philip@laptop:~$ sudo apt install -y network-manager-openvpn-gnome # GNOME: Settings → Network → VPN → + → Import from file → select client1.ovpn # XFCE/KDE: use nm-connection-editor or the network applet # or import via nmcli (no GUI needed) philip@laptop:~$ nmcli connection import type openvpn file client1.ovpn Connection 'client1' (uuid) successfully added. # connect / disconnect via nmcli philip@laptop:~$ nmcli connection up client1 philip@laptop:~$ nmcli connection down client1
nmcli vs openvpn --config: NetworkManager is better for laptops that roam between networks — it handles reconnection automatically and integrates with the desktop's network switcher. The raw openvpn --config approach is better for servers or scripts where you want explicit control.

Windows — OpenVPN GUI Client

🪟
Windows 10 / 11 — OpenVPN Connect
openvpn.net/client · also available via winget
  1. Install OpenVPN Connect from openvpn.net/client or run winget install OpenVPNTechnologies.OpenVPNConnect. This is the official client — not the older "OpenVPN GUI" which is community-maintained and less polished.
  2. Import the profile. Open OpenVPN Connect → click Upload File → select your client1.ovpn. The profile appears in the list.
  3. Connect. Click the toggle next to the profile name. Windows may prompt for admin approval on first connect — this is normal (OpenVPN needs to add a route to the routing table).
  4. Verify. The tray icon turns green. Open a browser and check ifconfig.me — it should show your server's IP.
Alternative — OpenVPN GUI (community): the older openvpn.net/community-downloads package installs a lighter tray-icon app. Copy client1.ovpn to C:\Program Files\OpenVPN\config\, right-click the tray icon → Connect. Useful if you prefer a simpler interface or need to run multiple profiles simultaneously.

Windows CLI — for scripts and automation

Windows PowerShell — openvpn CLI
# run openvpn from PowerShell (as Administrator) PS> & "C:\Program Files\OpenVPN\bin\openvpn.exe" --config client1.ovpn # check the VPN interface appeared PS> Get-NetAdapter | Where-Object { $_.InterfaceDescription -like "*TAP*" -or $_.InterfaceDescription -like "*Wintun*" }

The .ovpn File — Full Anatomy

Understanding every directive in the .ovpn file lets you adapt it for split tunnelling, different ports, or stricter security without guessing.

Directive
What it does
client
Declares this is a client config (implies pull — accept pushed settings from server)
dev tun
tun = layer-3 tunnel (IP routing). Use tap only for layer-2 bridging (rare)
proto udp
Transport protocol. Change to tcp for port 443 firewall bypass
remote 203.0.113.42 1194
Server IP (or hostname) and port. Can repeat for multiple servers — client tries each in turn
resolv-retry infinite
Keep trying to resolve the hostname if DNS fails on startup — important for dynamic IP servers
nobind
Don't bind to a specific local port — use any available ephemeral port
persist-key
persist-tun
Keep the key and tun device across restarts (required when running as non-root after dropping privileges)
remote-cert-tls server
Important security setting. Verifies the server cert has the server flag — prevents a client cert from being used to impersonate the server
cipher AES-256-GCM
Data channel cipher. Must match (or be negotiable with) the server. AES-256-GCM is the recommended modern choice
auth SHA256
HMAC digest for packet authentication. SHA256 is the minimum; SHA512 is stronger
key-direction 1
TLS-auth key direction. Server uses 0, client uses 1 — they use different halves of the ta.key
verb 3
Log verbosity. 3 = normal. Increase to 6 for debugging connection issues; 0 for silent
<ca>...</ca>
Inline CA certificate — used to verify the server's identity
<cert>...</cert>
Inline client certificate — proves this client's identity to the server
<key>...</key>
Inline client private key — keep this file secret
<tls-auth>...</tls-auth>
Inline TLS-auth HMAC key — shared secret between all clients and the server

Common customisations

# Split tunnel — only route VPN subnet through tunnel, NOT all internet traffic # Replace the "redirect-gateway" pushed by the server with a specific route route-nopull # ignore all routes pushed by server route 10.8.0.0 255.255.255.0 # add only the VPN subnet route manually # Connect to a different server if the first is unreachable remote server1.example.com 1194 remote server2.example.com 1194 # tried if server1 fails remote-random # pick a random server from the list # Reconnect automatically on failure connect-retry 5 # retry every 5 seconds connect-retry-max 10 # give up after 10 attempts # Use a specific DNS server on the client (overrides server-pushed DNS) dhcp-option DNS 1.1.1.1 # Increase log verbosity for debugging verb 6

Verifying the OpenVPN Connection

linux client — connection checks
# tunnel interface should be up philip@laptop:~$ ip addr show tun0 inet 10.8.0.2/24 scope global tun0 # default route should go through tun0 (full tunnel) philip@laptop:~$ ip route | grep default default via 10.8.0.1 dev tun0 # public IP should be server's IP philip@laptop:~$ curl -s ifconfig.me 203.0.113.42 # check the server log to confirm this client connected root@server:~# grep "client1" /var/log/openvpn/openvpn.log | tail -5 client1/82.45.110.23:54123 MULTI: Learn: 10.8.0.2 -> client1/82.45.110.23:54123 client1/82.45.110.23:54123 Initialization Sequence Completed

Common Connection Problems

TLS handshake failed
Certificate mismatch, wrong key-direction, or remote-cert-tls failing because the server cert wasn't signed with the server flag.
Check client has key-direction 1 (server has 0). Confirm server cert was generated with sign-req server not sign-req client. Set verb 6 for detailed TLS error output.
AUTH_FAILED — certificate revoked
This client's certificate is on the server's CRL (Certificate Revocation List).
Issue a new certificate with easyrsa gen-req + sign-req client and distribute a new .ovpn profile.
Connects but no internet (full tunnel)
Server's iptables MASQUERADE rule is missing or targets the wrong interface, or IP forwarding is disabled.
On server: sysctl net.ipv4.ip_forward should be 1. Check iptables -t nat -L POSTROUTING for the MASQUERADE rule. Confirm the interface name matches.
Cannot connect on corporate Wi-Fi
UDP port 1194 is blocked. The whole point of TCP 443 mode.
Change proto udpproto tcp and remote ... 1194remote ... 443 in the .ovpn file. Update the server config and UFW rule to match.
Next — Chapter 7: Commercial VPN Clients. Self-hosted VPNs give you full control but your public IP is still your home or VPS IP. Chapter 7 covers installing ProtonVPN and Mullvad on Linux via their CLI clients, using them from the terminal, and running DNS leak tests to verify they're working correctly.