idoq 0.1.1

DNS over QUIC (DoQ) client / DNS over QUIC (DoQ) 客户端
Documentation

English | 中文


idoq : DNS over QUIC Client for Rust

Table of Contents

Features

  • RFC 9250 compliant DoQ implementation
  • Built-in DoQ server list (AdGuard, ControlD, Alibaba DNS)
  • Async/await support with Tokio
  • TLS 1.3 with QUIC transport
  • Support for A, AAAA, MX, TXT, NS, CNAME, PTR, SRV records
  • Zero-copy DNS message parsing
  • Connection pooling with lazy initialization

Installation

Add to Cargo.toml:

[dependencies]
idoq = "0.1"

Usage

Query DNS records using built-in servers:

use idoq::{DOQ_LI, QType};
use idns::Query;

#[tokio::main]
async fn main() {
  let server = &DOQ_LI[0]; // AdGuard DNS

  match server.answer_li(QType::A, "example.com").await {
    Ok(Some(answers)) => {
      for a in answers {
        println!("{} TTL={}", a.val, a.ttl);
      }
    }
    Ok(None) => println!("No records"),
    Err(e) => eprintln!("Error: {e}"),
  }
}

Query with custom server:

use idoq::{host_ip, QType};
use idns::Query;

#[tokio::main]
async fn main() {
  let server = host_ip("dns.alidns.com", 223, 5, 5, 5);

  if let Ok(Some(answers)) = server.answer_li(QType::AAAA, "google.com").await {
    for a in answers {
      println!("{}", a.val);
    }
  }
}

API Reference

Structs

HostIp

DoQ server configuration with hostname and IP address.

pub struct HostIp {
  pub host: SmolStr,  // Server hostname for TLS SNI
  pub ip: IpAddr,     // Server IP address
}

Implements idns::Query trait for DNS queries.

Functions

host_ip

Create HostIp from static hostname and IPv4 octets.

