initial commit
This commit is contained in:
commit
d3bf08c523
|
|
@ -0,0 +1,107 @@
|
|||
# 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
|
||||
```bash
|
||||
sudo pacman -S openvpn oathtool socat libsecret
|
||||
```
|
||||
|
||||
### Sudo rule (no password prompt for openvpn)
|
||||
```bash
|
||||
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)
|
||||
```bash
|
||||
# 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
|
||||
|
||||
```bash
|
||||
# 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 — `y`↔`z` 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.
|
||||
|
|
@ -0,0 +1,78 @@
|
|||
#!/usr/bin/env bash
|
||||
# Connect to Sophos SSL VPN via openvpn management interface (same as NM)
|
||||
set -euo pipefail
|
||||
|
||||
VPN_USER="d-chrka"
|
||||
OVPN="/home/d-chrka@internal.lan/Downloads/sslvpn-fixed.ovpn"
|
||||
LOGFILE="/tmp/vpn-sophos.log"
|
||||
MGMT_SOCK="/tmp/vpn-mgmt-$$.sock"
|
||||
DNS_SERVER="172.21.20.201"
|
||||
DNS_SEARCH="krah-gruppe.de internal.lan krah.intranet.de hirsau.seuffer resistec.pri krahicenet.local"
|
||||
CERT_DIR="/home/chk/.local/share/networkmanagement/certificates/nm-openvpn"
|
||||
|
||||
PW=$(secret-tool lookup service sslvpn user "$VPN_USER")
|
||||
OTP_SECRET=$(secret-tool lookup service sslvpn-totp user "$VPN_USER")
|
||||
|
||||
# Wait for fresh OTP window (>20s remaining)
|
||||
while true; do
|
||||
REMAINING=$(( 30 - ($(date +%s) % 30) ))
|
||||
[ "$REMAINING" -gt 20 ] && break
|
||||
echo "Waiting for fresh OTP window (${REMAINING}s remaining)..."
|
||||
sleep $(( REMAINING + 1 ))
|
||||
done
|
||||
|
||||
OTP=$(oathtool --totp -b "$OTP_SECRET")
|
||||
echo "OTP generated, $(( 30 - ($(date +%s) % 30) ))s valid"
|
||||
|
||||
# Up-script: configure DNS once tun is up
|
||||
UPSCRIPT=$(mktemp /dev/shm/vpn-up-XXXXXX)
|
||||
cat > "$UPSCRIPT" << EOF
|
||||
#!/bin/bash
|
||||
DEV="\$1"
|
||||
resolvectl dns "\$DEV" $DNS_SERVER
|
||||
resolvectl domain "\$DEV" ~krah-gruppe.de ~internal.lan ~krah.intranet.de ~hirsau.seuffer ~resistec.pri ~krahicenet.local
|
||||
resolvectl default-route "\$DEV" no
|
||||
echo "DNS configured on \$DEV" >> "$LOGFILE"
|
||||
EOF
|
||||
chmod +x "$UPSCRIPT"
|
||||
|
||||
echo "Connecting..."
|
||||
sudo openvpn \
|
||||
--config "$OVPN" \
|
||||
--remote rcdro1.krah-gruppe.de 8443 udp \
|
||||
--cert "$CERT_DIR/sslvpn-fixed-cert.pem" \
|
||||
--key "$CERT_DIR/sslvpn-fixed-key.pem" \
|
||||
--auth-nocache \
|
||||
--management "$MGMT_SOCK" unix \
|
||||
--management-query-passwords \
|
||||
--auth-retry interact \
|
||||
--script-security 2 \
|
||||
--up "$UPSCRIPT" \
|
||||
--daemon vpn-sophos \
|
||||
--log "$LOGFILE"
|
||||
|
||||
# Feed credentials via management interface
|
||||
sleep 1
|
||||
(
|
||||
printf 'username "Auth" %s\n' "$VPN_USER"
|
||||
sleep 0.2
|
||||
printf 'password "Auth" "%s%s"\n' "$PW" "$OTP"
|
||||
sleep 2
|
||||
) | socat - UNIX-CONNECT:"$MGMT_SOCK" 2>/dev/null || true
|
||||
|
||||
# Wait for tun interface
|
||||
echo -n "Waiting for tunnel"
|
||||
for i in $(seq 1 30); do
|
||||
if ip link show tun0 &>/dev/null; then
|
||||
echo " connected."
|
||||
echo "Disconnect: ~/bin/vpn-disconnect.sh"
|
||||
rm -f "$UPSCRIPT"
|
||||
exit 0
|
||||
fi
|
||||
echo -n "."
|
||||
sleep 1
|
||||
done
|
||||
|
||||
rm -f "$UPSCRIPT" "$MGMT_SOCK"
|
||||
echo " failed. Log: sudo cat $LOGFILE"
|
||||
exit 1
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
#!/usr/bin/env bash
|
||||
# Disconnect Sophos SSL VPN
|
||||
sudo pkill -f "vpn-sophos" 2>/dev/null && echo "VPN disconnected." || echo "VPN was not running."
|
||||
Loading…
Reference in New Issue