diff --git a/apps/cistech-tunnel/docker-compose.json b/apps/cistech-tunnel/docker-compose.json index 1247e8a..d69aa3b 100755 --- a/apps/cistech-tunnel/docker-compose.json +++ b/apps/cistech-tunnel/docker-compose.json @@ -20,8 +20,7 @@ "volumes": [ { "hostPath": "${APP_DATA_DIR}/data", "containerPath": "/root" }, { "hostPath": "${APP_DATA_DIR}", "containerPath": "/runtime" }, - { "hostPath": "/etc/runtipi/repos/runtipi/apps/cistech-tunnel/shared", "containerPath": "/shared" }, - { "hostPath": "/etc/runtipi/repos/runtipi/apps/cistech-tunnel/shared/entrypoint.sh", "containerPath": "/entrypoint.sh", "readOnly": true } + { "hostPath": "/etc/runtipi/repos/runtipi/apps/cistech-tunnel/shared", "containerPath": "/shared" } ] } ] diff --git a/apps/cistech-tunnel/shared/entrypoint.sh b/apps/cistech-tunnel/shared/entrypoint.sh deleted file mode 100644 index 6eac090..0000000 --- a/apps/cistech-tunnel/shared/entrypoint.sh +++ /dev/null @@ -1,224 +0,0 @@ -#!/usr/bin/env bash -set -euo pipefail - -: "${OC_URL:?OC_URL required}" - -# Auto-fetch server certificate pin if not provided -get_server_cert_pin() { - local url="$1" - local host=$(echo "$url" | sed -E 's|https?://([^/:]+).*|\1|') - local port=443 - - echo "Fetching certificate pin from $host:$port..." >&2 - - # Get certificate and compute pin-sha256 - local pin=$(echo | openssl s_client -connect "$host:$port" -servername "$host" 2>/dev/null | \ - openssl x509 -pubkey -noout 2>/dev/null | \ - openssl pkey -pubin -outform DER 2>/dev/null | \ - openssl dgst -sha256 -binary | \ - base64) - - if [[ -n "$pin" ]]; then - echo "pin-sha256:$pin" - else - echo "ERROR: Failed to fetch certificate from $host" >&2 - return 1 - fi -} - -# Get or fetch OC_SERVERCERT -if [[ -z "${OC_SERVERCERT:-}" ]]; then - OC_SERVERCERT=$(get_server_cert_pin "$OC_URL") - echo "Auto-detected server cert: $OC_SERVERCERT" -fi - -NOVNC_PORT="${NOVNC_PORT:-6901}" -VNC_PASSWORD="${VNC_PASSWORD:-changeme}" -DISPLAY_ADDR="${DISPLAY:-:1}" -OC_INTERFACE="${OC_INTERFACE:-tun0}" -OC_USER="${OC_USER:-}" -OC_PASSWORD="${OC_PASSWORD:-}" -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_PASSWORD="$OC_PASSWORD" -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..." - -# Set password for openconnect -export OPENCONNECT_PASSWORD="$OC_PASSWORD" - -# openconnect-sso reads TOTP from keyring automatically -# Pass password via stdin for SSO form if needed -if [[ -n "$OC_USER" && -n "$OC_PASSWORD" ]]; then - echo "$OC_PASSWORD" | openconnect-sso -s "$OC_URL" ${OC_SSO_ARGS:-$OC_SSO_ARGS_DEFAULT} -- $OPENCONNECT_CMD -elif [[ -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 " Cistech 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 - rm -f /tmp/.X1-lock /tmp/.X11-unix/X1 2>/dev/null || true - Xvfb "$DISPLAY_ADDR" -screen 0 ${XVFB_WxHxD:-1280x800x24} +extension RANDR & - pids+=($!) - sleep 0.5 - export DISPLAY="$DISPLAY_ADDR" - fluxbox >/tmp/fluxbox.log 2>&1 & - pids+=($!) - x11vnc -display "$DISPLAY_ADDR" -rfbauth /root/.vnc/pass -forever -shared -rfbport 5900 -quiet & - pids+=($!) - websockify --web=/usr/share/novnc/ 0.0.0.0:"$NOVNC_PORT" localhost:5900 >/tmp/websockify.log 2>&1 & - pids+=($!) -} - -start_vpn_terminal() { - # Start xterm with VPN script - sleep 1 - xterm -fa 'Monospace' -fs 11 -bg black -fg white -geometry 120x35+50+50 \ - -T "Cistech VPN" -e /tmp/vpn-runner.sh & - pids+=($!) -} - -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() { - ( - 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" - - # Trigger host routing service - if [ -d /runtime ]; then - touch /runtime/restart-routing - echo "Host routing trigger sent" - fi - break - fi - sleep 2 - done - ) & -} - -trap 'kill 0' INT TERM - -# Always start GUI now -setup_keyring -create_vpn_command -create_vpn_script -start_gui -start_vpn_terminal -setup_nat -start_cloudflared -start_ssh_tunnel - -wait