GMDNS 是一个基于 Rust 开发的高性能 mDNS (Multicast DNS) 协议库,专门为 P2P 网络发现和穿透场景设计。它不仅支持标准的 RFC 6762 协议,还通过自定义资源记录扩展了端点(Endpoint)发现能力,支持直连和中继地址的发布与验证。
- 标准兼容:支持标准 DNS 报文格式及 mDNS 组播发现。
- P2P 增强:自定义
E记录,支持 IPv4/IPv6 的直连与中继地址。 - 安全验证:内置 Ed25519 等签名方案,确保端点数据的真实性与完整性。
- 高性能解析:基于
nom零拷贝解析框架,提供极速的报文处理能力。 - 异步驱动:完全适配
tokio异步运行时,适用于高并发网络环境。
在 Cargo.toml 中引用:
[dependencies]
gmdns = { path = "../gmdns" }use gmdns::mdns::Mdns;
use futures::StreamExt;
#[tokio::main]
async fn main() -> Result<(), std::io::Error> {
// 创建 mDNS 实例
let mdns = Mdns::new("_genmeta.local", "127.0.0.1".parse().unwrap(), "lo0")?;
// 监听发现流
let mut stream = mdns.discover();
while let Some((addr, packet)) = stream.next().await {
println!("发现来自 {} 的报文: {:?}", addr, packet);
}
Ok(())
}DNS 报文由固定头部和四个变长部分组成:
+---------------------+-----------------------+-----------------------+-----------------------+-----------------------+
| Header (12 bytes) | Question Section | Answer Section | Nameserver Section | Additional Section |
+---------------------+-----------------------+-----------------------+-----------------------+-----------------------+
| 事务 ID 与标志位 | 查询请求列表 | 回答资源记录列表 | 授权服务器记录列表 | 附加资源记录列表 |
+---------------------+-----------------------+-----------------------+-----------------------+-----------------------+
固定长度为 12 字节。包含 ID、Flags、以及后续各部分的计数器(QDCOUNT, ANCOUNT, NSCOUNT, ARCOUNT)。
Answer, Nameserver, Additional 部分均使用此格式:
- NAME: 变长域名,支持 RFC 1035 压缩算法。
- TYPE (u16): 记录类型(如 A=1, SRV=33, E=266 等)。
- CLASS (u16): 协议类。mDNS 中最高位 (bit 15) 用于缓存刷新标志。
- TTL (u32): 缓存生存时间(秒)。
- RDLEN (u16): 资源数据 (RDATA) 的长度。
- RDATA: 具体的资源内容,格式由 TYPE 决定。
| 类型 | 数值 | 描述 | RDATA 格式 |
|---|---|---|---|
| A | 1 | IPv4 地址 | 4 字节 IP |
| AAAA | 28 | IPv6 地址 | 16 字节 IP |
| SRV | 33 | 服务定位 | Priority + Weight + Port + Target |
| E | 266 | 端点地址 | Flags + Seq + Addr(s) + [Sig] |
+--------+-----------------+--------------------+----------------------------+
| flags | sequence(varint)| addr(s) | signature (optional) |
+--------+-----------------+--------------------+----------------------------+
| u8 | QUIC varint | v4: 2+4 / v6: 2+16 | scheme(u16)+len(varint)+N |
+--------+-----------------+--------------------+----------------------------+
- bit 7 (0x80): MAIN - 主地址标志
- bit 6 (0x40): SIGNED - 是否有签名标志
- bit 5 (0x20): SEQUENCED - 是否有序号
- bit 4 (0x10): FAMILY - 0=IPv4, 1=IPv6
- bit 3 (0x08): FORWARD - 0=直连, 1=中转
- bits 2-0: 保留位
- 直连:
port(u16)+IP(u32/u128) - 中转:
outer_port(u16)+outer_IP(u32/u128)+agent_port(u16)+agent_IP(u32/u128) sequence: DNS 记录编号,同一编号的记录视为一个机器,可以使用多路径连接signature: 当SIGNED置位时,允许附加签名字段
0b1000_0000: MAIN (主地址标志)0b0100_0000: SIGNED (包含签名标志)0b0010_0000: SEQUENCED (包含序号标志)0b0001_0000: FAMILY (地址族: 0=IPv4, 1=IPv6)0b0000_1000: FORWARD (连接类型: 0=直连, 1=中继)
- 直连:
Port(u16)+IP(u32/u128) - 中继:
OuterPort(u16)+OuterIP(u32/u128)+AgentPort(u16)+AgentIP(u32/u128)
若包含签名,格式为:Scheme (u16) + Length (VarInt) + Data (N bytes)。
src/parser/:核心协议解析实现(Nom 解析器)。src/protocol.rs:UDP 组播与报文路由逻辑。src/mdns.rs:高层 mDNS 发现与响应 API。examples/:包含查询、发现与广播的示例代码。