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
# 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)
# 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
# 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
- Install OpenVPN Connect from
openvpn.net/clientor runwinget install OpenVPNTechnologies.OpenVPNConnect. This is the official client — not the older "OpenVPN GUI" which is community-maintained and less polished. - Import the profile. Open OpenVPN Connect → click Upload File → select your
client1.ovpn. The profile appears in the list. - 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).
- 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
# 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 bypassremote 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
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
# 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 udp → proto tcp and remote ... 1194 → remote ... 443 in the .ovpn file. Update the server config and UFW rule to match.