zustand
This commit is contained in:
@@ -5,3 +5,9 @@ const password = process.argv[2];
|
|||||||
bcrypt.hash(password, 12).then(hash=>{
|
bcrypt.hash(password, 12).then(hash=>{
|
||||||
console.log(hash);
|
console.log(hash);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// node createPassword.js "geheim"
|
||||||
|
//docker exec AppServerAuth node -e "import bcrypt from 'bcrypt'; bcrypt.hash('abc', 12).then(h => console.log(h));"
|
||||||
|
|
||||||
|
// node cretePassword.js "geheim"
|
||||||
|
// $2b$12$Ld/e3h0ogkc1ELnAse9.dueckrJkUQXrvjy1mKKwCV5I61aS8Ge4G
|
||||||
@@ -0,0 +1,414 @@
|
|||||||
|
Ich habe einen weitergeleitete Applikation, bei dem der WSS momentan nicht durch kmmt.
|
||||||
|
|
||||||
|
|
||||||
|
https://tccontrol.server.schooltech.ch/
|
||||||
|
|
||||||
|
WebService.js:124 WebSocket connection to 'wss://tccontrol.server.schooltech.ch/echo' failed:
|
||||||
|
_connect @ WebService.js:124
|
||||||
|
(anonymous) @ WebService.js:179Understand this error
|
||||||
|
WebService.js:184 WebSocket error: Event {isTrusted: true, type: 'error', target: WebSocket, currentTarget: WebSocket, eventPhase: 2, …}
|
||||||
|
|
||||||
|
|
||||||
|
Aufbau des Systems: NGinx in docker container soll auf Tunnel weiter leiten. Service der erreicht werden soll, ist unter "https://thinkcentre.local:10010/" wunderbar erreichbar.
|
||||||
|
Von dort soll es über einen Tunnel gehen:
|
||||||
|
|
||||||
|
|
||||||
|
appRobot_Tunnel:
|
||||||
|
image: alpine:latest
|
||||||
|
container_name: appRobot_Tunnel
|
||||||
|
restart: unless-stopped
|
||||||
|
environment:
|
||||||
|
- TZ=Europe/Zurich
|
||||||
|
volumes:
|
||||||
|
- /home/chk/Documents/AppServerPortalUI/.ssh:/root/.ssh:ro
|
||||||
|
command: >
|
||||||
|
/bin/sh -c "
|
||||||
|
apk add --no-cache openssh-client autossh &&
|
||||||
|
autossh -M 0 -N -o StrictHostKeyChecking=no \
|
||||||
|
-i /root/.ssh/id_ed25519 \
|
||||||
|
-o StrictHostKeyChecking=no \
|
||||||
|
-o ServerAliveInterval=60 \
|
||||||
|
-o ServerAliveCountMax=10 \
|
||||||
|
-o ExitOnForwardFailure=yes \
|
||||||
|
-N \
|
||||||
|
-R 0.0.0.0:9780:appRobot_guacamole:8080 \
|
||||||
|
-R 0.0.0.0:9710:appRobot_Control:10010 \
|
||||||
|
-R 0.0.0.0:9703:portainer:9000 \
|
||||||
|
-R 0.0.0.0:9712:appRobot_Simulation:1003\
|
||||||
|
-R 0.0.0.0:9793:appRobot_Homing:2093 \
|
||||||
|
tunnel@server.schooltech.ch -p 2255
|
||||||
|
"
|
||||||
|
|
||||||
|
|
||||||
|
und dann vom nginx verarbeitet werden, denn der nginx ist von aussen per server.schooltech.ch erreichbar.
|
||||||
|
Dazu:
|
||||||
|
|
||||||
|
== nginx.conf ==
|
||||||
|
# /etc/nginx/conf.d/default.conf
|
||||||
|
server {
|
||||||
|
listen 80 default_server;
|
||||||
|
listen [::]:80 default_server;
|
||||||
|
|
||||||
|
# ACME HTTP-01 Challenge (Certbot)
|
||||||
|
location ^~ /.well-known/acme-challenge/ {
|
||||||
|
root /var/www/certbot;
|
||||||
|
default_type "text/plain; charset=utf-8";
|
||||||
|
}
|
||||||
|
|
||||||
|
# PortalUI root
|
||||||
|
root /usr/share/nginx/html;
|
||||||
|
index index.html;
|
||||||
|
|
||||||
|
# === API forwarding for Auth-Service ===
|
||||||
|
location /api/ {
|
||||||
|
proxy_pass http://appserverauth:3000/api/;
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
|
proxy_set_header X-Forwarded-Proto $scheme;
|
||||||
|
}
|
||||||
|
|
||||||
|
# === SPA routing (Portal UI) ===
|
||||||
|
location / {
|
||||||
|
try_files $uri $uri/ /index.html;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sowie die verschiedenen subdomains, im 50-subdomains-userA.conf, die erzeugt werden über
|
||||||
|
== connect-proxies.sh==
|
||||||
|
#!/bin/sh
|
||||||
|
# /docker-entrypoint.d/40-connect-proxies.sh
|
||||||
|
# Generiert pro Zeile in /etc/nginx/forwarding.conf:
|
||||||
|
# - HTTPS vHost (Proxy oder local static) NUR wenn Zertifikate existieren
|
||||||
|
# - optional 80->443 Redirect-Server (mit ACME-Ausnahme) bei http_behavior=redirect
|
||||||
|
# Läuft automatisch beim Containerstart (nginx:alpine EntryPoint).
|
||||||
|
|
||||||
|
set -eu
|
||||||
|
|
||||||
|
CONF_DIR="/etc/nginx/conf.d"
|
||||||
|
LIVE_DIR="/etc/letsencrypt/live"
|
||||||
|
FWD_FILE="/etc/nginx/forwarding.conf"
|
||||||
|
|
||||||
|
HTTPS_SUFFIX="-https.generated.conf"
|
||||||
|
HTTP_REDIRECT_SUFFIX="-http-redirect.generated.conf"
|
||||||
|
GLOBALS_FILE="$CONF_DIR/_globals.generated.conf"
|
||||||
|
|
||||||
|
echo "[connect-proxies] start …"
|
||||||
|
|
||||||
|
# 0) Forwarding-Datei vorhanden?
|
||||||
|
if [ ! -f "$FWD_FILE" ]; then
|
||||||
|
echo "[connect-proxies] WARN: $FWD_FILE fehlt – keine Proxies zu generieren."
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 1) Globale HTTP-Kontext-Map + Resolver (idempotent)
|
||||||
|
# >>> CHANGE: Resolver NICHT hardcoden. Dynamisch aus /etc/resolv.conf ableiten, Fallback 127.0.0.11
|
||||||
|
RESOLVERS="$(awk '/^nameserver/{print $2}' /etc/resolv.conf | xargs || true)"
|
||||||
|
if [ -n "${RESOLVERS:-}" ]; then
|
||||||
|
RESOLVER_LINE="resolver $RESOLVERS ipv6=off valid=30s;"
|
||||||
|
else
|
||||||
|
RESOLVER_LINE="resolver 127.0.0.11 ipv6=off valid=30s;"
|
||||||
|
fi
|
||||||
|
|
||||||
|
cat > "$GLOBALS_FILE" <<NGINX
|
||||||
|
# Automatisch generiert – nicht editieren
|
||||||
|
map \$http_upgrade \$connection_upgrade {
|
||||||
|
default upgrade;
|
||||||
|
'' close;
|
||||||
|
}
|
||||||
|
$RESOLVER_LINE
|
||||||
|
NGINX
|
||||||
|
# <<< END CHANGE
|
||||||
|
|
||||||
|
# 2) Alte generierte Confs entfernen
|
||||||
|
rm -f "$CONF_DIR/"*"$HTTPS_SUFFIX" 2>/dev/null || true
|
||||||
|
rm -f "$CONF_DIR/"*"$HTTP_REDIRECT_SUFFIX" 2>/dev/null || true
|
||||||
|
|
||||||
|
# 3) Zeilen verarbeiten
|
||||||
|
LINE_NO=0
|
||||||
|
while IFS= read -r RAW || [ -n "$RAW" ]; do
|
||||||
|
LINE_NO=$((LINE_NO+1))
|
||||||
|
# trim + CR entfernen
|
||||||
|
LINE="$(printf '%s' "$RAW" | tr -d '\r' | sed 's/^[[:space:]]*//; s/[[:space:]]*$//')"
|
||||||
|
[ -z "$LINE" ] && continue
|
||||||
|
case "$LINE" in \#*) continue;; esac
|
||||||
|
|
||||||
|
# Spalten splitten (mindestens 2 erforderlich)
|
||||||
|
set -- $LINE
|
||||||
|
SERVER_NAME="${1:-}"
|
||||||
|
UPSTREAM_URL="${2:-}"
|
||||||
|
HTTP_BEHAVIOR="${3:-redirect}"
|
||||||
|
WEBSOCKETS="${4:-false}"
|
||||||
|
VERIFY_TLS="${5:-false}"
|
||||||
|
CERT_DOMAIN="${6:-$SERVER_NAME}"
|
||||||
|
LISTEN_PORT="${7:-443}"
|
||||||
|
|
||||||
|
if [ -z "$SERVER_NAME" ] || [ -z "$UPSTREAM_URL" ]; then
|
||||||
|
echo "[connect-proxies] WARN(Line $LINE_NO): unvollständig -> $LINE"
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
FULLCHAIN="$LIVE_DIR/$CERT_DOMAIN/fullchain.pem"
|
||||||
|
PRIVKEY="$LIVE_DIR/$CERT_DOMAIN/privkey.pem"
|
||||||
|
|
||||||
|
HTTPS_OUT="$CONF_DIR/${SERVER_NAME}-p${LISTEN_PORT}${HTTPS_SUFFIX}"
|
||||||
|
HTTP_REDIRECT_OUT="$CONF_DIR/${SERVER_NAME}${HTTP_REDIRECT_SUFFIX}"
|
||||||
|
|
||||||
|
# >>> NEW: Upstream normalisieren (Trailing Slash entfernen) + DNS-Check vorbereiten
|
||||||
|
SANITIZED_UPSTREAM="${UPSTREAM_URL%/}"
|
||||||
|
DNS_OK="true"
|
||||||
|
SCHEME=""; HOST=""; PORT=""
|
||||||
|
|
||||||
|
if [ "$SANITIZED_UPSTREAM" != "local" ]; then
|
||||||
|
case "$SANITIZED_UPSTREAM" in
|
||||||
|
http://*)
|
||||||
|
URI="${SANITIZED_UPSTREAM#http://}"; SCHEME="http"; DEFAULT_PORT="80"
|
||||||
|
;;
|
||||||
|
https://*)
|
||||||
|
URI="${SANITIZED_UPSTREAM#https://}"; SCHEME="https"; DEFAULT_PORT="443"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "[connect-proxies] WARN(Line $LINE_NO): $SERVER_NAME upstream_url ungültig: '$UPSTREAM_URL' – überspringe."
|
||||||
|
continue
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
HOSTPORT="${URI%%/*}"
|
||||||
|
HOST="${HOSTPORT%%:*}"
|
||||||
|
PORT="${HOSTPORT#*:}"; [ "$PORT" = "$HOSTPORT" ] && PORT="$DEFAULT_PORT"
|
||||||
|
|
||||||
|
if command -v getent >/dev/null 2>&1; then
|
||||||
|
if ! getent hosts "$HOST" >/dev/null 2>&1; then
|
||||||
|
DNS_OK="false"
|
||||||
|
echo "[connect-proxies] [-] $SERVER_NAME: DNS nicht auflösbar ($HOST) – erzeuge 503-Placeholder statt Proxy."
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
DNS_OK="unknown"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
# <<< END NEW
|
||||||
|
|
||||||
|
if [ -f "$FULLCHAIN" ] && [ -f "$PRIVKEY" ]; then
|
||||||
|
echo "[connect-proxies] [+] $SERVER_NAME: Zertifikat OK (cert_domain=$CERT_DOMAIN). Erzeuge 443 …"
|
||||||
|
|
||||||
|
# Fall A: local (statisch, kein proxy_pass)
|
||||||
|
if [ "$SANITIZED_UPSTREAM" = "local" ]; then
|
||||||
|
cat > "$HTTPS_OUT" <<NGINX
|
||||||
|
# Auto-generated - 443 static site
|
||||||
|
server {
|
||||||
|
listen ${LISTEN_PORT} ssl http2;
|
||||||
|
listen [::]:${LISTEN_PORT} ssl http2;
|
||||||
|
server_name $SERVER_NAME;
|
||||||
|
|
||||||
|
ssl_certificate $FULLCHAIN;
|
||||||
|
ssl_certificate_key $PRIVKEY;
|
||||||
|
|
||||||
|
ssl_protocols TLSv1.2 TLSv1.3;
|
||||||
|
ssl_ciphers HIGH:!aNULL:!MD5;
|
||||||
|
|
||||||
|
root /usr/share/nginx/html;
|
||||||
|
index index.html;
|
||||||
|
|
||||||
|
location /api/ {
|
||||||
|
proxy_pass http://appserverauth:3000/api/;
|
||||||
|
|
||||||
|
proxy_set_header Host \$host;
|
||||||
|
proxy_set_header X-Real-IP \$remote_addr;
|
||||||
|
proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
|
||||||
|
proxy_set_header X-Forwarded-Proto \$scheme;
|
||||||
|
}
|
||||||
|
|
||||||
|
location / {
|
||||||
|
try_files \$uri \$uri/ /index.html;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
NGINX
|
||||||
|
|
||||||
|
else
|
||||||
|
# >>> NEW: Zwei Pfade – DNS_OK=false => Placeholder; sonst Proxy mit Laufzeit-Resolver
|
||||||
|
if [ "$DNS_OK" = "false" ]; then
|
||||||
|
# 443 Placeholder – keine Proxy-Verbindung, saubere 503
|
||||||
|
cat > "$HTTPS_OUT" <<NGINX
|
||||||
|
# Auto-generated - 443 placeholder (DNS failed)
|
||||||
|
server {
|
||||||
|
listen ${LISTEN_PORT} ssl http2;
|
||||||
|
listen [::]:${LISTEN_PORT} ssl http2;
|
||||||
|
server_name $SERVER_NAME;
|
||||||
|
|
||||||
|
ssl_certificate $FULLCHAIN;
|
||||||
|
ssl_certificate_key $PRIVKEY;
|
||||||
|
|
||||||
|
ssl_protocols TLSv1.2 TLSv1.3;
|
||||||
|
ssl_ciphers HIGH:!aNULL:!MD5;
|
||||||
|
|
||||||
|
location / {
|
||||||
|
default_type text/html;
|
||||||
|
return 503 "<!doctype html><html><head><meta charset='utf-8'><title>Service temporarily unavailable</title></head><body style='font-family:sans-serif;margin:3rem'><h1>\$server_name nicht erreichbar</h1><p>DNS-Auflösung fehlgeschlagen. Bitte später erneut versuchen.</p></body></html>";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
NGINX
|
||||||
|
else
|
||||||
|
# 443 Proxy – DNS ok/unknown: Laufzeit-Auflösung + freundlicher 503 bei Downstreams
|
||||||
|
cat > "$HTTPS_OUT" <<NGINX
|
||||||
|
# Auto-generated - 443 reverse proxy
|
||||||
|
server {
|
||||||
|
listen ${LISTEN_PORT} ssl http2;
|
||||||
|
listen [::]:${LISTEN_PORT} ssl http2;
|
||||||
|
server_name $SERVER_NAME;
|
||||||
|
|
||||||
|
ssl_certificate $FULLCHAIN;
|
||||||
|
ssl_certificate_key $PRIVKEY;
|
||||||
|
|
||||||
|
ssl_protocols TLSv1.2 TLSv1.3;
|
||||||
|
ssl_ciphers HIGH:!aNULL:!MD5;
|
||||||
|
|
||||||
|
# Fehler sauber abfangen und 503 liefern (statt rohe 502/504)
|
||||||
|
proxy_intercept_errors on;
|
||||||
|
error_page 502 503 504 = @service_down;
|
||||||
|
|
||||||
|
location / {
|
||||||
|
# >>> CHANGE: variable proxy_pass -> DNS zur Laufzeit (verhindert nginx -t Crash)
|
||||||
|
set \$target $SANITIZED_UPSTREAM;
|
||||||
|
proxy_pass \$target;
|
||||||
|
|
||||||
|
proxy_set_header Host \$host;
|
||||||
|
proxy_set_header X-Real-IP \$remote_addr;
|
||||||
|
proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
|
||||||
|
proxy_set_header X-Forwarded-Proto \$scheme;
|
||||||
|
|
||||||
|
proxy_http_version 1.1;
|
||||||
|
NGINX
|
||||||
|
|
||||||
|
if [ "$WEBSOCKETS" = "true" ]; then
|
||||||
|
cat >> "$HTTPS_OUT" <<'NGINX'
|
||||||
|
proxy_set_header Upgrade $http_upgrade;
|
||||||
|
proxy_set_header Connection $connection_upgrade;
|
||||||
|
NGINX
|
||||||
|
else
|
||||||
|
cat >> "$HTTPS_OUT" <<'NGINX'
|
||||||
|
proxy_set_header Upgrade "";
|
||||||
|
proxy_set_header Connection close;
|
||||||
|
NGINX
|
||||||
|
fi
|
||||||
|
|
||||||
|
case "$SANITIZED_UPSTREAM" in
|
||||||
|
https://*)
|
||||||
|
if [ "$VERIFY_TLS" = "true" ]; then
|
||||||
|
cat >> "$HTTPS_OUT" <<'NGINX'
|
||||||
|
proxy_ssl_verify on;
|
||||||
|
proxy_ssl_server_name on;
|
||||||
|
NGINX
|
||||||
|
else
|
||||||
|
cat >> "$HTTPS_OUT" <<'NGINX'
|
||||||
|
proxy_ssl_verify off;
|
||||||
|
proxy_ssl_server_name on;
|
||||||
|
NGINX
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
cat >> "$HTTPS_OUT" <<'NGINX'
|
||||||
|
client_max_body_size 50m;
|
||||||
|
proxy_connect_timeout 60s;
|
||||||
|
proxy_send_timeout 60s;
|
||||||
|
proxy_read_timeout 60s;
|
||||||
|
}
|
||||||
|
|
||||||
|
location @service_down {
|
||||||
|
default_type text/html;
|
||||||
|
return 503 "<!doctype html><html><head><meta charset='utf-8'><title>Service temporarily unavailable</title></head><body style='font-family:sans-serif;margin:3rem'><h1>$server_name nicht erreichbar</h1><p>Der Dienst ist momentan nicht verfügbar. Bitte später erneut versuchen.</p></body></html>";
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
NGINX
|
||||||
|
fi
|
||||||
|
# <<< END NEW
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 80->443 Redirect-Server nur, wenn gewünscht
|
||||||
|
if [ "$HTTP_BEHAVIOR" = "redirect" ]; then
|
||||||
|
cat > "$HTTP_REDIRECT_OUT" <<NGINX
|
||||||
|
# Auto-generated – 80->443 redirect for $SERVER_NAME
|
||||||
|
server {
|
||||||
|
listen 80;
|
||||||
|
listen [::]:80;
|
||||||
|
server_name $SERVER_NAME;
|
||||||
|
|
||||||
|
# ACME-Ausnahme
|
||||||
|
location ^~ /.well-known/acme-challenge/ {
|
||||||
|
root /var/www/certbot;
|
||||||
|
default_type "text/plain; charset=utf-8";
|
||||||
|
}
|
||||||
|
|
||||||
|
location / {
|
||||||
|
return 301 https://\$host\$request_uri;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
NGINX
|
||||||
|
else
|
||||||
|
# Sicherstellen, dass kein alter Redirect liegen bleibt
|
||||||
|
rm -f "$HTTP_REDIRECT_OUT" 2>/dev/null || true
|
||||||
|
fi
|
||||||
|
|
||||||
|
else
|
||||||
|
echo "[connect-proxies] [-] $SERVER_NAME: keine Zertifikate (cert_domain=$CERT_DOMAIN). Entferne evtl. alte Confs."
|
||||||
|
rm -f "$HTTPS_OUT" "$HTTP_REDIRECT_OUT" 2>/dev/null || true
|
||||||
|
fi
|
||||||
|
|
||||||
|
done < "$FWD_FILE"
|
||||||
|
|
||||||
|
echo "[connect-proxies] nginx -t …"
|
||||||
|
nginx -t
|
||||||
|
echo "[connect-proxies] done."
|
||||||
|
|
||||||
|
|
||||||
|
das connect proxies verwendet:
|
||||||
|
=== forwaring.conf ===
|
||||||
|
# server_name upstream_url http_behavior websockets verify_upstream_tls [cert_domain]
|
||||||
|
|
||||||
|
#fluidncRed.server.schooltech.ch http://appServer_TunnelHead:8120 redirect true false
|
||||||
|
|
||||||
|
# 444 → 8121 (WS/WSS)
|
||||||
|
# fluidncRedWs.server.schooltech.ch http://appServer_TunnelHead:8121 redirect true false fluidncRedWs.server.schooltech.ch 444
|
||||||
|
#server.schooltech.ch local static false false
|
||||||
|
server.schooltech.ch local redirect false false server.schooltech.ch 443
|
||||||
|
tcPortainer.server.schooltech.ch http://thinkcentre.local:9000 redirect true false
|
||||||
|
tcGuac.server.schooltech.ch http://thinkcentre.local:9000 redirect true false
|
||||||
|
|
||||||
|
#inf InformatiWeb ist per Tunnel angeschlossen. Soll auf 97xx Ports gehen
|
||||||
|
infPortainer.server.schooltech.ch http://appServer_TunnelHead:9903 redirect true false
|
||||||
|
infGuac.server.schooltech.ch http://appServer_TunnelHead:9980 redirect true false
|
||||||
|
|
||||||
|
#RP5 ist "Lokal" der Server
|
||||||
|
rp5Guac.server.schooltech.ch http://appServer_guacamole:8080 redirect true false
|
||||||
|
rp5Portainer.server.schooltech.ch http://portainer:9000 redirect true false
|
||||||
|
|
||||||
|
|
||||||
|
#RP3 ist Raspi für die Scara-Robots, per Tunnel angeschlossen. Er hat 81xx Ports am TunnelHead
|
||||||
|
rp3Portainer.server.schooltech.ch http://appServer_TunnelHead:8100 redirect true false
|
||||||
|
rp3Guac.server.schooltech.ch http://appServer_TunnelHead:8180 redirect true false
|
||||||
|
fluidncRed.server.schooltech.ch http://appServer_TunnelHead:8120 redirect true false
|
||||||
|
fluidncWhite.server.schooltech.ch https://appServer_TunnelHead:8104 redirect true false
|
||||||
|
|
||||||
|
# ThinkCentre ist ein MiniPC der neben dem einen Roboter steht. Hier sind die 97xx Ports zugewiesen
|
||||||
|
tcGuac.server.schooltech.ch http://appServer_TunnelHead:9780 redirect false false
|
||||||
|
tcPortainer.server.schooltech.ch http://appServer_TunnelHead:9703 redirect false false
|
||||||
|
tcSimulation.server.schooltech.ch https://appServer_TunnelHead:9712 redirect false false
|
||||||
|
#tcVideocontroller.server.schooltech.ch https://tcvideo:9443 redirect true false
|
||||||
|
robotHoming.server.schooltech.ch https://appServer_TunnelHead:9793 redirect false false
|
||||||
|
tcControl.server.schooltech.ch https://appServer_TunnelHead:9710 redirect false false
|
||||||
|
|
||||||
|
|
||||||
|
# Beispiel mit abweichendem Zertifikats-Ordner (Lineage-Suffix)
|
||||||
|
# tcGuac.server.schooltech.ch https://guac:8443 redirect true false server.schooltech.ch-0002
|
||||||
|
|
||||||
|
# Beispiel für WS auf port+1 (zwei Einträge, einer nur für WS-Endpunkt)
|
||||||
|
# wsApp.server.schooltech.ch https://wsapp:443 redirect true false
|
||||||
|
|
||||||
|
|
||||||
|
===============
|
||||||
|
|
||||||
|
Jetzt die Frage:
|
||||||
|
|
||||||
|
1) Siehst du, wie es aufgebaut ist? Siehst du, wie die adresse vom nginx weiter geleitet wird? Hast du fragen dazu?
|
||||||
|
Die weiterleitung läuft. ich sehe die WebPage. Nur der WSS kommt nicht durch
|
||||||
|
2) siehst du, woran das liegt, dass der WSS nicht durch kommt?
|
||||||
@@ -0,0 +1,358 @@
|
|||||||
|
die Authentifizierung von server.schooltech.ch funktioniert. Ich komme wie gewünscht nur mit aktivem
|
||||||
|
cookie rein.
|
||||||
|
|
||||||
|
# /etc/nginx/conf.d/default.conf
|
||||||
|
server {
|
||||||
|
listen 80 default_server;
|
||||||
|
listen [::]:80 default_server;
|
||||||
|
|
||||||
|
# ACME HTTP-01 Challenge (Certbot)
|
||||||
|
location ^~ /.well-known/acme-challenge/ {
|
||||||
|
root /var/www/certbot;
|
||||||
|
default_type "text/plain; charset=utf-8";
|
||||||
|
}
|
||||||
|
|
||||||
|
# PortalUI root
|
||||||
|
root /usr/share/nginx/html;
|
||||||
|
index index.html;
|
||||||
|
|
||||||
|
# === API forwarding for Auth-Service ===
|
||||||
|
location /api/ {
|
||||||
|
proxy_pass http://appserverauth:3000/api/;
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
|
proxy_set_header X-Forwarded-Proto $scheme;
|
||||||
|
}
|
||||||
|
|
||||||
|
# === SPA routing (Portal UI) ===
|
||||||
|
location / {
|
||||||
|
try_files $uri $uri/ /index.html;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Die SubDomains werden in 50-subdomains-userA.conf verwaltet. Und bei diesen Subdomains sollen einige auch nur mit aktivem cookie erreichbar sein.
|
||||||
|
Aber nicht alle. Deshalb: Eine weitere spalte in der forwarding.conf datei.
|
||||||
|
|
||||||
|
#!/bin/sh
|
||||||
|
# /docker-entrypoint.d/40-connect-proxies.sh
|
||||||
|
# Generiert pro Zeile in /etc/nginx/forwarding.conf:
|
||||||
|
# - HTTPS vHost (Proxy oder local static) NUR wenn Zertifikate existieren
|
||||||
|
# - optional 80->443 Redirect-Server (mit ACME-Ausnahme) bei http_behavior=redirect
|
||||||
|
# Läuft automatisch beim Containerstart (nginx:alpine EntryPoint).
|
||||||
|
#
|
||||||
|
#
|
||||||
|
# Die Datei: connect-proxies.sh läuft, wenn nginx docker container startet
|
||||||
|
|
||||||
|
set -eu
|
||||||
|
|
||||||
|
CONF_DIR="/etc/nginx/conf.d"
|
||||||
|
LIVE_DIR="/etc/letsencrypt/live"
|
||||||
|
FWD_FILE="/etc/nginx/forwarding.conf"
|
||||||
|
|
||||||
|
HTTPS_SUFFIX="-https.generated.conf"
|
||||||
|
HTTP_REDIRECT_SUFFIX="-http-redirect.generated.conf"
|
||||||
|
GLOBALS_FILE="$CONF_DIR/_globals.generated.conf"
|
||||||
|
|
||||||
|
echo "[connect-proxies] start …"
|
||||||
|
|
||||||
|
# 0) Forwarding-Datei vorhanden?
|
||||||
|
if [ ! -f "$FWD_FILE" ]; then
|
||||||
|
echo "[connect-proxies] WARN: $FWD_FILE fehlt – keine Proxies zu generieren."
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 1) Globale HTTP-Kontext-Map + Resolver (idempotent)
|
||||||
|
# >>> CHANGE: Resolver NICHT hardcoden. Dynamisch aus /etc/resolv.conf ableiten, Fallback 127.0.0.11
|
||||||
|
RESOLVERS="$(awk '/^nameserver/{print $2}' /etc/resolv.conf | xargs || true)"
|
||||||
|
if [ -n "${RESOLVERS:-}" ]; then
|
||||||
|
RESOLVER_LINE="resolver $RESOLVERS ipv6=off valid=30s;"
|
||||||
|
else
|
||||||
|
RESOLVER_LINE="resolver 127.0.0.11 ipv6=off valid=30s;"
|
||||||
|
fi
|
||||||
|
|
||||||
|
cat > "$GLOBALS_FILE" <<NGINX
|
||||||
|
# Automatisch generiert – nicht editieren
|
||||||
|
map \$http_upgrade \$connection_upgrade {
|
||||||
|
default upgrade;
|
||||||
|
'' close;
|
||||||
|
}
|
||||||
|
$RESOLVER_LINE
|
||||||
|
NGINX
|
||||||
|
# <<< END CHANGE
|
||||||
|
|
||||||
|
# 2) Alte generierte Confs entfernen
|
||||||
|
rm -f "$CONF_DIR/"*"$HTTPS_SUFFIX" 2>/dev/null || true
|
||||||
|
rm -f "$CONF_DIR/"*"$HTTP_REDIRECT_SUFFIX" 2>/dev/null || true
|
||||||
|
|
||||||
|
# 3) Zeilen verarbeiten
|
||||||
|
LINE_NO=0
|
||||||
|
while IFS= read -r RAW || [ -n "$RAW" ]; do
|
||||||
|
LINE_NO=$((LINE_NO+1))
|
||||||
|
# trim + CR entfernen
|
||||||
|
LINE="$(printf '%s' "$RAW" | tr -d '\r' | sed 's/^[[:space:]]*//; s/[[:space:]]*$//')"
|
||||||
|
[ -z "$LINE" ] && continue
|
||||||
|
case "$LINE" in \#*) continue;; esac
|
||||||
|
|
||||||
|
# Spalten splitten (mindestens 2 erforderlich)
|
||||||
|
set -- $LINE
|
||||||
|
SERVER_NAME="${1:-}"
|
||||||
|
UPSTREAM_URL="${2:-}"
|
||||||
|
HTTP_BEHAVIOR="${3:-redirect}"
|
||||||
|
WEBSOCKETS="${4:-false}"
|
||||||
|
VERIFY_TLS="${5:-false}"
|
||||||
|
CERT_DOMAIN="${6:-$SERVER_NAME}"
|
||||||
|
LISTEN_PORT="${7:-443}"
|
||||||
|
|
||||||
|
if [ -z "$SERVER_NAME" ] || [ -z "$UPSTREAM_URL" ]; then
|
||||||
|
echo "[connect-proxies] WARN(Line $LINE_NO): unvollständig -> $LINE"
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
FULLCHAIN="$LIVE_DIR/$CERT_DOMAIN/fullchain.pem"
|
||||||
|
PRIVKEY="$LIVE_DIR/$CERT_DOMAIN/privkey.pem"
|
||||||
|
|
||||||
|
HTTPS_OUT="$CONF_DIR/${SERVER_NAME}-p${LISTEN_PORT}${HTTPS_SUFFIX}"
|
||||||
|
HTTP_REDIRECT_OUT="$CONF_DIR/${SERVER_NAME}${HTTP_REDIRECT_SUFFIX}"
|
||||||
|
|
||||||
|
# >>> NEW: Upstream normalisieren (Trailing Slash entfernen) + DNS-Check vorbereiten
|
||||||
|
SANITIZED_UPSTREAM="${UPSTREAM_URL%/}"
|
||||||
|
DNS_OK="true"
|
||||||
|
SCHEME=""; HOST=""; PORT=""
|
||||||
|
|
||||||
|
if [ "$SANITIZED_UPSTREAM" != "local" ]; then
|
||||||
|
case "$SANITIZED_UPSTREAM" in
|
||||||
|
http://*)
|
||||||
|
URI="${SANITIZED_UPSTREAM#http://}"; SCHEME="http"; DEFAULT_PORT="80"
|
||||||
|
;;
|
||||||
|
https://*)
|
||||||
|
URI="${SANITIZED_UPSTREAM#https://}"; SCHEME="https"; DEFAULT_PORT="443"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "[connect-proxies] WARN(Line $LINE_NO): $SERVER_NAME upstream_url ungültig: '$UPSTREAM_URL' – überspringe."
|
||||||
|
continue
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
HOSTPORT="${URI%%/*}"
|
||||||
|
HOST="${HOSTPORT%%:*}"
|
||||||
|
PORT="${HOSTPORT#*:}"; [ "$PORT" = "$HOSTPORT" ] && PORT="$DEFAULT_PORT"
|
||||||
|
|
||||||
|
if command -v getent >/dev/null 2>&1; then
|
||||||
|
if ! getent hosts "$HOST" >/dev/null 2>&1; then
|
||||||
|
DNS_OK="false"
|
||||||
|
echo "[connect-proxies] [-] $SERVER_NAME: DNS nicht auflösbar ($HOST) – erzeuge 503-Placeholder statt Proxy."
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
DNS_OK="unknown"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
# <<< END NEW
|
||||||
|
|
||||||
|
if [ -f "$FULLCHAIN" ] && [ -f "$PRIVKEY" ]; then
|
||||||
|
echo "[connect-proxies] [+] $SERVER_NAME: Zertifikat OK (cert_domain=$CERT_DOMAIN). Erzeuge 443 …"
|
||||||
|
|
||||||
|
# Fall A: local (statisch, kein proxy_pass)
|
||||||
|
if [ "$SANITIZED_UPSTREAM" = "local" ]; then
|
||||||
|
cat > "$HTTPS_OUT" <<NGINX
|
||||||
|
# Auto-generated - 443 static site
|
||||||
|
server {
|
||||||
|
listen ${LISTEN_PORT} ssl http2;
|
||||||
|
listen [::]:${LISTEN_PORT} ssl http2;
|
||||||
|
server_name $SERVER_NAME;
|
||||||
|
|
||||||
|
ssl_certificate $FULLCHAIN;
|
||||||
|
ssl_certificate_key $PRIVKEY;
|
||||||
|
|
||||||
|
ssl_protocols TLSv1.2 TLSv1.3;
|
||||||
|
ssl_ciphers HIGH:!aNULL:!MD5;
|
||||||
|
|
||||||
|
root /usr/share/nginx/html;
|
||||||
|
index index.html;
|
||||||
|
|
||||||
|
location /api/ {
|
||||||
|
proxy_pass http://appserverauth:3000/api/;
|
||||||
|
|
||||||
|
proxy_set_header Host \$host;
|
||||||
|
proxy_set_header X-Real-IP \$remote_addr;
|
||||||
|
proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
|
||||||
|
proxy_set_header X-Forwarded-Proto \$scheme;
|
||||||
|
}
|
||||||
|
|
||||||
|
location / {
|
||||||
|
try_files \$uri \$uri/ /index.html;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
NGINX
|
||||||
|
|
||||||
|
else
|
||||||
|
# >>> NEW: Zwei Pfade – DNS_OK=false => Placeholder; sonst Proxy mit Laufzeit-Resolver
|
||||||
|
if [ "$DNS_OK" = "false" ]; then
|
||||||
|
# 443 Placeholder – keine Proxy-Verbindung, saubere 503
|
||||||
|
cat > "$HTTPS_OUT" <<NGINX
|
||||||
|
# Auto-generated - 443 placeholder (DNS failed)
|
||||||
|
server {
|
||||||
|
listen ${LISTEN_PORT} ssl http2;
|
||||||
|
listen [::]:${LISTEN_PORT} ssl http2;
|
||||||
|
server_name $SERVER_NAME;
|
||||||
|
|
||||||
|
ssl_certificate $FULLCHAIN;
|
||||||
|
ssl_certificate_key $PRIVKEY;
|
||||||
|
|
||||||
|
ssl_protocols TLSv1.2 TLSv1.3;
|
||||||
|
ssl_ciphers HIGH:!aNULL:!MD5;
|
||||||
|
|
||||||
|
location / {
|
||||||
|
default_type text/html;
|
||||||
|
return 503 "<!doctype html><html><head><meta charset='utf-8'><title>Service temporarily unavailable</title></head><body style='font-family:sans-serif;margin:3rem'><h1>\$server_name nicht erreichbar</h1><p>DNS-Auflösung fehlgeschlagen. Bitte später erneut versuchen.</p></body></html>";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
NGINX
|
||||||
|
else
|
||||||
|
# 443 Proxy – DNS ok/unknown: Laufzeit-Auflösung + freundlicher 503 bei Downstreams
|
||||||
|
cat > "$HTTPS_OUT" <<NGINX
|
||||||
|
# Auto-generated - 443 reverse proxy
|
||||||
|
server {
|
||||||
|
listen ${LISTEN_PORT} ssl http2;
|
||||||
|
listen [::]:${LISTEN_PORT} ssl http2;
|
||||||
|
server_name $SERVER_NAME;
|
||||||
|
|
||||||
|
ssl_certificate $FULLCHAIN;
|
||||||
|
ssl_certificate_key $PRIVKEY;
|
||||||
|
|
||||||
|
ssl_protocols TLSv1.2 TLSv1.3;
|
||||||
|
ssl_ciphers HIGH:!aNULL:!MD5;
|
||||||
|
|
||||||
|
# Fehler sauber abfangen und 503 liefern (statt rohe 502/504)
|
||||||
|
proxy_intercept_errors on;
|
||||||
|
error_page 502 503 504 = @service_down;
|
||||||
|
|
||||||
|
location / {
|
||||||
|
# >>> CHANGE: variable proxy_pass -> DNS zur Laufzeit (verhindert nginx -t Crash)
|
||||||
|
set \$target $SANITIZED_UPSTREAM;
|
||||||
|
proxy_pass \$target;
|
||||||
|
|
||||||
|
proxy_set_header Host \$host;
|
||||||
|
proxy_set_header X-Real-IP \$remote_addr;
|
||||||
|
proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
|
||||||
|
proxy_set_header X-Forwarded-Proto \$scheme;
|
||||||
|
|
||||||
|
proxy_http_version 1.1;
|
||||||
|
NGINX
|
||||||
|
|
||||||
|
if [ "$WEBSOCKETS" = "true" ]; then
|
||||||
|
cat >> "$HTTPS_OUT" <<'NGINX'
|
||||||
|
proxy_set_header Upgrade $http_upgrade;
|
||||||
|
proxy_set_header Connection $connection_upgrade;
|
||||||
|
NGINX
|
||||||
|
else
|
||||||
|
cat >> "$HTTPS_OUT" <<'NGINX'
|
||||||
|
proxy_set_header Upgrade "";
|
||||||
|
proxy_set_header Connection close;
|
||||||
|
NGINX
|
||||||
|
fi
|
||||||
|
|
||||||
|
case "$SANITIZED_UPSTREAM" in
|
||||||
|
https://*)
|
||||||
|
if [ "$VERIFY_TLS" = "true" ]; then
|
||||||
|
cat >> "$HTTPS_OUT" <<'NGINX'
|
||||||
|
proxy_ssl_verify on;
|
||||||
|
proxy_ssl_server_name on;
|
||||||
|
NGINX
|
||||||
|
else
|
||||||
|
cat >> "$HTTPS_OUT" <<'NGINX'
|
||||||
|
proxy_ssl_verify off;
|
||||||
|
proxy_ssl_server_name on;
|
||||||
|
NGINX
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
cat >> "$HTTPS_OUT" <<'NGINX'
|
||||||
|
client_max_body_size 50m;
|
||||||
|
proxy_connect_timeout 60s;
|
||||||
|
proxy_send_timeout 60s;
|
||||||
|
proxy_read_timeout 60s;
|
||||||
|
}
|
||||||
|
|
||||||
|
location @service_down {
|
||||||
|
default_type text/html;
|
||||||
|
return 503 "<!doctype html><html><head><meta charset='utf-8'><title>Service temporarily unavailable</title></head><body style='font-family:sans-serif;margin:3rem'><h1>$server_name nicht erreichbar</h1><p>Der Dienst ist momentan nicht verfügbar. Bitte später erneut versuchen.</p></body></html>";
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
NGINX
|
||||||
|
fi
|
||||||
|
# <<< END NEW
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 80->443 Redirect-Server nur, wenn gewünscht
|
||||||
|
if [ "$HTTP_BEHAVIOR" = "redirect" ]; then
|
||||||
|
cat > "$HTTP_REDIRECT_OUT" <<NGINX
|
||||||
|
# Auto-generated – 80->443 redirect for $SERVER_NAME
|
||||||
|
server {
|
||||||
|
listen 80;
|
||||||
|
listen [::]:80;
|
||||||
|
server_name $SERVER_NAME;
|
||||||
|
|
||||||
|
# ACME-Ausnahme
|
||||||
|
location ^~ /.well-known/acme-challenge/ {
|
||||||
|
root /var/www/certbot;
|
||||||
|
default_type "text/plain; charset=utf-8";
|
||||||
|
}
|
||||||
|
|
||||||
|
location / {
|
||||||
|
return 301 https://\$host\$request_uri;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
NGINX
|
||||||
|
else
|
||||||
|
# Sicherstellen, dass kein alter Redirect liegen bleibt
|
||||||
|
rm -f "$HTTP_REDIRECT_OUT" 2>/dev/null || true
|
||||||
|
fi
|
||||||
|
|
||||||
|
else
|
||||||
|
echo "[connect-proxies] [-] $SERVER_NAME: keine Zertifikate (cert_domain=$CERT_DOMAIN). Entferne evtl. alte Confs."
|
||||||
|
rm -f "$HTTPS_OUT" "$HTTP_REDIRECT_OUT" 2>/dev/null || true
|
||||||
|
fi
|
||||||
|
|
||||||
|
done < "$FWD_FILE"
|
||||||
|
|
||||||
|
echo "[connect-proxies] nginx -t …"
|
||||||
|
nginx -t
|
||||||
|
echo "[connect-proxies] done."
|
||||||
|
|
||||||
|
# server_name upstream_url http_behavior websockets verify_upstream_tls [cert_domain]
|
||||||
|
|
||||||
|
#fluidncRed.server.schooltech.ch http://appServer_TunnelHead:8120 redirect true false
|
||||||
|
|
||||||
|
# 444 → 8121 (WS/WSS)
|
||||||
|
# fluidncRedWs.server.schooltech.ch http://appServer_TunnelHead:8121 redirect true false fluidncRedWs.server.schooltech.ch 444
|
||||||
|
#server.schooltech.ch local static false false
|
||||||
|
server.schooltech.ch local redirect false false server.schooltech.ch 443
|
||||||
|
tcPortainer.server.schooltech.ch http://thinkcentre.local:9000 redirect true false
|
||||||
|
tcGuac.server.schooltech.ch http://thinkcentre.local:9000 redirect true false
|
||||||
|
|
||||||
|
#inf InformatiWeb ist per Tunnel angeschlossen. Soll auf 97xx Ports gehen
|
||||||
|
infPortainer.server.schooltech.ch http://appServer_TunnelHead:9903 redirect true false
|
||||||
|
infGuac.server.schooltech.ch http://appServer_TunnelHead:9980 redirect true false
|
||||||
|
|
||||||
|
#RP5 ist "Lokal" der Server
|
||||||
|
rp5Guac.server.schooltech.ch http://appServer_guacamole:8080 redirect true false
|
||||||
|
rp5Portainer.server.schooltech.ch http://portainer:9000 redirect true false
|
||||||
|
|
||||||
|
|
||||||
|
#RP3 ist Raspi für die Scara-Robots, per Tunnel angeschlossen. Er hat 81xx Ports am TunnelHead
|
||||||
|
rp3Portainer.server.schooltech.ch http://appServer_TunnelHead:8100 redirect true false
|
||||||
|
rp3Guac.server.schooltech.ch http://appServer_TunnelHead:8180 redirect true false
|
||||||
|
fluidncRed.server.schooltech.ch http://appServer_TunnelHead:8120 redirect true false
|
||||||
|
fluidncWhite.server.schooltech.ch https://appServer_TunnelHead:8104 redirect true false
|
||||||
|
|
||||||
|
============
|
||||||
|
Fragen:
|
||||||
|
1) ist der aufbau einigermassen klar?
|
||||||
|
|
||||||
|
2) weisst du, wo die User-Authentifizierung eingebaut wereden könnte?
|
||||||
|
|
||||||
|
3) Ist es sinnvoll, das in der forwaring.conf abzuspeichern?
|
||||||
@@ -26,7 +26,7 @@ fluidncWhite.server.schooltech.ch https://appServer_TunnelHead:8104 redirect tru
|
|||||||
|
|
||||||
# ThinkCentre ist ein MiniPC der neben dem einen Roboter steht. Hier sind die 97xx Ports zugewiesen
|
# ThinkCentre ist ein MiniPC der neben dem einen Roboter steht. Hier sind die 97xx Ports zugewiesen
|
||||||
tcGuac.server.schooltech.ch http://appServer_TunnelHead:9780 redirect false false
|
tcGuac.server.schooltech.ch http://appServer_TunnelHead:9780 redirect false false
|
||||||
tcPortainer.server.schooltech.ch http://appServer_TunnelHead:9703 redirect false false
|
tcPortainer.server.schooltech.ch http://appServer_TunnelHead:9703 redirect true false
|
||||||
tcSimulation.server.schooltech.ch https://appServer_TunnelHead:9712 redirect true false
|
tcSimulation.server.schooltech.ch https://appServer_TunnelHead:9712 redirect true false
|
||||||
#tcVideocontroller.server.schooltech.ch https://tcvideo:9443 redirect true false
|
#tcVideocontroller.server.schooltech.ch https://tcvideo:9443 redirect true false
|
||||||
robotHoming.server.schooltech.ch https://appServer_TunnelHead:9793 redirect true fals
|
robotHoming.server.schooltech.ch https://appServer_TunnelHead:9793 redirect true fals
|
||||||
|
|||||||
Reference in New Issue
Block a user