[GH-ISSUE #6068] Reverse Proxy: TLS passthrough not working #12087

Open
opened 2026-08-05 01:32:23 -04:00 by saavagebueno · 15 comments
Owner

Originally created by @johannesbolnbach on GitHub (May 4, 2026).
Original GitHub issue: https://github.com/netbirdio/netbird/issues/6068

Describe the problem

It just shows "Error" in the UI..

Image

When I open the domain, it gives me a 404 page:

Image

When I use https as service type, it works fine.

To Reproduce

Host some TLS app and use "TLS" type when setting up the service.

Expected behavior

Should work normally.

Are you using NetBird Cloud?

I am using https://app.netbird.io/reverse-proxy/services

NetBird version

0.70.4

Is any other VPN software installed?

No

Debug output

To help us resolve the problem, please attach the following anonymized status output

Peers detail:
 proxy-d7sft1afadhs73d7hsdg-92-109.netbird.cloud:
  NetBird IP: 100.113.92.109
  Public key: uOTHhN4EvIENj1HdTFihX/oXAPq2RXPWKiPV0ByR1yo=
  Status: Connecting
  -- detail --
  Connection type: -
  ICE candidate (Local/Remote): -/-
  ICE candidate endpoints (Local/Remote): -/-
  Relay server address: 
  Last connection update: 34 seconds ago
  Last WireGuard handshake: -
  Transfer status (received/sent) 0 B/0 B
  Quantum resistance: false
  Networks: -
  Latency: 0s

 proxy-d7sfqiafadhs73d6shpg-111-108.netbird.cloud:
  NetBird IP: 100.113.111.108
  Public key: 3GlInK5CT+992p9uEfCZvUFG2JEx6oSU16ygfkI6iHo=
  Status: Connecting
  -- detail --
  Connection type: -
  ICE candidate (Local/Remote): -/-
  ICE candidate endpoints (Local/Remote): -/-
  Relay server address: 
  Last connection update: 36 seconds ago
  Last WireGuard handshake: -
  Transfer status (received/sent) 0 B/0 B
  Quantum resistance: false
  Networks: -
  Latency: 0s

 proxy-d7sft1bl0ubs73aqr3k0-114-147.netbird.cloud:
  NetBird IP: 100.113.114.147
  Public key: Hz/XSedm8DeXF5L2pdViqzFTqRKOaySvdGtt8hv8m20=
  Status: Connecting
  -- detail --
  Connection type: -
  ICE candidate (Local/Remote): -/-
  ICE candidate endpoints (Local/Remote): -/-
  Relay server address: 
  Last connection update: 34 seconds ago
  Last WireGuard handshake: -
  Transfer status (received/sent) 0 B/0 B
  Quantum resistance: false
  Networks: -
  Latency: 0s

 proxy-d7sfqibl0ubs73apuadg-228-158.netbird.cloud:
  NetBird IP: 100.113.228.158
  Public key: 92z97j74NVqo9YRUsesqJG3LWhYeojo3YwEFkZrFaHI=
  Status: Connecting
  -- detail --
  Connection type: -
  ICE candidate (Local/Remote): -/-
  ICE candidate endpoints (Local/Remote): -/-
  Relay server address: 
  Last connection update: 36 seconds ago
  Last WireGuard handshake: -
  Transfer status (received/sent) 0 B/0 B
  Quantum resistance: false
  Networks: -
  Latency: 0s

Events:
  [INFO] SYSTEM (89d9b064-5144-440c-8200-87864b2cb91b)
    Message: Network map updated
    Time: 11 minutes, 5 seconds ago
  [INFO] SYSTEM (c2eb24ec-62b5-4384-8e0f-d6d5814f6440)
    Message: Network map updated
    Time: 11 minutes, 4 seconds ago
  [INFO] SYSTEM (20c17d60-68cc-4a4b-8687-bc120170d8fd)
    Message: Network map updated
    Time: 6 minutes, 26 seconds ago
  [INFO] SYSTEM (8f9266f9-a5fe-4677-ad10-7f84d3ebab18)
    Message: Network map updated
    Time: 5 minutes, 51 seconds ago
  [INFO] SYSTEM (31eb2fd5-9564-4edd-9788-60cf7e47bfbb)
    Message: Network map updated
    Time: 5 minutes, 50 seconds ago
  [INFO] SYSTEM (60da252e-9ad2-4c6b-ae6b-c122bc4ec5bf)
    Message: Network map updated
    Time: 5 minutes, 14 seconds ago
  [INFO] SYSTEM (42b70a10-b073-467f-9936-35101d543eb6)
    Message: Network map updated
    Time: 1 minute, 44 seconds ago
  [INFO] SYSTEM (dfe2d4b0-037a-4626-9336-7697eec758a0)
    Message: Network map updated
    Time: 41 seconds ago
  [INFO] SYSTEM (fa9f95c9-032f-4351-a88f-fc9eee9b02e4)
    Message: Network map updated
    Time: 36 seconds ago
  [INFO] SYSTEM (b87c7879-cf6b-42b2-9128-22dc58416c2c)
    Message: Network map updated
    Time: 34 seconds ago
OS: linux/amd64
Daemon version: 0.70.4
CLI version: 0.70.4
Profile: default
Management: Connected to https://api.netbird.io:443
Signal: Connected to https://signal.netbird.io:443
Relays: 
  [stun:stun.netbird.io:443] is Available
  [stun:stun.netbird.io:5555] is Available
  [turns:turn.netbird.io:443?transport=tcp] is Available
  [rels://streamline-de-fra1-9.relay.netbird.io:443] is Available
Nameservers: 
FQDN: host.netbird.cloud
NetBird IP: 100.113.67.163/16
Interface type: Kernel
Quantum resistance: false
Lazy connection: false
SSH Server: Disabled
Networks: -
Peers count: 0/4 Connected

Additional context

Add any other context about the problem here.

Have you tried these troubleshooting steps?

  • [ x ] Reviewed client troubleshooting (if applicable)
  • [ x ] Checked for newer NetBird versions
  • [ x ] Searched for similar issues on GitHub (including closed ones)
  • [ x ] Restarted the NetBird client
  • [ x ] Disabled other VPN software
  • [ x ] Checked firewall settings
Originally created by @johannesbolnbach on GitHub (May 4, 2026). Original GitHub issue: https://github.com/netbirdio/netbird/issues/6068 **Describe the problem** It just shows "Error" in the UI.. <img width="373" height="138" alt="Image" src="https://github.com/user-attachments/assets/06fd8f0c-d189-432e-8029-38f7551ce56f" /> When I open the domain, it gives me a 404 page: <img width="505" height="196" alt="Image" src="https://github.com/user-attachments/assets/cba6c5ce-3f1f-49cc-ab1d-c33cf9f2a17c" /> When I use https as service type, it works fine. **To Reproduce** Host some TLS app and use "TLS" type when setting up the service. **Expected behavior** Should work normally. **Are you using NetBird Cloud?** I am using `https://app.netbird.io/reverse-proxy/services` **NetBird version** 0.70.4 **Is any other VPN software installed?** No **Debug output** To help us resolve the problem, please attach the following anonymized status output ``` Peers detail: proxy-d7sft1afadhs73d7hsdg-92-109.netbird.cloud: NetBird IP: 100.113.92.109 Public key: uOTHhN4EvIENj1HdTFihX/oXAPq2RXPWKiPV0ByR1yo= Status: Connecting -- detail -- Connection type: - ICE candidate (Local/Remote): -/- ICE candidate endpoints (Local/Remote): -/- Relay server address: Last connection update: 34 seconds ago Last WireGuard handshake: - Transfer status (received/sent) 0 B/0 B Quantum resistance: false Networks: - Latency: 0s proxy-d7sfqiafadhs73d6shpg-111-108.netbird.cloud: NetBird IP: 100.113.111.108 Public key: 3GlInK5CT+992p9uEfCZvUFG2JEx6oSU16ygfkI6iHo= Status: Connecting -- detail -- Connection type: - ICE candidate (Local/Remote): -/- ICE candidate endpoints (Local/Remote): -/- Relay server address: Last connection update: 36 seconds ago Last WireGuard handshake: - Transfer status (received/sent) 0 B/0 B Quantum resistance: false Networks: - Latency: 0s proxy-d7sft1bl0ubs73aqr3k0-114-147.netbird.cloud: NetBird IP: 100.113.114.147 Public key: Hz/XSedm8DeXF5L2pdViqzFTqRKOaySvdGtt8hv8m20= Status: Connecting -- detail -- Connection type: - ICE candidate (Local/Remote): -/- ICE candidate endpoints (Local/Remote): -/- Relay server address: Last connection update: 34 seconds ago Last WireGuard handshake: - Transfer status (received/sent) 0 B/0 B Quantum resistance: false Networks: - Latency: 0s proxy-d7sfqibl0ubs73apuadg-228-158.netbird.cloud: NetBird IP: 100.113.228.158 Public key: 92z97j74NVqo9YRUsesqJG3LWhYeojo3YwEFkZrFaHI= Status: Connecting -- detail -- Connection type: - ICE candidate (Local/Remote): -/- ICE candidate endpoints (Local/Remote): -/- Relay server address: Last connection update: 36 seconds ago Last WireGuard handshake: - Transfer status (received/sent) 0 B/0 B Quantum resistance: false Networks: - Latency: 0s Events: [INFO] SYSTEM (89d9b064-5144-440c-8200-87864b2cb91b) Message: Network map updated Time: 11 minutes, 5 seconds ago [INFO] SYSTEM (c2eb24ec-62b5-4384-8e0f-d6d5814f6440) Message: Network map updated Time: 11 minutes, 4 seconds ago [INFO] SYSTEM (20c17d60-68cc-4a4b-8687-bc120170d8fd) Message: Network map updated Time: 6 minutes, 26 seconds ago [INFO] SYSTEM (8f9266f9-a5fe-4677-ad10-7f84d3ebab18) Message: Network map updated Time: 5 minutes, 51 seconds ago [INFO] SYSTEM (31eb2fd5-9564-4edd-9788-60cf7e47bfbb) Message: Network map updated Time: 5 minutes, 50 seconds ago [INFO] SYSTEM (60da252e-9ad2-4c6b-ae6b-c122bc4ec5bf) Message: Network map updated Time: 5 minutes, 14 seconds ago [INFO] SYSTEM (42b70a10-b073-467f-9936-35101d543eb6) Message: Network map updated Time: 1 minute, 44 seconds ago [INFO] SYSTEM (dfe2d4b0-037a-4626-9336-7697eec758a0) Message: Network map updated Time: 41 seconds ago [INFO] SYSTEM (fa9f95c9-032f-4351-a88f-fc9eee9b02e4) Message: Network map updated Time: 36 seconds ago [INFO] SYSTEM (b87c7879-cf6b-42b2-9128-22dc58416c2c) Message: Network map updated Time: 34 seconds ago OS: linux/amd64 Daemon version: 0.70.4 CLI version: 0.70.4 Profile: default Management: Connected to https://api.netbird.io:443 Signal: Connected to https://signal.netbird.io:443 Relays: [stun:stun.netbird.io:443] is Available [stun:stun.netbird.io:5555] is Available [turns:turn.netbird.io:443?transport=tcp] is Available [rels://streamline-de-fra1-9.relay.netbird.io:443] is Available Nameservers: FQDN: host.netbird.cloud NetBird IP: 100.113.67.163/16 Interface type: Kernel Quantum resistance: false Lazy connection: false SSH Server: Disabled Networks: - Peers count: 0/4 Connected ``` **Additional context** Add any other context about the problem here. **Have you tried these troubleshooting steps?** - [ x ] Reviewed [client troubleshooting](https://docs.netbird.io/how-to/troubleshooting-client) (if applicable) - [ x ] Checked for newer NetBird versions - [ x ] Searched for similar issues on GitHub (including closed ones) - [ x ] Restarted the NetBird client - [ x ] Disabled other VPN software - [ x ] Checked firewall settings
Author
Owner

@johannesbolnbach commented on GitHub (May 4, 2026):

I tested it with a windows peer (default settings) and it failed as well.

It first shows "Setting up device", but then again just fails..

Image Image
<!-- gh-comment-id:4375181894 --> @johannesbolnbach commented on GitHub (May 4, 2026): I tested it with a windows peer (default settings) and it failed as well. It first shows "Setting up device", but then again just fails.. <img width="201" height="79" alt="Image" src="https://github.com/user-attachments/assets/edf2387a-752e-48db-bb01-9c82c2e1a775" /> <img width="107" height="64" alt="Image" src="https://github.com/user-attachments/assets/7c07af42-2c79-4e3c-9b35-09ddee1097af" />
Author
Owner

@web2brain commented on GitHub (May 5, 2026):

Experiencing the same issue

<!-- gh-comment-id:4380667260 --> @web2brain commented on GitHub (May 5, 2026): Experiencing the same issue
Author
Owner

@lukuichina commented on GitHub (May 8, 2026):

So did I

<!-- gh-comment-id:4410795085 --> @lukuichina commented on GitHub (May 8, 2026): So did I
Author
Owner

@lukuichina commented on GitHub (May 14, 2026):

Do not use the default remote 443 port.
It will work well

■Video
https://youtu.be/A15xiNuo-Z0

<!-- gh-comment-id:4450037772 --> @lukuichina commented on GitHub (May 14, 2026): Do not use the default remote 443 port. It will work well ■Video https://youtu.be/A15xiNuo-Z0
Author
Owner

@Lemmmma commented on GitHub (May 16, 2026):

There seems to be an issue with certain ports. I can set up the service on listen port 443 but when I try to connect I get SSL_ERROR_INTERNAL_ERROR_ALERT. On the ports I tested so far it works fine for listen ports 7000, 7001, 7443, 9443 and 10443. However, on ports 444 and 8443 I can set up the service but I get a timeout instead when trying to connect. This is while keeping the local port of the service the same

<!-- gh-comment-id:4468446369 --> @Lemmmma commented on GitHub (May 16, 2026): There seems to be an issue with certain ports. I can set up the service on listen port 443 but when I try to connect I get SSL_ERROR_INTERNAL_ERROR_ALERT. On the ports I tested so far it works fine for listen ports 7000, 7001, 7443, 9443 and 10443. However, on ports 444 and 8443 I can set up the service but I get a timeout instead when trying to connect. This is while keeping the local port of the service the same
Author
Owner

@erdelmaero commented on GitHub (May 19, 2026):

Confirming on self-hosted v0.71.0 (not just Cloud), and adding the underlying error from netbird-proxy since I don't see it in the thread yet — may help locate the bug:

WARN [http-server: https] http: TLS handshake error from <client-ip>: acme/autocert: unknown domain "<service-domain>"

The autocert library rejects the SNI with a 7-byte TLS alert (tlsv1 alert internal error, SSL alert 80) because the domain isn't in its host policy. This matches openssl s_client reporting "7 bytes read … no peer certificate available" and Firefox/Chrome showing SSL_ERROR_INTERNAL_ERROR_ALERT (mentioned upthread).

Worth noting: netbird-proxy does register the service correctly otherwise — I see this immediately after creating the service:

INFO [target: <internal-ip>:<port>, port: 443, service: <id>, domain: <service-domain>] proxy/server.go:1319: TLS passthrough mapping added

So the TLS-passthrough mapping is wired up; the issue appears to be that autocert sits in front of it and isn't told to allow mode=tls service domains through. The service record's meta.certificate_issued_at is never populated for mode=tls services (it is populated normally for mode=http), which seems consistent with that diagnosis — autocert never issues because the domain isn't in the policy.

Things that don't help (tried):

  • Restarting netbird-proxy
  • Deleting and recreating the service via the API (POST /api/reverse-proxies/services) — new record, same broken state

The workaround from @lukuichina / @Lemmmma (use a non-443 listen_port) is consistent with the diagnosis: a different listen_port lands the SNI on a TCP listener that isn't fronted by the autocert HTTPS handler.

<!-- gh-comment-id:4488807858 --> @erdelmaero commented on GitHub (May 19, 2026): Confirming on **self-hosted v0.71.0** (not just Cloud), and adding the underlying error from `netbird-proxy` since I don't see it in the thread yet — may help locate the bug: ``` WARN [http-server: https] http: TLS handshake error from <client-ip>: acme/autocert: unknown domain "<service-domain>" ``` The autocert library rejects the SNI with a 7-byte TLS alert (`tlsv1 alert internal error`, SSL alert 80) because the domain isn't in its host policy. This matches `openssl s_client` reporting *"7 bytes read … no peer certificate available"* and Firefox/Chrome showing `SSL_ERROR_INTERNAL_ERROR_ALERT` (mentioned upthread). Worth noting: `netbird-proxy` *does* register the service correctly otherwise — I see this immediately after creating the service: ``` INFO [target: <internal-ip>:<port>, port: 443, service: <id>, domain: <service-domain>] proxy/server.go:1319: TLS passthrough mapping added ``` So the TLS-passthrough mapping is wired up; the issue appears to be that **autocert sits in front of it and isn't told to allow `mode=tls` service domains through**. The service record's `meta.certificate_issued_at` is never populated for `mode=tls` services (it is populated normally for `mode=http`), which seems consistent with that diagnosis — autocert never issues because the domain isn't in the policy. Things that don't help (tried): - Restarting `netbird-proxy` - Deleting and recreating the service via the API (`POST /api/reverse-proxies/services`) — new record, same broken state The workaround from @lukuichina / @Lemmmma (use a non-443 `listen_port`) is consistent with the diagnosis: a different `listen_port` lands the SNI on a TCP listener that isn't fronted by the autocert HTTPS handler.
Author
Owner

@Lemmmma commented on GitHub (May 23, 2026):

I also did some experimenting using the self-hosted server. It seems that changing the label

- traefik.tcp.services.proxy-tls.loadbalancer.server.port=8443

in the docker-compose proxy service to

- traefik.tcp.services.proxy-tls.loadbalancer.server.port=443

fixed the problem and lets me do a working TLS passthrough on port 443. However, I'm not sure if this breaks anything else.

<!-- gh-comment-id:4526536675 --> @Lemmmma commented on GitHub (May 23, 2026): I also did some experimenting using the self-hosted server. It seems that changing the label ``` - traefik.tcp.services.proxy-tls.loadbalancer.server.port=8443 ``` in the docker-compose proxy service to ``` - traefik.tcp.services.proxy-tls.loadbalancer.server.port=443 ``` fixed the problem and lets me do a working TLS passthrough on port 443. However, I'm not sure if this breaks anything else.
Author
Owner

@erdelmaero commented on GitHub (May 24, 2026):

Following up on @Lemmmma's comment:

changing the label
- traefik.tcp.services.proxy-tls.loadbalancer.server.port=8443
in the docker-compose proxy service to
- traefik.tcp.services.proxy-tls.loadbalancer.server.port=443
fixed the problem and lets me do a working TLS passthrough on port 443. However, I'm not sure if this breaks anything else.

This works cleanly only if all services routed through the catch-all are mode=tls.

Mechanism: the label flip reroutes Traefik's TCP passthrough to netbird-proxy's per-port router on :443, which lives outside the autocert host-policy gate. But per-port routers only spin up when a mode=tls service registers with that listen_port. Any mode=http services on the same proxy (HTTP-level routing, pass_host_header, OAuth callback paths, path-based service mapping) stay on the main :8443 HTTPS handler with autocert — and after the label change, no longer receive traffic.

Verified on a stack with mixed mode=http + mode=tls: nothing listens on :443 inside the container unless an explicit listen_port=443 service is configured.

So this is a viable workaround for SNI-passthrough-only deployments, but it breaks HTTP-routed services in a mixed deployment.

The proper fix is upstream: register mode=tls service domains in autocert's host policy (or skip the autocert layer entirely for per-port-router SNIs).

<!-- gh-comment-id:4527811278 --> @erdelmaero commented on GitHub (May 24, 2026): Following up on **@Lemmmma**'s comment: > changing the label > `- traefik.tcp.services.proxy-tls.loadbalancer.server.port=8443` > in the docker-compose proxy service to > `- traefik.tcp.services.proxy-tls.loadbalancer.server.port=443` > fixed the problem and lets me do a working TLS passthrough on port 443. However, I'm not sure if this breaks anything else. This works cleanly **only if all services routed through the catch-all are `mode=tls`**. **Mechanism:** the label flip reroutes Traefik's TCP passthrough to netbird-proxy's per-port router on `:443`, which lives outside the autocert host-policy gate. But per-port routers only spin up when a `mode=tls` service registers with that `listen_port`. Any `mode=http` services on the same proxy (HTTP-level routing, `pass_host_header`, OAuth callback paths, path-based service mapping) stay on the main `:8443` HTTPS handler with autocert — and after the label change, no longer receive traffic. **Verified** on a stack with mixed `mode=http` + `mode=tls`: nothing listens on `:443` inside the container unless an explicit `listen_port=443` service is configured. So this is a viable workaround for SNI-passthrough-only deployments, but it breaks HTTP-routed services in a mixed deployment. **The proper fix is upstream:** register `mode=tls` service domains in autocert's host policy (or skip the autocert layer entirely for per-port-router SNIs).
Author
Owner

@tnucera commented on GitHub (Jun 3, 2026):

NetBird Cloud (eu1) — same failure; differential evidence that the proxy never starts its peer side for mode=tls services

Reproduced on NetBird Cloud, eu1.netbird.services, validated custom domain, agent v0.71.4 on the routing peer:

  • mode=tls service (TLS passthrough, listen 443, subnet target behind a routing peer) → dashboard stuck on error ("Something went wrong while setting up this service"), zero Proxy Events.
  • Edge behaves as if the SNI was never registered: openssl s_client with the configured service SNI returns TLS alert 80 (internal_error) immediately after ClientHello — byte-identical to an unknown/unconfigured SNI and to no SNI at all. The tls service registered no route at the edge.
  • Routing peer logs show the proxy's ephemeral peer never comes up for tls services. Same routing peer, same account, ~30 min apart:
    • tls service peer: SentOffer: 17, RemoteOffer: 0, RemoteAnswer: 0, RemoteCandidate: 0, RelayConnected: 0 — the peer is pushed by management, our side keeps offering, the proxy side never answers, the peer is then removed on the next sync (loops on every enable).
    • http (L7) control service on the same target host: RemoteOffer: 3, RemoteAnswer: 4, RemoteCandidate: 14, RelayConnected: 1, LocalProxies: 1 — connects in seconds and serves traffic first try.
  • This matches the autocert host-policy / per-port-router analysis above: the service setup aborts proxy-side for mode=tls, while management still provisions the ephemeral peers.
  • The "non-443 listen port" workaround is not available on Cloud: both built-in and custom domains report supports_custom_ports: false via the API.

Happy to share account/service IDs privately.

<!-- gh-comment-id:4614273145 --> @tnucera commented on GitHub (Jun 3, 2026): **NetBird Cloud (eu1) — same failure; differential evidence that the proxy never starts its peer side for `mode=tls` services** Reproduced on NetBird Cloud, `eu1.netbird.services`, validated custom domain, agent v0.71.4 on the routing peer: - `mode=tls` service (TLS passthrough, listen 443, subnet target behind a routing peer) → dashboard stuck on `error` ("Something went wrong while setting up this service"), zero Proxy Events. - **Edge behaves as if the SNI was never registered**: `openssl s_client` with the configured service SNI returns `TLS alert 80 (internal_error)` immediately after ClientHello — byte-identical to an unknown/unconfigured SNI and to no SNI at all. The tls service registered no route at the edge. - **Routing peer logs show the proxy's ephemeral peer never comes up for tls services.** Same routing peer, same account, ~30 min apart: - tls service peer: `SentOffer: 17, RemoteOffer: 0, RemoteAnswer: 0, RemoteCandidate: 0, RelayConnected: 0` — the peer is pushed by management, our side keeps offering, the proxy side never answers, the peer is then removed on the next sync (loops on every enable). - http (L7) control service on the **same target host**: `RemoteOffer: 3, RemoteAnswer: 4, RemoteCandidate: 14, RelayConnected: 1, LocalProxies: 1` — connects in seconds and serves traffic first try. - This matches the autocert host-policy / per-port-router analysis above: the service setup aborts proxy-side for `mode=tls`, while management still provisions the ephemeral peers. - The "non-443 listen port" workaround is **not available on Cloud**: both built-in and custom domains report `supports_custom_ports: false` via the API. Happy to share account/service IDs privately.
Author
Owner

@polettix commented on GitHub (Jun 7, 2026):

Just out of curiosity, is this "beta" of TLS passthrough working for anyone?

It never worked for me, even though my setup is as basic as possible:

  • Cloud-based, no self-hosting where I could botch the whole thing
  • I'm always updating the netbird client in Linux before trying to use the feature
  • I'm not doing any tweaking on the client side, just netbird up, logging in and confirming that the peer is marked as being up
  • The Custom Domain is Active in the web interface, pointing to eu1.netbird.services which is the one and only option available (even though the docs say it should be eu.proxy.netbird.io, whatever)
  • I just follow the instructions and the web form for adding a Service with TLS Passthrough.
  • The service is up and using a self-signed certificate; it can be invoked successfully by another Peer on its target port.

Using ports 443 and 8443 simply gives a plain Error in the web interface like many others pointed out.

Using port 10443 as hinted in some other post here gets rid of the Error in the web interface but does not work practically:

# from the outside
$ curl -k https://***:10443/
curl: (35) OpenSSL SSL_connect: SSL_ERROR_SYSCALL in connection to ***:10443

$ openssl s_client -connect ***:10443
CONNECTED(00000003)
400725546D760000:error:0A000126:SSL routines:ssl3_read_n:unexpected eof while reading:../ssl/record/rec_layer_s3.c:318:
---
no peer certificate available
---
No client certificate CA names sent
---
SSL handshake has read 0 bytes and written 345 bytes
Verification: OK
---
New, (NONE), Cipher is (NONE)
Secure Renegotiation IS NOT supported
Compression: NONE
Expansion: NONE
No ALPN negotiated
Early data was not sent
Verify return code: 0 (ok)
---

I also tried to use the free domain, with the same results as above.

So back to my initial question: is TLS Passthrough working for anyone?

<!-- gh-comment-id:4642109176 --> @polettix commented on GitHub (Jun 7, 2026): Just out of curiosity, is this "beta" of TLS passthrough working for anyone? It **never** worked for me, even though my setup is as basic as possible: * Cloud-based, no self-hosting where I could botch the whole thing * I'm always updating the netbird client in Linux before trying to use the feature * I'm not doing any tweaking on the client side, just `netbird up`, logging in and confirming that the peer is marked as being *up* * The Custom Domain is `Active` in the web interface, pointing to `eu1.netbird.services` which is the one and only option available (even though the docs say it should be `eu.proxy.netbird.io`, whatever) * I just follow the instructions and the web form for adding a Service with TLS Passthrough. * The service is up and using a self-signed certificate; it can be invoked successfully by another Peer on its target port. Using ports 443 and 8443 simply gives a plain `Error` in the web interface like many others pointed out. Using port 10443 as hinted in some other post here gets rid of the `Error` in the web interface but does not work practically: ``` # from the outside $ curl -k https://***:10443/ curl: (35) OpenSSL SSL_connect: SSL_ERROR_SYSCALL in connection to ***:10443 $ openssl s_client -connect ***:10443 CONNECTED(00000003) 400725546D760000:error:0A000126:SSL routines:ssl3_read_n:unexpected eof while reading:../ssl/record/rec_layer_s3.c:318: --- no peer certificate available --- No client certificate CA names sent --- SSL handshake has read 0 bytes and written 345 bytes Verification: OK --- New, (NONE), Cipher is (NONE) Secure Renegotiation IS NOT supported Compression: NONE Expansion: NONE No ALPN negotiated Early data was not sent Verify return code: 0 (ok) --- ``` I also tried to use the free domain, with the same results as above. So back to my initial question: is TLS Passthrough working for anyone?
Author
Owner

@mariowolff commented on GitHub (Jul 3, 2026):

Just to let you know: Updated my self- hosted environment this morning to
{
"dashboard_available_version": "2.90.3",
"management_available_version": "0.74.1",
"management_current_version": "0.74.1",
"management_update_available": false
}
and this problem still exists!

<!-- gh-comment-id:4874347734 --> @mariowolff commented on GitHub (Jul 3, 2026): Just to let you know: Updated my self- hosted environment this morning to { "dashboard_available_version": "2.90.3", "management_available_version": "0.74.1", "management_current_version": "0.74.1", "management_update_available": false } and this problem still exists!
Author
Owner

@kleuveld commented on GitHub (Jul 6, 2026):

I can confirm the fix by @Lemmmma does still work. The fact that it allegedly breaks "regular" HTPPS reverse proxy doesn't bother me, so I haven't even checked it.

<!-- gh-comment-id:4892480174 --> @kleuveld commented on GitHub (Jul 6, 2026): I can confirm the fix by @Lemmmma does still work. The fact that it allegedly breaks "regular" HTPPS reverse proxy doesn't bother me, so I haven't even checked it.
Author
Owner

@Lemmmma commented on GitHub (Jul 7, 2026):

In case that does bother anyone, heres a workaround that doesn't break regular HTTPS. Just add this in your docker-compose.yml in the labels sections of the proxy service:

      - traefik.tcp.routers.proxy-passthrough-443.entrypoints=websecure
      - traefik.tcp.routers.proxy-passthrough-443.rule=HostSNI(`your-passthrough.example.com`)
      - traefik.tcp.routers.proxy-passthrough-443.tls.passthrough=true
      - traefik.tcp.routers.proxy-passthrough-443.service=proxy-tls-443
      - traefik.tcp.routers.proxy-passthrough-443.priority=2
      - traefik.tcp.services.proxy-tls-443.loadbalancer.server.port=443
      - traefik.tcp.services.proxy-tls-443.loadbalancer.serverstransport=pp-v2@file

So that the proxy section looks like

  # NetBird Proxy - exposes internal resources to the internet
  proxy:
    image: netbirdio/reverse-proxy:latest
    container_name: netbird-proxy
    ports:
    - 51820:51820/udp
    restart: unless-stopped
    networks: [netbird]
    depends_on:
      netbird-server:
        condition: service_started
      crowdsec:
        condition: service_healthy
    env_file:
      - ./proxy.env
    volumes:
      - netbird_proxy_certs:/certs
    labels:
      # TCP passthrough for any unmatched domain (proxy handles its own TLS)
      - traefik.enable=true
      # only for passthrough on port 443
      - traefik.tcp.routers.proxy-passthrough-443.entrypoints=websecure
      - traefik.tcp.routers.proxy-passthrough-443.rule=HostSNI(`your-passthrough.example.com`)
      - traefik.tcp.routers.proxy-passthrough-443.tls.passthrough=true
      - traefik.tcp.routers.proxy-passthrough-443.service=proxy-tls-443
      - traefik.tcp.routers.proxy-passthrough-443.priority=2
      - traefik.tcp.services.proxy-tls-443.loadbalancer.server.port=443
      - traefik.tcp.services.proxy-tls-443.loadbalancer.serverstransport=pp-v2@file
      # all other passthrough
      - traefik.tcp.routers.proxy-passthrough.entrypoints=websecure
      - traefik.tcp.routers.proxy-passthrough.rule=HostSNI(`*`)
      - traefik.tcp.routers.proxy-passthrough.tls.passthrough=true
      - traefik.tcp.routers.proxy-passthrough.service=proxy-tls
      - traefik.tcp.routers.proxy-passthrough.priority=1
      - traefik.tcp.services.proxy-tls.loadbalancer.server.port=8443
      - traefik.tcp.services.proxy-tls.loadbalancer.serverstransport=pp-v2@file
    logging:
      driver: "json-file"
      options:
        max-size: "500m"
        max-file: "2"

Change the HostSNI argument to the domains you want to work with TLS passthrough. TLS passthrough works perfectly fine for me like this and in some very basic testing regular HTTPS reverse proxy also seems to work fine.
If you want multiple domains you should be able to use wildcards or to separate them with commas like so:

      - traefik.tcp.routers.proxy-passthrough-443.rule=HostSNI(`your-passthrough.example.com`,`your-passthrough1.example.com`,`your-passthrough2.example.com`)
<!-- gh-comment-id:4908556335 --> @Lemmmma commented on GitHub (Jul 7, 2026): In case that does bother anyone, heres a workaround that doesn't break regular HTTPS. Just add this in your docker-compose.yml in the labels sections of the proxy service: ``` - traefik.tcp.routers.proxy-passthrough-443.entrypoints=websecure - traefik.tcp.routers.proxy-passthrough-443.rule=HostSNI(`your-passthrough.example.com`) - traefik.tcp.routers.proxy-passthrough-443.tls.passthrough=true - traefik.tcp.routers.proxy-passthrough-443.service=proxy-tls-443 - traefik.tcp.routers.proxy-passthrough-443.priority=2 - traefik.tcp.services.proxy-tls-443.loadbalancer.server.port=443 - traefik.tcp.services.proxy-tls-443.loadbalancer.serverstransport=pp-v2@file ``` So that the proxy section looks like ``` # NetBird Proxy - exposes internal resources to the internet proxy: image: netbirdio/reverse-proxy:latest container_name: netbird-proxy ports: - 51820:51820/udp restart: unless-stopped networks: [netbird] depends_on: netbird-server: condition: service_started crowdsec: condition: service_healthy env_file: - ./proxy.env volumes: - netbird_proxy_certs:/certs labels: # TCP passthrough for any unmatched domain (proxy handles its own TLS) - traefik.enable=true # only for passthrough on port 443 - traefik.tcp.routers.proxy-passthrough-443.entrypoints=websecure - traefik.tcp.routers.proxy-passthrough-443.rule=HostSNI(`your-passthrough.example.com`) - traefik.tcp.routers.proxy-passthrough-443.tls.passthrough=true - traefik.tcp.routers.proxy-passthrough-443.service=proxy-tls-443 - traefik.tcp.routers.proxy-passthrough-443.priority=2 - traefik.tcp.services.proxy-tls-443.loadbalancer.server.port=443 - traefik.tcp.services.proxy-tls-443.loadbalancer.serverstransport=pp-v2@file # all other passthrough - traefik.tcp.routers.proxy-passthrough.entrypoints=websecure - traefik.tcp.routers.proxy-passthrough.rule=HostSNI(`*`) - traefik.tcp.routers.proxy-passthrough.tls.passthrough=true - traefik.tcp.routers.proxy-passthrough.service=proxy-tls - traefik.tcp.routers.proxy-passthrough.priority=1 - traefik.tcp.services.proxy-tls.loadbalancer.server.port=8443 - traefik.tcp.services.proxy-tls.loadbalancer.serverstransport=pp-v2@file logging: driver: "json-file" options: max-size: "500m" max-file: "2" ``` Change the HostSNI argument to the domains you want to work with TLS passthrough. TLS passthrough works perfectly fine for me like this and in some very basic testing regular HTTPS reverse proxy also seems to work fine. If you want multiple domains you should be able to use wildcards or to separate them with commas like so: ``` - traefik.tcp.routers.proxy-passthrough-443.rule=HostSNI(`your-passthrough.example.com`,`your-passthrough1.example.com`,`your-passthrough2.example.com`) ```
Author
Owner

@kleuveld commented on GitHub (Jul 9, 2026):

The only thing that doesn't work for me is disabling a service. The service will be greyed out in the GUI, but netbird will happily continue forwarding traffic, which seems odd and potentially unsafe. I haven't noticed this with HTTP(s) services.

<!-- gh-comment-id:4928271671 --> @kleuveld commented on GitHub (Jul 9, 2026): The only thing that doesn't work for me is disabling a service. The service will be greyed out in the GUI, but netbird will happily continue forwarding traffic, which seems odd and potentially unsafe. I haven't noticed this with HTTP(s) services.
Author
Owner

@sdegroot commented on GitHub (Jul 12, 2026):

I've been in contact @emrcbrn via email. He mentioned they're going to have a look. As of today I still see 'Error' upon creating a TLS Passthrough service in Netbird (Cloud)

<!-- gh-comment-id:4952085594 --> @sdegroot commented on GitHub (Jul 12, 2026): I've been in contact @emrcbrn via email. He mentioned they're going to have a look. As of today I still see 'Error' upon creating a TLS Passthrough service in Netbird (Cloud)
Sign in to join this conversation.
No Label
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: DYNR/netbird#12087