{"record":{"id":"0e9a7af2abe777d7","repo":"netbirdio/netbird","slug":"auth-is-not-supported-for-tcp-udp-services","errorCode":null,"errorMessage":"auth is not supported for TCP/UDP services","messagePattern":"auth is not supported for TCP/UDP services","errorType":"validation","errorClass":null,"httpStatus":400,"severity":"error","filePath":"management/internals/modules/reverseproxy/service/service.go","lineNumber":925,"sourceCode":"\treturn nil\n}\n\nfunc (s *Service) validateHTTPMode() error {\n\tif s.Domain == \"\" {\n\t\treturn errors.New(\"service domain is required\")\n\t}\n\tif s.ListenPort != 0 {\n\t\treturn errors.New(\"listen_port is not supported for HTTP services\")\n\t}\n\treturn s.validateHTTPTargets()\n}\n\nfunc (s *Service) validateTCPUDPMode() error {\n\tif s.Domain == \"\" {\n\t\treturn errors.New(\"domain is required for TCP/UDP services (used for cluster derivation)\")\n\t}\n\tif s.isAuthEnabled() {\n\t\treturn errors.New(\"auth is not supported for TCP/UDP services\")\n\t}\n\tif len(s.Targets) != 1 {\n\t\treturn errors.New(\"TCP/UDP services must have exactly one target\")\n\t}\n\tif s.Mode == ModeUDP && s.Targets[0].ProxyProtocol {\n\t\treturn errors.New(\"proxy_protocol is not supported for UDP services\")\n\t}\n\treturn s.validateL4Target(s.Targets[0])\n}\n\nfunc (s *Service) validateTLSMode() error {\n\tif s.Domain == \"\" {\n\t\treturn errors.New(\"domain is required for TLS services (used for SNI matching)\")\n\t}\n\tif s.isAuthEnabled() {\n\t\treturn errors.New(\"auth is not supported for TLS services\")\n\t}\n\tif s.ListenPort == 0 {","sourceCodeStart":907,"sourceCodeEnd":943,"githubUrl":"https://github.com/netbirdio/netbird/blob/93e97f4bf1ad715072dcb3fb6cdb1763431b5a9c/management/internals/modules/reverseproxy/service/service.go#L907-L943","documentation":"Returned by validateTCPUDPMode when isAuthEnabled() is true: any of password_auth, pin_auth, bearer_auth, or an entry in header_auths with enabled=true triggers it. TCP/UDP modes are byte-stream/datagram passthrough and cannot present an HTTP auth challenge, so the combination is rejected outright rather than silently ignored.","triggerScenarios":"Creating a tcp/udp service whose payload still carries auth.password_auth.enabled=true, auth.pin_auth, auth.bearer_auth, or auth.header_auths[*].enabled=true; switching a previously HTTP service with basic auth to mode tcp without stripping the auth block.","commonSituations":"Cloning an HTTP service JSON (which had basic auth) for a new database TCP forward. A UI auth tab left enabled when the mode dropdown changed to TCP. A version upgrade where auth fields on L4 services were previously ignored and are now validated, breaking old automation payloads.","solutions":["Remove or set enabled=false on all auth blocks (password_auth, pin_auth, bearer_auth, header_auths) for the tcp/udp service.","If callers genuinely need a login screen, keep the service in http mode where auth is supported.","Restrict access at the network layer instead: NetBird access groups, ACLs, or access_restrictions (allowed_cidrs).","Audit the full auth object, not just one sub-block - isAuthEnabled() checks every auth type."],"exampleFix":"// before\n{\n  \"mode\": \"tcp\",\n  \"listen_port\": 3306,\n  \"auth\": { \"password_auth\": { \"enabled\": true, \"password\": \"secret\" } },\n  \"targets\": [...]\n}\n\n// after\n{\n  \"mode\": \"tcp\",\n  \"listen_port\": 3306,\n  \"targets\": [...]\n}","handlingStrategy":"validation","validationCode":"func anyAuthEnabled(a AuthConfig) bool {\n\tif (a.PasswordAuth != nil && a.PasswordAuth.Enabled) ||\n\t\t(a.PinAuth != nil && a.PinAuth.Enabled) ||\n\t\t(a.BearerAuth != nil && a.BearerAuth.Enabled) {\n\t\treturn true\n\t}\n\tfor _, h := range a.HeaderAuths {\n\t\tif h != nil && h.Enabled {\n\t\t\treturn true\n\t\t}\n\t}\n\treturn false\n}\n\nfunc checkL4NoAuth(mode string, auth AuthConfig) error {\n\tif (mode == \"tcp\" || mode == \"udp\") && anyAuthEnabled(auth) {\n\t\treturn errors.New(\"strip all auth blocks for tcp/udp services\")\n\t}\n\treturn nil\n}","typeGuard":"func isL4AuthClean(mode string, auth AuthConfig) bool {\n\tif mode != \"tcp\" && mode != \"udp\" {\n\t\treturn true\n\t}\n\treturn !anyAuthEnabled(auth)\n}","tryCatchPattern":"if err := svc.Validate(); err != nil {\n\tif strings.Contains(err.Error(), \"auth is not supported for TCP/UDP\") {\n\t\treturn respondBadRequest(errors.New(\"remove auth or switch to http mode\"))\n\t}\n\treturn respondBadRequest(err)\n}","preventionTips":["When switching a service's mode in automation, re-derive the whole payload instead of patching one field.","Remember all four auth types count: password, pin, bearer, header.","For L4 access control use NetBird groups/ACLs or access_restrictions, never the auth block."],"tags":["netbird","reverse-proxy","validation","auth","l4","configuration","go"],"backgroundTag":null,"analyzedSha":"93e97f4bf1ad715072dcb3fb6cdb1763431b5a9c","analyzedAt":"2026-08-16T03:09:19.136Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}