Skip to content

gRPC client sets :authority header with port, breaking GKE Gateway compatibility #5086

@eliminyro

Description

@eliminyro

Description

When connecting to a NetBird management server behind a GKE Gateway (Google Kubernetes Engine Gateway API), native clients fail with:

retrying Login to the Management service in 1.102599784s due to error rpc error: code = Unknown desc = getting device authorization flow info failed with error: failed while getting Management Service public key

Extended debugging reveals the underlying gRPC error:

GRPC_GO_LOG_VERBOSITY_LEVEL=99 GRPC_GO_LOG_SEVERITY_LEVEL=info sudo netbird up -F -l debug --management-url https://nb-api.example.com
2026-01-10T17:07:08+01:00 DEBG client/net/dialer_dial.go:20: Dialing tcp nb-api.example.com:443
2026-01-10T17:07:09+01:00 DEBG client/internal/login.go:65: connected to the Management service https://nb-api.example.com:443
2026-01-10T17:07:09+01:00 ERRO shared/management/client/grpc.go:282: failed while getting Management Service public key: rpc error: code = Unimplemented desc = fault filter abort
2026-01-10T17:07:09+01:00 ERRO client/internal/login.go:111: failed while getting Management Service public key: failed while getting Management Service public key
2026-01-10T17:07:09+01:00 WARN client/cmd/root.go:248: retrying Login to the Management service in 963.390646ms due to error failed while getting Management Service public key

Root Cause

The NetBird gRPC client sends the :authority HTTP/2 pseudo-header with the port included (e.g., nb-api.example.com:443), but GKE Gateway's HTTPRoute only matches hostnames without ports (e.g., nb-api.example.com). This causes the gateway to reject the request with "fault filter abort".

Evidence

Testing with grpcurl reproduces the issue:

# Fails - sends :authority with port
$ grpcurl -proto management.proto nb-api.example.com:443 management.ManagementService/GetServerKey
ERROR: Code: Unimplemented, Message: fault filter abort

# Works - explicit authority without port
$ grpcurl -authority nb-api.example.com -proto management.proto nb-api.example.com:443 management.ManagementService/GetServerKey
{
  "key": "...",
  "expiresAt": ...
}

Additionally, curl (which sends :authority without port) works correctly:

$ curl --http2 -X POST -H "Content-Type: application/grpc" https://nb-api.example.com/management.ManagementService/GetServerKey
# Returns grpc-status: 2 (expected for empty request body)

Direct connection via kubectl port-forward (bypassing the gateway) works perfectly, confirming the management server itself is correctly configured.

Environment

  • Deployment: Self-hosted NetBird on GKE
  • Gateway: GKE Gateway API with gke-l7-regional-external-managed gateway class
  • NetBird version: latest (netbirdio/management:latest)
  • Client: Native macOS client
  • Protocol: gRPC over HTTPS (TLS termination at gateway, re-encryption to backend)

Expected Behavior

The gRPC client should send the :authority header without the port when connecting to standard HTTPS port 443, matching the behavior of other HTTP/2 clients like curl.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions