This commit is contained in:
@@ -1,12 +1,20 @@
|
||||
FROM ubuntu:24.04
|
||||
ENV DEBIAN_FRONTEND=noninteractive \
|
||||
VNC_PASSWORD="vpnpass" \
|
||||
NOVNC_PORT=8806
|
||||
PLAYWRIGHT_BROWSERS_PATH=/ms-playwright \
|
||||
VIRTUAL_ENV=/opt/venv \
|
||||
PATH=/opt/venv/bin:$PATH \
|
||||
QTWEBENGINE_DISABLE_SANDBOX=1 \
|
||||
QTWEBENGINE_CHROMIUM_FLAGS="--no-sandbox --disable-gpu" \
|
||||
OC_URL="https://vpn.rego.net/Employees" \
|
||||
OC_SERVERCERT="pin-sha256:HyHob3LiVmIp8ch9AzHJ9jMYqI43tO5N13oWeBLiZ/0=" \
|
||||
OC_USER="alex.zaw@rego.net" \
|
||||
OC_TOTP_SECRET="t6ypnjqvyx2yvw2l" \
|
||||
VNC_PASSWORD="Az@83278327\$\$@@"
|
||||
|
||||
# Install base dependencies - same as cistech-tunnel for noVNC
|
||||
RUN apt-get update && apt-get install -y \
|
||||
iproute2 iptables ca-certificates \
|
||||
curl wget openssh-client \
|
||||
openconnect iproute2 iptables ca-certificates \
|
||||
python3 python3-pip python3-venv \
|
||||
vpnc-scripts curl wget openssh-client \
|
||||
x11vnc xvfb fluxbox novnc websockify xterm nano oathtool \
|
||||
xauth libnss3 libatk1.0-0 libatk-bridge2.0-0 \
|
||||
libx11-6 libx11-xcb1 libxcomposite1 libxrandr2 libgbm1 libxdamage1 \
|
||||
@@ -14,25 +22,23 @@ RUN apt-get update && apt-get install -y \
|
||||
libegl1 libgl1 libopengl0 libdbus-1-3 libglib2.0-0 \
|
||||
libxkbcommon0 libxkbcommon-x11-0 \
|
||||
libxcb1 libxcb-cursor0 libxcb-icccm4 libxcb-image0 libxcb-keysyms1 libxcb-render0 libxcb-render-util0 libxcb-shm0 libxcb-xfixes0 libxcb-xinerama0 libxcb-randr0 libxcb-glx0 \
|
||||
xdotool xclip \
|
||||
libwebkit2gtk-4.1-0 libgtk-3-0 libxml2 libxss1 libcairo2 libgdk-pixbuf2.0-0 \
|
||||
sudo && rm -rf /var/lib/apt/lists/*
|
||||
|
||||
RUN apt-get update && (apt-get install -y libasound2t64 || apt-get install -y libasound2) && rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# Install Cisco Secure Client
|
||||
COPY cisco-secure-client-linux64-5.1.11.388-core-vpn-webdeploy-k9.sh /tmp/cisco-install.sh
|
||||
RUN chmod +x /tmp/cisco-install.sh && \
|
||||
/tmp/cisco-install.sh && \
|
||||
rm /tmp/cisco-install.sh
|
||||
# Python venv + Playwright + openconnect-sso
|
||||
RUN python3 -m venv "$VIRTUAL_ENV"
|
||||
RUN pip install --no-cache-dir openconnect-sso playwright keyring keyrings.alt && \
|
||||
python -m playwright install --with-deps chromium
|
||||
|
||||
# Copy hostscan files
|
||||
COPY hostscan /root/.cisco/hostscan
|
||||
RUN chmod -R 755 /root/.cisco/hostscan
|
||||
|
||||
# Copy VPN automation script
|
||||
COPY vpn-sso.sh /root/vpn-sso.sh
|
||||
RUN chmod +x /root/vpn-sso.sh
|
||||
# Cloudflared (amd64)
|
||||
RUN arch=$(dpkg --print-architecture) && \
|
||||
if [ "$arch" = "amd64" ]; then \
|
||||
curl -fsSL https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-amd64.deb -o /tmp/cloudflared.deb && \
|
||||
apt-get update && apt-get install -y /tmp/cloudflared.deb && rm -f /tmp/cloudflared.deb ; \
|
||||
else \
|
||||
echo "Install cloudflared manually for arch=$arch" && exit 1 ; \
|
||||
fi
|
||||
|
||||
COPY entrypoint.sh /entrypoint.sh
|
||||
RUN chmod +x /entrypoint.sh
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,12 +1,109 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
NOVNC_PORT="${NOVNC_PORT:-8806}"
|
||||
VNC_PASSWORD="${VNC_PASSWORD:-vpnpass}"
|
||||
: "${OC_URL:?OC_URL required}"
|
||||
: "${OC_SERVERCERT:?OC_SERVERCERT required}"
|
||||
|
||||
NOVNC_PORT="${NOVNC_PORT:-6901}"
|
||||
VNC_PASSWORD="${VNC_PASSWORD:-changeme}"
|
||||
DISPLAY_ADDR="${DISPLAY:-:1}"
|
||||
OC_INTERFACE="${OC_INTERFACE:-tun0}"
|
||||
OC_USER="${OC_USER:-}"
|
||||
OC_TOTP_SECRET="${OC_TOTP_SECRET:-}"
|
||||
|
||||
# Default to hidden browser if OC_USER is set
|
||||
if [[ -n "$OC_USER" ]]; then
|
||||
OC_SSO_ARGS_DEFAULT="--browser-display-mode hidden -u $OC_USER"
|
||||
else
|
||||
OC_SSO_ARGS_DEFAULT="--browser-display-mode shown"
|
||||
fi
|
||||
|
||||
CLOUDFLARED_MODE="${CLOUDFLARED_MODE:-off}" # off|token|config
|
||||
CLOUDFLARED_TOKEN="${CLOUDFLARED_TOKEN:-}"
|
||||
SSH_TUNNEL_ENABLE="${SSH_TUNNEL_ENABLE:-0}"
|
||||
SSH_DEST="${SSH_DEST:-zawa@10.3.1.201}"
|
||||
SSH_FORWARDS="${SSH_FORWARDS:-0.0.0.0:8090:localhost:8090}"
|
||||
|
||||
pids=()
|
||||
|
||||
# Setup keyring with TOTP secret if provided
|
||||
setup_keyring() {
|
||||
if [[ -n "$OC_TOTP_SECRET" && -n "$OC_USER" ]]; then
|
||||
python3 -c "
|
||||
import keyring
|
||||
keyring.set_password('openconnect-sso', 'totp/$OC_USER', '$OC_TOTP_SECRET'.upper())
|
||||
print('TOTP secret stored in keyring for $OC_USER')
|
||||
"
|
||||
fi
|
||||
}
|
||||
|
||||
# Create vpn_connect command in PATH and save environment
|
||||
create_vpn_command() {
|
||||
# Save environment variables to a file
|
||||
cat > /etc/vpn.env << ENVFILE
|
||||
export OC_URL="$OC_URL"
|
||||
export OC_SERVERCERT="$OC_SERVERCERT"
|
||||
export OC_INTERFACE="$OC_INTERFACE"
|
||||
export OC_USER="$OC_USER"
|
||||
export OC_SSO_ARGS_DEFAULT="$OC_SSO_ARGS_DEFAULT"
|
||||
export OC_SSO_ARGS="${OC_SSO_ARGS:-$OC_SSO_ARGS_DEFAULT}"
|
||||
export OC_AUTHGROUP="${OC_AUTHGROUP:-}"
|
||||
export OC_USERAGENT="${OC_USERAGENT:-}"
|
||||
export OC_EXTRA_ARGS="${OC_EXTRA_ARGS:-}"
|
||||
export OC_TOTP_SECRET="$OC_TOTP_SECRET"
|
||||
export DISPLAY=":1"
|
||||
ENVFILE
|
||||
|
||||
# Build openconnect command
|
||||
OPENCONNECT_CMD="/usr/sbin/openconnect --protocol=anyconnect --servercert $OC_SERVERCERT --interface $OC_INTERFACE --script /usr/share/vpnc-scripts/vpnc-script"
|
||||
[[ -n "${OC_AUTHGROUP:-}" ]] && OPENCONNECT_CMD+=" --authgroup $OC_AUTHGROUP"
|
||||
[[ -n "${OC_USERAGENT:-}" ]] && OPENCONNECT_CMD+=" --useragent $OC_USERAGENT"
|
||||
[[ -n "${OC_EXTRA_ARGS:-}" ]] && OPENCONNECT_CMD+=" ${OC_EXTRA_ARGS}"
|
||||
echo "export OPENCONNECT_CMD=\"$OPENCONNECT_CMD\"" >> /etc/vpn.env
|
||||
|
||||
cat > /usr/local/bin/vpn_connect << 'VPNCMD'
|
||||
#!/usr/bin/env bash
|
||||
source /etc/vpn.env
|
||||
echo "[$(date)] Starting VPN connection..."
|
||||
|
||||
# openconnect-sso reads TOTP from keyring automatically
|
||||
if [[ -n "$OC_USER" ]]; then
|
||||
echo "" | openconnect-sso -s "$OC_URL" ${OC_SSO_ARGS:-$OC_SSO_ARGS_DEFAULT} -- $OPENCONNECT_CMD
|
||||
else
|
||||
openconnect-sso -s "$OC_URL" ${OC_SSO_ARGS:-$OC_SSO_ARGS_DEFAULT} -- $OPENCONNECT_CMD
|
||||
fi
|
||||
VPNCMD
|
||||
chmod +x /usr/local/bin/vpn_connect
|
||||
}
|
||||
|
||||
# Create VPN runner script that keeps shell open
|
||||
create_vpn_script() {
|
||||
cat > /tmp/vpn-runner.sh << 'VPNSCRIPT'
|
||||
#!/usr/bin/env bash
|
||||
cd /root
|
||||
|
||||
echo "============================================"
|
||||
echo " Rego VPN Container"
|
||||
echo "============================================"
|
||||
echo ""
|
||||
echo "Commands:"
|
||||
echo " vpn_connect - Start/restart VPN connection"
|
||||
echo " Ctrl+C - Stop auto-reconnect and drop to shell"
|
||||
echo ""
|
||||
echo "Starting VPN with auto-reconnect..."
|
||||
echo ""
|
||||
|
||||
while true; do
|
||||
vpn_connect
|
||||
echo ""
|
||||
echo "[$(date)] VPN disconnected. Reconnecting in 10 seconds..."
|
||||
echo "(Press Ctrl+C to stop auto-reconnect)"
|
||||
sleep 10
|
||||
done
|
||||
VPNSCRIPT
|
||||
chmod +x /tmp/vpn-runner.sh
|
||||
}
|
||||
|
||||
start_gui() {
|
||||
mkdir -p /root/.vnc
|
||||
x11vnc -storepasswd "$VNC_PASSWORD" /root/.vnc/pass >/dev/null 2>&1 || true
|
||||
@@ -23,38 +120,63 @@ start_gui() {
|
||||
pids+=($!)
|
||||
}
|
||||
|
||||
start_vpnagent() {
|
||||
/opt/cisco/secureclient/bin/vpnagentd -execv_instance &
|
||||
start_vpn_terminal() {
|
||||
# Start xterm with VPN script
|
||||
sleep 1
|
||||
xterm -fa 'Monospace' -fs 11 -bg black -fg white -geometry 120x35+50+50 \
|
||||
-T "Rego VPN" -e /tmp/vpn-runner.sh &
|
||||
pids+=($!)
|
||||
}
|
||||
|
||||
setup_tun() {
|
||||
mkdir -p /dev/net
|
||||
if [ ! -c /dev/net/tun ]; then
|
||||
mknod /dev/net/tun c 10 200
|
||||
chmod 600 /dev/net/tun
|
||||
fi
|
||||
start_cloudflared() {
|
||||
case "$CLOUDFLARED_MODE" in
|
||||
token)
|
||||
[ -n "$CLOUDFLARED_TOKEN" ] && cloudflared tunnel run --token "$CLOUDFLARED_TOKEN" >/tmp/cloudflared.log 2>&1 &
|
||||
pids+=($!)
|
||||
;;
|
||||
config)
|
||||
cloudflared --no-autoupdate --config /etc/cloudflared/config.yml tunnel run >/tmp/cloudflared.log 2>&1 &
|
||||
pids+=($!)
|
||||
;;
|
||||
off|*)
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
start_ssh_tunnel() {
|
||||
[ "$SSH_TUNNEL_ENABLE" = "1" ] || return 0
|
||||
IFS=',' read -ra LINES <<< "$SSH_FORWARDS"
|
||||
args=(-N -o StrictHostKeyChecking=no -o ServerAliveInterval=60)
|
||||
for m in "${LINES[@]}"; do args+=(-L "$m"); done
|
||||
ssh "${args[@]}" "$SSH_DEST" &
|
||||
pids+=($!)
|
||||
}
|
||||
|
||||
setup_nat() {
|
||||
sysctl -w net.ipv4.ip_forward=1 >/dev/null 2>&1 || true
|
||||
}
|
||||
|
||||
start_terminal() {
|
||||
sleep 1
|
||||
xterm -fa 'Monospace' -fs 11 -bg black -fg white -geometry 120x35+50+50 \
|
||||
-T "Rego VPN" -e bash &
|
||||
pids+=($!)
|
||||
(
|
||||
for i in {1..60}; do
|
||||
if ip link show "$OC_INTERFACE" >/dev/null 2>&1; then
|
||||
sysctl -w net.ipv4.ip_forward=1 >/dev/null
|
||||
iptables -t nat -C POSTROUTING -o "$OC_INTERFACE" -j MASQUERADE 2>/dev/null || \
|
||||
iptables -t nat -A POSTROUTING -o "$OC_INTERFACE" -j MASQUERADE
|
||||
echo "NAT enabled on $OC_INTERFACE"
|
||||
break
|
||||
fi
|
||||
sleep 2
|
||||
done
|
||||
) &
|
||||
}
|
||||
|
||||
trap 'kill 0' INT TERM
|
||||
|
||||
echo "Starting Rego VPN container..."
|
||||
setup_tun
|
||||
setup_nat
|
||||
# Always start GUI now
|
||||
setup_keyring
|
||||
create_vpn_command
|
||||
create_vpn_script
|
||||
start_gui
|
||||
start_vpnagent
|
||||
start_terminal
|
||||
start_vpn_terminal
|
||||
setup_nat
|
||||
start_cloudflared
|
||||
start_ssh_tunnel
|
||||
|
||||
echo "All services started. noVNC available on port $NOVNC_PORT"
|
||||
wait
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,536 +0,0 @@
|
||||
#!/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='Ji@83278327$$@@'
|
||||
TOTP_SECRET="rzqtqskdwkhz6zyr"
|
||||
VPN_HOST="vpn-ord1.dovercorp.com"
|
||||
TARGET_IP="10.35.33.230"
|
||||
|
||||
# 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}q${NC} - Quit"
|
||||
echo ""
|
||||
}
|
||||
|
||||
# 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"
|
||||
|
||||
# Wait a bit for routes to stabilize
|
||||
log DEBUG "Waiting for routes to stabilize..."
|
||||
sleep 3
|
||||
|
||||
# Setup forwarding
|
||||
setup_forwarding
|
||||
|
||||
# Test connection
|
||||
log INFO "Testing connection to $TARGET_IP..."
|
||||
if ping -c 2 -W 3 "$TARGET_IP" &>/dev/null; then
|
||||
log INFO "Connection test: ${GREEN}SUCCESS${NC}"
|
||||
else
|
||||
log WARN "Connection test: ${RED}FAILED${NC} (may need manual route on Windows)"
|
||||
fi
|
||||
}
|
||||
|
||||
# Main
|
||||
log INFO "Script started"
|
||||
echo ""
|
||||
|
||||
# Check current status
|
||||
if check_vpn_status; then
|
||||
echo ""
|
||||
log INFO "VPN already connected. Setting up forwarding..."
|
||||
setup_forwarding
|
||||
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
|
||||
;;
|
||||
q|Q)
|
||||
log INFO "Goodbye!"
|
||||
exit 0
|
||||
;;
|
||||
*)
|
||||
log ERROR "Invalid choice"
|
||||
;;
|
||||
esac
|
||||
done
|
||||
Reference in New Issue
Block a user