This commit is contained in:
@@ -1,11 +1,42 @@
|
|||||||
# Cistech Tunnel (VPN + SSH)
|
# Cistech Tunnel
|
||||||
|
|
||||||
- VPN: OpenConnect-SSO with noVNC for first-time SSO (port 6901)
|
OpenConnect-SSO VPN client running in a container with noVNC for browser-based access.
|
||||||
- SSH tunnels: forwards to 10.3.1.201 inside the VPN namespace
|
|
||||||
|
|
||||||
Usage
|
## Features
|
||||||
- Copy `.env.example` to `.env` and adjust values.
|
|
||||||
- Build and start:
|
- **OpenConnect-SSO**: Cisco AnyConnect VPN with SSO/SAML authentication
|
||||||
docker compose build
|
- **TOTP Support**: Automatic 2FA via keyring integration
|
||||||
docker compose up -d vpn ssh_tunnel
|
- **Auto-reconnect**: Automatically reconnects on disconnection
|
||||||
- First-time SSO: open http://<host>:6901 and complete login; then set `OC_SSO_ARGS=--browser-display-mode hidden` and restart `vpn`.
|
- **noVNC**: Browser-based VNC access on port 6902
|
||||||
|
- **NAT/Masquerade**: Routes traffic through VPN tunnel
|
||||||
|
- **Cloudflared**: Optional Cloudflare tunnel support
|
||||||
|
- **SSH Tunnels**: Optional SSH port forwarding
|
||||||
|
|
||||||
|
## Runtipi Installation
|
||||||
|
|
||||||
|
1. Install from the app store or custom repo
|
||||||
|
2. Configure the required environment variables
|
||||||
|
3. Start the app via Runtipi dashboard
|
||||||
|
|
||||||
|
## First-time SSO Login
|
||||||
|
|
||||||
|
1. Open noVNC at `http://<host>:6902`
|
||||||
|
2. Enter VNC password
|
||||||
|
3. Complete SSO login in the browser window
|
||||||
|
4. VPN will connect and auto-reconnect on disconnect
|
||||||
|
|
||||||
|
## Source Files
|
||||||
|
|
||||||
|
- `source/Dockerfile`: Container build file
|
||||||
|
- `source/entrypoint.sh`: Container entrypoint with auto-reconnect
|
||||||
|
|
||||||
|
## Environment Variables
|
||||||
|
|
||||||
|
| Variable | Required | Description |
|
||||||
|
|----------|----------|-------------|
|
||||||
|
| OC_URL | Yes | VPN server URL |
|
||||||
|
| OC_SERVERCERT | Yes | Server certificate pin |
|
||||||
|
| OC_USER | No | Username (enables hidden browser mode) |
|
||||||
|
| VNC_PASSWORD | Yes | noVNC access password |
|
||||||
|
| OC_TOTP_SECRET | No | TOTP secret for auto 2FA |
|
||||||
|
| NOVNC_PORT | No | noVNC port (default: 6901) |
|
||||||
|
|||||||
@@ -1,25 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "Cistech Tunnel",
|
|
||||||
"id": "cistech-tunnel",
|
|
||||||
"available": true,
|
|
||||||
"short_desc": "OpenConnect-SSO VPN + SSH forwards (noVNC)",
|
|
||||||
"author": "alexz",
|
|
||||||
"port": 6901,
|
|
||||||
"categories": ["networking", "utilities"],
|
|
||||||
"description": "OpenConnect-SSO VPN running in an isolated namespace with noVNC for first-time SSO and an SSH tunnel service for local forwards.",
|
|
||||||
"tipi_version": 1,
|
|
||||||
"version": "1.0.0",
|
|
||||||
"source": "https://git.alexzaw.dev/alexz/cistech-tunnel",
|
|
||||||
"exposable": true,
|
|
||||||
"dynamic_config": true,
|
|
||||||
"no_gui": false,
|
|
||||||
"form_fields": [
|
|
||||||
{ "label": "VPN URL", "type": "text", "env_variable": "OC_URL_A", "required": true, "default": "https://vpn.cistech.net/Employees" },
|
|
||||||
{ "label": "Server Cert Pin", "type": "text", "env_variable": "OC_SERVERCERT_A", "required": true, "default": "pin-sha256:HyHob3LiVmIp8ch9AzHJ9jMYqI43tO5N13oWeBLiZ/0=" },
|
|
||||||
{ "label": "Auth Group", "type": "text", "env_variable": "OC_AUTHGROUP_A", "required": false, "default": "" },
|
|
||||||
{ "label": "SSO Mode", "type": "text", "env_variable": "OC_SSO_ARGS_A", "required": true, "default": "--browser-display-mode shown" },
|
|
||||||
{ "label": "VNC Password", "type": "password", "env_variable": "VNC_PASS_A", "required": true, "default": "vpnSSO12" },
|
|
||||||
{ "label": "SSH Key Path", "type": "text", "env_variable": "SSH_KEY_PATH", "required": true, "default": "/home/alexz/.ssh/id_ed25519-lenovo" }
|
|
||||||
],
|
|
||||||
"supported_architectures": ["arm64", "amd64"]
|
|
||||||
}
|
|
||||||
@@ -1,67 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "Cistech Tunnel",
|
|
||||||
"id": "cistech-tunnel",
|
|
||||||
"available": true,
|
|
||||||
"short_desc": "OpenConnect-SSO VPN + SSH forwards (noVNC)",
|
|
||||||
"author": "alexz",
|
|
||||||
"port": 6901,
|
|
||||||
"categories": [
|
|
||||||
"utilities",
|
|
||||||
"network"
|
|
||||||
],
|
|
||||||
"description": "OpenConnect-SSO VPN running in an isolated namespace with noVNC for first-time SSO and an SSH tunnel service for local forwards.",
|
|
||||||
"tipi_version": 1,
|
|
||||||
"version": "1.0.0",
|
|
||||||
"source": "https://git.alexzaw.dev/alexz/cistech-tunnel",
|
|
||||||
"exposable": true,
|
|
||||||
"dynamic_config": true,
|
|
||||||
"no_gui": false,
|
|
||||||
"form_fields": [
|
|
||||||
{
|
|
||||||
"label": "VPN URL",
|
|
||||||
"type": "text",
|
|
||||||
"env_variable": "OC_URL",
|
|
||||||
"required": true,
|
|
||||||
"default": "https://vpn.cistech.net/Employees"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"label": "Server Cert Pin",
|
|
||||||
"type": "text",
|
|
||||||
"env_variable": "OC_SERVERCERT",
|
|
||||||
"required": true,
|
|
||||||
"default": "pin-sha256:HyHob3LiVmIp8ch9AzHJ9jMYqI43tO5N13oWeBLiZ/0="
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"label": "Auth Group",
|
|
||||||
"type": "text",
|
|
||||||
"env_variable": "OC_AUTHGROUP",
|
|
||||||
"required": false,
|
|
||||||
"default": ""
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"label": "SSO Mode",
|
|
||||||
"type": "text",
|
|
||||||
"env_variable": "OC_SSO_ARGS",
|
|
||||||
"required": true,
|
|
||||||
"default": "--browser-display-mode shown"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"label": "VNC Password",
|
|
||||||
"type": "password",
|
|
||||||
"env_variable": "VNC_PASSWORD",
|
|
||||||
"required": true,
|
|
||||||
"default": "vpnSSO12"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"label": "SSH Key Path",
|
|
||||||
"type": "text",
|
|
||||||
"env_variable": "SSH_KEY_PATH",
|
|
||||||
"required": true,
|
|
||||||
"default": "/home/alexz/.ssh/id_ed25519-lenovo"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"supported_architectures": [
|
|
||||||
"arm64",
|
|
||||||
"amd64"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
@@ -1,39 +0,0 @@
|
|||||||
{
|
|
||||||
"$schema": "https://schemas.runtipi.io/v2/dynamic-compose.json",
|
|
||||||
"schemaVersion": 2,
|
|
||||||
"services": [
|
|
||||||
{
|
|
||||||
"name": "vpn_a",
|
|
||||||
"image": "vpn-openconnect-sso:latest",
|
|
||||||
"isMain": true,
|
|
||||||
"internalPort": 6901,
|
|
||||||
"capAdd": ["NET_ADMIN"],
|
|
||||||
"devices": [
|
|
||||||
{ "hostPath": "/dev/net/tun", "containerPath": "/dev/net/tun" }
|
|
||||||
],
|
|
||||||
"environment": [
|
|
||||||
{ "key": "OC_URL", "value": "${OC_URL_A}" },
|
|
||||||
{ "key": "OC_SERVERCERT", "value": "${OC_SERVERCERT_A}" },
|
|
||||||
{ "key": "OC_AUTHGROUP", "value": "${OC_AUTHGROUP_A}" },
|
|
||||||
{ "key": "OC_INTERFACE", "value": "tun0" },
|
|
||||||
{ "key": "OC_SSO_ARGS", "value": "${OC_SSO_ARGS_A}" },
|
|
||||||
{ "key": "VNC_PASSWORD", "value": "${VNC_PASS_A}" },
|
|
||||||
{ "key": "NOVNC_PORT", "value": "6901" }
|
|
||||||
],
|
|
||||||
"volumes": [
|
|
||||||
{ "hostPath": "${APP_DATA_DIR}/data/vpn_a_state", "containerPath": "/root" }
|
|
||||||
],
|
|
||||||
"restartPolicy": "unless-stopped"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "ssh_tunnel",
|
|
||||||
"image": "alpine:3.20",
|
|
||||||
"networkMode": "service:vpn_a",
|
|
||||||
"volumes": [
|
|
||||||
{ "hostPath": "${SSH_KEY_PATH}", "containerPath": "/root/.ssh/id_ed25519-lenovo", "readOnly": true }
|
|
||||||
],
|
|
||||||
"command": "sh -lc \"apk add --no-cache openssh-client && exec ssh -N -i /root/.ssh/id_ed25519-lenovo -o StrictHostKeyChecking=no -o ServerAliveInterval=60 -o ExitOnForwardFailure=yes -L 127.0.0.1:8090:localhost:8090 -L 127.0.0.1:2001:localhost:2001 -L 127.0.0.1:36001:localhost:36001 zawa@10.3.1.201\"",
|
|
||||||
"restartPolicy": "unless-stopped"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
46
apps/cistech-tunnel/source/Dockerfile
Normal file
46
apps/cistech-tunnel/source/Dockerfile
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
FROM ubuntu:24.04
|
||||||
|
ENV DEBIAN_FRONTEND=noninteractive \
|
||||||
|
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.cistech.net/Employees" \
|
||||||
|
OC_SERVERCERT="pin-sha256:HyHob3LiVmIp8ch9AzHJ9jMYqI43tO5N13oWeBLiZ/0=" \
|
||||||
|
OC_USER="alex.zaw@cistech.net" \
|
||||||
|
OC_TOTP_SECRET="t6ypnjqvyx2yvw2l" \
|
||||||
|
VNC_PASSWORD="Az@83278327\$\$@@"
|
||||||
|
|
||||||
|
RUN apt-get update && apt-get install -y \
|
||||||
|
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 \
|
||||||
|
libpango-1.0-0 fonts-liberation \
|
||||||
|
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 \
|
||||||
|
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/*
|
||||||
|
|
||||||
|
# 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
|
||||||
|
|
||||||
|
# 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
|
||||||
|
EXPOSE 6901
|
||||||
|
ENTRYPOINT ["/entrypoint.sh"]
|
||||||
182
apps/cistech-tunnel/source/entrypoint.sh
Executable file
182
apps/cistech-tunnel/source/entrypoint.sh
Executable file
@@ -0,0 +1,182 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
: "${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 " 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"
|
||||||
|
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
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
FROM ubuntu:24.04
|
|
||||||
ENV QTWEBENGINE_DISABLE_SANDBOX=1
|
|
||||||
ENV QTWEBENGINE_CHROMIUM_FLAGS="--no-sandbox --disable-gpu"
|
|
||||||
ENV DEBIAN_FRONTEND=noninteractive \
|
|
||||||
PLAYWRIGHT_BROWSERS_PATH=/ms-playwright \
|
|
||||||
VIRTUAL_ENV=/opt/venv \
|
|
||||||
PATH=/opt/venv/bin:$PATH
|
|
||||||
|
|
||||||
RUN apt-get update && apt-get install -y \
|
|
||||||
openconnect iproute2 iptables ca-certificates \
|
|
||||||
python3 python3-pip python3-venv \
|
|
||||||
vpnc-scripts curl \
|
|
||||||
x11vnc xvfb fluxbox novnc websockify \
|
|
||||||
xauth libnss3 libatk1.0-0 libatk-bridge2.0-0 \
|
|
||||||
libx11-6 libx11-xcb1 libxcomposite1 libxrandr2 libgbm1 libxdamage1 \
|
|
||||||
libpango-1.0-0 fonts-liberation \
|
|
||||||
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 \
|
|
||||||
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/*
|
|
||||||
|
|
||||||
RUN python3 -m venv "$VIRTUAL_ENV"
|
|
||||||
RUN pip install --no-cache-dir openconnect-sso playwright \
|
|
||||||
&& python -m playwright install --with-deps chromium
|
|
||||||
|
|
||||||
COPY entrypoint.sh /entrypoint.sh
|
|
||||||
RUN chmod +x /entrypoint.sh
|
|
||||||
|
|
||||||
EXPOSE 6901
|
|
||||||
ENTRYPOINT ["/entrypoint.sh"]
|
|
||||||
@@ -1,36 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
set -euo pipefail
|
|
||||||
|
|
||||||
: "${OC_URL:?OC_URL is required}"
|
|
||||||
: "${OC_SERVERCERT:?OC_SERVERCERT is required}"
|
|
||||||
|
|
||||||
NOVNC_PORT="${NOVNC_PORT:-6901}"
|
|
||||||
VNC_PASSWORD="${VNC_PASSWORD:-changeme}"
|
|
||||||
DISPLAY_ADDR="${DISPLAY:-:1}"
|
|
||||||
OC_INTERFACE="${OC_INTERFACE:-tun0}"
|
|
||||||
OC_SSO_ARGS_DEFAULT="--browser-display-mode shown"
|
|
||||||
|
|
||||||
if [[ "${OC_SSO_ARGS:-$OC_SSO_ARGS_DEFAULT}" == *"shown"* ]]; then
|
|
||||||
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 &
|
|
||||||
sleep 0.5
|
|
||||||
export DISPLAY="$DISPLAY_ADDR"
|
|
||||||
fluxbox >/tmp/fluxbox.log 2>&1 &
|
|
||||||
x11vnc -display "$DISPLAY_ADDR" -rfbauth /root/.vnc/pass -forever -shared -rfbport 5900 -quiet &
|
|
||||||
websockify --web=/usr/share/novnc/ 0.0.0.0:"$NOVNC_PORT" localhost:5900 >/tmp/websockify.log 2>&1 &
|
|
||||||
fi
|
|
||||||
|
|
||||||
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})
|
|
||||||
|
|
||||||
exec openconnect-sso -s "$OC_URL" ${OC_SSO_ARGS:-$OC_SSO_ARGS_DEFAULT} -- "${OPENCONNECT_CMD[@]}"
|
|
||||||
Reference in New Issue
Block a user