pub const fn host_ip(host: &'static str, a: u8, b: u8, c: u8, d: u8) -> HostIp

Constants

DOQ_LI

Pre-configured DoQ server list:

Server IP
AdGuard DNS 94.140.14.140, 94.140.14.141
ControlD 76.76.2.11
Alibaba DNS 223.5.5.5, 223.6.6.6

site module

Server hostname constants:

  • site::ADGUARD - "unfiltered.adguard-dns.com"
  • site::CONTROLD - "p0.freedns.controld.com"
  • site::ALIDNS - "dns.alidns.com"

Types

QType

DNS query types (re-exported from idns):

  • QType::A (1) - IPv4 address
  • QType::AAAA (28) - IPv6 address
  • QType::MX (15) - Mail exchange
  • QType::TXT (16) - Text record
  • QType::NS (2) - Name server
  • QType::CNAME (5) - Canonical name
  • QType::PTR (12) - Pointer record
  • QType::SRV (33) - Service record

Architecture

graph TD
    A[Client Code] --> B[HostIp.answer_li]
    B --> C[query_with]
    C --> D[connect]
    C --> E[query_dns]
    D --> F[QUIC Endpoint]
    F --> G[TLS Handshake]
    G --> H[QUIC Connection]
    E --> I[build_query]
    E --> J[Send DNS Message]
    J --> K[Receive Response]
    K --> L[parse]
    L --> M[Answer List]

Query Flow

  1. HostIp.answer_li() - Entry point implementing idns::Query trait
  2. query_with() - Establishes connection and executes query
  3. connect() - Creates QUIC endpoint with TLS 1.3, ALPN "doq"
  4. query_dns() - Opens bidirectional stream, sends query with 2-byte length prefix
  5. build_query() - Constructs DNS message (ID=0 per RFC 9250) with EDNS
  6. parse() - Parses DNS response, extracts answer records

Key Implementation Details

  • DNS message ID set to 0 (RFC 9250 requirement)
  • 2-byte length prefix for message framing
  • EDNS OPT record with 4096 byte UDP payload size
  • Lazy-initialized ClientConfig for connection reuse
  • 7-second timeout for connection and read operations

Tech Stack

Component Library
QUIC quinn
TLS rustls + ring
Async Runtime tokio
Buffer bytes
Error Handling thiserror

Directory Structure

idoq/
├── src/
│   ├── lib.rs      # Public API, HostIp, DOQ_LI
│   ├── query.rs    # QUIC connection, DNS query
│   ├── parser.rs   # DNS message build/parse
│   └── error.rs    # Error types
├── tests/
│   └── main.rs     # Integration tests
└── Cargo.toml

History

DNS over QUIC (DoQ) was standardized in RFC 9250 (May 2022), building on the encrypted DNS movement that began with DNS over HTTPS (DoH, RFC 8484, 2018) and DNS over TLS (DoT, RFC 7858, 2016).

QUIC, originally developed by Google in 2012 as "Quick UDP Internet Connections", was standardized as RFC 9000 in 2021. It provides TLS 1.3 encryption at the transport layer with reduced connection latency through 0-RTT handshakes.

DoQ combines the privacy benefits of encrypted DNS with QUIC's performance advantages: multiplexed streams prevent head-of-line blocking, and connection migration handles network changes gracefully. Unlike DoH which runs over HTTP/2 or HTTP/3, DoQ operates directly over QUIC, reducing protocol overhead.

AdGuard was among the first to deploy public DoQ servers in 2020, followed by providers like Alibaba DNS and ControlD. The protocol is gaining adoption as QUIC becomes the foundation for HTTP/3 and other modern internet protocols.


About

This project is an open-source component of js0.site ⋅ Refactoring the Internet Plan.

We are redefining the development paradigm of the Internet in a componentized way. Welcome to follow us:


idoq : Rust DNS over QUIC 客户端

目录

特性

  • 符合 RFC 9250 的 DoQ 实现
  • 内置 DoQ 服务器列表 (AdGuard、ControlD、阿里 DNS)
  • 基于 Tokio 的异步支持
  • TLS 1.3 + QUIC 传输
  • 支持 A、AAAA、MX、TXT、NS、CNAME、PTR、SRV 记录
  • 零拷贝 DNS 消息解析
  • 延迟初始化的连接池

安装

添加到 Cargo.toml:

[dependencies]
idoq = "0.1"

使用

使用内置服务器查询 DNS 记录:

use idoq::{DOQ_LI, QType};
use idns::Query;

#[tokio::main]
async fn main() {
  let server = &DOQ_LI[0]; // AdGuard DNS

  match server.answer_li(QType::A, "example.com").await {
    Ok(Some(answers)) => {
      for a in answers {
        println!("{} TTL={}", a.val, a.ttl);
      }
    }
    Ok(None) => println!("无记录"),
    Err(e) => eprintln!("错误: {e}"),
  }
}

使用自定义服务器查询:

use idoq::{host_ip, QType};
use idns::Query;

#[tokio::main]
async fn main() {
  let server = host_ip("dns.alidns.com", 223, 5, 5, 5);

  if let Ok(Some(answers)) = server.answer_li(QType::AAAA, "google.com").await {
    for a in answers {
      println!("{}", a.val);
    }
  }
}

API 参考

结构体

HostIp

DoQ 服务器配置,包含主机名和 IP 地址。

pub struct HostIp {
  pub host: SmolStr,  // TLS SNI 服务器主机名
  pub ip: IpAddr,     // 服务器 IP 地址
}

实现 idns::Query trait 用于 DNS 查询。

函数

host_ip

从静态主机名和 IPv4 八位组创建 HostIp

pub const fn host_ip(host: &'static str, a: u8, b: u8, c: u8, d: u8) -> HostIp

常量

DOQ_LI

预配置的 DoQ 服务器列表:

服务器 IP
AdGuard DNS 94.140.14.140, 94.140.14.141
ControlD 76.76.2.11
阿里 DNS 223.5.5.5, 223.6.6.6

site 模块

服务器主机名常量:

  • site::ADGUARD - "unfiltered.adguard-dns.com"
  • site::CONTROLD - "p0.freedns.controld.com"
  • site::ALIDNS - "dns.alidns.com"

类型

QType

DNS 查询类型 (从 idns 重导出):

  • QType::A (1) - IPv4 地址
  • QType::AAAA (28) - IPv6 地址
  • QType::MX (15) - 邮件交换
  • QType::TXT (16) - 文本记录
  • QType::NS (2) - 域名服务器
  • QType::CNAME (5) - 别名
  • QType::PTR (12) - 指针记录
  • QType::SRV (33) - 服务记录

架构

graph TD
    A[客户端代码] --> B[HostIp.answer_li]
    B --> C[query_with]
    C --> D[connect]
    C --> E[query_dns]
    D --> F[QUIC Endpoint]
    F --> G[TLS 握手]
    G --> H[QUIC 连接]
    E --> I[build_query]
    E --> J[发送 DNS 消息]
    J --> K[接收响应]
    K --> L[parse]
    L --> M[Answer 列表]

查询流程

  1. HostIp.answer_li() - 入口点,实现 idns::Query trait
  2. query_with() - 建立连接并执行查询
  3. connect() - 创建 QUIC 端点,TLS 1.3,ALPN "doq"
  4. query_dns() - 打开双向流,发送带 2 字节长度前缀的查询
  5. build_query() - 构造 DNS 消息 (ID=0,符合 RFC 9250) 及 EDNS
  6. parse() - 解析 DNS 响应,提取应答记录

关键实现细节

  • DNS 消息 ID 设为 0 (RFC 9250 要求)
  • 2 字节长度前缀用于消息分帧
  • EDNS OPT 记录,UDP 负载大小 4096 字节
  • 延迟初始化 ClientConfig 以复用连接
  • 连接和读取操作 7 秒超时

技术栈

组件
QUIC quinn
TLS rustls + ring
异步运行时 tokio
缓冲区 bytes
错误处理 thiserror

目录结构

idoq/
├── src/
│   ├── lib.rs      # 公开 API、HostIp、DOQ_LI
│   ├── query.rs    # QUIC 连接、DNS 查询
│   ├── parser.rs   # DNS 消息构建/解析
│   └── error.rs    # 错误类型
├── tests/
│   └── main.rs     # 集成测试
└── Cargo.toml

历史

DNS over QUIC (DoQ) 于 2022 年 5 月在 RFC 9250 中标准化,是加密 DNS 运动的延续。此前有 DNS over HTTPS (DoH, RFC 8484, 2018) 和 DNS over TLS (DoT, RFC 7858, 2016)。

QUIC 最初由 Google 于 2012 年开发,名为 "Quick UDP Internet Connections",2021 年标准化为 RFC 9000。它在传输层提供 TLS 1.3 加密,通过 0-RTT 握手降低连接延迟。

DoQ 结合了加密 DNS 的隐私优势和 QUIC 的性能优势:多路复用流避免队头阻塞,连接迁移优雅处理网络切换。与运行在 HTTP/2 或 HTTP/3 上的 DoH 不同,DoQ 直接运行在 QUIC 上,减少协议开销。

AdGuard 于 2020 年率先部署公共 DoQ 服务器,随后阿里 DNS、ControlD 等提供商跟进。随着 QUIC 成为 HTTP/3 和其他现代互联网协议的基础,DoQ 正在获得更广泛的采用。


关于

本项目为 js0.site ⋅ 重构互联网计划 的开源组件。

我们正在以组件化的方式重新定义互联网的开发范式,欢迎关注: