Go to file
Christian Kauer b8f7457791 upd readme 2026-03-22 16:21:09 +01:00
__pycache__ upd vpn clip 2026-03-22 16:12:00 +01:00
README.md upd readme 2026-03-22 16:21:09 +01:00
vpn-clip.py upd vpn clip 2026-03-22 16:12:00 +01:00
vpn-connect.sh initial commit 2026-03-15 21:14:29 +01:00
vpn-disconnect.sh initial commit 2026-03-15 21:14:29 +01:00
vpn-profiles.enc upd vpn clip 2026-03-22 16:12:00 +01:00

README.md

fastvpn — Automated Sophos SSL VPN Connect

Fully automated connect to Sophos SSL VPN with TOTP (no dialog, no manual input).

How it works

Sophos SSL VPN uses OpenVPN with certificate + username/password+OTP authentication. NetworkManager's normal flow requires an interactive KDE dialog which cannot be automated reliably on Wayland. Instead, vpn-connect.sh starts openvpn directly with a Unix management socket and feeds credentials programmatically via socat.

Prerequisites

Packages

sudo pacman -S openvpn oathtool socat libsecret

Sudo rule (no password prompt for openvpn)

sudo bash -c 'echo "YOUR_USER ALL=(ALL) NOPASSWD: /usr/bin/openvpn" > /etc/sudoers.d/vpn-openvpn && chmod 440 /etc/sudoers.d/vpn-openvpn'

Store credentials in keyring (once)

# VPN password
secret-tool store --label="Sophos VPN password" service sslvpn user YOUR_USER

# TOTP secret (base32 seed from your authenticator app)
secret-tool store --label="Sophos VPN TOTP" service sslvpn-totp user YOUR_USER

Required files

  • OpenVPN config: ~/Downloads/sslvpn-fixed.ovpn (exported from Sophos user portal)
  • Client certificate + key in NetworkManager certificate store: /home/chk/.local/share/networkmanagement/certificates/nm-openvpn/
    • sslvpn-fixed-cert.pem
    • sslvpn-fixed-key.pem

The .ovpn file has empty <cert> and <key> blocks — NM stores them separately. The scripts reference the NM certificate path directly.

Usage

# Connect
~/bin/vpn-connect.sh

# Disconnect
~/bin/vpn-disconnect.sh

# Check log
sudo cat /tmp/vpn-sophos.log

Configuration

Edit the variables at the top of vpn-connect.sh:

Variable Description
VPN_USER VPN username
OVPN Path to .ovpn config file
DNS_SERVER VPN DNS server IP
DNS_SEARCH Space-separated search domains
CERT_DIR Directory containing cert/key PEM files

Pitfalls & lessons learned

# in password breaks openvpn management interface

The openvpn management protocol interprets # as a comment character. Passwords containing # must be wrapped in double quotes:

password "Auth" "mypassword#123456"

Without quotes, everything after # is silently ignored → AUTH_FAILED.

ydotool / wtype don't work on KDE Wayland

  • ydotool sends US keycodes — yz swap, # becomes $ on DE layout
  • wtype requires zwp_virtual_keyboard protocol — not supported by KDE Plasma
  • xdotool works via XWayland but the KDE auth dialog runs natively on Wayland

NM passwd-file is ignored with challenge-response-flags=2

Sophos VPN profiles exported from the user portal set challenge-response-flags=2 in the NetworkManager connection. With this flag, NM ignores --passwd-file and waits for its interactive secret agent (KDE dialog). Removing the flag causes connection timeouts. The only reliable automation path is bypassing NM entirely.

OTP timing

The script waits for a fresh 30s TOTP window (>20s remaining) before generating the OTP to avoid expiry during the TLS handshake.

DNS requires routing domains (~ prefix)

resolvectl domain tun0 krah-gruppe.de sets a search domain but does NOT route DNS queries for that domain to tun0. The ~ prefix is required:

