idoq : DNS over QUIC Client for Rust
Based on idns. See idns for DnsRace, Parse trait, caching, and more.
Table of Contents
Features
- RFC 9250 compliant DoQ implementation
- Built-in DoQ server list (AdGuard, ControlD, Alibaba DNS)
- Async/await with Tokio
- TLS 1.3 over QUIC
- A, AAAA, MX, TXT, NS, CNAME, PTR, SRV record types
- Zero-copy DNS message parsing
- Lazy-initialized TLS config
- Connection reuse with auto-reconnect
Installation
[]
= "0.1"
Usage
Basic query:
use ;
use Query;
async
Custom server:
use ;
use Query;
async
MX records with Parse trait:
use ;
use ;
async
Race multiple servers:
use ;
use ;
async
API Reference
Types
QType
DNS query types (re-exported from idns):
| Type | Value | Description |
|---|---|---|
| A | 1 | IPv4 address |
| NS | 2 | Name server |
| CNAME | 5 | Canonical name |
| PTR | 12 | Pointer record |
| MX | 15 | Mail exchange |
| TXT | 16 | Text record |
| AAAA | 28 | IPv6 address |
| SRV | 33 | Service record |
Structs
Doq
DoQ client with connection reuse. Implements idns::Query trait.
Methods:
new(server: HostIp) -> Selfquery(&self, domain: &str, qtype: QType) -> Result<Option<Vec<Answer>>>
HostIp
Server configuration.
Functions
host_ip
pub const
doq_li
Constants
DOQ_LI
Pre-configured DoQ servers:
| 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
site::ADGUARD-"unfiltered.adguard-dns.com"site::CONTROLD-"p0.freedns.controld.com"site::ALIDNS-"dns.alidns.com"
Architecture
graph TD
A[Client] --> B[Doq.query]
B --> C[Doq.conn]
C --> D{Alive?}
D -->|Yes| E[Reuse]
D -->|No| F[Doq.dial]
F --> G[QUIC Endpoint]
G --> H[TLS Handshake]
H --> I[Connection]
E --> J[Doq.send]
I --> J
J --> K[parser.build]
K --> L[Send]
L --> M[Receive]
M --> N[parser.parse]
N --> O[Answers]
Query Flow
Doq.query()- Entry pointDoq.conn()- Double-checked locking for connection reuseDoq.dial()- QUIC endpoint with TLS 1.3, ALPN "doq"Doq.send()- Bidirectional stream, 2-byte length prefixparser.build()- DNS message (ID=0 per RFC 9250) with EDNSparser.parse()- Extract answer records
Implementation Details
- DNS message ID = 0 (RFC 9250)
- 2-byte length prefix for framing
- EDNS OPT with 4096 byte payload
LazyLockforClientConfigRwLock<Option<Connection>>for caching- Auto-reconnect on error
- 7s timeout
Tech Stack
| Component | Library |
|---|---|
| QUIC | quinn |
| TLS | rustls + ring |
| Async | tokio |
| Buffer | bytes |
| Error | thiserror |
Directory Structure
idoq/
├── src/
│ ├── lib.rs # API, HostIp, DOQ_LI
│ ├── doq.rs # Doq client
│ ├── parser.rs # DNS build/parse
│ └── error.rs # Error types
├── tests/
│ └── main.rs
└── Cargo.toml
History
DNS over QUIC (DoQ) was standardized in RFC 9250 (May 2022), following DNS over HTTPS (DoH, RFC 8484, 2018) and DNS over TLS (DoT, RFC 7858, 2016).
QUIC, developed by Google in 2012, became RFC 9000 in 2021. It provides TLS 1.3 at transport layer with 0-RTT handshakes.
DoQ combines encrypted DNS privacy with QUIC performance: multiplexed streams prevent head-of-line blocking, connection migration handles network changes. Unlike DoH over HTTP/2 or HTTP/3, DoQ runs directly on QUIC with less overhead.
AdGuard deployed public DoQ servers in 2020, followed by Alibaba DNS and ControlD. Adoption grows as QUIC becomes the foundation for HTTP/3.
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 客户端
基于 idns。DnsRace、Parse trait、缓存等更多功能请查看 idns。
目录
特性
- 符合 RFC 9250 的 DoQ 实现
- 内置 DoQ 服务器列表 (AdGuard、ControlD、阿里 DNS)
- 基于 Tokio 异步
- TLS 1.3 + QUIC
- 支持 A、AAAA、MX、TXT、NS、CNAME、PTR、SRV 记录
- 零拷贝 DNS 消息解析
- 延迟初始化 TLS 配置
- 连接复用,自动重连
安装
[]
= "0.1"
使用
基本查询:
use ;
use Query;
async
自定义服务器:
use ;
use Query;
async
使用 Parse trait 查询 MX 记录:
use ;
use ;
async
竞速查询多个服务器:
use ;
use ;
async
API 参考
类型
QType
DNS 查询类型 (从 idns 重导出):
| 类型 | 值 | 说明 |
|---|---|---|
| A | 1 | IPv4 地址 |
| NS | 2 | 域名服务器 |
| CNAME | 5 | 别名 |
| PTR | 12 | 指针记录 |
| MX | 15 | 邮件交换 |
| TXT | 16 | 文本记录 |
| AAAA | 28 | IPv6 地址 |
| SRV | 33 | 服务记录 |
结构体
Doq
DoQ 客户端,支持连接复用。实现 idns::Query trait。
方法:
new(server: HostIp) -> Selfquery(&self, domain: &str, qtype: QType) -> Result<Option<Vec<Answer>>>
HostIp
服务器配置。
函数
host_ip
pub const
doq_li
常量
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"
架构
graph TD
A[客户端] --> B[Doq.query]
B --> C[Doq.conn]
C --> D{存活?}
D -->|是| E[复用]
D -->|否| F[Doq.dial]
F --> G[QUIC Endpoint]
G --> H[TLS 握手]
H --> I[连接]
E --> J[Doq.send]
I --> J
J --> K[parser.build]
K --> L[发送]
L --> M[接收]
M --> N[parser.parse]
N --> O[应答]
查询流程
Doq.query()- 入口Doq.conn()- 双重检查锁定,复用连接Doq.dial()- QUIC 端点,TLS 1.3,ALPN "doq"Doq.send()- 双向流,2 字节长度前缀parser.build()- DNS 消息 (ID=0,RFC 9250) + EDNSparser.parse()- 提取应答记录
实现细节
- DNS 消息 ID = 0 (RFC 9250)
- 2 字节长度前缀分帧
- EDNS OPT 4096 字节负载
LazyLock延迟初始化ClientConfigRwLock<Option<Connection>>缓存连接- 错误时自动重连
- 7 秒超时
技术栈
| 组件 | 库 |
|---|---|
| QUIC | quinn |
| TLS | rustls + ring |
| 异步 | tokio |
| 缓冲 | bytes |
| 错误 | thiserror |
目录结构
idoq/
├── src/
│ ├── lib.rs # API、HostIp、DOQ_LI
│ ├── doq.rs # Doq 客户端
│ ├── parser.rs # DNS 构建/解析
│ └── error.rs # 错误类型
├── tests/
│ └── main.rs
└── Cargo.toml
历史
DNS over QUIC (DoQ) 于 2022 年 5 月在 RFC 9250 中标准化,继 DNS over HTTPS (DoH, RFC 8484, 2018) 和 DNS over TLS (DoT, RFC 7858, 2016) 之后。
QUIC 由 Google 于 2012 年开发,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 ⋅ 重构互联网计划 的开源组件。
我们正在以组件化的方式重新定义互联网的开发范式,欢迎关注: