upload current sources
Some checks failed
Test / test (push) Has been cancelled

This commit is contained in:
2025-12-14 07:02:02 +00:00
commit cd78becb97
35 changed files with 1283 additions and 0 deletions

View File

@@ -0,0 +1,11 @@
# Required
OC_URL=https://vpn.cistech.net/Employees
OC_SERVERCERT=pin-sha256:HyHob3LiVmIp8ch9AzHJ9jMYqI43tO5N13oWeBLiZ/0=
# Optional
OC_AUTHGROUP=
OC_SSO_ARGS=--browser-display-mode shown
VNC_PASSWORD=vpnSSO12
NOVNC_PORT=6901
PUBLISH_ADDR=0.0.0.0
SSH_KEY_PATH=/home/alexz/.ssh/id_ed25519-lenovo

11
apps/cistech-tunnel/README.md Executable file
View File

@@ -0,0 +1,11 @@
# Cistech Tunnel (VPN + SSH)
- VPN: OpenConnect-SSO with noVNC for first-time SSO (port 6901)
- SSH tunnels: forwards to 10.3.1.201 inside the VPN namespace
Usage
- Copy `.env.example` to `.env` and adjust values.
- Build and start:
docker compose build
docker compose up -d vpn ssh_tunnel
- First-time SSO: open http://<host>:6901 and complete login; then set `OC_SSO_ARGS=--browser-display-mode hidden` and restart `vpn`.

25
apps/cistech-tunnel/config.json Executable file
View File

@@ -0,0 +1,25 @@
{
"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": false,
"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":"Az@83278327$$@@"},
{"label":"SSH Key Path","type":"text","env_variable":"SSH_KEY_PATH","required":true,"default":"/home/alexz/.ssh/id_ed25519-lenovo"}
],
"supported_architectures": ["arm64","amd64"]
}

View File

@@ -0,0 +1,25 @@
{
"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"]
}

View File

@@ -0,0 +1,67 @@
{
"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"
]
}

View File

@@ -0,0 +1,39 @@
{
"$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"
}
]
}

View File

@@ -0,0 +1,43 @@
services:
vpn:
build: ./vpn-openconnect-sso
container_name: cistech-vpn
cap_add:
- NET_ADMIN
devices:
- /dev/net/tun:/dev/net/tun
environment:
OC_URL: ${OC_URL}
OC_SERVERCERT: ${OC_SERVERCERT}
OC_AUTHGROUP: ${OC_AUTHGROUP}
OC_INTERFACE: tun0
OC_SSO_ARGS: ${OC_SSO_ARGS:- --browser-display-mode shown}
VNC_PASSWORD: ${VNC_PASSWORD:-changeme}
NOVNC_PORT: ${NOVNC_PORT:-6901}
ports:
- "${PUBLISH_ADDR:-0.0.0.0}:${NOVNC_PORT:-6901}:${NOVNC_PORT:-6901}"
volumes:
- vpn_state:/root
restart: unless-stopped
ssh_tunnel:
image: alpine:3.20
container_name: cistech-ssh-tunnel
network_mode: "service:vpn"
depends_on:
- vpn
volumes:
- ${SSH_KEY_PATH:-/home/alexz/.ssh/id_ed25519-lenovo}:/root/.ssh/id_ed25519-lenovo:ro
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 0.0.0.0:8090:localhost:8090 \
-L 0.0.0.0:2001:localhost:2001 \
-L 0.0.0.0:36001:localhost:36001 \
-L 0.0.0.0:36000:localhost:36000 \
zawa@10.3.1.201"
restart: unless-stopped
volumes:
vpn_state: {}

View File

@@ -0,0 +1,20 @@
# Dockerized OpenConnect-SSO with noVNC and Cloudflared
## Setup
1) Copy `.env.example` to `.env` and fill values (URLs, servercert pins, VNC passwords, cloudflared tokens).
2) First-time SSO: leave `OC_SSO_ARGS_*=--browser-display-mode visible`.
3) Build and start:
docker compose build
docker compose up -d vpn_a
# Open http://localhost:6901, complete SSO.
# After success, attach app containers or start cloudflared_a.
4) Optional: switch to headless after first login:
Set `OC_SSO_ARGS_*=--browser-display-mode hidden` (or `headless`) and restart the vpn service.
## Notes
- Each VPN runs in its own net namespace; routes from one cannot affect the other or the host.
- DNS from the VPN applies within its container namespace and attached services only.
- Persisted state lives in the named volumes mounted at `/root` (Playwright cache, configs).

Binary file not shown.

After

Width:  |  Height:  |  Size: 609 KiB

View File

@@ -0,0 +1,33 @@
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"]

View File

@@ -0,0 +1,36 @@
#!/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[@]}"