Absturzschleife des Proxy Managers: IP-Bereich-Abruf abschaltbar
Das Containerprotokoll eines Kunden zeigte, was hinter dem 502 steckte: der Dienst stuerzt in einer Schleife ab. [IP Ranges] Fetching https://ip-ranges.amazonaws.com/ip-ranges.json Uncaught Error: Client network socket disconnected before secure TLS connection was established ... node --abort_on_uncaught_exception ... index.js Starting backend ... [und das immer wieder] Beim Start holt der Proxy Manager IP-Bereiche von AWS und Cloudflare - gebraucht wird das nur fuer Zugriffslisten mit deren Adressbereichen, auf einem internen Server also nie. Der Code faengt Fehler dabei ab, dieser kommt aber asynchron vom TLS-Socket und laeuft am catch vorbei; weil node mit --abort_on_uncaught_exception laeuft, bricht der Prozess ab, s6 startet neu, und nginx davor antwortet durchgehend mit 502. Am Abbild nachgesehen und ausprobiert: - IP_RANGES_FETCH_ENABLED=false verhindert den Abruf; im Protokoll steht dann "IP Ranges fetch is disabled by environment variable", das Backend laeuft. - Scheitert der Abruf sauber (DNS-Fehler, Verbindung abgelehnt), faengt der Code ihn ab und der Dienst laeuft weiter - der Absturz haengt also wirklich an der gekappten TLS-Verbindung. - initTimer() laeuft unabhaengig vom Schalter und versucht es alle sechs Stunden erneut. Das steht als Hinweis samt extra_hosts in der README. Neu: NPM_IP_RANGES_FETCH, Vorgabe false. Und die Fehlermeldung erkennt den Fall selbst - sie zaehlt Startversuche und Ausnahmen im Containerprotokoll und nennt den Schalter, statt den Benutzer weiter auf "startet noch" warten zu lassen. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -140,6 +140,13 @@ NPM_ADMIN_PORT=81
|
||||
# 127.0.0.1 trotzdem ueber den Proxy. Dann hier auf localhost stellen.
|
||||
NPM_API_HOST=127.0.0.1
|
||||
|
||||
# Holt der Proxy Manager beim Start IP-Bereiche von AWS und Cloudflare?
|
||||
# Gebraucht wird das nur fuer Zugriffslisten mit deren Adressbereichen.
|
||||
# Vorgabe hier: false. In Netzen, die TLS aufbrechen oder Verbindungen
|
||||
# kappen, stirbt der Dienst sonst an einer unbehandelten Ausnahme und
|
||||
# startet endlos neu - sichtbar nur als "502 Bad Gateway".
|
||||
NPM_IP_RANGES_FETCH=false
|
||||
|
||||
# =====================================================================
|
||||
# TERMINAL-BROWSER (lokale Bedienung des Proxy Managers)
|
||||
# Fuer den Fall, dass Port 81 von aussen nicht erreichbar ist.
|
||||
|
||||
@@ -554,6 +554,7 @@ Die wichtigsten Schalter:
|
||||
| `NPM_ENABLED` | `on`/`off` – soll der Proxy-Manager-Container überhaupt laufen? Siehe [12.4](#124-proxy-manager-ganz-abschalten-externer-nginx) |
|
||||
| `NPM_ADMIN_PORT` | Port der Proxy-Manager-Oberfläche (Vorgabe 81) – nur über `npm-port` bzw. das Menü ändern |
|
||||
| `NPM_API_HOST` | Name für die Schnittstelle (`127.0.0.1` oder `localhost`) – siehe [Kapitel 14.6](#146-netze-mit-zwangsproxy-api-fehler-der-keiner-ist) |
|
||||
| `NPM_IP_RANGES_FETCH` | IP-Bereiche von AWS/Cloudflare holen (Vorgabe `false`) – siehe [Kapitel 10.1.2](#1012-der-dienst-stürzt-in-einer-schleife-ab) |
|
||||
| `NPM_ADMIN_URL` | Startseite des Terminal-Browsers; leer = automatisch aus `NPM_ADMIN_PORT` |
|
||||
| `BACKUP_DIR` | Ablage für **manuelle** Backups (Vorgabe `./backups`); geplante Jobs haben eigene Pfade |
|
||||
| `BACKUP_AUTO` | `on`/`off` – sollen die Backup-Jobs per cron laufen? |
|
||||
@@ -1254,6 +1255,62 @@ man erkennt, wer da geantwortet hat:
|
||||
<html><head><title>502 Proxy Error</title></head>...
|
||||
```
|
||||
|
||||
### 10.1.2 Der Dienst stürzt in einer Schleife ab
|
||||
|
||||
Sieht das Protokoll des Containers so aus, ist der `502` erklärt:
|
||||
|
||||
```
|
||||
[IP Ranges] › info Fetching https://ip-ranges.amazonaws.com/ip-ranges.json
|
||||
Uncaught Error: Client network socket disconnected before secure TLS connection was established
|
||||
at TLSSocket.emit (node:events:497:7)
|
||||
... node --abort_on_uncaught_exception ... index.js
|
||||
❯ Starting backend ...
|
||||
[und das immer wieder]
|
||||
```
|
||||
|
||||
Der Proxy Manager holt beim Start IP-Bereiche von AWS und Cloudflare –
|
||||
gebraucht wird das **nur** für Zugriffslisten mit deren Adressbereichen, in
|
||||
einem internen Netz also nie. Der Code fängt Fehler dabei ab, aber dieser
|
||||
kommt asynchron vom TLS-Socket und läuft am `catch` vorbei. Weil node mit
|
||||
`--abort_on_uncaught_exception` läuft, bricht der Prozess ab, s6 startet ihn
|
||||
neu – und nginx davor antwortet die ganze Zeit mit `502`.
|
||||
|
||||
Ausgelöst wird das von Netzen, die die Verbindung **annehmen und dann kappen**
|
||||
(aufbrechende Proxys, Firewalls). Scheitert der Abruf sauber – DNS-Fehler,
|
||||
Verbindung abgelehnt –, passiert nichts; der Dienst läuft weiter.
|
||||
|
||||
Abhilfe:
|
||||
|
||||
```bash
|
||||
./scripts/cmk-manage.sh config set NPM_IP_RANGES_FETCH false
|
||||
./scripts/cmk-manage.sh up
|
||||
```
|
||||
|
||||
Im Protokoll steht dann `IP Ranges fetch is disabled by environment variable`.
|
||||
**Vorgabe in diesem Projekt ist `false`** – der Abruf bringt einem internen
|
||||
Monitoring-Server nichts und kann ihn lahmlegen.
|
||||
|
||||
> Ein Rest bleibt: `initTimer()` läuft unabhängig vom Schalter und versucht es
|
||||
> **alle sechs Stunden** erneut. Soll auch das ausgeschlossen sein, zeigen die
|
||||
> Namen ins Leere – dann scheitert der Abruf sauber und wird abgefangen:
|
||||
>
|
||||
> ```yaml
|
||||
> extra_hosts:
|
||||
> - "ip-ranges.amazonaws.com:127.0.0.1"
|
||||
> - "www.cloudflare.com:127.0.0.1"
|
||||
> ```
|
||||
|
||||
Die Fehlermeldung erkennt den Fall übrigens selbst – sie zählt Startversuche
|
||||
und Ausnahmen im Containerprotokoll:
|
||||
|
||||
```
|
||||
Der Dienst startet nicht nur - er stuerzt in einer Schleife ab.
|
||||
Im Protokoll: 4 Startversuche, 4 unbehandelte Ausnahmen.
|
||||
Die Ausnahmen kommen vom Abruf der IP-Bereiche bei AWS und
|
||||
Cloudflare. ... Abschalten:
|
||||
cmk-manage.sh config set NPM_IP_RANGES_FETCH false
|
||||
```
|
||||
|
||||
### 10.2 Proxy-Host anlegen – ohne Browser
|
||||
|
||||
Die Weboberfläche lässt sich im Terminal-Browser nur mühsam bedienen; Formulare
|
||||
|
||||
@@ -557,6 +557,7 @@ The most important settings:
|
||||
| `NPM_ENABLED` | `on`/`off` – should the Proxy Manager container run at all? See [12.4](#124-turning-the-proxy-manager-off-entirely-external-nginx) |
|
||||
| `NPM_ADMIN_PORT` | port of the Proxy Manager interface (default 81) – change only via `npm-port` or the menu |
|
||||
| `NPM_API_HOST` | name the API is addressed by (`127.0.0.1` or `localhost`) – see [chapter 14.6](#146-networks-with-a-mandatory-proxy-an-api-error-that-is-none) |
|
||||
| `NPM_IP_RANGES_FETCH` | fetch IP ranges from AWS/Cloudflare (default `false`) – see [chapter 10.1.2](#1012-the-service-crashes-in-a-loop) |
|
||||
| `NPM_ADMIN_URL` | start page of the terminal browser; empty = derived from `NPM_ADMIN_PORT` |
|
||||
| `BACKUP_DIR` | location for **manual** backups (default `./backups`); scheduled jobs have their own paths |
|
||||
| `BACKUP_AUTO` | `on`/`off` – should the backup jobs run via cron? |
|
||||
@@ -1251,6 +1252,62 @@ line, which reveals who answered:
|
||||
<html><head><title>502 Proxy Error</title></head>...
|
||||
```
|
||||
|
||||
### 10.1.2 The service crashes in a loop
|
||||
|
||||
If the container log looks like this, the `502` is explained:
|
||||
|
||||
```
|
||||
[IP Ranges] › info Fetching https://ip-ranges.amazonaws.com/ip-ranges.json
|
||||
Uncaught Error: Client network socket disconnected before secure TLS connection was established
|
||||
at TLSSocket.emit (node:events:497:7)
|
||||
... node --abort_on_uncaught_exception ... index.js
|
||||
❯ Starting backend ...
|
||||
[over and over]
|
||||
```
|
||||
|
||||
At startup the Proxy Manager fetches IP ranges from AWS and Cloudflare – needed
|
||||
**only** for access lists using those address ranges, so never on an internal
|
||||
network. The code does catch errors there, but this one arrives asynchronously
|
||||
on the TLS socket and bypasses the `catch`. Since node runs with
|
||||
`--abort_on_uncaught_exception`, the process aborts, s6 restarts it – and nginx
|
||||
in front answers `502` the whole time.
|
||||
|
||||
It is triggered by networks that **accept the connection and then cut it**
|
||||
(TLS-intercepting proxies, firewalls). If the fetch fails cleanly – DNS error,
|
||||
connection refused – nothing happens; the service keeps running.
|
||||
|
||||
The fix:
|
||||
|
||||
```bash
|
||||
./scripts/cmk-manage.sh config set NPM_IP_RANGES_FETCH false
|
||||
./scripts/cmk-manage.sh up
|
||||
```
|
||||
|
||||
The log then says `IP Ranges fetch is disabled by environment variable`.
|
||||
**This project defaults to `false`** – the fetch gains an internal monitoring
|
||||
server nothing and can take it down.
|
||||
|
||||
> One remainder: `initTimer()` runs regardless of the switch and retries **every
|
||||
> six hours**. To rule that out as well, point the names nowhere – then the
|
||||
> fetch fails cleanly and is caught:
|
||||
>
|
||||
> ```yaml
|
||||
> extra_hosts:
|
||||
> - "ip-ranges.amazonaws.com:127.0.0.1"
|
||||
> - "www.cloudflare.com:127.0.0.1"
|
||||
> ```
|
||||
|
||||
The error message recognises this case by itself – it counts start attempts and
|
||||
exceptions in the container log:
|
||||
|
||||
```
|
||||
Der Dienst startet nicht nur - er stuerzt in einer Schleife ab.
|
||||
Im Protokoll: 4 Startversuche, 4 unbehandelte Ausnahmen.
|
||||
Die Ausnahmen kommen vom Abruf der IP-Bereiche bei AWS und
|
||||
Cloudflare. ... Abschalten:
|
||||
cmk-manage.sh config set NPM_IP_RANGES_FETCH false
|
||||
```
|
||||
|
||||
### 10.2 Creating a proxy host – without a browser
|
||||
|
||||
The web interface is painful in a terminal browser, and forms with file uploads
|
||||
|
||||
@@ -68,6 +68,14 @@ services:
|
||||
# REST-API laesst sich nicht ohne Weiteres nutzen.
|
||||
INITIAL_ADMIN_EMAIL: ${NPM_ADMIN_EMAIL:-}
|
||||
INITIAL_ADMIN_PASSWORD: ${NPM_ADMIN_PASSWORD:-}
|
||||
# Beim Start holt der Proxy Manager sonst IP-Bereiche von AWS und
|
||||
# Cloudflare. Gebraucht wird das nur fuer Zugriffslisten mit deren
|
||||
# Adressbereichen - in einem internen Netz also nie. Wird die
|
||||
# TLS-Verbindung dabei aufgebaut und dann gekappt (aufbrechender
|
||||
# Proxy, Firewall), stirbt der Dienst an einer unbehandelten
|
||||
# Ausnahme und startet in einer Schleife neu; nach aussen sieht man
|
||||
# nur "502 Bad Gateway".
|
||||
IP_RANGES_FETCH_ENABLED: ${NPM_IP_RANGES_FETCH:-false}
|
||||
volumes:
|
||||
- ${NPM_DATA_DIR:-./data/npm/data}:/data:Z
|
||||
- ${NPM_LE_DIR:-./data/npm/letsencrypt}:/etc/letsencrypt:Z
|
||||
|
||||
+38
-5
@@ -3309,6 +3309,7 @@ npm|NPM_ADMIN_EMAIL|text|Konto des Proxy Managers (E-Mail)||1
|
||||
npm|NPM_ADMIN_PASSWORD|password|Kennwort des Proxy-Manager-Kontos||1
|
||||
npm|NPM_ADMIN_PORT|port|Port der Adminoberflaeche||
|
||||
npm|NPM_API_HOST|text|Name fuer die Schnittstelle (127.0.0.1 oder localhost)||1
|
||||
npm|NPM_IP_RANGES_FETCH|choice|IP-Bereiche von AWS/Cloudflare holen|false:true|1
|
||||
npm|PROXY_DOMAIN|text|Vorgabe-Domain fuer Proxy-Hosts||1
|
||||
npm|PROXY_FORWARD_HOST|text|Weiterleitungsziel (Host)||
|
||||
npm|PROXY_FORWARD_PORT|port|Weiterleitungsziel (Port)||
|
||||
@@ -3445,7 +3446,7 @@ settings_post_set() {
|
||||
cmd_cert_external --watch "$val" ;;
|
||||
CERT_EXTERNAL_DIR)
|
||||
log "Wirksam nach: $SELF up (das Verzeichnis wird erst dann eingehaengt)" ;;
|
||||
CMK_IMAGE|CMK_SITE_ID|CMK_CONTAINER_NAME|NPM_IMAGE|NPM_CONTAINER_NAME|TZ|CMK_LIVESTATUS_TCP|NPM_DISABLE_IPV6|CMK_DATA_DIR|NPM_DATA_DIR|NPM_LE_DIR)
|
||||
CMK_IMAGE|CMK_SITE_ID|CMK_CONTAINER_NAME|NPM_IMAGE|NPM_CONTAINER_NAME|TZ|CMK_LIVESTATUS_TCP|NPM_DISABLE_IPV6|CMK_DATA_DIR|NPM_DATA_DIR|NPM_LE_DIR|NPM_IP_RANGES_FETCH)
|
||||
log "Wirksam nach: $SELF up (Container werden neu erstellt)" ;;
|
||||
esac
|
||||
}
|
||||
@@ -3771,6 +3772,37 @@ json_str() { printf '%s' "$1" | tr ',' '\n' | sed -n "s/.*\"$2\"[[:space:]]*:[[:
|
||||
# certificate_id oder owner_user_id zu, weil dort ein _ vor dem id steht.
|
||||
json_ids() { printf '%s' "$1" | grep -o '"id":[0-9]*' | sed 's/.*://' ; }
|
||||
|
||||
# Stirbt der Dienst hinter nginx in einer Schleife? Das sieht von aussen
|
||||
# aus wie "startet noch", hoert aber nie auf. Im Protokoll steht es.
|
||||
npm_diagnose_backend() {
|
||||
container_running "$NPM_CONTAINER_NAME" || return 0
|
||||
local log starts crash
|
||||
log="$($RUNTIME logs --tail 200 "$NPM_CONTAINER_NAME" 2>&1 || true)"
|
||||
starts="$(printf '%s\n' "$log" | grep -c 'Starting backend' || true)"
|
||||
crash="$(printf '%s\n' "$log" | grep -c 'Uncaught Error' || true)"
|
||||
[ "${starts:-0}" -ge 3 ] || [ "${crash:-0}" -ge 2 ] || return 0
|
||||
|
||||
printf '
|
||||
%sDer Dienst startet nicht nur - er stuerzt in einer Schleife ab.%s
|
||||
Im Protokoll: %s Startversuche, %s unbehandelte Ausnahmen.\n' \
|
||||
"$C_YEL" "$C_RST" "${starts:-0}" "${crash:-0}" >&2
|
||||
|
||||
case "$log" in
|
||||
*ip-ranges.amazonaws.com*|*"IP Ranges"*)
|
||||
printf '
|
||||
Die Ausnahmen kommen vom Abruf der IP-Bereiche bei AWS und
|
||||
Cloudflare. In Netzen, die TLS aufbrechen oder Verbindungen kappen,
|
||||
faellt der Dienst darueber - und startet endlos neu. Abschalten:
|
||||
%s config set NPM_IP_RANGES_FETCH false
|
||||
%s up
|
||||
Gebraucht wird der Abruf nur fuer Zugriffslisten mit den
|
||||
Adressbereichen von AWS oder Cloudflare.\n' "$SELF" "$SELF" >&2 ;;
|
||||
*)
|
||||
printf ' Letzte Ausnahme im Protokoll:
|
||||
%s\n' "$(printf '%s\n' "$log" | grep -A1 'Uncaught Error' | tail -1 | cut -c1-70)" >&2 ;;
|
||||
esac
|
||||
}
|
||||
|
||||
npm_api_token() {
|
||||
local base; base="$(npm_api_base)"
|
||||
if [ -z "${NPM_ADMIN_EMAIL:-}" ] || [ -z "${NPM_ADMIN_PASSWORD:-}" ]; then
|
||||
@@ -3911,11 +3943,12 @@ EOF
|
||||
printf ' Der Proxy Manager selbst hat geantwortet (%s) - aber der
|
||||
Dienst DAHINTER ist nicht erreichbar. Das ist normal, solange er
|
||||
noch startet: nach einem Neustart dauert es rund zehn Sekunden,
|
||||
bis die Schnittstelle antwortet.
|
||||
|
||||
Kurz warten und noch einmal, sonst ins Protokoll sehen:
|
||||
bis die Schnittstelle antwortet.\n' "$srv" >&2
|
||||
npm_diagnose_backend
|
||||
printf '
|
||||
Sonst ins Protokoll sehen:
|
||||
%s logs
|
||||
%s proxy restart\n' "$srv" "$SELF" "$SELF" >&2
|
||||
%s proxy restart\n' "$SELF" "$SELF" >&2
|
||||
else
|
||||
printf ' Die Antwort kam ueber einen Proxy (Via: %s), nicht direkt.
|
||||
Pruefen: %s noproxy\n' "$via" "$SELF" >&2
|
||||
|
||||
Reference in New Issue
Block a user