From b56f0eb8a481866d3eadfb2d9e605327ec0793a1 Mon Sep 17 00:00:00 2001 From: twothatit Date: Sun, 8 Feb 2026 20:45:01 +0100 Subject: [PATCH] Fix NPM forward host: use real host IP instead of Docker gateway - npm_service._get_forward_host() now detects the actual host IP via UDP socket (works inside Docker containers) instead of using 172.17.0.1 Docker gateway which NPM can't reach - install.sh uses hostname -I for NPM forward host - Removed npm_api_url parameter from _get_forward_host() Co-Authored-By: Claude Opus 4.6 --- app/services/netbird_service.py | 2 +- app/services/npm_service.py | 39 ++++++++++++++------------------- install.sh | 11 ++-------- 3 files changed, 20 insertions(+), 32 deletions(-) diff --git a/app/services/netbird_service.py b/app/services/netbird_service.py index 6c2fb08..7c19ca0 100644 --- a/app/services/netbird_service.py +++ b/app/services/netbird_service.py @@ -224,7 +224,7 @@ async def deploy_customer(db: Session, customer_id: int) -> dict[str, Any]: npm_proxy_id = None npm_stream_id = None if not local_mode: - forward_host = npm_service._get_forward_host(config.npm_api_url) + forward_host = npm_service._get_forward_host() npm_result = await npm_service.create_proxy_host( api_url=config.npm_api_url, npm_email=config.npm_api_email, diff --git a/app/services/npm_service.py b/app/services/npm_service.py index dc40e86..b990e59 100644 --- a/app/services/npm_service.py +++ b/app/services/npm_service.py @@ -13,8 +13,8 @@ Also manages NPM streams for STUN/TURN relay UDP ports. """ import logging +import socket from typing import Any -from urllib.parse import urlparse import httpx @@ -24,34 +24,29 @@ logger = logging.getLogger(__name__) NPM_TIMEOUT = 30 -def _get_forward_host(npm_api_url: str) -> str: - """Determine the IP/hostname to forward traffic to. +def _get_forward_host() -> str: + """Detect the host machine's real IP address. - The NPM proxy host must forward to the MSP appliance's host IP, - NOT to a Docker container name, because the customer's Caddy - container exposes its port on the host via Docker port mapping. + NPM proxy hosts must forward to the actual host IP where Docker + port mappings are exposed — NOT a container name or Docker gateway. - We extract the host from the NPM API URL — if the admin configured - ``http://10.0.0.5:81/api``, we forward to ``10.0.0.5``. - If the admin configured ``http://npm:81/api`` (container name), - we fall back to the Docker gateway IP ``172.17.0.1``. - - Args: - npm_api_url: The NPM API base URL from system config. + Uses a UDP socket to determine the primary outbound IP address + of the host (works inside Docker containers). Returns: - IP address or hostname to forward to. + The host's primary IP address (e.g. ``192.168.26.191``). """ - parsed = urlparse(npm_api_url) - host = parsed.hostname or "172.17.0.1" - - # If the host looks like a container name (no dots, not an IP), use Docker gateway - if not any(c == "." for c in host) and not host.startswith("172.") and host != "localhost": - logger.info("NPM URL host '%s' looks like a container name, using Docker gateway 172.17.0.1", host) + try: + s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) + s.connect(("8.8.8.8", 80)) + host_ip = s.getsockname()[0] + s.close() + logger.info("Detected host IP: %s", host_ip) + return host_ip + except Exception: + logger.warning("Could not detect host IP, falling back to 172.17.0.1") return "172.17.0.1" - return host - async def _npm_login(client: httpx.AsyncClient, api_url: str, email: str, password: str) -> str: """Authenticate with NPM and return a JWT token. diff --git a/install.sh b/install.sh index 5535c91..f81c93e 100644 --- a/install.sh +++ b/install.sh @@ -442,15 +442,8 @@ if [ -n "$MSP_DOMAIN" ]; then echo "" echo -e "${CYAN}Creating NPM proxy host for MSP Appliance (${MSP_DOMAIN})...${NC}" - # Determine forward host from NPM API URL - NPM_HOST=$(echo "$NPM_API_URL" | sed -E 's|https?://([^:/]+).*|\1|') - - # If host looks like a container name (no dots), use Docker gateway - if ! echo "$NPM_HOST" | grep -q '\.'; then - FORWARD_HOST="172.17.0.1" - else - FORWARD_HOST="$NPM_HOST" - fi + # Use the actual host IP for NPM forwarding (not Docker gateway!) + FORWARD_HOST=$(hostname -I | awk '{print $1}') # Step 1: Login to NPM NPM_TOKEN=$(curl -s -X POST "${NPM_API_URL}/tokens" \