Created
February 10, 2025 17:33
-
-
Save numpde/e7f264c2c0ff353bf263e5f53a7680ba to your computer and use it in GitHub Desktop.
Sets up a tray icon to connect to the ETHZ VPN
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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