| Crates.io | idot |
| lib.rs | idot |
| version | 0.1.2 |
| created_at | 2025-12-19 22:34:22.287084+00 |
| updated_at | 2025-12-23 03:07:23.440033+00 |
| description | DNS over TLS (DoT) client / DNS over TLS (DoT) 客户端 |
| homepage | https://github.com/js0-dns/rust/tree/main/idot |
| repository | https://github.com/js0-dns/rust.git |
| max_upload_size | |
| id | 1995683 |
| size | 69,015 |
Based on idns. See idns for DnsRace, Cache, Parse trait, and more.
[dependencies]
idot = "0.1"
idns = "0.1"
Race multiple servers and cache results:
use idot::{DOT_LI, dot_li};
use idns::{Cache, DnsRace, Mx, Query};
use std::time::Instant;
#[tokio::main]
async fn main() {
let race = DnsRace::new(dot_li(DOT_LI));
let cache: Cache<Mx> = Cache::new(60); // 60s TTL
// First query (cache miss)
let t1 = Instant::now();
let r1 = cache.query(&race, "gmail.com").await;
let d1 = t1.elapsed();
println!("First: {}ms", d1.as_millis());
if let Some(mx_list) = &*r1.unwrap() {
for mx in mx_list {
println!(" {} {}", mx.priority, mx.server);
}
}
// Second query (cache hit)
let t2 = Instant::now();
let _ = cache.query(&race, "gmail.com").await;
let d2 = t2.elapsed();
println!("Cache: {}μs", d2.as_micros());
}
use idot::{Dot, host_ip, QType};
use idns::Query;
#[tokio::main]
async fn main() {
let client = Dot::new(host_ip("cloudflare-dns.com", 1, 1, 1, 1));
if let Ok(Some(answers)) = client.answer_li(QType::A, "example.com").await {
for a in answers {
println!("{} TTL={}", a.val, a.ttl);
}
}
}
use idot::{Dot, host_ip, QType};
use idns::Query;
#[tokio::main]
async fn main() {
let server = host_ip("dns.google", 8, 8, 8, 8);
let client = Dot::new(server);
if let Ok(Some(answers)) = client.answer_li(QType::AAAA, "google.com").await {
for a in answers {
println!("{}", a.val);
}
}
}
DotDoT client with connection reuse. Implements idns::Query trait.
HostIpServer configuration with host: SmolStr (TLS SNI) and ip: IpAddr.
host_ip(host, a, b, c, d) -> HostIp - Create HostIp from hostname and IPv4dot_li(li: &[HostIp]) -> Vec<Dot> - Create Dot clients from HostIp listDOT_LIPre-configured DoT servers:
| Server | IP |
|---|---|
| Cloudflare | 1.1.1.1, 1.0.0.1 |
| 8.8.8.8, 8.8.4.4 | |
| Quad9 | 9.9.9.9 |
| 360 DNS (China) | 101.226.4.6, 218.30.118.6 |
| TWNIC (Taiwan) | 101.101.101.101 |
| IIJ DNS (Japan) | 103.2.57.5 |
dns moduleServer hostname constants:
dns::CLOUDFLARE - "cloudflare-dns.com"dns::GOOGLE - "dns.google"dns::QUAD9 - "dns.quad9.net"dns::DNS360 - "dot.360.cn"dns::TWNIC - "101.101.101.101"dns::IIJ - "public.dns.iij.jp"dns::ALIDNS - "dns.alidns.com" (disabled: incomplete TXT records)dns::DNSPOD - "dot.pub" (disabled: connection issues)graph TD
A[Client] --> B[Dot.query]
B --> C[conn]
C --> D{Has conn?}
D -->|Yes| E[Take]
D -->|No| F[dial]
F --> G[TCP + TLS 1.3]
G --> I[TlsStream]
E --> J[send]
I --> J
J --> K[DNS Message]
K --> L[Response]
L --> M[Parse]
M --> N[Answers]
N --> O[return_conn]
LazyLock for TLS ClientConfigRwLock<Option<TlsStream>> for connection reuse| Component | Library |
|---|---|
| TLS | rustls + tokio-rustls |
| Async | tokio |
| Buffer | bytes |
| Error | thiserror |
| DNS Parse | dns_parse |
| Feature | DoT (idot) | DoQ (idoq) |
|---|---|---|
| Protocol | TCP + TLS | QUIC |
| Port | 853 | 853 |
| Multiplexing | No | Yes |
| 0-RTT | No | Yes |
| Head-of-line blocking | Yes | No |
| Maturity | High | Medium |
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:
基于 idns。DnsRace、Cache、Parse trait 等更多功能请查看 idns。
[dependencies]
idot = "0.1"
idns = "0.1"
竞速查询多个服务器并缓存结果:
use idot::{DOT_LI, dot_li};
use idns::{Cache, DnsRace, Mx, Query};
use std::time::Instant;
#[tokio::main]
async fn main() {
let race = DnsRace::new(dot_li(DOT_LI));
let cache: Cache<Mx> = Cache::new(60); // 60 秒 TTL
// 首次查询(缓存未命中)
let t1 = Instant::now();
let r1 = cache.query(&race, "gmail.com").await;
let d1 = t1.elapsed();
println!("首次: {}ms", d1.as_millis());
if let Some(mx_list) = &*r1.unwrap() {
for mx in mx_list {
println!(" {} {}", mx.priority, mx.server);
}
}
// 再次查询(缓存命中)
let t2 = Instant::now();
let _ = cache.query(&race, "gmail.com").await;
let d2 = t2.elapsed();
println!("缓存: {}μs", d2.as_micros());
}
use idot::{Dot, host_ip, QType};
use idns::Query;
#[tokio::main]
async fn main() {
let client = Dot::new(host_ip("cloudflare-dns.com", 1, 1, 1, 1));
if let Ok(Some(answers)) = client.answer_li(QType::A, "example.com").await {
for a in answers {
println!("{} TTL={}", a.val, a.ttl);
}
}
}
use idot::{Dot, host_ip, QType};
use idns::Query;
#[tokio::main]
async fn main() {
let server = host_ip("dns.google", 8, 8, 8, 8);
let client = Dot::new(server);
if let Ok(Some(answers)) = client.answer_li(QType::AAAA, "google.com").await {
for a in answers {
println!("{}", a.val);
}
}
}
DotDoT 客户端,支持连接复用。实现 idns::Query trait。
HostIp服务器配置,包含 host: SmolStr(TLS SNI)和 ip: IpAddr。
host_ip(host, a, b, c, d) -> HostIp - 从主机名和 IPv4 创建 HostIpdot_li(li: &[HostIp]) -> Vec<Dot> - 从 HostIp 列表创建 Dot 客户端DOT_LI预配置 DoT 服务器:
| 服务器 | IP |
|---|---|
| Cloudflare | 1.1.1.1, 1.0.0.1 |
| 8.8.8.8, 8.8.4.4 | |
| Quad9 | 9.9.9.9 |
| 360 DNS(中国) | 101.226.4.6, 218.30.118.6 |
| TWNIC(台湾) | 101.101.101.101 |
| IIJ DNS(日本) | 103.2.57.5 |
dns 模块服务器主机名常量:
dns::CLOUDFLARE - "cloudflare-dns.com"dns::GOOGLE - "dns.google"dns::QUAD9 - "dns.quad9.net"dns::DNS360 - "dot.360.cn"dns::TWNIC - "101.101.101.101"dns::IIJ - "public.dns.iij.jp"dns::ALIDNS - "dns.alidns.com"(已禁用:TXT 记录不完整)dns::DNSPOD - "dot.pub"(已禁用:连接问题)graph TD
A[客户端] --> B[Dot.query]
B --> C[conn]
C --> D{有连接?}
D -->|是| E[取出]
D -->|否| F[dial]
F --> G[TCP + TLS 1.3]
G --> I[TlsStream]
E --> J[send]
I --> J
J --> K[DNS 消息]
K --> L[响应]
L --> M[解析]
M --> N[应答]
N --> O[return_conn]
LazyLock 延迟初始化 TLS ClientConfigRwLock<Option<TlsStream>> 连接复用| 组件 | 库 |
|---|---|
| TLS | rustls + tokio-rustls |
| 异步 | tokio |
| 缓冲 | bytes |
| 错误 | thiserror |
| DNS 解析 | dns_parse |
| 特性 | DoT (idot) | DoQ (idoq) |
|---|---|---|
| 协议 | TCP + TLS | QUIC |
| 端口 | 853 | 853 |
| 多路复用 | 否 | 是 |
| 0-RTT | 否 | 是 |
| 队头阻塞 | 是 | 否 |
| 成熟度 | 高 | 中 |
本项目为 js0.site ⋅ 重构互联网计划 的开源组件。
我们正在以组件化的方式重新定义互联网的开发范式,欢迎关注: