Skip to content

Instantly share code, notes, and snippets.

@numpde
Created February 10, 2025 17:33
Show Gist options
  • Save numpde/e7f264c2c0ff353bf263e5f53a7680ba to your computer and use it in GitHub Desktop.
Save numpde/e7f264c2c0ff353bf263e5f53a7680ba to your computer and use it in GitHub Desktop.
Sets up a tray icon to connect to the ETHZ VPN
#!/bin/bash
set -euo pipefail
LOGIN_NAME="[email protected]"
GENERAL_PASSWORD=''
OTP_SECRET="..."
HOST="sslvpn.ethz.ch"
OPTS=""
export GDK_BACKEND=x11 # Ensure yad works on Wayland
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
ICON_CONNECTED="$SCRIPT_DIR/vpn-on.png"
ICON_DISCONNECTED="$SCRIPT_DIR/vpn-off.png"
# Function to check if ETH Zurich VPN is active
is_vpn_active() {
ip link show tun0 &>/dev/null && ip -4 addr show tun0 | grep -q "inet 10\.5\."
}
# Test external connectivity
is_vpn_reachable() {
ping -c 1 -W 2 8.8.8.8 &>/dev/null
}
# Start VPN function
start_vpn() {
echo "Attempting to start VPN..." > /dev/tty
(echo "$GENERAL_PASSWORD"; oathtool -b --totp "$OTP_SECRET"; sleep 1) | sudo /usr/sbin/openconnect --useragent=AnyConnect -g student-net "$HOST" --passwd-on-stdin -u "$LOGIN_NAME" $OPTS &
echo "Started openconnect..."
}
# Stop VPN function
stop_vpn() {
echo "Stopping ETH Zurich VPN..." > /dev/tty
VPN_PIDS=$(pgrep -f "openconnect .* $HOST") || true
if [[ -n "$VPN_PIDS" ]]; then
echo "Stopping OpenConnect processes (PIDs: $VPN_PIDS)..." > /dev/tty
sudo kill $VPN_PIDS
wait $VPN_PIDS 2>/dev/null || true
else
echo "No active ETH Zurich VPN connection found." > /dev/tty
fi
if ip link show tun0 &>/dev/null; then
echo "Bringing down tun0 interface..." > /dev/tty
sudo ip link set tun0 down || true
fi
echo "VPN Disconnected." > /dev/tty
}
# If script is called with "start" or "stop", handle VPN directly
if [[ $# -gt 0 ]]; then
case "$1" in
start) start_vpn; exit 0 ;;
stop) stop_vpn; exit 0 ;;
*) echo "Usage: $0 [start|stop]"; exit 1 ;;
esac
fi
# Ensure yad is installed
if ! command -v yad &>/dev/null; then
echo "Error: 'yad' is not installed. Install it with: sudo apt install yad"
exit 1
fi
# Cleanup function to remove tray icon on exit
cleanup() {
pkill --parent $$ -f "yad --notification" || true
}
trap cleanup EXIT
PREV_STATE=""
CURRENT_STATE="?"
while :; do
T=`date +%T`
if ! is_vpn_active || ! is_vpn_reachable; then
echo "VPN status ($T): disconnected."
ICON=$ICON_DISCONNECTED
TOOLTIP="VPN Disconnected"
CURRENT_STATE="disconnected"
ACTION="start"
else
echo "VPN status ($T): connected."
ICON=$ICON_CONNECTED
TOOLTIP="VPN Connected (ETH Zurich)"
CURRENT_STATE="connected"
ACTION="stop"
fi
# Only update the tray icon if the VPN state has changed
if [[ "$CURRENT_STATE" != "$PREV_STATE" ]]; then
echo "State changed: Updating tray icon..."
# Kill only yad instances launched by this script
pkill --parent $$ -f "yad --notification" || true
# Clicking the icon toggles VPN state by calling this script with "start" or "stop"
yad --notification --image="$ICON" --text="$TOOLTIP" --command="bash $0 $ACTION" &
fi
PREV_STATE="$CURRENT_STATE"
sleep 2
done
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment