Skip to content

[reverse-proxy] Support multiple port mappings per service - #723

Draft
heywander wants to merge 3 commits into
netbirdio:mainfrom
free-netbird:codex/multiport-pr
Draft

[reverse-proxy] Support multiple port mappings per service#723
heywander wants to merge 3 commits into
netbirdio:mainfrom
free-netbird:codex/multiport-pr

Conversation

@heywander

@heywander heywander commented Jul 21, 2026

Copy link
Copy Markdown

Issue ticket number and link

Related to netbirdio/netbird#5821

Backend companion: netbirdio/netbird#6842

This draft adds the dashboard side of the multi-port reverse-proxy feature:

  • Edit multiple TCP and UDP mappings inside one service instead of duplicating the entire service form.
  • Add, remove, and reorder mappings.
  • Configure a listener port or inclusive range and its destination port or range.
  • Show inline validation for invalid ports, reversed ranges, mismatched range sizes, duplicate mappings, and listener conflicts.
  • Preserve editing of existing legacy single-port services.
  • Support compatible services sharing a hostname, including HTTPS with non-conflicting raw TCP/UDP listeners.
  • Keep TLS passthrough hostname-exclusive.
  • Extend reverse-proxy Playwright coverage for TCP, UDP, translated ranges, mapping deletion, and HTTPS/L4 shared-domain behavior.

Validation

  • Production dashboard build completed successfully, including type checking, static generation, and postbuild processing.
  • Relevant Playwright specs were exercised against the coordinated locally built management and reverse-proxy stack.
  • A VPS Docker deployment was used to confirm the updated form and raw-port publication behavior.

This is a draft pending maintainer confirmation of the backend model in netbirdio/netbird#6842.

Documentation

Select exactly one:

  • I added/updated documentation for this change
  • Documentation is not needed for this change (explain why)

Docs PR URL (required if "docs added" is checked)

netbirdio/docs#867

E2E tests

The new tests require the compatible management and reverse-proxy implementation from netbirdio/netbird#6842. The upstream image tags remain on main until that implementation is available as NetBird-hosted PR images or is merged.

management-cloud-tag: main
reverse-proxy-tag: main

Summary by CodeRabbit

  • New Features
    • Added support for multiple TCP, UDP, and TLS port mappings per Layer 4 service.
    • Added a port-mapping editor to add, remove, reorder, and configure listener and destination port ranges.
    • Added validation for invalid, overlapping, or inconsistent port ranges.
    • Split timeout settings into separate connection and UDP session idle timeouts.
    • Improved domain conflict handling to enable safe HTTPS hostname reuse across compatible service modes.
  • Tests
    • Expanded end-to-end coverage for HTTPS, TCP, and UDP reverse-proxy service creation/edit flows, including mixed protocol mapping behavior.

@CLAassistant

CLAassistant commented Jul 21, 2026

Copy link
Copy Markdown

CLA assistant check
All committers have signed the CLA.

@coderabbitai

coderabbitai Bot commented Jul 21, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: ef0650b6-9a47-47c3-9174-d96ea503d27a

📥 Commits

Reviewing files that changed from the base of the PR and between da81b99 and ea0fa06.

📒 Files selected for processing (3)
  • e2e/tests/reverse-proxy-services-https.spec.ts
  • e2e/tests/reverse-proxy-services-tcp.spec.ts
  • src/modules/reverse-proxy/ReverseProxyHTTPTargets.tsx
🚧 Files skipped from review as they are similar to previous changes (2)
  • e2e/tests/reverse-proxy-services-https.spec.ts
  • e2e/tests/reverse-proxy-services-tcp.spec.ts

📝 Walkthrough

Walkthrough

Reverse-proxy L4 services now support multiple TCP, UDP, and TLS port mappings, mode-aware domain conflict checks, separate timeout settings, updated payload handling, and expanded end-to-end coverage.

Changes

Reverse-proxy L4 services

Layer / File(s) Summary
Mapping contracts and domain conflict rules
src/interfaces/ReverseProxy.ts, src/modules/reverse-proxy/domain/useReverseProxyDomain.ts
Adds typed port mappings and normalized, mode-aware domain conflict checks.
Multi-port mapping editor
src/modules/reverse-proxy/ReverseProxyLayer4Content.tsx
Replaces single-port inputs with editable, reorderable TCP/UDP/TLS mapping cards and per-mapping validation.
Modal state and submission integration
src/modules/reverse-proxy/ReverseProxyModal.tsx
Integrates mapping state, separate timeout controls, validation, payload construction, and service-mode synchronization.
End-to-end L4 service coverage
e2e/tests/reverse-proxy-services-*.spec.ts, src/modules/reverse-proxy/ReverseProxyHTTPTargets.tsx
Covers mixed mappings, domain reuse, UDP-specific behavior, layout constraints, persistence, editing, deletion, and stable HTTPS target queries.

Estimated code review effort: 4 (Complex) | ~60 minutes

Poem

A rabbit hops through ports in rows,
With TCP, UDP, TLS it goes.
Mappings turn and errors clear,
Timeout carrots draw near.
The proxy dashboard blooms anew!

Sequence Diagram(s)

