{"id":"cee29237fc14327e","repo":"gofiber/fiber","slug":"errupstreamhostblocked","errorCode":"ErrUpstreamHostBlocked","errorMessage":"%w: %s","messagePattern":"%w: %s","errorType":"http","errorClass":null,"httpStatus":null,"severity":"error","filePath":"middleware/proxy/security.go","lineNumber":355,"sourceCode":"}\n\n// validateUpstreamForBalancer validates a statically configured Balancer\n// upstream. It enforces the scheme allowlist and rejects IP-literal hosts\n// in blocked ranges, but defers hostname resolution to the SSRF-guarded\n// dialer (see newSSRFDialer). Deferring DNS keeps a transient resolver\n// failure at startup from panicking the application (e.g. crash loops in\n// container orchestrators) and re-checks the resolved IP on every dial,\n// which also defeats DNS-rebinding.\nfunc validateUpstreamForBalancer(raw string, policy SecurityPolicy) (*url.URL, error) {\n\tu, err := parseUpstreamScheme(raw, policy)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tif policy.AllowPrivateIPs {\n\t\treturn u, nil\n\t}\n\tif ip := net.ParseIP(trimBrackets(u.Hostname())); ip != nil && isBlockedIP(ip) {\n\t\treturn nil, fmt.Errorf(\"%w: %s\", ErrUpstreamHostBlocked, ip)\n\t}\n\treturn u, nil\n}\n\n// schemeAllowed reports whether scheme is on the allowlist. An empty\n// allowlist falls back to the secure defaults.\nfunc schemeAllowed(scheme string, allowed []string) bool {\n\tif scheme == \"\" {\n\t\treturn false\n\t}\n\tif len(allowed) == 0 {\n\t\tallowed = defaultAllowedSchemes\n\t}\n\tfor _, s := range allowed {\n\t\tif utils.EqualFold(s, scheme) {\n\t\t\treturn true\n\t\t}\n\t}","sourceCodeStart":337,"sourceCodeEnd":373,"githubUrl":"https://github.com/gofiber/fiber/blob/9a4c7e57fe0b080a04235d28a4b0d2b4b353d58c/middleware/proxy/security.go#L337-L373","documentation":"Returned by validateUpstreamForBalancer at Balancer construction when a statically configured upstream host is an IP literal that falls in a blocked range (loopback, RFC1918 private, link-local, multicast, unspecified, CGNAT, or blocked IPv6 transition ranges) and AllowPrivateIPs is false.","triggerScenarios":"A Balancer server entry is a numeric IP like 127.0.0.1, 10.0.0.5, 169.254.169.254, or 100.64.0.1 while AllowPrivateIPs is false (the default). The IP-literal shortcut at security.go:354 rejects it without DNS.","commonSituations":"Pointing a Balancer at an internal/private service during local development or inside a cluster; using a cloud metadata IP by mistake; forgetting to set AllowPrivateIPs when the backend genuinely is on a private network.","solutions":["If the private backend is intentional and trusted, enable AllowPrivateIPs:true on the SecurityPolicy (understand it widens SSRF exposure).","Otherwise point the Balancer at a public IP or resolvable public hostname.","Re-check the server list for accidentally pasted loopback/metadata addresses."],"exampleFix":"// before: private IP blocked by default SSRF policy\nbalancer := proxy.Balancer(proxy.Config{\n    Servers: []string{\"http://10.0.0.5:8080\"},\n})\n\n// after: explicitly opt in for a trusted internal backend\npolicy := proxy.DefaultSecurityPolicy()\npolicy.AllowPrivateIPs = true\nbalancer := proxy.Balancer(proxy.Config{\n    Servers:        []string{\"http://10.0.0.5:8080\"},\n    SecurityPolicy: &policy,\n})","handlingStrategy":"validation","validationCode":"// At config time, decide policy for private backends explicitly.\nfunc balancerPolicy(servers []string, allowPrivate bool) *proxy.SecurityPolicy {\n    p := proxy.DefaultSecurityPolicy()\n    p.AllowPrivateIPs = allowPrivate // true only for trusted internal backends\n    return &p\n}","typeGuard":null,"tryCatchPattern":"// validateUpstreamForBalancer runs at Balancer construction; wrap New\n// and report the error clearly at startup.\nb, err := proxy.Balancer(proxy.Config{Servers: svrs, SecurityPolicy: &p})\nif err != nil {\n    if errors.Is(err, proxy.ErrUpstreamHostBlocked) {\n        log.Fatal().Err(err).Msg(\"backend IP blocked; set AllowPrivateIPs if trusted\")\n    }\n    log.Fatal().Err(err).Msg(\"balancer init failed\")\n}","preventionTips":["Audit Balancer server entries for loopback/private/metadata IPs.","Enable AllowPrivateIPs only for genuinely trusted internal backends.","Prefer public hostnames or properly scoped service DNS."],"tags":["proxy","balancer","ssrf","private-ip","security","configuration"],"analyzedSha":"9a4c7e57fe0b080a04235d28a4b0d2b4b353d58c","analyzedAt":"2026-08-04T21:44:03.395Z","schemaVersion":2}