Tencent/WeKnora · error
DNS resolution returned no addresses for %s
Error message
DNS resolution returned no addresses for %s
What it means
The DNS lookup for the host succeeded but returned an empty answer set, so SSRF validation has nothing to check and the dial is refused. This is distinct from a resolver error: the resolver responded, but with zero addresses. The library treats an empty answer as a hard failure rather than falling back to the standard dialer, preserving the rebinding-free guarantee.
Source
Thrown at internal/utils/security.go:835
return nil, fmt.Errorf("connection blocked: hostname %s is restricted", host)
}
}
for _, suffix := range restrictedHostSuffixes {
if strings.HasSuffix(hostLower, suffix) {
return nil, fmt.Errorf("connection blocked: hostname suffix %s is restricted", suffix)
}
}
// 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)View on GitHub (pinned to 988cbb0330)
Solutions
- Inspect the DNS zone and add proper A/AAAA records for the hostname, or point the client at a hostname that has addresses.
- Check whether a corporate/security resolver is empty-answering the domain and switch to the correct internal resolver.
- Dial the intended IP literal directly (subject to isRestrictedIP validation) if you know the address.
- Retry after DNS propagation if the record was just created.
Example fix
// before
conn, err := utils.SSRFSafeDialContext(ctx, "tcp", "staging-api.example.com:443") // no A record
// after
ips, err := net.LookupIP("staging-api.example.com")
if err != nil || len(ips) == 0 {
// fix DNS or fall back to a known-good address
return utils.SSRFSafeDialContext(ctx, "tcp", "203.0.113.10:443")
}
conn, err := utils.SSRFSafeDialContext(ctx, "tcp", "staging-api.example.com:443") Defensive patterns
Strategy: validation
Validate before calling
ips, err := net.LookupIP(host)
if err == nil && len(ips) == 0 {
return fmt.Errorf("hostname %s has no A/AAAA records; fix DNS or dial a literal IP", host)
} Try / catch
conn, err := utils.SSRFSafeDialContext(ctx, "tcp", addr)
if err != nil && strings.Contains(err.Error(), "returned no addresses") {
return nil, fmt.Errorf("no DNS addresses for %s: verify records or dial IP directly", host)
} Prevention
- Ensure every configured hostname has A/AAAA records in the zone the resolver actually queries.
- Watch for security appliances that empty-answer filtered domains.
- Check split-horizon DNS views if the record exists externally but not internally.
- Prefer IP literals for infrastructure endpoints that never need names.
When it happens
Trigger: LookupIPAddr returning no IPs — typically a name that exists but has no A/AAAA records (e.g. only CNAME to nothing, a NULL record, or a DNS64/filtering resolver returning an empty answer) — passed to SSRFSafeDialContext / SSRFSafeGRPCDialer / a transport DialContext.
Common situations: DNS entries pointing at services with missing A records; split-horizon DNS where the external view has no records; security appliances or sinkhole resolvers that return empty answers for blocked domains; recently created records not yet propagated.
Understand the failure class
- DNS resolution errors: ENOTFOUND and getaddrinfo failures — how hostname lookups fail and how to debug them.
Related errors
- DNS resolution failed for %s: %w
- fetch failed: %w
- HTTP GET: %w
- HTTP request: %w
- failed to execute request: %w
AI-assisted analysis of Tencent/WeKnora@988cbb0330 (2026-09-02).
Data as JSON: /api/errors/2c2da4c8f5d5db7f.
Report an issue: GitHub.