sequenceDiagram
  participant Dashboard
  participant ReverseProxyModal
  participant MappingEditor
  participant ReverseProxyAPI
  Dashboard->>ReverseProxyModal: configure an L4 service
  ReverseProxyModal->>MappingEditor: render port mappings
  MappingEditor-->>ReverseProxyModal: return validated mappings
  ReverseProxyModal->>ReverseProxyAPI: submit service and port mappings
  ReverseProxyAPI-->>ReverseProxyModal: return creation result
Loading
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed It clearly summarizes the main change: supporting multiple port mappings per reverse-proxy service.
Description check ✅ Passed It includes the issue reference, documentation choice with PR URL, and the E2E test configuration block.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Warning

Review ran into problems

🔥 Problems

Git: Failed to clone repository. Please run the @coderabbitai full review command to re-trigger a full review. If the issue persists, set path_filters to include or exclude specific files.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
e2e/tests/reverse-proxy-services-https.spec.ts (1)

1-1: 🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win

Missing { force: true } on mapping-protocol combobox clicks (same root cause across two files). These Radix Select triggers are clicked inside the service-creation modal, where every sibling trigger click (service-mode-select-button, service-mode-option-*) uses { force: true } to avoid the documented Radix outside-click/pointer-events timing issue; these mapping-protocol trigger clicks don't, risking intermittent flakiness.

  • e2e/tests/reverse-proxy-services-https.spec.ts#L151-155: add { force: true } to both secondMapping.getByRole("combobox").click() calls.
  • e2e/tests/reverse-proxy-services-tcp.spec.ts#L94-94: add { force: true } to udpMapping.getByRole("combobox").click().
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@e2e/tests/reverse-proxy-services-https.spec.ts` at line 1, Update the
mapping-protocol combobox clicks in the HTTPS and TCP reverse-proxy tests to
pass { force: true }, including both clicks on secondMapping and the click on
udpMapping. Keep the existing selectors and surrounding test flow unchanged.

Source: Path instructions

🧹 Nitpick comments (1)
e2e/tests/reverse-proxy-services-https.spec.ts (1)

221-222: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Avoid .locator("..") parent traversal; prefer a dedicated data-testid container.

page.getByText("HTTPS Targets").locator("..") climbs to the text node's parent to scope the subsequent table lookup. This is brittle — any markup change (e.g., wrapping the label in an extra <span>) breaks the selector silently. As per path instructions, "Always use data-testid selectors via page.getByTestId() for element selection in Playwright tests."

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@e2e/tests/reverse-proxy-services-https.spec.ts` around lines 221 - 222,
Replace the parent traversal in the HTTPS Targets assertion with a dedicated
data-testid container selected via page.getByTestId(). Scope the existing table
row count assertion to that test-id element, and ensure the corresponding
container markup exposes the stable test id.

Source: Path instructions

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@e2e/tests/reverse-proxy-services-https.spec.ts`:
- Around line 151-155: Update both secondMapping combobox click calls in the
HTTPS reverse-proxy test to pass the force option, matching the existing Radix
trigger interaction pattern; leave the surrounding TLS and TCP option selections
unchanged.
- Around line 163-193: Wrap the viewport-resize loop in a try/finally block and
move the existing page.setViewportSize(originalViewport) call into finally.
Preserve the current assertions and resize behavior while ensuring
dashboardAsOwner’s page viewport is restored even when an assertion or other
operation in the loop fails.

---

Outside diff comments:
In `@e2e/tests/reverse-proxy-services-https.spec.ts`:
- Line 1: Update the mapping-protocol combobox clicks in the HTTPS and TCP
reverse-proxy tests to pass { force: true }, including both clicks on
secondMapping and the click on udpMapping. Keep the existing selectors and
surrounding test flow unchanged.

---

Nitpick comments:
In `@e2e/tests/reverse-proxy-services-https.spec.ts`:
- Around line 221-222: Replace the parent traversal in the HTTPS Targets
assertion with a dedicated data-testid container selected via
page.getByTestId(). Scope the existing table row count assertion to that test-id
element, and ensure the corresponding container markup exposes the stable test
id.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 54d4f43e-d4f7-421c-a192-a1d6be46c170

📥 Commits

Reviewing files that changed from the base of the PR and between e4f5046 and da81b99.

📒 Files selected for processing (8)
  • e2e/tests/reverse-proxy-services-https.spec.ts
  • e2e/tests/reverse-proxy-services-tcp.spec.ts
  • e2e/tests/reverse-proxy-services-udp-no-custom-ports.spec.ts
  • e2e/tests/reverse-proxy-services-udp.spec.ts
  • src/interfaces/ReverseProxy.ts
  • src/modules/reverse-proxy/ReverseProxyLayer4Content.tsx
  • src/modules/reverse-proxy/ReverseProxyModal.tsx
  • src/modules/reverse-proxy/domain/useReverseProxyDomain.ts

Comment thread e2e/tests/reverse-proxy-services-https.spec.ts Outdated
Comment thread e2e/tests/reverse-proxy-services-https.spec.ts Outdated
@heywander
heywander marked this pull request as draft July 21, 2026 15:36
@heywander
heywander marked this pull request as ready for review July 21, 2026 15:36
@heywander
heywander marked this pull request as draft July 21, 2026 17:27
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.

2 participants