Skip to content

fix(stream): bracket IPv6 forward host for valid nginx upstream#5741

Open
addielaruee wants to merge 1 commit into
NginxProxyManager:developfrom
addielaruee:fix/stream-ipv6-forward-host-brackets
Open

fix(stream): bracket IPv6 forward host for valid nginx upstream#5741
addielaruee wants to merge 1 commit into
NginxProxyManager:developfrom
addielaruee:fix/stream-ipv6-forward-host-brackets

Conversation

@addielaruee

Copy link
Copy Markdown

Why

Fixes #5740.

When a Stream Host uses an IPv6 address as its Forward Host, NPM accepts and stores it, but the generated nginx stream config is invalid, so the stream saves yet never activates.

backend/templates/stream.conf renders the upstream as:

proxy_pass {{ forwarding_host }}:{{ forwarding_port }};

For forwarding_host = fe80::528:3c87:e7bb:ab08, forwarding_port = 25 this produces:

proxy_pass fe80::528:3c87:e7bb:ab08:25;

which nginx rejects, because an IPv6 literal must be wrapped in square brackets before the port:

nginx: [emerg] invalid port in upstream "fe80::528:3c87:e7bb:ab08:25"

The stream row is saved (nginx_online: false), but the config never loads.

Fix

Normalize the stream forward host in internalNginx.generateConfig, in the same "manipulate the data before the template" block that already special-cases redirection_host. Using Node's net.isIPv6() (authoritative, no regex/heuristics), an IPv6 forward host is wrapped in brackets so it renders proxy_pass [address]:port;; IPv4 addresses and hostnames are left untouched.

generateConfig operates on a deep copy of the row (JSON.parse(JSON.stringify(host_row))), so persisted and audit-log data are unaffected — this only shapes the value handed to the template.

Scope is intentionally limited to Stream Hosts (the reported bug). Proxy Hosts use a different field/template path and are out of scope here.

Verification

Rendered the real backend/templates/stream.conf with LiquidJS 10.27.0 (the version in backend/package.json) after applying the same normalization:

Forward Host Rendered proxy_pass
fe80::528:3c87:e7bb:ab08 (bug report) proxy_pass [fe80::528:3c87:e7bb:ab08]:25;
::1 proxy_pass [::1]:25;
192.168.1.10 proxy_pass 192.168.1.10:25; (unchanged) ✅
backend.internal proxy_pass backend.internal:25; (unchanged) ✅

biome lint passes on the changed file.

Type of Change

  • Bug fix (non-breaking change that fixes an issue)
  • New feature (non-breaking change that adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)
  • Documentation update
  • Code refactoring
  • API changes
  • Performance improvement
  • Test addition or update

AI Usage

  • AI was used to write this
  • AI was used to review this

A Stream Host with an IPv6 address as the Forward Host was accepted and
saved but never activated. The generated stream config rendered
`proxy_pass {{ forwarding_host }}:{{ forwarding_port }}` as e.g.
`fe80::528:3c87:e7bb:ab08:25`, which nginx rejects with
"invalid port in upstream" because an IPv6 literal must be wrapped in
square brackets before the port is appended (`[fe80::...]:25`).

Normalize the stream forward host in generateConfig (alongside the existing
per-host-type data massaging) using net.isIPv6(), so IPv6 hosts render as
`[address]:port` while IPv4 addresses and hostnames are emitted unchanged.
The mutation is applied to the deep-copied render object, so persisted and
audit data are unaffected.

Fixes NginxProxyManager#5740
@nginxproxymanagerci

Copy link
Copy Markdown

Docker Image for build 1 is available on DockerHub:

nginxproxymanager/nginx-proxy-manager-dev:pr-5741

Note

Ensure you backup your NPM instance before testing this image! Especially if there are database changes.
This is a different docker image namespace than the official image.

Warning

Changes and additions to DNS Providers require verification by at least 2 members of the community!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Stream Hosts: IPv6 Forward Host generates invalid nginx upstream syntax

1 participant