netbirdio/netbird · warning

invalid user@host format

Error message

invalid user@host format

What it means

The main IP-restriction deny in checkIPRestrictions (proxy/internal/auth/middleware.go:261). After resolving the client IP, the filter produces a restrict.Verdict: over the NetBird overlay (types.IsOverlayOrigin) only CheckCIDR applies, otherwise Check also runs Geo/CrowdSec. Verdicts other than Allow that are not in observe-only mode end here — blockIPRestriction records the reason, then the client gets 403.

Source

Thrown at client/cmd/ssh.go:497

		logLevel = flags.LogLevel
	}

	localForwards = localForwardFlags
	remoteForwards = remoteForwardFlags

	return parseHostnameAndCommand(remaining)
}

func parseHostnameAndCommand(args []string) error {
	if len(args) < 1 {
		return errors.New(hostArgumentRequired)
	}

	arg := args[0]
	if strings.Contains(arg, "@") {
		parts := strings.SplitN(arg, "@", 2)
		if len(parts) != 2 || parts[0] == "" || parts[1] == "" {
			return errors.New("invalid user@host format")
		}
		if username == "" {
			username = parts[0]
		}
		host = parts[1]
	} else {
		host = arg
	}

	if username == "" {
		if sudoUser := os.Getenv("SUDO_USER"); sudoUser != "" {
			username = sudoUser
		} else if currentUser, err := user.Current(); err == nil {
			username = currentUser.Username
		} else {
			username = "root"
		}
	}

View on GitHub (pinned to 93e97f4bf1)

Solutions

  1. Read the reason passed to blockIPRestriction (verdict.String() is logged/recorded) to learn which rule fired: CIDR, geo, or CrowdSec.
  2. Add the client's effective IP or range to the service's allowed ranges — remember the effective IP comes from CapturedData (X-Forwarded-For honored only for trusted proxies), not necessarily the TCP peer.
  3. For CrowdSec, keep the restriction in observe mode while onboarding so verdicts are only logged until the ranges are proven.
  4. For geo blocks, either add the country to the allow set or disable geo filtering for that domain.
Defensive patterns

Strategy: validation

Validate before calling

// Caller-side pre-check: verify the effective egress IP is inside the
// service's allowed ranges before sending real traffic.
func allowed(myIP netip.Addr, ranges []netip.Prefix) bool {
    for _, p := range ranges {
        if p.Contains(myIP) {
            return true
        }
    }
    return false
}

Try / catch

resp, err := client.Get(url)
if err == nil && resp.StatusCode == http.StatusForbidden {
    // Distinguish restriction blocks from private-service blocks: restrictions
    // log a verdict (cidr/geo/crowdsec) server-side; check which rule matches
    // your effective IP (X-Forwarded-For aware), fix the range, retry.
}

Prevention

When it happens

Trigger: Client IP outside the allowed CIDR ranges for the domain; Geo verdict from a disallowed country when geo policy is attached; CrowdSec verdict while the restriction is in enforce (not observe) mode; overlay-origin request from a tunnel IP not in the permitted NetBird ranges.

Common situations: Corporate allow-list missing the contractor's new subnet; geo-restriction blocking a travelling user; CrowdSec escalated from observe to enforce and started blocking previously-warned IPs; service shared with a partner whose overlay range was never added.

Related errors


AI-assisted analysis of netbirdio/netbird@93e97f4bf1 (2026-08-16). Data as JSON: /api/errors/3409225fa42ff2bd. Report an issue: GitHub.