Tencent/WeKnora · error
connection blocked: %s resolves to restricted IP %s (%s)
Error message
connection blocked: %s resolves to restricted IP %s (%s)
What it means
After resolving the hostname, SSRFSafeDialContext validates every returned IP with isRestrictedIP; if any answer is private, loopback, link-local, metadata, or otherwise restricted, the whole dial is blocked. This closes DNS-rebinding attacks where a public name resolves to an internal address. The reason string in the message names the specific restricted category.
Source
Thrown at internal/utils/security.go:841
}
}
// Resolve the hostname once, validate every answer, and then dial one of
// those exact IPs. Dialing the original hostname here would make the
// standard dialer resolve it a second time, leaving a DNS-rebinding window
// between validation and connection establishment.
ips, err := net.DefaultResolver.LookupIPAddr(ctx, host)
if err != nil {
return nil, fmt.Errorf("DNS resolution failed for %s: %w", host, err)
}
if len(ips) == 0 {
return nil, fmt.Errorf("DNS resolution returned no addresses for %s", host)
}
// Validate all resolved IPs
for _, ipAddr := range ips {
if restricted, reason := isRestrictedIP(ipAddr.IP); restricted {
return nil, fmt.Errorf("connection blocked: %s resolves to restricted IP %s (%s)", host, ipAddr.IP.String(), reason)
}
}
// If we get here, all IPs are safe. Pin the connection to the validated DNS
// answers; TLS still uses the request hostname for SNI/certificate checks.
dialer := &net.Dialer{
Timeout: 30 * time.Second,
KeepAlive: 30 * time.Second,
}
var lastErr error
for _, ipAddr := range ips {
pinnedAddr := net.JoinHostPort(ipAddr.IP.String(), port)
conn, dialErr := dialer.DialContext(ctx, network, pinnedAddr)
if dialErr == nil {
return conn, nil
}
lastErr = dialErr
}View on GitHub (pinned to 988cbb0330)
Solutions
- Read the reason in the error to see which restricted class fired, then verify the DNS records for the host and remove any pointing at private/loopback/metadata space.
- If the host is legitimately internal and trusted, add it to the SSRF whitelist so dial-time IP checks are bypassed for it.
- If you suspect rebinding/abuse, treat it as a security event: audit who configured the record and block the domain.
- Dial the specific public IP literal if you know the correct address and it passes isRestrictedIP.
Example fix
// before // evil.example.com resolves to 169.254.169.254 conn, err := utils.SSRFSafeDialContext(ctx, "tcp", "evil.example.com:80") // after // correct the DNS record to a public IP, then dial conn, err := utils.SSRFSafeDialContext(ctx, "tcp", "api.example.com:443") // or whitelist trusted internal host
Defensive patterns
Strategy: validation
Validate before calling
ips, _ := net.LookupIP(host)
for _, ip := range ips {
if restricted, reason := utils.IsRestrictedIPCheck(ip); restricted { // or reuse library's isRestrictedIP via exported helper
return fmt.Errorf("%s resolves to restricted IP (%s); fix DNS or whitelist host", host, reason)
}
} Try / catch
conn, err := utils.SSRFSafeDialContext(ctx, "tcp", addr)
if err != nil && strings.Contains(err.Error(), "resolves to restricted IP") {
// do NOT retry — treat as either misconfigured DNS or an SSRF attempt; alert and fail closed
return nil, fmt.Errorf("possible DNS rebinding or internal-target attempt: %w", err)
} Prevention
- Treat this error as a potential security event, not a transient failure — never auto-retry.
- Audit DNS records for hosts that mix public names with private answers.
- Whitelist genuinely internal, trusted hosts instead of weakening checks.
- Keep the restricted-IP lists updated with new cloud metadata ranges.
When it happens
Trigger: A hostname whose DNS answer includes any restricted IP (e.g. resolves to 127.0.0.1, 10.x/172.16.x/192.168.x, 169.254.169.254, or IPv6 equivalents) dialed through SSRFSafeDialContext / SSRFSafeGRPCDialer without a whitelist entry; malicious or misconfigured DNS records; hosts legitimately dual-homed onto private ranges.
Common situations: Attack or misconfiguration where a public domain points at 169.254.169.254 (metadata SSRF attempt); internal services whose DNS returns private IPs to the guarded client; VPN/split-horizon setups where the same name yields private answers internally.
Related errors
- unsafe MinIO endpoint: %w
- unsafe OSS endpoint: %w
- unsafe S3 endpoint: %w
- unsafe TOS endpoint: %w
- %s failed SSRF validation: %w
AI-assisted analysis of Tencent/WeKnora@988cbb0330 (2026-09-02).
Data as JSON: /api/errors/5cdca433858cbb5e.
Report an issue: GitHub.