{"record":{"id":"ba11794b8d2bce7d","repo":"nginx/nginx","slug":"unknown-query-class-ui-in-dns-response","errorCode":null,"errorMessage":"unknown query class %ui in DNS response","messagePattern":"unknown query class %ui in DNS response","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"src/core/ngx_resolver.c","lineNumber":1867,"sourceCode":"        goto done;\n    }\n\n    if (i + sizeof(ngx_resolver_qs_t) + nan * (2 + sizeof(ngx_resolver_an_t))\n        > (ngx_uint_t) n)\n    {\n        goto short_response;\n    }\n\n    qs = (ngx_resolver_qs_t *) &buf[i];\n\n    qtype = (qs->type_hi << 8) + qs->type_lo;\n    qclass = (qs->class_hi << 8) + qs->class_lo;\n\n    ngx_log_debug2(NGX_LOG_DEBUG_CORE, r->log, 0,\n                   \"resolver DNS response qt:%ui cl:%ui\", qtype, qclass);\n\n    if (qclass != 1) {\n        ngx_log_error(r->log_level, r->log, 0,\n                      \"unknown query class %ui in DNS response\", qclass);\n        return;\n    }\n\n    switch (qtype) {\n\n    case NGX_RESOLVE_A:\n#if (NGX_HAVE_INET6)\n    case NGX_RESOLVE_AAAA:\n#endif\n\n        ngx_resolver_process_a(r, buf, n, ident, code, qtype, nan, trunc,\n                               i + sizeof(ngx_resolver_qs_t));\n\n        break;\n\n    case NGX_RESOLVE_SRV:\n","sourceCodeStart":1849,"sourceCodeEnd":1885,"githubUrl":"https://github.com/nginx/nginx/blob/3f6f7824d4e2eb1ac37dec76683d525ac0ff521c/src/core/ngx_resolver.c#L1849-L1885","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["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.","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.","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).","If the message is rare and names still resolve, treat it as dropped-packet noise: queries are resent automatically until resolver_timeout."],"exampleFix":"# before\nresolver 10.0.0.1 valid=300s;\n\n# after - conforming local recursive resolver, second upstream, fast timeout\nresolver 127.0.0.1:5353 1.1.1.1 valid=300s;\nresolver_timeout 5s;","handlingStrategy":"validation","validationCode":"#!/bin/sh\n# confirm the resolver answers with IN-class questions before trusting it in nginx.conf\ndig @10.0.0.1 example.com A +qr +noall +question | grep -q 'IN A$' \\\n  || { echo 'resolver not echoing IN-class questions'; exit 1; }","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Run a conforming local recursive resolver (unbound/bind) on 127.0.0.1 and point the nginx resolver directive at it.","Monitor nginx error logs for 'unknown query class' as an early signal of DNS interception on the host's network path.","Always set resolver_timeout so a dropped reply fails over quickly instead of hanging.","Keep production nginx hosts off captive/intercepted networks; use a VPN or DoH stub resolver when unavoidable."],"tags":["dns","resolver","nginx","protocol","network"],"backgroundTag":"dns-malformed-response","analyzedSha":"3f6f7824d4e2eb1ac37dec76683d525ac0ff521c","analyzedAt":"2026-08-22T03:09:46.447Z","schemaVersion":2},"datasetVersion":"2026-08-22T04:17:13.399Z"}