resolvectl domain tun0 ~krah-gruppe.de ~internal.lan ...

VPN network icon does not show connected state

Since openvpn is started directly (not via NM), the NetworkManager applet in the system tray does not reflect the VPN state. Functionally everything works. To check: ip link show tun0 or sudo cat /tmp/vpn-sophos.log.

Account lockout

Sophos locks the account after several failed AUTH attempts. Wait ~5 minutes before retrying after multiple failures.


vpn-clip.py — GUI Clipboard Tool

PyQt6 tool to manage VPN profiles (password + TOTP) and copy credentials to the Wayland clipboard. Useful when vpn-connect.sh is not an option (e.g. manual OpenVPN clients, other VPN systems).

Prerequisites

# PyQt6 (usually already present on KDE Plasma)
sudo pacman -S python-pyqt6

# oathtool and wl-clipboard (wl-copy) — already needed by vpn-connect.sh
sudo pacman -S oath-toolkit wl-clipboard

# Required: encrypt/decrypt stored profiles
sudo pacman -S python-cryptography

python-cryptography is required. Without it, profiles encrypted on another machine cannot be decrypted. A warning banner is shown in the UI when the package is missing.

Usage

python3 /path/to/fastvpn/vpn-clip.py
  • First run: no profiles file exists → prompted to set a master password, then immediately asked to create the first profile.
  • Subsequent runs: enter master password to decrypt and load profiles.
  • Select profile from dropdown.
  • Click PW+OTP kopieren to concatenate password + current TOTP and pipe it to wl-copy. If no OTP secret is set, only the password is copied.
  • The timer label shows seconds remaining in the current 30s TOTP window (turns red below 8s — consider waiting for the next window).
  • Click Profil bearbeiten to open the profile manager (add / edit / delete).

Profile storage

Profiles are stored in vpn-profiles.enc next to the script.

With cryptography installed the file layout is:

[2 bytes: salt length] [16 bytes: random salt] [Fernet token]

Key derivation: PBKDF2-HMAC-SHA256, 480 000 iterations, 32-byte key.

Installation as desktop app

To make vpn-clip.py appear in the application launcher and allow pinning to the taskbar:

# 1. Make executable
chmod +x /path/to/fastvpn/vpn-clip.py

# 2. Create .desktop entry  (adjust Exec= path)
cat > ~/.local/share/applications/vpn-clip.desktop << 'EOF'
[Desktop Entry]
Version=1.0
Type=Application
Name=VPN Clip
Comment=VPN password+OTP clipboard tool
Exec=/path/to/fastvpn/vpn-clip.py
Icon=network-vpn
Terminal=false
Categories=Network;Security;Utility;
Keywords=vpn;otp;password;clipboard;
StartupNotify=true
EOF

# 3. Refresh launcher database
update-desktop-database ~/.local/share/applications/

After step 3 the app appears under Network / Utilities in the start menu. Right-click the icon → Pin to taskbar (KDE: "Add to panel").

To use a custom icon instead of the system network-vpn icon, place a PNG at ~/.local/share/icons/vpn-clip.png and set Icon=vpn-clip in the .desktop file.

Pitfalls (vpn-clip)

cryptography not on PATH / wrong Python pacman -S python-cryptography installs for the system Python. If you run the script with a venv or a different Python binary the package may not be found and the fallback kicks in silently — check the warning banner in the UI.

wl-copy requires a running Wayland session Running the script over SSH without a forwarded Wayland socket will make wl-copy fail. The error is shown in a dialog box.

OTP secret format oathtool --totp -b expects a base32-encoded secret (the "seed" shown by most authenticator apps as a QR code alternative). Spaces in the secret are fine; oathtool ignores them.

Password + OTP concatenation The tool concatenates password and OTP with no separator (e.g. hunter2123456). Sophos and most other SSL VPN gateways expect exactly this format in the password field. If your gateway uses a different format, edit _copy() in the script.