This commit is contained in:
chk
2026-03-22 22:06:35 +01:00
parent 5c6ea53bd4
commit 072693d57e
4 changed files with 780 additions and 2 deletions

View File

@@ -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

View File

@@ -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?

View File

@@ -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?

View File

@@ -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