dns_client 1.3.1 copy "dns_client: ^1.3.1" to clipboard
dns_client: ^1.3.1 copied to clipboard

Dart DNS-over-HTTPS (DoH) client supporting Google, Cloudflare, AdGuard, and Quad9 providers.

dns_client #

Dart implementation of DNS-over-HTTPS (DoH).

CodeFactor pub.flutter-io.cn license

Korean (한국어)

Features #

  • Multiple DNS Providers - Google, Cloudflare, AdGuard, NextDNS, Quad9, OpenDNS, or custom DoH endpoints
  • Wire Format Support - RFC 1035/8484 compliant DNS wire format with HTTP/2 for Quad9
  • 36 DNS Record Types - A, AAAA, MX, TXT, SRV, CAA, HTTPS, SVCB, DNSKEY, DS, and more
  • Privacy Protection - Hide client IP from authoritative nameservers
  • Error Handling - Detailed exceptions for DNS and HTTP failures
  • Dart 3 Support - Requires Dart SDK 3.7.0+

Installation #

Add to your pubspec.yaml:

dependencies:
  dns_client: ^1.0.0

Then run:

dart pub get

Quick Start #

import 'package:dns_client/dns_client.dart';

void main() async {
  final dns = DnsOverHttps.google();

  final addresses = await dns.lookup('google.com');
  for (final address in addresses) {
    print(address.address);
  }

  dns.close();
}

Usage Examples #

Basic DNS Lookup #

// Using Google DNS
final dns = DnsOverHttps.google();
final addresses = await dns.lookup('example.com');
dns.close();

// Using Cloudflare DNS
final dns = DnsOverHttps.cloudflare();
final addresses = await dns.lookup('example.com');
dns.close();

// Using AdGuard DNS (blocks ads and trackers)
final dns = DnsOverHttps.adguard();
final addresses = await dns.lookup('example.com');
dns.close();

// Using AdGuard DNS (no filtering)
final dns = DnsOverHttps.adguardNonFiltering();
final addresses = await dns.lookup('example.com');
dns.close();

// Using AdGuard DNS (family protection)
final dns = DnsOverHttps.adguardFamily();
final addresses = await dns.lookup('example.com');
dns.close();

// Using Quad9 DNS (malware blocking + DNSSEC)
final dns = DnsOverHttpsWire.quad9();
final addresses = await dns.lookup('example.com');
dns.close();

// Using Quad9 DNS with ECS (geolocation hints)
final dns = DnsOverHttpsWire.quad9Ecs();
final addresses = await dns.lookup('example.com');
dns.close();

// Using Quad9 DNS (no filtering)
final dns = DnsOverHttpsWire.quad9Unsecured();
final addresses = await dns.lookup('example.com');
dns.close();

// Using NextDNS
final dns = DnsOverHttps.nextdns();
final addresses = await dns.lookup('example.com');
dns.close();

// Using NextDNS with custom configuration
final dns = DnsOverHttps.nextdns(configId: 'abc123');
final addresses = await dns.lookup('example.com');
dns.close();

// Using OpenDNS
final dns = DnsOverHttpsWire.opendns();
final addresses = await dns.lookup('example.com');
dns.close();

// Using OpenDNS FamilyShield (blocks adult content)
final dns = DnsOverHttpsWire.opendnsFamilyShield();
final addresses = await dns.lookup('example.com');
dns.close();

Query Specific Record Types #

final dns = DnsOverHttps.google();

// MX records (mail servers)
final mxRecords = await dns.lookupDataByRRType('example.com', RRType.MX);
print('Mail servers: $mxRecords');

// TXT records (SPF, DKIM, domain verification)
final txtRecords = await dns.lookupDataByRRType('example.com', RRType.TXT);
print('TXT records: $txtRecords');

// SRV records (service discovery)
final srvRecords = await dns.lookupDataByRRType(
  '_jmap._tcp.fastmail.com',
  RRType.SRV,
);
print('SRV records: $srvRecords');

// CAA records (certificate authority authorization)
final caaRecords = await dns.lookupDataByRRType('example.com', RRType.CAA);
print('CAA records: $caaRecords');

