nginx/nginx · warning

unknown query class %ui in DNS response

Error message

unknown query class %ui in DNS response

What it means

Logged in ngx_resolver_process_response while parsing the question section of a DNS reply: the reply's QCLASS is not 1 (IN). nginx only issues Internet-class queries, so any other value (3=CH, 4=HS, 255=ANY, or garbage) means the reply does not correspond to a well-formed exchange, and nginx drops it. The pending lookup stays queued and is resent until resolver_timeout (default 30s) fails it. Replies of this shape almost always come from a broken, intercepting, or hostile DNS path, not from nginx itself.

Source

Thrown at src/core/ngx_resolver.c:1867

        goto done;
    }

    if (i + sizeof(ngx_resolver_qs_t) + nan * (2 + sizeof(ngx_resolver_an_t))
        > (ngx_uint_t) n)
    {
        goto short_response;
    }

    qs = (ngx_resolver_qs_t *) &buf[i];

    qtype = (qs->type_hi << 8) + qs->type_lo;
    qclass = (qs->class_hi << 8) + qs->class_lo;

    ngx_log_debug2(NGX_LOG_DEBUG_CORE, r->log, 0,
                   "resolver DNS response qt:%ui cl:%ui", qtype, qclass);

    if (qclass != 1) {
        ngx_log_error(r->log_level, r->log, 0,
                      "unknown query class %ui in DNS response", qclass);
        return;
    }

    switch (qtype) {

    case NGX_RESOLVE_A:
#if (NGX_HAVE_INET6)
    case NGX_RESOLVE_AAAA:
#endif

        ngx_resolver_process_a(r, buf, n, ident, code, qtype, nan, trunc,
                               i + sizeof(ngx_resolver_qs_t));

        break;

    case NGX_RESOLVE_SRV:

View on GitHub (pinned to 3f6f7824d4)

Solutions

  1. Inspect what the configured resolver really returns: dig @10.0.0.1 example.com A +qr +noall +question and check the question section shows IN class.
  2. Point the nginx resolver directive at a known-conforming recursive resolver you control (127.0.0.1 running unbound/bind/systemd-resolved, or 1.1.1.1/8.8.8.8) and re-test.
  3. If the host sits on a captive/intercepted network, fix or bypass the interceptor for that host (static DNS entries, VPN, or a local DoH stub resolver).
  4. If the message is rare and names still resolve, treat it as dropped-packet noise: queries are resent automatically until resolver_timeout.

Example fix

# before
resolver 10.0.0.1 valid=300s;

# after - conforming local recursive resolver, second upstream, fast timeout
resolver 127.0.0.1:5353 1.1.1.1 valid=300s;
resolver_timeout 5s;
Defensive patterns

Strategy: validation

Validate before calling

#!/bin/sh
# confirm the resolver answers with IN-class questions before trusting it in nginx.conf
dig @10.0.0.1 example.com A +qr +noall +question | grep -q 'IN A$' \
  || { echo 'resolver not echoing IN-class questions'; exit 1; }

Prevention

When it happens

Trigger: Any response read on the resolver UDP/TCP socket whose question-section class field is not 1: a captive portal or DPI box answering with a rewritten/invalid DNS packet, a spoofed reply from an on-path attacker, a resolver that echoes malformed questions, or corrupted packets on lossy links. Fires on every reply of that shape to an A/AAAA/SRV/PTR query issued via the resolver directive.

Common situations: Captive portals (hotel/conference Wi-Fi), ISP or corporate DNS interception and rebinding-protection middleboxes, NAT/firewall DNS ALGs mangling packets, resolvers behind load balancers that splice unrelated replies onto one socket.

Related errors


AI-assisted analysis of nginx/nginx@3f6f7824d4 (2026-08-22). Data as JSON: /api/errors/ba11794b8d2bce7d. Report an issue: GitHub.