ory/hydra · error

neither remote address nor any x-forwarded-for values match

Error message

neither remote address nor any x-forwarded-for values match CIDR ranges %+v: %v, ranges, check)

What it means

matchesRange verifies that a plain-HTTP request may be TLS-terminated by checking that either the direct RemoteAddr or any X-Forwarded-For entry falls inside one of the configured allowTerminationFrom CIDR ranges. If none of the candidate IPs (remote IP plus every comma-separated X-Forwarded-For value) is contained in any configured network, it returns this error and the middleware rejects the request with 502 Bad Gateway. It is the library's safeguard against accepting TLS-terminated traffic from untrusted proxies.

Source

Thrown at oryx/tlsx/termination.go:94

	remoteIP, _, err := net.SplitHostPort(r.RemoteAddr)
	if err != nil {
		return errors.WithStack(err)
	}

	check := []string{remoteIP}
	for fwd := range strings.SplitSeq(r.Header.Get("X-Forwarded-For"), ",") {
		check = append(check, strings.TrimSpace(fwd))
	}

	for _, ipNet := range networks {
		for _, ip := range check {
			addr := net.ParseIP(ip)
			if ipNet.Contains(addr) {
				return nil
			}
		}
	}
	return errors.Errorf("neither remote address nor any x-forwarded-for values match CIDR ranges %+v: %v, ranges, check)", networks, check)
}

View on GitHub (pinned to 4174065ffb)

Solutions

  1. Add the actual proxy/source IP range to the allowTerminationFrom configuration (e.g. the Kubernetes node/pod CIDR or LB egress range).
  2. Verify with logs what RemoteAddr and X-Forwarded-For the service sees and confirm the CIDR notation is correct (net.ParseCIDR format, e.g. 10.0.0.0/8).
  3. If the proxy legitimately strips X-Forwarded-For, whitelist the proxy's direct IP instead.
  4. If you do not run a TLS-terminating proxy at all, serve the service over HTTPS directly so the middleware is bypassed (r.TLS != nil).

Example fix

// before (config)
allowTerminationFrom:
  - 127.0.0.1/32
// after (include proxy subnet)
allowTerminationFrom:
  - 127.0.0.1/32
  - 10.244.0.0/16
Defensive patterns

Strategy: validation

Validate before calling

// verify source IP is inside allowTerminationFrom before deploying
ip := net.ParseIP(proxyIP)
_, cidr, _ := net.ParseCIDR("10.244.0.0/16")
if !cidr.Contains(ip) {
    log.Printf("proxy IP %s not in allowTerminationFrom", proxyIP)
}

Prevention

When it happens

Trigger: A request arrives over plain HTTP, allowTerminationFrom is configured, but the proxy's IP (RemoteAddr) and all X-Forwarded-For entries are outside the configured CIDR ranges — e.g. a new proxy pod IP, an SNAT-ed address, or the X-Forwarded-For header being stripped or appended with unexpected values.

Common situations: Kubernetes: proxy/ingress pods rescheduled onto nodes with IPs outside the configured subnet; adding a second load balancer whose egress IP is not whitelisted; configuring 127.0.0.1/32 but connecting through Docker bridge or a container network; X-Forwarded-For missing so only RemoteAddr is checked.

Related errors


AI-assisted analysis of ory/hydra@4174065ffb (2026-09-03). Data as JSON: /api/errors/6fb2cf423beb74b1. Report an issue: GitHub.