packet

MoonBit 协议解析层:Ethernet/IPv4/IPv6/TCP/UDP 头解析

packet
parser
tcp
udp
ipv4
ipv6
network
Download zip
Author
Version
0.1.1
License
MIT
Last updated
27 days ago
Downloads
3

#moonbit-packet

MoonBit 协议解析层:纯 MoonBit、零外部依赖,解析 Ethernet / IPv4 / IPv6 / TCP / UDP / ICMP 头,提取五元组、判定方向、按连接聚合统计。

只做头部解析与连接跟踪,不做流重组与应用层解析(YAGNI)。

#特性

  • 零依赖纯 MoonBit:可独立测试复用,不依赖任何外部包
  • 按需提取:数值字段按偏移读取(大小端转换),不拷贝整个头
  • 模式匹配分派:EtherType / IP 协议号用 match 穷尽分派,防漏分支
  • 容错解析:截断、未知协议返回 None,不 panic
  • 连接跟踪:五元组归一化(双向流量归同一连接),空闲连接超时清理

#安装

moon add chensuiyi/packet

#快速开始

// moon.pkg: import "chensuiyi/packet"
// 解析一个原始包(data 来自 pcap 层或任何 Bytes)
let ips : FixedArray[IpAddr] = ... // 本机 IP 列表(含回环 127.0.0.1 / ::1)
match packet.parse(data, ts_sec, ts_usec, ips) {
Some(p) => {
// p.tuple: 五元组(src_ip/src_port/dst_ip/dst_port/proto)
// p.direction: In / Out / Local
// p.payload_len / p.total_len: 载荷与包长
println(p.tuple.to_string())
}
None => () // 截断 / ARP / 未知协议
}

连接跟踪聚合:

let tracker = packet.ConnTracker::new(60L) // 60 秒无流量即清理
// 每个包:
tracker.update(p)
tracker.cleanup(p.ts_sec)
// 每秒输出一行 JSON 快照:
println(tracker.snapshot_json(ts))

#API 一览

类型 / 函数说明
ProtoTcp / Udp / Icmp / Icmpv6 / Other
DirectionIn(入)/ Out(出)/ Local(本机到本机)
IpAddr::new(v4 : Bool, bytes : Bytes)IP 地址(v4=4 字节,v6=16 字节)
FiveTuple::new(...)五元组(连接跟踪 key)
ParsedPacket解析结果:时间戳 + 五元组 + 方向 + 载荷/总长
parse(data, ts_sec, ts_usec, local_ips) -> ParsedPacket?解析入口
ConnTracker::new(idle_timeout)连接跟踪器
ConnTracker::update(pkt)更新统计(Local 流量计入入方向)
ConnTracker::cleanup(now)清理空闲连接
ConnTracker::snapshot(ts) / snapshot_json(ts)连接快照 / JSON 行

JSON 快照格式(按入+出流量降序):

{"ts":1780000000,"conns":[{"src_ip":"1.2.3.4","src_port":443,"dst_ip":"5.6.7.8","dst_port":54321,"proto":"tcp","packets":12,"bytes_in":1024,"bytes_out":512,"first_seen":1780000000,"last_seen":1780000005}]}

#测试

moon test

#与绑定层配合

原始包由 chensuiyi/pcap(运行时动态加载 wpcap.dll)抓取,完整采集服务见 chensuiyi/monitor

#License

MIT

ConnStats

pub struct ConnStats {
packets : Int
bytes_in : Int64
bytes_out : Int64
first_seen : Int64
last_seen : Int64
} derive(Default)

连接统计

ConnStats::to_string

fn ConnStats::to_string(self : ConnStats) -> String

ConnTracker

pub struct ConnTracker {
conns :
HashMap
[FiveTuple, ConnStats]
idle_timeout : Int64
}

连接跟踪器:五元组 → 统计(双向流量归同一连接)

ConnTracker::cleanup

fn ConnTracker::cleanup(self : ConnTracker, now : Int64) -> Unit

清理空闲连接(last_seen 距 now 超过 idle_timeout 秒)

ConnTracker::new

fn ConnTracker::new(idle_timeout : Int64) -> ConnTracker

新建跟踪器;idle_timeout 秒无流量后 cleanup 会移除连接

ConnTracker::snapshot

fn ConnTracker::snapshot(self : ConnTracker) -> Array[(FiveTuple, ConnStats)]

连接快照(含归一化后的五元组)

ConnTracker::snapshot_json

fn ConnTracker::snapshot_json(self : ConnTracker, ts : Int64) -> String

每秒一行 JSON 快照:{ts, conns:[{src_ip,src_port,dst_ip,dst_port,proto,packets,bytes_in,bytes_out,first_seen,last_seen}]} 按流量(入+出)降序排列

ConnTracker::update

fn ConnTracker::update(self : ConnTracker, pkt : ParsedPacket) -> Unit

更新连接统计;Local(回环)流量计入入方向

Direction

pub(all) enum Direction {
In
Out
Local
}

包方向(Local = 本机到本机,如回环)

Direction::to_string

fn Direction::to_string(self : Direction) -> String

FiveTuple

pub struct FiveTuple {
src_ip : IpAddr
dst_ip : IpAddr
src_port : Int
dst_port : Int
proto : Proto
} derive(Eq, Hash)

五元组(连接跟踪的 key)

FiveTuple::new

fn FiveTuple::new(src_ip : IpAddr, dst_ip : IpAddr, src_port : Int, dst_port : Int, proto : Proto) -> FiveTuple

构造五元组

FiveTuple::to_string

fn FiveTuple::to_string(self : FiveTuple) -> String

IpAddr

pub struct IpAddr {
v4 : Bool
bytes : Bytes
} derive(Compare, Eq, Hash)

IP 地址(v4 = 4 字节,v6 = 16 字节)

IpAddr::new

fn IpAddr::new(v4 : Bool, bytes : Bytes) -> IpAddr

构造 IP 地址

IpAddr::to_string

fn IpAddr::to_string(self : IpAddr) -> String

ParsedPacket

pub struct ParsedPacket {
ts_sec : Int64
ts_usec : Int
tuple : FiveTuple
direction : Direction
payload_len : Int
total_len : Int
}

解析结果:时间戳 + 五元组 + 方向 + 载荷长度(供流量统计)

ParsedPacket::new

fn ParsedPacket::new(ts_sec : Int64, ts_usec : Int, tuple : FiveTuple, direction : Direction, payload_len : Int, total_len : Int) -> ParsedPacket

构造解析结果

Proto

pub(all) enum Proto {
Tcp
Udp
Icmp
Icmpv6
Other
} derive(Eq, Hash)

传输层协议

Proto::to_string

fn Proto::to_string(self : Proto) -> String

direction

fn direction(src : IpAddr, dst : IpAddr, local_ips : FixedArray[IpAddr]) -> Direction

方向判定:src 本机 + dst 外部 → Out;反 → In;都本机 → Local

parse

fn parse(data : Bytes, ts_sec : Int64, ts_usec : Int, local_ips : FixedArray[IpAddr]) -> ParsedPacket?

解析入口:Ethernet 帧 → 按 EtherType 分派;截断/未知协议返回 None