diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile index 8ac7cfff..a7640f26 100755 --- a/.devcontainer/Dockerfile +++ b/.devcontainer/Dockerfile @@ -137,7 +137,7 @@ ENV LANG=C.UTF-8 RUN apk add --no-cache bash mtr libbsd zip lsblk tzdata curl arp-scan iproute2 iproute2-ss nmap fping \ nmap-scripts traceroute nbtscan net-tools net-snmp-tools bind-tools awake ca-certificates \ sqlite php83 php83-fpm php83-cgi php83-curl php83-sqlite3 php83-session python3 envsubst \ - nginx supercronic shadow su-exec && \ + nginx supercronic shadow su-exec jq && \ rm -Rf /var/cache/apk/* && \ rm -Rf /etc/nginx && \ addgroup -g ${NETALERTX_GID} ${NETALERTX_GROUP} && \ diff --git a/Dockerfile b/Dockerfile index 6d308642..0836f7fd 100755 --- a/Dockerfile +++ b/Dockerfile @@ -134,7 +134,7 @@ ENV LANG=C.UTF-8 RUN apk add --no-cache bash mtr libbsd zip lsblk tzdata curl arp-scan iproute2 iproute2-ss nmap fping \ nmap-scripts traceroute nbtscan net-tools net-snmp-tools bind-tools awake ca-certificates \ sqlite php83 php83-fpm php83-cgi php83-curl php83-sqlite3 php83-session python3 envsubst \ - nginx supercronic shadow su-exec && \ + nginx supercronic shadow su-exec jq && \ rm -Rf /var/cache/apk/* && \ rm -Rf /etc/nginx && \ addgroup -g ${NETALERTX_GID} ${NETALERTX_GROUP} && \ diff --git a/Dockerfile.debian b/Dockerfile.debian index 958390ba..e3b196d5 100755 --- a/Dockerfile.debian +++ b/Dockerfile.debian @@ -134,6 +134,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ mtr \ procps \ gosu \ + jq \ && wget -qO /etc/apt/trusted.gpg.d/php.gpg https://packages.sury.org/php/apt.gpg \ && echo "deb https://packages.sury.org/php/ $(lsb_release -sc) main" > /etc/apt/sources.list.d/php.list \ && apt-get update \ diff --git a/back/app.conf b/back/app.conf index d0281eaa..9c1bbfe9 100755 --- a/back/app.conf +++ b/back/app.conf @@ -16,7 +16,7 @@ # # Scan multiple interfaces (eth1 and eth0): # SCAN_SUBNETS = [ '192.168.1.0/24 --interface=eth1', '192.168.1.0/24 --interface=eth0' ] - +BACKEND_API_URL='/server' DISCOVER_PLUGINS=True SCAN_SUBNETS=['--localnet'] TIMEZONE='Europe/Berlin' @@ -100,6 +100,8 @@ MQTT_PASSWORD='passw0rd' MQTT_QOS=0 MQTT_DELAY_SEC=2 +GRAPHQL_PORT=20212 + #-------------------IMPORTANT INFO-------------------# # This file is ingested by a python script, so if # diff --git a/front/js/api.js b/front/js/api.js index 6f927913..32129ab0 100644 --- a/front/js/api.js +++ b/front/js/api.js @@ -4,11 +4,8 @@ function getApiBase() if(apiBase == "") { - const protocol = window.location.protocol.replace(':', ''); - const host = window.location.hostname; - const port = getSetting("GRAPHQL_PORT"); - - apiBase = `${protocol}://${host}:${port}`; + // Default to the same-origin proxy bridge + apiBase = "/server"; } // Remove trailing slash for consistency diff --git a/install/production-filesystem/services/config/nginx/netalertx.conf.template b/install/production-filesystem/services/config/nginx/netalertx.conf.template index 6a567056..0dfbeb18 100755 --- a/install/production-filesystem/services/config/nginx/netalertx.conf.template +++ b/install/production-filesystem/services/config/nginx/netalertx.conf.template @@ -94,6 +94,19 @@ http { access_log /tmp/log/nginx-access.log main; + # Map 1: The Legacy Logic (Referer Match) + map "$http_referer|$http_host" $sec_legacy { + "~^https?://(?[^/:]+)(?::\d+)?/.*\|\k(?::\d+)?$" "TRUSTED"; + default "UNTRUSTED"; + } + + # Map 2: Strict Same-Origin Enforcement + map $http_sec_fetch_site $is_trusted { + "same-origin" "TRUSTED"; + "" $sec_legacy; # Fallback only if header is missing + default "UNTRUSTED"; # Blocks 'same-site' and 'cross-site' + } + # Virtual host config server { listen ${LISTEN_ADDR}:${PORT} default_server; @@ -102,6 +115,30 @@ http { index index.php; add_header X-Forwarded-Prefix "/app" always; + location /server/ { + # 1. Enforcement + if ($is_trusted != "TRUSTED") { + return 403; + } + + # 2. Path Rewriting & Proxy + rewrite ^/server/(.*)$ /$1 break; + proxy_pass http://127.0.0.1:${BACKEND_PORT}; + + # 3. Performance & SSE (Per #1440) + proxy_buffering off; + proxy_cache off; + proxy_http_version 1.1; + proxy_set_header Connection ""; + client_max_body_size 50m; + proxy_read_timeout 3600s; + + # 4. Standard Proxy Headers + 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 ~* \.php$ { # Set Cache-Control header to prevent caching on the first load diff --git a/install/production-filesystem/services/start-nginx.sh b/install/production-filesystem/services/start-nginx.sh index 7f17fbac..4d4bb668 100755 --- a/install/production-filesystem/services/start-nginx.sh +++ b/install/production-filesystem/services/start-nginx.sh @@ -42,9 +42,32 @@ if [ "$(id -u)" -eq 0 ]; then NGINX_USER_DIRECTIVE="user root;" fi +# ------------------------------------------------------------------ +# BACKEND_PORT RESOLUTION +# ------------------------------------------------------------------ +# Priority 1: APP_CONF_OVERRIDE (parsed via jq) +# Priority 2: GRAPHQL_PORT env var +# Priority 3: Default 20212 + +# Default +export BACKEND_PORT=20212 + +# Check env var +if [ -n "${GRAPHQL_PORT:-}" ]; then + export BACKEND_PORT="${GRAPHQL_PORT}" +fi + +# Check override (highest priority) +if [ -n "${APP_CONF_OVERRIDE:-}" ]; then + override_port=$(echo "${APP_CONF_OVERRIDE}" | jq -r '.GRAPHQL_PORT // empty') + if [ -n "${override_port}" ]; then + export BACKEND_PORT="${override_port}" + fi +fi + # Shell check doesn't recognize envsubst variables # shellcheck disable=SC2016 -if envsubst '${LISTEN_ADDR} ${PORT} ${NGINX_USER_DIRECTIVE}' < "${SYSTEM_NGINX_CONFIG_TEMPLATE}" > "${TEMP_CONFIG_FILE}" 2>/dev/null; then +if envsubst '${LISTEN_ADDR} ${PORT} ${NGINX_USER_DIRECTIVE} ${BACKEND_PORT}' < "${SYSTEM_NGINX_CONFIG_TEMPLATE}" > "${TEMP_CONFIG_FILE}" 2>/dev/null; then mv "${TEMP_CONFIG_FILE}" "${SYSTEM_SERVICES_ACTIVE_CONFIG_FILE}" else echo "Note: Unable to write to ${SYSTEM_SERVICES_ACTIVE_CONFIG_FILE}. Using default configuration."