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
- Read the reason passed to blockIPRestriction (verdict.String() is logged/recorded) to learn which rule fired: CIDR, geo, or CrowdSec.
- 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.
- For CrowdSec, keep the restriction in observe mode while onboarding so verdicts are only logged until the ranges are proven.
- 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
- Track which effective IP the proxy sees for you (trusted XFF is honored), not just your local address.
- Keep CrowdSec-backed restrictions in observe mode until ranges are validated.
- Maintain the allow-list as part of onboarding for new offices/contractors.
- For overlay-origin traffic, remember only CIDR rules apply — add the NetBird ranges.
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
- host argument required
- engine not started
- client already started
- client not started
- tun module not available
AI-assisted analysis of netbirdio/netbird@93e97f4bf1 (2026-08-16).
Data as JSON: /api/errors/3409225fa42ff2bd.
Report an issue: GitHub.