// HTTPS records (service binding)
final httpsRecords = await dns.lookupDataByRRType('example.com', RRType.HTTPS);
print('HTTPS records: $httpsRecords');

dns.close();

Custom DNS Provider #

final dns = DnsOverHttps(
  'https://dns.quad9.net:5053/dns-query',
  timeout: Duration(seconds: 10),
);

final addresses = await dns.lookup('example.com');
dns.close();

Privacy Settings #

Hide your IP address from authoritative nameservers:

final dns = DnsOverHttps(
  'https://dns.google/resolve',
  maximalPrivacy: true,  // Sets edns_client_subnet=0.0.0.0/0
);

final addresses = await dns.lookup('example.com');
dns.close();

Timeout Configuration #

final dns = DnsOverHttps.google(
  timeout: Duration(seconds: 10),  // Default is 5 seconds
);

final addresses = await dns.lookup('example.com');
dns.close();

Error Handling #

final dns = DnsOverHttps.google();

try {
  final records = await dns.lookupDataByRRType(
    'nonexistent.invalid',
    RRType.A,
  );
} on DnsLookupException catch (e) {
  // DNS-level error (NXDOMAIN, SERVFAIL, etc.)
  print('DNS error: ${e.message}');
  print('Hostname: ${e.hostname}');
  print('Status: ${e.status}');  // 3 = NXDOMAIN, 2 = SERVFAIL
} on DnsHttpException catch (e) {
  // HTTP-level error
  print('HTTP error: ${e.statusCode}');
  print('Message: ${e.message}');
} finally {
  dns.close();
}

Full Response Inspection #

Access the complete DNS response for detailed information:

final dns = DnsOverHttps.google();

final record = await dns.lookupHttpsByRRType('example.com', RRType.MX);

if (record.isSuccess) {
  print('Status: ${record.status}');  // 0 = NOERROR

  for (final answer in record.answer ?? []) {
    print('Name: ${answer.name}');
    print('Type: ${answer.type}');
    print('TTL: ${answer.TTL} seconds');
    print('Data: ${answer.data}');
  }
} else if (record.isNxDomain) {
  print('Domain does not exist');
} else if (record.isServerFailure) {
  print('Server failure');
}

dns.close();

API Reference #

DnsOverHttps #

Constructors:

Constructor Description
DnsOverHttps(url, {timeout, maximalPrivacy}) Custom DoH endpoint
DnsOverHttps.google({timeout}) Google DNS (dns.google)
DnsOverHttps.cloudflare({timeout}) Cloudflare DNS (1.1.1.1)
DnsOverHttps.adguard({timeout}) AdGuard DNS (blocks ads/trackers)
DnsOverHttps.adguardNonFiltering({timeout}) AdGuard DNS (no filtering)
DnsOverHttps.adguardFamily({timeout}) AdGuard DNS (family protection)
DnsOverHttps.nextdns({configId, timeout}) NextDNS (optional custom config)
DnsOverHttps.nextdnsAnycast({configId, timeout}) NextDNS Anycast endpoint

Methods:

Method Returns Description
lookup(hostname) Future<List<InternetAddress>> Resolve hostname to IP addresses
lookupDataByRRType(hostname, rrType) Future<List<String>> Query specific record type
lookupHttpsByRRType(hostname, rrType) Future<DnsRecord> Get full DNS response
close({force}) void Shutdown HTTP client

DnsOverHttpsWire #

Wire format DoH client using HTTP/2 (RFC 1035/8484). Required for Quad9 and OpenDNS.

Constructors:

Constructor Description
DnsOverHttpsWire(url, {timeout}) Custom wire format DoH endpoint
DnsOverHttpsWire.quad9({timeout}) Quad9 DNS (malware blocking + DNSSEC)
DnsOverHttpsWire.quad9Ecs({timeout}) Quad9 DNS with EDNS Client Subnet
DnsOverHttpsWire.quad9Unsecured({timeout}) Quad9 DNS (no filtering)
DnsOverHttpsWire.opendns({timeout}) OpenDNS (enterprise-grade)
DnsOverHttpsWire.opendnsFamilyShield({timeout}) OpenDNS FamilyShield (blocks adult)

