Sign in

    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
    2 months ago
    Downloads
    32

    No dependencies

    #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