57 个版本
0.10.10 | 2024 年 8 月 6 日 |
---|---|
0.10.9 | 2024 年 4 月 12 日 |
0.10.6 | 2024 年 3 月 30 日 |
0.10.0-alpha.8 | 2023 年 12 月 6 日 |
0.6.0-rc.7 | 2021 年 11 月 29 日 |
在 网络编程 中排名 70
每月下载量 797 次
用于 3 crates
590KB
12K SLoC
BGPKIT 解析器
此说明由库的文档注释生成,使用 cargo-readme。请参阅 Rust 文档网站以获取 完整文档
BGPKIT 解析器旨在提供最便捷的 MRT/BGP/BMP 消息解析 Rust API。
BGPKIT 解析器具有以下特性
- 高效:与基于 C 的实现(如
bgpdump
或bgpreader
)相当。 - 积极维护:我们持续引入功能更新和错误修复,并支持大多数相关的 BGP RFC。
- 便捷的 API:三行循环即可开始。
- 功能全面:开箱即用,可处理远程或本地,bzip2 或 gz 数据文件。
示例
有关完整示例,请参阅 示例文件夹。
解析单个 MRT 文件
假设我们想打印出单个 MRT 文件中的所有 BGP 通告/撤回,无论是远程的还是本地的。以下是一个示例。
use bgpkit_parser::BgpkitParser;
let parser = BgpkitParser::new("http://archive.routeviews.org/bgpdata/2021.10/UPDATES/updates.20211001.0000.bz2").unwrap();
for elem in parser {
println!("{}", elem)
}
是的,就这么简单!
您甚至可以进行一些更有趣的迭代操作,而这些操作更加简洁。例如,统计该文件中通告/撤回的数量
use bgpkit_parser::BgpkitParser;
let url = "http://archive.routeviews.org/bgpdata/2021.10/UPDATES/updates.20211001.0000.bz2";
let count = BgpkitParser::new(url).unwrap().into_iter().count();
println!("total: {}", count);
然后它会打印出
total: 255849
使用 BGPKIT Broker 解析多个 MRT 文件
BGPKIT Broker 库为所有 RouteViews 和 RIPE RIS MRT 数据文件提供搜索 API。使用经纪人的 Rust API(bgpkit-broker
),我们可以轻松地编译出我们感兴趣的任何时间段和任何数据类型(update
或 rib
)的 MRT 文件列表。这使得用户无需了解特定数据文件的存储位置即可收集信息。
以下示例展示了相对更有趣的例子,该例子执行以下操作:
- 查找在时间 1634693400 上创建的所有 BGP 存档数据
- 仅筛选 BGP 更新文件
- 查找所有来自 AS13335 的通告
- 打印通告的总数
use bgpkit_parser::{BgpkitParser, BgpElem};
let broker = bgpkit_broker::BgpkitBroker::new()
.ts_start("1634693400")
.ts_end("1634693400")
.page(1);
for item in broker.into_iter().take(2) {
log::info!("downloading updates file: {}", &item.url);
let parser = BgpkitParser::new(item.url.as_str()).unwrap();
log::info!("parsing updates file");
// iterating through the parser. the iterator returns `BgpElem` one at a time.
let elems = parser
.into_elem_iter()
.filter_map(|elem| {
if let Some(origins) = &elem.origin_asns {
if origins.contains(&13335.into()) {
Some(elem)
} else {
None
}
} else {
None
}
})
.collect::<Vec<BgpElem>>();
log::info!("{} elems matches", elems.len());
}
筛选 BGP 消息
BGPKIT 解析器还包含一个内置的[筛选]机制。在创建新的BgpkitParser
实例时,也可以调用add_filter
函数来自定义解析器,使其在迭代[BgpElem]时仅显示匹配的消息。
有关所有类型的筛选,请参阅[Filter]枚举文档。
use bgpkit_parser::BgpkitParser;
/// This example shows how to parse an MRT file and filter by prefix.
env_logger::Builder::from_env(env_logger::Env::default().default_filter_or("info")).init();
log::info!("downloading updates file");
// create a parser that takes the buffered reader
let parser = BgpkitParser::new("http://archive.routeviews.org/bgpdata/2021.10/UPDATES/updates.20211001.0000.bz2").unwrap()
.add_filter("prefix", "211.98.251.0/24").unwrap();
log::info!("parsing updates file");
// iterating through the parser. the iterator returns `BgpElem` one at a time.
for elem in parser {
log::info!("{}", &elem);
}
log::info!("done");
解析实时数据流
BGPKIT 解析器还提供了解析实时数据流的功能,包括RIS-Live和BMP/OpenBMP消息。请参阅下面的示例和文档以了解更多信息。
解析 RIS-Live 消息
以下是一个处理 RIS-Live 消息流的示例。连接到 WebSocket 服务器后,我们需要订阅特定的数据流。在这个例子中,我们订阅了来自收集器(rrc21
)的数据流。然后我们可以循环读取 WebSocket 的消息。
use bgpkit_parser::parse_ris_live_message;
use serde_json::json;
use tungstenite::{connect, Message};
const RIS_LIVE_URL: &str = "ws://ris-live.ripe.net/v1/ws/?client=rust-bgpkit-parser";
/// This is an example of subscribing to RIS-Live's streaming data from one host (`rrc21`).
///
/// For more RIS-Live details, check out their documentation at https://ris-live.ripe.net/manual/
fn main() {
// connect to RIPE RIS Live websocket server
let (mut socket, _response) =
connect(RIS_LIVE_URL)
.expect("Can't connect to RIS Live websocket server");
// subscribe to messages from one collector
let msg = json!({"type": "ris_subscribe", "data": {"host": "rrc21"}}).to_string();
socket.send(Message::Text(msg)).unwrap();
loop {
let msg = socket.read().expect("Error reading message").to_string();
if let Ok(elems) = parse_ris_live_message(msg.as_str()) {
for elem in elems {
println!("{}", elem);
}
}
}
}
从 RouteViews Kafka 流解析 OpenBMP 消息
RouteViews提供了一个实时 Kafka 流,包含从其收集器接收到的 OpenBMP 数据。以下是处理从 Kafka 流接收到的原始字节的局部示例。有关完整示例,请参阅GitHub上的示例文件夹。
let bytes = m.value;
let mut reader = Cursor::new(Vec::from(bytes));
let header = parse_openbmp_header(&mut reader).unwrap();
let bmp_msg = parse_bmp_msg(&mut reader);
match bmp_msg {
Ok(msg) => {
let timestamp = header.timestamp;
let per_peer_header = msg.per_peer_header.unwrap();
match msg.message_body {
MessageBody::RouteMonitoring(m) => {
for elem in Elementor::bgp_to_elems(
m.bgp_message,
timestamp,
&per_peer_header.peer_ip,
&per_peer_header.peer_asn
)
{
info!("{}", elem);
}
}
_ => {}
}
}
Err(_e) => {
let hex = hex::encode(bytes);
error!("{}", hex);
break
}
}
将筛选后的 MRT 记录存档到磁盘上的新 MRT 文件
此示例将从 RouteViews 下载一个 MRT 文件,筛选出所有不是来自 AS3356 的 BGP 消息,并将筛选后的 MRT 记录写入磁盘。然后它重新解析筛选后的 MRT 文件并打印出 BGP 消息的数量。
use bgpkit_parser::Elementor;
use itertools::Itertools;
use std::io::Write;
let mut updates_encoder = bgpkit_parser::encoder::MrtUpdatesEncoder::new();
bgpkit_parser::BgpkitParser::new(
"http://archive.routeviews.org/bgpdata/2023.10/UPDATES/updates.20231029.2015.bz2",
).unwrap()
.add_filter("origin_asn", "3356").unwrap()
.into_iter()
.for_each(|elem| {
updates_encoder.process_elem(&elem);
});
let mut mrt_writer = oneio::get_writer("as3356_mrt.gz").unwrap();
mrt_writer.write_all(updates_encoder.export_bytes().as_ref()).unwrap();
drop(mrt_writer);
命令行工具
bgpkit-parser
附带了一个名为bgpkit-parser-cli
的实用命令行工具。
安装
安装编译的二进制文件
您可以使用以下方法安装编译的bgpkit-parser
CLI 二进制文件:
- Homebrew(macOS):
brew install bgpkit/tap/bgpkit-parser
- Cargo binstall:
cargo binstall bgpkit-parser
从源码
您可以通过运行以下命令安装工具:
cargo install bgpkit-parser --features cli
或检出此存储库并运行
cargo install --path . --features cli
用法
运行 bgpkit-parser --help
以查看完整选项列表。
MRT/BGP/BMP data processing library
Usage: bgpkit-parser [OPTIONS] <FILE>
Arguments:
<FILE> File path to a MRT file, local or remote
Options:
-c, --cache-dir <CACHE_DIR> Set the cache directory for caching remote files. Default behavior does not enable caching
--json Output as JSON objects
--psv Output as full PSV entries with header
--pretty Pretty-print JSON output
-e, --elems-count Count BGP elems
-r, --records-count Count MRT records
-o, --origin-asn <ORIGIN_ASN> Filter by origin AS Number
-p, --prefix <PREFIX> Filter by network prefix
-4, --ipv4-only Filter by IPv4 only
-6, --ipv6-only Filter by IPv6 only
-s, --include-super Include super-prefix when filtering
-S, --include-sub Include sub-prefix when filtering
-j, --peer-ip <PEER_IP> Filter by peer IP address
-J, --peer-asn <PEER_ASN> Filter by peer ASN
-m, --elem-type <ELEM_TYPE> Filter by elem type: announce (a) or withdraw (w)
-t, --start-ts <START_TS> Filter by start unix timestamp inclusive
-T, --end-ts <END_TS> Filter by end unix timestamp inclusive
-a, --as-path <AS_PATH> Filter by AS path regex string
-h, --help Print help
-V, --version Print version
数据表示
了解解析结果需要理解两个关键数据结构:[MrtRecord] 和 [BgpElem]。
MrtRecord
:未修改的 MRT 信息表示
[MrtRecord] 是一个数据结构,用于保存从 MRT 数据文件中解析出的未修改的完整信息。
pub struct MrtRecord {
pub common_header: CommonHeader,
pub message: MrtMessage,
}
pub enum MrtMessage {
TableDumpMessage(TableDumpMessage),
TableDumpV2Message(TableDumpV2Message),
Bgp4Mp(Bgp4Mp),
}
MrtRecord
记录表示简洁、存储效率高,但通常不太方便使用。例如,当尝试找出特定 IP 前缀的特定 BGP 通告时,我们通常需要通过内部数据结构(NLRI、通告、前缀,甚至查找表 dump V2 格式的对等体索引表)的嵌套层,这可能并不符合用户真正想要做的事情。
【BgpElem】:与每个前缀相关的BGP信息,不依赖于MRT格式
为了简化BGP数据的分析,我们在本库中定义了一种新的数据结构,称为[BgpElem]。每个[BgpElem]包含有关单个IP前缀的独立BGP信息。例如,当处理共享相同AS路径的三条前缀P1、P2、P3的捆绑公告时,我们将单个记录拆分为三个不同的[BgpElem]对象,每个对象表示一个前缀。
pub struct BgpElem {
pub timestamp: f64,
pub elem_type: ElemType,
pub peer_ip: IpAddr,
pub peer_asn: Asn,
pub prefix: NetworkPrefix,
pub next_hop: Option<IpAddr>,
pub as_path: Option<AsPath>,
pub origin_asns: Option<Vec<Asn>>,
pub origin: Option<Origin>,
pub local_pref: Option<u32>,
pub med: Option<u32>,
pub communities: Option<Vec<Community>>,
pub atomic: Option<AtomicAggregate>,
pub aggr_asn: Option<Asn>,
pub aggr_ip: Option<IpAddr>,
}
使用[BgpElem]的主要优点是可以按前缀进行逐个分析,不受后端MRT数据格式(bgp4mp、tabledumpv1、tabledumpv2等)的限制。明显的缺点是我们必须在每个elem中重复信息以节省空间,这会消耗更多的内存。
RFC支持
我们支持大多数RFC,并计划在未来继续添加对更近RFC的支持。以下是我们要支持或计划添加支持的有关RFC的列表。
如果您希望看到特定RFC的支持,请在GitHub上提交一个问题。
BGP
- RFC 2042:注册新的BGP属性类型
- RFC 3392:使用BGP-4进行能力广告
- RFC 4271:边界网关协议4(BGP-4)
- RFC 4724:BGP的优雅重启机制
- RFC 4456:BGP路由反射:替代全网状内部BGP(IBGP)的一种方法
- RFC 5065:BGP自治系统联盟
- RFC 6793:BGP对四字节自治系统(AS)号空间的支持
- RFC 7911:在BGP中广告多条路径(ADD-PATH)
- RFC 8950:使用IPv6下一跳广告IPv4网络层可达信息(NLRI)
- RFC 9072:BGP OPEN消息更新的扩展可选参数长度
- RFC 9234:使用UPDATE和OPEN消息中的角色预防和使用路由泄露检测
MRT
- RFC 6396:多线程路由工具包(MRT)路由信息导出格式
- RFC 6397:带地理定位扩展的多线程路由工具包(MRT)BGP路由信息导出格式
- RFC 8050:带BGP附加路径扩展的多线程路由工具包(MRT)路由信息导出格式
BMP
社区
我们支持标准社区、扩展社区和大型社区。
- RFC 1977:BGP社区属性
- RFC 4360:BGP扩展社区属性
- RFC 5668:4字节AS特定BGP扩展社区
- RFC 5701:IPv6地址特定BGP扩展社区属性
- RFC 7153:BGP扩展社区更新IANA注册表4360,5701
- RFC 8097:BGP前缀来源验证状态扩展社区
- RFC 8092:BGP大社区
FlowSpec
由BGPKIT团队用❤️构建
许可协议
MIT
依赖项
~0-17MB
~252K SLoC