Methods:

Method Returns Description
lookup(hostname) Future<List<InternetAddress>> Resolve hostname to IP addresses
lookupDataByRRType(hostname, rrType) Future<List<String>> Query specific record type
lookupWire(hostname, rrType) Future<DnsRecord> Get full DNS response
close({force}) Future<void> Shutdown HTTP/2 client

Supported Record Types (RRType) #

Type Constant Value Description
A RRType.A 1 IPv4 address
NS RRType.NS 2 Name server
CNAME RRType.CNAME 5 Canonical name (alias)
SOA RRType.SOA 6 Start of authority
PTR RRType.PTR 12 Reverse DNS pointer
HINFO RRType.HINFO 13 Host information
MX RRType.MX 15 Mail exchanger
TXT RRType.TXT 16 Text record
RP RRType.RP 17 Responsible person
AFSDB RRType.AFSDB 18 AFS database
KEY RRType.KEY 25 Security key
AAAA RRType.AAAA 28 IPv6 address
LOC RRType.LOC 29 Geographic location
SRV RRType.SRV 33 Service location
NAPTR RRType.NAPTR 35 Naming authority pointer
KX RRType.KX 36 Key exchanger
CERT RRType.CERT 37 Certificate
APL RRType.APL 42 Address prefix list
DS RRType.DS 43 Delegation signer (DNSSEC)
IPSECKEY RRType.IPSECKEY 45 IPsec key
NSEC RRType.NSEC 47 Next secure (DNSSEC)
DNSKEY RRType.DNSKEY 48 DNS key (DNSSEC)
DHCID RRType.DHCID 49 DHCP identifier
NSEC3 RRType.NSEC3 50 Hashed denial (DNSSEC)
NSEC3PARAM RRType.NSEC3PARAM 51 NSEC3 parameters
SMIMEA RRType.SMIMEA 53 S/MIME certificate
HIP RRType.HIP 55 Host identity protocol
CDS RRType.CDS 59 Child DS (DNSSEC)
SVCB RRType.SVCB 64 Service binding
HTTPS RRType.HTTPS 65 HTTPS binding
EUI48 RRType.EUI48 108 MAC address (48-bit)
EUI64 RRType.EUI64 109 MAC address (64-bit)
URI RRType.URI 256 URI mapping
CAA RRType.CAA 257 CA authorization
TA RRType.TA 32768 Trust anchor
DLV RRType.DLV 32769 DNSSEC lookaside

Custom record types:

// TLSA record (type 52)
final tlsaType = RRType('TLSA', 52);
final tlsaRecords = await dns.lookupDataByRRType('example.com', tlsaType);

Response Classes #

DnsRecord:

Property Type Description
status int DNS response code
answer List<Answer>? DNS answers
isSuccess bool True if status == 0
isFailure bool True if status != 0
isNxDomain bool True if status == 3
isServerFailure bool True if status == 2

Answer:

Property Type Description
name String Domain name
type int Record type code
TTL int Time to live (seconds)
data String Record data

Exceptions #

DnsLookupException - Thrown when DNS query fails:

  • hostname - The queried hostname
  • status - DNS status code (2=SERVFAIL, 3=NXDOMAIN, etc.)
  • message - Error description

DnsHttpException - Thrown when HTTP request fails:

  • statusCode - HTTP status code
  • message - Error description

DnsWireFormatException - Thrown when wire format parsing fails:

  • message - Error description
  • offset - Byte offset where error occurred

Requirements #

  • Dart SDK: >=3.7.0 <4.0.0

License #

See LICENSE file.

Contributing #

Please file feature requests and bugs at the issue tracker.

14
likes
160
points
173
downloads

Publisher

verified publisheramond.dev

Weekly Downloads

Dart DNS-over-HTTPS (DoH) client supporting Google, Cloudflare, AdGuard, and Quad9 providers.

Repository (GitHub)
View/report issues

Documentation

API reference

License

MIT (license)

Dependencies

equatable, freezed_annotation, http, http2, json_annotation

More

Packages that depend on dns_client