#!/bin/bash # Dover VPN Connection Script with Semi-Automation # Keyboard shortcuts (global, work anywhere): # Ctrl+1 - Type email # Ctrl+2 - Type password # Ctrl+3 - Type TOTP code # Ctrl+4 - Type email + Tab + password (combo) # Ctrl+5 - Full sequence: email + Tab + password + Tab + TOTP + Enter EMAIL="c-azaw@regoproducts.com" PASSWORD='Cj@83278327$$@@' TOTP_SECRET="rzqtqskdwkhz6zyr" VPN_HOST="vpn-ord1.dovercorp.com" TARGET_IP="10.35.33.230" # Parse command line arguments SKIP_AUTO_LOGIN=false while [[ $# -gt 0 ]]; do case $1 in -m|--menu) SKIP_AUTO_LOGIN=true shift ;; *) shift ;; esac done # Default /etc/hosts content DEFAULT_HOSTS='127.0.0.1 localhost ::1 localhost ip6-localhost ip6-loopback fe00::0 ip6-localnet ff00::0 ip6-mcastprefix ff02::1 ip6-allnodes ff02::2 ip6-allrouters 162.209.24.100 vpn-ord1.dovercorp.com 13.67.192.27 vpn.dovercorp.com' # Colors RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' CYAN='\033[0;36m' GRAY='\033[0;90m' NC='\033[0m' # Logging function with timestamp log() { local level="$1" local msg="$2" local timestamp=$(date '+%H:%M:%S') case $level in INFO) echo -e "${GRAY}[$timestamp]${NC} ${GREEN}[INFO]${NC} $msg" ;; WARN) echo -e "${GRAY}[$timestamp]${NC} ${YELLOW}[WARN]${NC} $msg" ;; ERROR) echo -e "${GRAY}[$timestamp]${NC} ${RED}[ERROR]${NC} $msg" ;; DEBUG) echo -e "${GRAY}[$timestamp]${NC} ${CYAN}[DEBUG]${NC} $msg" ;; CMD) echo -e "${GRAY}[$timestamp]${NC} ${GRAY}[CMD]${NC} $msg" ;; *) echo -e "${GRAY}[$timestamp]${NC} $msg" ;; esac } # Run command with logging run_cmd() { local desc="$1" shift log CMD "$desc: $*" output=$("$@" 2>&1) local rc=$? if [ -n "$output" ]; then echo "$output" | while IFS= read -r line; do echo -e " ${GRAY}│${NC} $line" done fi return $rc } echo -e "${CYAN}========================================${NC}" echo -e "${CYAN} Dover VPN Connection Script ${NC}" echo -e "${CYAN}========================================${NC}" echo "" # Function to get current TOTP get_totp() { oathtool --totp -b "$TOTP_SECRET" } # Function to detect VPN tunnel interface dynamically get_vpn_interface() { # Look for cscotun* or tun* interfaces that are UP local iface=$(ip link show | grep -oP '(cscotun\d+|tun\d+)(?=:.*UP)' | head -1) if [ -z "$iface" ]; then # Fallback: any cscotun interface iface=$(ip link show | grep -oP 'cscotun\d+' | head -1) fi echo "$iface" } # Function to get VM's IP on host-only network (for Windows routing) get_vm_hostonly_ip() { # Get IP from ens38 (host-only adapter) - could be any 192.168.x.x ip addr show ens38 2>/dev/null | grep -oP 'inet \K[\d.]+' | head -1 } # Function to get VPN tunnel IP get_vpn_ip() { local iface=$(get_vpn_interface) if [ -n "$iface" ]; then ip addr show "$iface" 2>/dev/null | grep -oP 'inet \K[\d.]+' | head -1 fi } # Start xbindkeys for keyboard macros start_xbindkeys() { log INFO "Starting keyboard macro listener (xbindkeys)..." # Kill any existing xbindkeys pkill xbindkeys 2>/dev/null sleep 0.5 # Start xbindkeys xbindkeys -f ~/.xbindkeysrc 2>/dev/null & XBINDKEYS_PID=$! if pgrep xbindkeys >/dev/null; then log DEBUG "xbindkeys started (PID: $(pgrep xbindkeys))" log INFO "Keyboard shortcuts active: Ctrl+1=email, Ctrl+2=pass, Ctrl+3=TOTP, Ctrl+4=combo, Ctrl+5=all" else log WARN "Failed to start xbindkeys" fi } # Stop xbindkeys stop_xbindkeys() { if pgrep xbindkeys >/dev/null; then log INFO "Stopping keyboard macro listener..." pkill xbindkeys 2>/dev/null log DEBUG "xbindkeys stopped" fi } # Kill all Cisco-related processes kill_cisco_processes() { log INFO "Killing all Cisco-related processes..." local killed=0 local my_pid=$$ local my_ppid=$(ps -o ppid= -p $$ | tr -d ' ') # Kill vpnui specifically (not just any process with "vpn" in name) for pid in $(pgrep -x "vpnui" 2>/dev/null); do if [ "$pid" != "$my_pid" ] && [ "$pid" != "$my_ppid" ]; then log DEBUG "Killing vpnui (PID $pid)" sudo kill -9 "$pid" 2>/dev/null && ((killed++)) fi done # Note: Don't kill vpnagentd - we need it running # Kill Cisco-specific processes by exact path for proc in cstub cscan acwebsecagent vpndownloader; do for pid in $(pgrep -x "$proc" 2>/dev/null); do log DEBUG "Killing $proc (PID $pid)" sudo kill -9 "$pid" 2>/dev/null && ((killed++)) done done # Kill openconnect (exact match) for pid in $(pgrep -x "openconnect" 2>/dev/null); do log DEBUG "Killing openconnect (PID $pid)" sudo kill -9 "$pid" 2>/dev/null && ((killed++)) done if [ $killed -eq 0 ]; then log INFO "No Cisco processes were running" else log INFO "Killed $killed process(es)" sleep 1 fi } # Function to setup iptables rules for forwarding setup_forwarding() { log INFO "Setting up IP forwarding rules for $TARGET_IP..." local vpn_iface=$(get_vpn_interface) if [ -z "$vpn_iface" ]; then log ERROR "No VPN interface found! Is VPN connected?" return 1 fi local vpn_ip=$(get_vpn_ip) local vm_ip=$(get_vm_hostonly_ip) log DEBUG "VPN interface: $vpn_iface" log DEBUG "VPN IP: $vpn_ip" log DEBUG "VM host-only IP: $vm_ip" # Enable IP forwarding run_cmd "Enabling IP forwarding" sudo sysctl -w net.ipv4.ip_forward=1 # NAT masquerade if ! sudo iptables -t nat -C POSTROUTING -d "$TARGET_IP" -j MASQUERADE 2>/dev/null; then run_cmd "Adding NAT masquerade rule" sudo iptables -t nat -A POSTROUTING -d "$TARGET_IP" -j MASQUERADE else log DEBUG "NAT masquerade rule already exists" fi # Forward rules if ! sudo iptables -C FORWARD -d "$TARGET_IP" -j ACCEPT 2>/dev/null; then run_cmd "Adding forward rule (to target)" sudo iptables -A FORWARD -d "$TARGET_IP" -j ACCEPT else log DEBUG "Forward rule (to target) already exists" fi if ! sudo iptables -C FORWARD -s "$TARGET_IP" -j ACCEPT 2>/dev/null; then run_cmd "Adding forward rule (from target)" sudo iptables -A FORWARD -s "$TARGET_IP" -j ACCEPT else log DEBUG "Forward rule (from target) already exists" fi # Cisco VPN chain bypass (insert at top if chain exists) if sudo iptables -L ciscovpn -n &>/dev/null; then if ! sudo iptables -C ciscovpn -o "$vpn_iface" -d "$TARGET_IP" -j ACCEPT 2>/dev/null; then run_cmd "Adding ciscovpn bypass (outbound)" sudo iptables -I ciscovpn 1 -o "$vpn_iface" -d "$TARGET_IP" -j ACCEPT else log DEBUG "Ciscovpn bypass (outbound) already exists" fi if ! sudo iptables -C ciscovpn -i "$vpn_iface" -s "$TARGET_IP" -j ACCEPT 2>/dev/null; then run_cmd "Adding ciscovpn bypass (inbound)" sudo iptables -I ciscovpn 2 -i "$vpn_iface" -s "$TARGET_IP" -j ACCEPT else log DEBUG "Ciscovpn bypass (inbound) already exists" fi else log DEBUG "ciscovpn chain does not exist (yet)" fi log INFO "Forwarding rules configured" echo "" log INFO "Windows route command (run as Admin):" echo -e " ${CYAN}route add $TARGET_IP mask 255.255.255.255 $vm_ip${NC}" echo "" } # Copy credentials to clipboard as alternative copy_to_clipboard() { log INFO "Starting clipboard credential rotation..." echo "" log INFO "Copying EMAIL to clipboard" echo "$EMAIL" | xclip -selection clipboard echo -e " ${CYAN}Email ready: $EMAIL${NC}" echo -e " Paste now (Ctrl+V), then press ${GREEN}Enter${NC} here for password..." read -r log INFO "Copying PASSWORD to clipboard" echo "$PASSWORD" | xclip -selection clipboard echo -e " ${CYAN}Password ready${NC}" echo -e " Paste now (Ctrl+V), then press ${GREEN}Enter${NC} here for TOTP..." read -r TOTP=$(get_totp) log INFO "Copying TOTP to clipboard" echo "$TOTP" | xclip -selection clipboard echo -e " ${CYAN}TOTP ready: $TOTP${NC}" echo -e " Paste now (Ctrl+V)" } # Print current TOTP with countdown show_totp() { log INFO "Starting live TOTP display (Ctrl+C to stop)" echo "" while true; do TOTP=$(get_totp) SECONDS_LEFT=$((30 - ($(date +%s) % 30))) echo -ne "\r ${CYAN}Current TOTP:${NC} ${GREEN}$TOTP${NC} (expires in ${YELLOW}${SECONDS_LEFT}s${NC}) " sleep 1 done } # Show network status show_network_status() { log INFO "Current network status:" # VM IPs echo "" log DEBUG "VM Network Interfaces:" ip -4 addr show | grep -E "inet |^[0-9]+:" | while IFS= read -r line; do echo -e " ${GRAY}│${NC} $line" done # VPN status echo "" local vpn_iface=$(get_vpn_interface) if [ -n "$vpn_iface" ]; then local vpn_ip=$(get_vpn_ip) log INFO "VPN Status: ${GREEN}CONNECTED${NC}" log DEBUG " Interface: $vpn_iface" log DEBUG " VPN IP: $vpn_ip" else log WARN "VPN Status: ${RED}NOT CONNECTED${NC}" fi # Host-only IP for Windows local vm_ip=$(get_vm_hostonly_ip) if [ -n "$vm_ip" ]; then log DEBUG "Host-only IP (for Windows): $vm_ip" fi echo "" } # Main menu main_menu() { echo -e "${GREEN}Options:${NC}" echo -e " ${CYAN}1${NC} - Start Cisco AnyConnect (kill existing + launch)" echo -e " ${CYAN}2${NC} - Copy credentials to clipboard (one by one)" echo -e " ${CYAN}3${NC} - Show live TOTP" echo -e " ${CYAN}4${NC} - Setup IP forwarding rules only" echo -e " ${CYAN}5${NC} - Test connection to $TARGET_IP" echo -e " ${CYAN}6${NC} - Show network status" echo -e " ${CYAN}7${NC} - Kill all Cisco processes" echo -e " ${CYAN}8${NC} - Restart vpnagentd + test load_tun.sh" echo -e " ${CYAN}9${NC} - Edit /etc/hosts" echo -e " ${CYAN}0${NC} - Reset /etc/hosts to default" echo -e " ${CYAN}q${NC} - Quit" echo "" } # Restart vpnagentd and test load_tun restart_vpnagentd() { log INFO "Testing load_tun.sh..." /opt/cisco/secureclient/bin/load_tun.sh if [ $? -eq 0 ]; then log INFO "load_tun.sh: ${GREEN}OK${NC}" else log WARN "load_tun.sh: ${YELLOW}WARNING${NC}" fi log INFO "Restarting vpnagentd..." sudo pkill -9 vpnagentd 2>/dev/null sleep 1 # Clean up stale IPC socket rm -f /root/.cisco/hostscan/.libcsd.ipc 2>/dev/null sudo /opt/cisco/secureclient/bin/vpnagentd & sleep 2 if pgrep -x vpnagentd >/dev/null; then log INFO "vpnagentd: ${GREEN}RUNNING${NC}" else log ERROR "vpnagentd: ${RED}FAILED TO START${NC}" fi } # Edit /etc/hosts edit_hosts() { log INFO "Opening /etc/hosts in nano..." sudo nano /etc/hosts } # Reset /etc/hosts to default reset_hosts() { log INFO "Resetting /etc/hosts to default..." echo "$DEFAULT_HOSTS" | sudo tee /etc/hosts > /dev/null log INFO "/etc/hosts reset complete" log DEBUG "Current contents:" cat /etc/hosts | while IFS= read -r line; do echo -e " ${GRAY}│${NC} $line" done } # Check if VPN is already connected check_vpn_status() { local vpn_iface=$(get_vpn_interface) if [ -n "$vpn_iface" ]; then local vpn_ip=$(get_vpn_ip) log INFO "VPN is ${GREEN}CONNECTED${NC}" log DEBUG " Interface: $vpn_iface" log DEBUG " VPN IP: $vpn_ip" return 0 else log WARN "VPN is ${RED}NOT CONNECTED${NC}" return 1 fi } # Focus on Cisco AnyConnect window focus_vpn_window() { local win_id=$(xdotool search --name "Cisco" 2>/dev/null | head -1) if [ -n "$win_id" ]; then xdotool windowactivate --sync "$win_id" 2>/dev/null sleep 0.3 return 0 fi return 1 } # Auto-login sequence using xdotool (no auto-focus, types to active window) auto_login() { log INFO "Starting automated login sequence..." # Wait for UI to fully load log DEBUG "Waiting 5s for UI to load..." sleep 5 # Press Enter to initiate connection log DEBUG "Pressing Enter to start connection..." xdotool key Return sleep 5 # Press Enter again (Connect button) log DEBUG "Pressing Enter for Connect..." xdotool key Return # Wait for SSO browser to open log DEBUG "Waiting for SSO browser to open..." sleep 7 # Type email log DEBUG "Typing email..." xdotool type --delay 50 "$EMAIL" xdotool key Return sleep 5 # Type password log DEBUG "Typing password..." xdotool type --delay 50 "$PASSWORD" xdotool key Return sleep 5 # Type TOTP log DEBUG "Typing TOTP..." local totp=$(oathtool --totp -b "$TOTP_SECRET") log DEBUG "TOTP: $totp" xdotool type --delay 50 "$totp" xdotool key Return sleep 5 # Extra enters for any confirmation dialogs log DEBUG "Sending confirmation enters..." xdotool key Return sleep 2 xdotool key Return sleep 5 xdotool key Return log INFO "Auto-login sequence completed" } # Start Cisco AnyConnect with logging start_anyconnect() { log INFO "=== Starting Cisco AnyConnect VPN (FULLY AUTOMATED) ===" echo "" # Kill existing processes first kill_cisco_processes # Start vpnagentd if not running if ! pgrep -x vpnagentd >/dev/null; then log INFO "Starting vpnagentd..." sudo /opt/cisco/secureclient/bin/vpnagentd & log DEBUG "Waiting for vpnagentd to initialize..." sleep 5 fi # Show credentials log INFO "Credentials for SSO login:" echo -e " ${CYAN}Email: $EMAIL${NC}" echo -e " ${CYAN}Password: $PASSWORD${NC}" TOTP=$(get_totp) echo -e " ${CYAN}TOTP: $TOTP${NC}" echo "" # Start AnyConnect with GPU/WebKit workarounds log INFO "Launching Cisco AnyConnect UI..." export GDK_BACKEND=x11 export WEBKIT_DISABLE_DMABUF_RENDERER=1 /opt/cisco/secureclient/bin/vpnui & VPNUI_PID=$! log DEBUG "vpnui started with PID $VPNUI_PID" # Run auto-login in background auto_login & AUTO_LOGIN_PID=$! log DEBUG "Auto-login started with PID $AUTO_LOGIN_PID" # Wait for VPN to connect log INFO "Waiting for VPN connection..." local wait_count=0 local max_wait=300 # 5 minutes while [ -z "$(get_vpn_interface)" ]; do sleep 2 ((wait_count+=2)) if [ $((wait_count % 10)) -eq 0 ]; then log DEBUG "Still waiting for VPN... (${wait_count}s)" fi if [ $wait_count -ge $max_wait ]; then log ERROR "Timeout waiting for VPN connection after ${max_wait}s" stop_xbindkeys return 1 fi done log INFO "VPN connected!" local vpn_iface=$(get_vpn_interface) local vpn_ip=$(get_vpn_ip) log DEBUG " Interface: $vpn_iface" log DEBUG " VPN IP: $vpn_ip" # Skip auto-routing - use menu option 4 to setup forwarding manually log INFO "VPN ready. Use menu option 4 to setup forwarding if needed." } # Main log INFO "Script started" echo "" # Check current status and auto-start unless --menu flag if [ "$SKIP_AUTO_LOGIN" = true ]; then log INFO "Menu mode - skipping auto-login" elif check_vpn_status; then echo "" log INFO "VPN already connected. Use menu option 4 to setup forwarding if needed." else echo "" log INFO "Auto-starting VPN connection..." echo "" start_anyconnect fi echo "" main_menu while true; do echo -ne "${CYAN}Choice: ${NC}" read -r choice case $choice in 1) echo "" start_anyconnect echo "" main_menu ;; 2) echo "" copy_to_clipboard echo "" main_menu ;; 3) echo "" show_totp echo "" main_menu ;; 4) echo "" setup_forwarding echo "" main_menu ;; 5) echo "" log INFO "Testing connection to $TARGET_IP..." if ping -c 3 "$TARGET_IP"; then log INFO "Connection test: ${GREEN}SUCCESS${NC}" else log ERROR "Connection test: ${RED}FAILED${NC}" fi echo "" main_menu ;; 6) echo "" show_network_status main_menu ;; 7) echo "" kill_cisco_processes echo "" main_menu ;; 8) echo "" restart_vpnagentd echo "" main_menu ;; 9) echo "" edit_hosts echo "" main_menu ;; 0) echo "" reset_hosts echo "" main_menu ;; q|Q) log INFO "Goodbye!" exit 0 ;; *) log ERROR "Invalid choice" ;; esac done