Your Employer Chose AnyConnect. Your Linux Box Disagrees.
IT hands you a VPN. On Windows it’s fine — you double-click, it works, you move on. On Linux it’s a 200MB tarball with a GUI that crashes on Wayland, a service that fights NetworkManager, and a kernel module that breaks on every other kernel update.
Enter OpenConnect: an open-source client that speaks the same SSL VPN protocol as Cisco AnyConnect — plus Juniper Network Connect, Pulse Secure, Fortinet SSL VPN, Palo Alto GlobalProtect, and F5 BIG-IP. One tool, your whole graveyard of enterprise VPN software.
And if you’re building your own road-warrior VPN from scratch? There’s ocserv — the open-source server that any AnyConnect-compatible client can talk to, running on a $5 VPS on TCP port 443.
This is that guide.
What’s Actually on the Wire
AnyConnect’s SSL VPN uses Cisco’s DTLS-over-UDP or TLS-over-TCP fallback. When you connect to a Cisco ASA or FTD firewall, the exchange is:
- TLS handshake on port 443
- Server sends a cookie/token
- DTLS tunnel spins up on UDP 443 (if allowed)
- DNS and routing pushed down from server
OpenConnect reverse-engineered this protocol, then also added support for:
| Protocol | Server software | Client flag |
|---|---|---|
| Cisco AnyConnect / Secure Client | Cisco ASA, FTD, ISE | (default) |
| Juniper Network Connect / Pulse | Pulse Secure, Ivanti | --protocol=nc |
| Fortinet SSL VPN | FortiGate | --protocol=fortinet |
| Palo Alto GlobalProtect | PAN-OS | --protocol=gp |
| F5 BIG-IP | BIG-IP APM | --protocol=f5 |
| ocserv | ocserv (self-hosted) | (default) |
If your employer rotates between security vendors every 18 months, you’ll appreciate that --protocol flag.
Installing OpenConnect
Linux
# Debian/Ubuntusudo apt install openconnect network-manager-openconnect-gnome
# Fedora/RHELsudo dnf install openconnect NetworkManager-openconnect-gnome
# Archsudo pacman -S openconnect networkmanager-openconnectThe network-manager-openconnect-gnome package gives you the GUI integration — VPN shows up in your network settings like a normal connection.
macOS
brew install openconnectNo GUI integration on macOS, but the CLI is perfectly usable.
Windows
There’s an official OpenConnect-GUI project, but honestly this is mostly a Linux story. On Windows, the official Cisco client is fine. On Linux it’s not, which is why you’re reading this.
Connecting to a Corporate AnyConnect VPN
CLI — the simple case
sudo openconnect vpn.yourcompany.comIt prompts for username and password, negotiates the tunnel, and drops you into a read-eval loop. Ctrl+C disconnects. That’s it.
Scripted / headless
Password from stdin, sent via echo — useful for scripts:
echo "yourpassword" | sudo openconnect --user=jsmith --passwd-on-stdin vpn.yourcompany.comBackground mode with PID file for clean disconnects:
sudo openconnect \ --background \ --pid-file=/var/run/openconnect.pid \ --user=jsmith \ --passwd-on-stdin \ vpn.yourcompany.com <<< "yourpassword"
# Later, to disconnect:sudo kill $(cat /var/run/openconnect.pid)Put this in a script, and your CI runner or cron job can connect, do its thing, and clean up without leaving a tunnel hanging.
MFA: TOTP, Push, and RSA SecurID
This is where it gets interesting — or painful, depending on your setup.
TOTP (time-based OTP): Most deployments just ask for your password + OTP as two sequential prompts. OpenConnect handles this interactively. If you want to automate it, you need to pre-generate the OTP or use --token-mode=totp with a TOTP secret:
sudo openconnect \ --user=jsmith \ --token-mode=totp \ --token-secret=base32:YOURSECRETHERE \ vpn.yourcompany.comDuo / Okta push: Works interactively — OpenConnect relays the push prompt and you approve it on your phone. You cannot automate push without also automating your phone. No shame in that limit.
RSA SecurID: Supported via --token-mode=rsa if you have the token serial and seed. Most enterprise users have hardware tokens; if you’re using the RSA app, export the SDTID file and pass it with --token-secret=@/path/to/token.sdtid.
What doesn’t work: Posture checks. Cisco’s host scanning (checking whether your antivirus is updated, whether you’re on an approved OS) runs inside the official AnyConnect client. OpenConnect bypasses these entirely. This is either a feature or a policy violation depending on your employer’s mood.
NetworkManager Integration
If you installed the network-manager-openconnect-gnome package, you get a proper VPN entry in GNOME Settings or nm-connection-editor. Fill in the gateway, username, and certificate settings — it works like any other VPN type.
# Import via nmcli if you have an existing confignmcli connection import type openconnect file /path/to/vpn.ovpn
# Or add manuallynmcli connection add \ type vpn \ con-name "Work VPN" \ vpn-type openconnect \ -- vpn.data "gateway=vpn.yourcompany.com,username=jsmith"One note: there’s a persistent fight between openconnect and the vpnc-helper script that NetworkManager uses to push routes. If your DNS resolution breaks after connecting — which happens more often than it should — check /etc/resolv.conf and compare it to what the VPN server pushes. Sometimes you need to set vpn.dns-priority to a negative value to force VPN DNS to win:
nmcli connection modify "Work VPN" ipv4.dns-priority -42Split Tunneling
By default, the VPN server pushes a routing policy. On AnyConnect servers configured for full-tunnel, all your traffic goes through the VPN — including your Netflix stream, which your employer’s IT team is definitely logging and definitely judging.
To force split-tunneling client-side regardless of server policy:
sudo openconnect \ --no-dtls \ --script-tun \ --script '/usr/share/vpnc-scripts/vpnc-script' \ vpn.yourcompany.comOr more surgically, with a custom script that only routes specific subnets through the tunnel. OpenConnect calls $VPNC_SCRIPT with environment variables including INTERNAL_IP4_NETLIST — you can modify those routes however you like.
Running Your Own: ocserv
Here’s where this gets genuinely useful for home labbers. ocserv is the OpenConnect server — you run it, you control it, any AnyConnect-compatible client (including the official Cisco app on iOS/Android) connects to it.
Why this matters: it runs on TCP 443. Hotel WiFi that blocks UDP 1194 (OpenVPN) and UDP 51820 (WireGuard)? Doesn’t matter. To the network, your VPN looks like HTTPS traffic.
Install ocserv
# Debian/Ubuntusudo apt install ocserv
# From source on anything else# https://gitlab.com/openconnect/ocservConfigure ocserv
# /etc/ocserv/ocserv.conf
# Auth — start with local password file, move to RADIUS/PAM laterauth = "plain[passwd=/etc/ocserv/ocpasswd]"
# TCP and UDP listenerstcp-port = 443udp-port = 443
# TLS certificates (Let's Encrypt works fine)server-cert = /etc/letsencrypt/live/vpn.yourdomain.com/fullchain.pemserver-key = /etc/letsencrypt/live/vpn.yourdomain.com/privkey.pem
# Logginglog-level = 0
# Max clientsmax-clients = 10max-same-clients = 2
# IPv4 pool for tunnel clientsipv4-network = 192.168.99.0ipv4-netmask = 255.255.255.0
# DNS pushed to clientsdns = 1.1.1.1dns = 8.8.8.8
# Routes pushed to clients# Remove these to default to full-tunnelroute = 192.168.99.0/24
# Ping intervalkeepalive = 32400
# Compressioncompression = trueCreate users
# Add a user (prompts for password)sudo ocpasswd -c /etc/ocserv/ocpasswd yourusername
# Delete a usersudo ocpasswd -d yourusername -c /etc/ocserv/ocpasswdLet’s Encrypt cert
sudo certbot certonly --standalone -d vpn.yourdomain.com
# Post-renewal hook to reload ocservecho "systemctl reload ocserv" > /etc/letsencrypt/renewal-hooks/post/ocserv.shchmod +x /etc/letsencrypt/renewal-hooks/post/ocserv.shFirewall and NAT
# Allow the VPN portsudo ufw allow 443/tcpsudo ufw allow 443/udp
# Enable IP forwardingecho "net.ipv4.ip_forward=1" | sudo tee -a /etc/sysctl.confsudo sysctl -p
# NAT masquerade for VPN clients (replace eth0 with your interface)sudo iptables -t nat -A POSTROUTING -s 192.168.99.0/24 -o eth0 -j MASQUERADE
# Make it persistentsudo apt install iptables-persistentsudo netfilter-persistent saveStart and test
sudo systemctl enable --now ocservsudo systemctl status ocserv
# Connect from your Linux boxsudo openconnect vpn.yourdomain.comIf you have the Cisco AnyConnect app on your phone, it’ll also connect to your ocserv instance. It just works — same protocol.
ocserv with TOTP (MFA)
If you want MFA on your self-hosted server, ocserv supports TOTP natively via PAM or via ocserv-script:
sudo apt install libpam-oath oathtool# Switch auth to PAMauth = "pam[gid-min=1000]"Then configure PAM to require TOTP for the ocserv service. Details vary by distro, but the pam_oath module is the standard path.
ocserv vs WireGuard: When to Pick Which
WireGuard is faster, simpler to configure, and the right answer for green-field VPN setups where you control both ends. If you’re setting up a home lab VPN from scratch and your clients are on networks you don’t hate, use WireGuard.
ocserv wins when:
- You’re behind a restrictive network (hotel, corporate, airport) that blocks UDP
- Your clients include iOS/Android users who already have the Cisco app installed
- You need username/password auth without distributing key files
- You want compatibility with a heterogeneous mix of AnyConnect-compatible clients
The 443/TCP fallback is the killer feature. WireGuard over UDP is great until you’re on conference hotel WiFi that blocks everything except 80 and 443. ocserv laughs at that network.
Common Pitfalls
Certificate trust errors on connect:
# Accept a self-signed cert (don't do this in production)sudo openconnect --no-cert-check vpn.yourcompany.com
# Or pin the cert fingerprintsudo openconnect --servercert pin-sha256:BASE64HASH== vpn.yourcompany.comDNS leaks after connect:
Check resolvectl status — if your system resolver isn’t using the VPN-pushed DNS, set vpn.dns-priority to a negative number in NetworkManager or manually update /etc/resolv.conf.
Routing table conflicts:
ip route show before and after connecting. If you’re losing default route or existing routes, your VPN is pushing a full-tunnel config. Use --no-dtls and a custom vpnc-script to control what gets routed.
“Host unreachable” after reconnect:
ocserv assigns IPs from a pool and doesn’t always release cleanly on abrupt disconnects. Wait for the lease timeout or bump max-same-clients in ocserv.conf.
Verdict
Using a corporate AnyConnect VPN on Linux? Use OpenConnect. Install it, point it at your gateway, done. The NetworkManager plugin means you don’t have to fight the terminal every morning. The official Cisco client is fine if IT requires it — but OpenConnect usually isn’t detectable and handles MFA flows well enough for daily use.
Running your own road-warrior VPN? ocserv is the right call when you need TCP-443 compatibility and want AnyConnect protocol support for mixed clients. For everyone else — WireGuard.
AnyConnect itself? It’s fine on Windows. On Linux it’s a cargo cult install that occasionally breaks your kernel and ships a 200MB GUI for something that fundamentally needs three configuration values. You can do better.
Your 2 AM self trying to SSH into prod from airport WiFi will appreciate the ocserv port 443 choice. Guaranteed.