Skip to content

esp_dns DoT resolver can fail valid responses due to shared state and incomplete TCP/TLS reads #1053

Description

Answers checklist.

  • I have read the documentation for esp-protocols components and the issue is not addressed there.
  • I have updated my esp-protocols branch (master or release) to the latest version and checked that the issue is present there.
  • I have searched the issue tracker for a similar issue and not found a similar issue.

General issue report

esp_dns 0.1.0 DNS-over-TLS resolution can fail valid DNS responses with:

ESP_DNS_DOT: Failed to extract IP address from DNS response
esp-tls: couldn't get hostname for :: getaddrinfo() returns 202

Environment:

  • Component: espressif/esp_dns 0.1.0
  • ESP-IDF: v6.0
  • Target observed: ESP32-C6
  • Resolver: Cloudflare DoT, 1dot1dot1dot1.cloudflare-dns.com:853
  • lwIP hook: CONFIG_LWIP_HOOK_NETCONN_EXT_RESOLVE_CUSTOM=y
  • TLS config uses crt_bundle_attach

Suspected issues:

  1. esp_dns stores per-query response state in the singleton handle, including response_buffer and expected transaction ID, but dns_resolve_dot() does not take handle->lock. Concurrent getaddrinfo() calls can overwrite each other’s transaction ID / response state
  2. dns_resolve_dot() performs one esp_transport_read() and immediately parses the data. DoT uses a TCP/TLS stream with a 2-byte length prefix, so the implementation should read the prefix and then loop until the full DNS message is received
  3. CNAME handling is fragile because parsed DNS answer RRs are capped by CONFIG_LWIP_DNS_MAX_HOST_IP, which is a max returned-IP count, not a max DNS answer RR count

Expected:

  • Concurrent getaddrinfo() calls should not corrupt resolver state
  • DoT should read a complete RFC 7858 length-prefixed DNS response before parsing
  • Valid CNAME -> A / AAAA responses should resolve successfully

Suggested fixes:

  • Serialize DoT/TCP/DoH resolution with handle->lock, or move per-query response state to stack/local storage
  • Read the complete DoT frame before parsing
  • Decouple max parsed answer RRs from CONFIG_LWIP_DNS_MAX_HOST_IP
  • Skip CNAME/unsupported RRs while continuing to collect A/AAAA records
  • Add tests for CNAME responses, partial TLS reads, and concurrent getaddrinfo() calls

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions