25 个版本

0.7.1 2024 年 8 月 13 日
0.7.0 2024 年 3 月 25 日
0.6.2 2024 年 2 月 27 日
0.5.7 2023 年 10 月 17 日
0.1.1 2021 年 6 月 8 日

#60解析器实现

Download history 21468/week @ 2024-05-02 21417/week @ 2024-05-09 21750/week @ 2024-05-16 33563/week @ 2024-05-23 30227/week @ 2024-05-30 21336/week @ 2024-06-06 25250/week @ 2024-06-13 26991/week @ 2024-06-20 25404/week @ 2024-06-27 25079/week @ 2024-07-04 28921/week @ 2024-07-11 34650/week @ 2024-07-18 33442/week @ 2024-07-25 27611/week @ 2024-08-01 44190/week @ 2024-08-08 31910/week @ 2024-08-15

144,241 每月下载量
131 仓库中使用 (直接使用 9 个)

MIT 许可证

170KB
4K SLoC

Simple DNS

纯 Rust 实现,用于处理 DNS 数据包

您可以使用 Packet 来解析或写入 DNS 数据包

Packet

Packet 代表一个 DNS 数据包,它是构造和操作数据包并在写入线格式之前的主要结构。

use simple_dns::*;
use simple_dns::rdata::*;

let mut packet = Packet::new_query(1);

let question = Question::new(Name::new_unchecked("_srv._udp.local"), TYPE::TXT.into(), CLASS::IN.into(), false);
packet.questions.push(question);

let resource = ResourceRecord::new(Name::new_unchecked("_srv._udp.local"), CLASS::IN, 10, RData::A(A { address: 10 }));
packet.additional_records.push(resource);

// Write the packet in the provided buffer;
let mut bytes = [0u8; 200];
assert!(packet.write_to(&mut &mut bytes[..]).is_ok());

// Same as above, but allocates and returns a Vec<u8>
let bytes = packet.build_bytes_vec();
assert!(bytes.is_ok());

// Same as above, but Names are compressed
let bytes = packet.build_bytes_vec_compressed();
assert!(bytes.is_ok());

资源的添加顺序无关紧要,只有在调用 build_bytes_vecwrite_to 时才会构建数据包

要将缓冲区的内容解析为数据包,需要调用 Packet::parse

use simple_dns::Packet;

let bytes = b"\x00\x03\x01\x00\x00\x01\x00\x00\x00\x00\x00\x00\x06\x67\x6f\x6f\x67\x6c\x65\x03\x63\x6f\x6d\x00\x00\x01\x00\x01";
let packet = Packet::parse(&bytes[..]);
assert!(packet.is_ok());

可以使用 header_buffer 模块函数来检查数据包的一些信息,而无需解析数据包。
检查 RCODE 和数据包标志时要小心,请参阅模块文档以获取更多信息。

use simple_dns::{header_buffer, PacketFlag};
let buffer = b"\x00\x03\x01\x00\x00\x01\x00\x00\x00\x00\x00\x00\x06\x67\x6f\x6f\x67\x6c\x65\x03\x63\x6f\x6d\x00\x00\x01\x00\x01";

assert_eq!(Ok(3), header_buffer::id(&buffer[..]));
assert!(!header_buffer::has_flags(&buffer[..], PacketFlag::RESPONSE).unwrap());

Packet 支持 EDNS,通过 optopt_mut 函数。当处理 EDNS 数据包时,您 不应该OPT 资源记录 直接添加到 附加记录 部分,除非您确切知道自己在做什么。

EDNS0 注意事项

EDNS 通过添加一个 OPT 资源记录并将部分头信息移动到附加记录部分来扩展 DNS 数据包头。RCODE 从 4 位增加到 12 位,其中前 4 位存储在头部部分,而最后 8 位存储在数据包的某个其他地方。

这将对数据包的解析或构建有一些影响

use simple_dns::{header_buffer, RCODE, Packet};

let buffer = b"\x00\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x01\x01\x2e\x00\x00\x29\x01\xf4\x00\x00\x03\x01\x00\x04\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00";
let packet = Packet::parse(&buffer[..]).unwrap();

// Without parsing the full packet, it is impossible to know the true RCODE of the packet
assert_eq!(RCODE::NoError, header_buffer::rcode(&buffer[..]).unwrap());
assert_eq!(RCODE::BADVERS, packet.rcode());

请参阅 RFC 6891 以获取更多信息

DNS 数据包解析器/构建器

Packet 结构提供了数据包的解析和构建,它旨在完全符合以下 RFC

其他由其他RFC定义但不在本列表中的资源记录将逐步实现

更新数据包(RFC 2136)

此库可以解析更新数据包,但它不验证更新规则,并且更新字段在数据包字段中过载,如RFC 2136中定义。

依赖关系

~110KB