gecsemax/Oneida-Network-Steganography-Detector-

GitHub: gecsemax/Oneida-Network-Steganography-Detector-

一款基于 12 通道统计的高性能网络隐写术检测器,用于被动识别隐蔽通信并触发告警。

Stars: 1 | Forks: 0

``` # Oneida v4.2 – 网络隐写术检测器 > A high-performance, 12-channel network covert channel detector written in C. > Designed for live traffic analysis and PCAP replay on Linux and macOS. --- ## 目录 - [Overview](#overview) - [How It Works](#how-it-works) - [Detection Channels](#detection-channels) - [Architecture](#architecture) - [Requirements](#requirements) - [Build](#build) - [Usage](#usage) - [Output Formats](#output-formats) - [Configuration Reference](#configuration-reference) - [Signals](#signals) - [Performance Tuning](#performance-tuning) - [Version History](#version-history) - [License](#license) --- ## 概述 **Oneida** passively monitors network traffic and scores every TCP, UDP, and ICMP flow across 12 independent statistical channels. When the weighted composite score of a flow exceeds a configurable threshold, an alert is emitted — either as human-readable text or as a JSON record suitable for SIEM ingestion. Oneida detects: - **Timing-based covert channels** — inter-packet delay modulation - **Size-based covert channels** — fixed or patterned packet lengths - **Header covert channels** — TCP flag abuse, TTL manipulation, IP-ID modulation - **DNS tunnels** — iodine, dnscat2, dns2tcp (label encoding + query rate + record type) - **Payload covert channels** — high-entropy payloads hidden inside normal-looking flows - **Burst-pattern channels** — timer-driven injectors with regular IPD spacing - **Directional covert channels** — extreme traffic asymmetry --- ## 工作原理 ``` 网络接口/PCAP文件 │ ▼ ┌─────────────┐ memcpy ┌──────────────────────┐ │ pcap_loop │ ──────────► │ 无锁环形缓冲区 │ 65 536 个槽位 │ (捕获 │ │ (SPSC, 原子头/尾) │ 64 MB 内核环形缓冲区 │ 线程) │ │ │ └─────────────┘ └──────────┬───────────┘ │ sem_post (上限) ▼ ┌──────────────────────┐ │ 工作线程 │ │ process_one() │ │ ├─ parse_packet() │ │ ├─ 流查找/分配 │ 每个桶的读写锁 │ ├─ 重传检查 │ O(1) 序列号哈希集合 │ ├─ DNS 解码 │ │ ├─ 窗口槽位写入 │ 256 个槽位的循环缓冲区 │ ├─ 计算分数 │ 脏标志 / N=64 │ └─ 发出告警 │ └──────────────────────┘ │ ┌──────────▼───────────┐ │ 清理线程 │ 每 30 秒 │ 过期空闲流 │ 安全锁顺序 └──────────────────────┘ ``` Each flow is tracked using a bidirectional canonical key (`min(src,dst)` always first), so `A→B` and `B→A` packets update the same flow record. A pre-allocated slab pool of 32 768 flow structs avoids dynamic allocation on the hot path. --- ## 检测通道 | Ch | Name | What it measures | Suspicious pattern | |----|------|------------------|--------------------| | 0 | **IPD CoV** | Inter-packet delay Coefficient of Variation | CoV < 0.10 → timer-driven (score 0.85) | | 1 | **Length Std Dev** | Standard deviation of packet lengths | Std < 2.0 → fixed-size encoding (score 0.85) | | 2 | **Protocol Entropy** | Shannon entropy of L4 protocol field | Unexpected protocol diversity | | 3 | **TCP Flag Entropy** | Entropy of observed TCP flag combinations | Unusual flag patterns / covert flag abuse | | 4 | **SEQ Variance** | Variance of TCP sequence numbers | Low variance = suspiciously predictable SEQ | | 5 | **IP-ID Delta** | Delta between consecutive IP Identification fields | Static or tiny-range modulation = covert channel | | 6 | **Window Variance** | TCP receive window size variance | Constant window = possible encoding | | 7 | **TTL Variance** | Variance of IP Time-To-Live values | High variance = TTL manipulation | | 8 | **Payload Entropy + DNS** | Shannon entropy of payload bytes; DNS tunnel heuristics | High entropy = encrypted carrier; DNS rate/charset/type | | 9 | **Directional Asymmetry** | `|bytes_fwd/total − 0.5| × 2` | > 0.85 → one-way-only flow | | 10 | **Burst Regularity** | CoV of inter-packet delays (burst view) | CoV < 0.10 → equal-spacing = timer injector | | 11 | **Retransmit Rate** | Retransmissions / total packets | Unusually high retransmit rate | ### 加权综合评分 ```text score = Σ(channel_score[i] × weight[i]) / Σ(weight[i]) ``` 默认权重:时机×2,长度×2,标志×1.5,负载×2,突发×2,不对称×1.5,IP-ID×1.5,其余×1。 当 `score > threshold`(默认 **0.45**)且至少经过 30 个数据包后触发告警,每个流有冷却时间(默认 **5 秒**)。 ### DNS 隧道检测(第 8 章子计分器) Oneida 从 UDP 端口 53 流量解码 DNS 查询名称,并应用四种独立启发式方法: | 启发式方法 | 分数贡献 | 目标 | |------------|----------|------| | 查询速率 > 10/10 秒 | +0.40 | 所有隧道 | | TXT 或 NULL 记录类型 | +0.30 | iodine、dnscat2 | | 标签中使用 Base32/Base64 字符集 | +0.35 | iodine、dns2tcp | | 标签长度 > 40 字符 | +0.25 | 所有隧道 | DNS 分数在更高时替代负载熵分数。 ### IP-ID 隐蔽信道(第 5 章) | Delta 模式 | 分数 | 解释 | |------------|------|------| | 标准差 < 1.0(静态) | 0.55 | ID 冻结 — 故意隐藏 | | 标准差 < 8,平均值 < 8 | 0.60 | 小范围调制 | | 标准差 < 3,平均值 0.5–5 | 0.10 | 正常内核计数器 | | 其他情况 | 0.05 | 随机化(现代操作系统) | ## 架构 ### 线程模型 | 线程 | 角色 | CPU 绑定标志 | |------|------|-------------| | 主线程 / pcap | `pcap_loop`、`capture_callback` |(默认) | | 工作线程 | 从环形缓冲区出队,运行评分管道 | `-W <核心>` | | 清理线程 | 每 30 秒清理过期/旧流 | `-C <核心>` | ### 流表 - **8192 个哈希桶**,每个桶包含一个 `pthread_rwlock_t` - 查找(热路径)仅对一个桶获取**读锁** - 写入插入时进行双重检查(无 TOCTOU 竞争) - 每个流使用 `pthread_mutex_t` 进行槽位写入和评分 - **安全清理:** 在获取每个流的互斥锁之前先释放桶的写锁,以避免死锁 ### 内存 - **预分配 slab 池**,包含 32768 个 `flow_t` 结构体 - 启动后无动态分配 - 池使用 `uint32_t` 空闲列表计数器(适合长时间运行) ### 环形缓冲区 - **65536 个槽位**,单生产者/单消费者 - 使用原子操作实现无锁头/尾 - `sem_post` 有**上限**(通过 `sem_getvalue`)——高 PPS 下不会失控 - 通过 `pcap_set_buffer_size` 提供 64 MB 内核环形缓冲区 ## 需求 | 依赖项 | 版本 | 说明 | |--------|------|------| | `libpcap` | ≥ 1.5 | `libpcap-dev` / `libpcap-devel` | | GCC 或 Clang | GCC ≥ 9,Clang ≥ 11 | 需要 C11 | | Linux 内核 | ≥ 3.10 | `AF_PACKET`、CPU 亲和性 | | macOS | ≥ 10.15 | BPF,不支持 CPU 亲和性 | ``` # Debian / Ubuntu sudo apt install libpcap-dev gcc make # RHEL / Fedora sudo dnf install libpcap-devel gcc make # macOS brew install libpcap ``` ## 构建 ``` # 标准构建 gcc -O2 -std=c11 -Wall -Wextra -o oneida oneida.c -lpcap -lm -lpthread # 编译时覆盖 gcc -O2 -std=c11 -DMAX_FLOWS=65536 -DWINDOW_SIZE=512 \ -o oneida oneida.c -lpcap -lm -lpthread # 调试构建 gcc -O0 -g -fsanitize=address,undefined -std=c11 \ -o oneida_dbg oneida.c -lpcap -lm -lpthread ``` ## 使用 ### 实时捕获(需要 root 权限) ``` sudo ./oneida eth0 sudo ./oneida enp3s0 ``` ### PCAP 文件回放 ``` ./oneida capture.pcap ./oneida capture.pcapng ``` ### 通用选项 ``` # 低阈值(更敏感),10 秒冷却时间 sudo ./oneida -t 0.35 -a 10 eth0 # 纳秒时间戳,详尽输出 sudo ./oneida -n -v eth0 # JSON 输出,管道到 jq sudo ./oneida -j eth0 | jq 'select(.score > 0.6)' # 固定线程,禁用混杂模式 sudo ./oneida -W 2 -C 3 -p eth0 # 完整选项 sudo ./oneida -t 0.40 -a 5 -i 120 -l 1800 -n -v -W 2 -C 3 eth0 ``` ## 输出格式 ### 纯文本(默认) ``` 🚨 STEG ALERT [0.623] 10.0.0.5:54321 -> 8.8.8.8:53 | UDP | pkts=412 frags=0 icmp=0 Timing=0.85 Len=0.85 Flags=0.05 Payload=0.75 Burst=0.85 Asym=0.25 TTL=0.05 Retrans=0.05 DNS tunnel score=0.70 qrate=14 txt/null=3 b32b64=5 ``` ### JSON(`-j`) ``` { "alert": true, "score": 0.6231, "flow_id": "a3f2c1d490e87b12", "src": "10.0.0.5", "dst": "8.8.8.8", "sport": 54321, "dport": 53, "proto": "UDP", "pkts": 412, "bytes_fwd": 38204, "bytes_rev": 12800, "frags": 0, "icmp": 0, "dns_score": 0.700, "ipid_var": 0.000, "ch": [0.850, 0.850, 0.050, 0.050, 0.100, 0.050, 0.100, 0.050, 0.750, 0.250, 0.850, 0.050] } ``` ### SIEM 集成 ``` # 写入文件 sudo ./oneida -j eth0 >> /var/log/oneida/alerts.jsonl # 管道到 Elasticsearch sudo ./oneida -j eth0 | \ while read line; do curl -s -X POST "http://localhost:9200/oneida/_doc" \ -H 'Content-Type: application/json' -d "$line" > /dev/null done ``` ## 配置参考 | 标志 | 默认值 | 描述 | |------|--------|------| | `-t <浮点数>` | `0.45` | 告警阈值(0.0–1.0) | | `-a <秒>` | `5` | 每个流的告警冷却时间(秒) | | `-i <秒>` | `300` | 空闲流过期时间(秒) | | `-l <秒>` | `3600` | 最大流生命周期(秒) | | `-j` | 关闭 | JSON 输出模式 | | `-p` | 关闭 | 禁用混杂模式 | | `-n` | 关闭 | 纳秒时间戳精度 | | `-W <核心>` | 关闭 | 将工作线程绑定到 CPU 核心 N | | `-C <核心>` | 关闭 | 将清理线程绑定到 CPU 核心 N | | `-v` | 关闭 | 详细模式:告警时打印特征值 | | `-h` | — | 打印帮助并退出 | ### 编译期常量 | 宏 | 默认值 | 描述 | |----|--------|------| | `MAX_FLOWS` | 32768 | 最大并发跟踪流数 | | `FLOW_HASH_SIZE` | 8192 | 哈希表桶数(2 的幂) | | `WINDOW_SIZE` | 256 | 每个流的滑动窗口包数 | | `RING_CAPACITY` | 65536 | 环形缓冲区槽位(2 的幂) | | `KERNEL_RING_BYTES` | 64 MB | libpcap 内核环形缓冲区大小 | | `RESCORE_INTERVAL` | 64 | 每 N 个包重新评分 | | `DNS_RATE_THRESH` | 10 | 每 10 秒 DNS 查询数达到阈值则标记为隧道 | ## 信号 | 信号 | 效果 | |------|------| | `SIGINT` / `SIGTERM` | 优雅关闭,排出环形缓冲区,打印统计信息 | | `SIGUSR1` | 打印实时统计信息而不中断捕获 | ``` # 实时统计 kill -USR1 $(pgrep oneida) # 示例输出 [stats] active_flows=1423 dropped=0 alerts=7 ``` ## 性能调优 ### 高流量环境(> 1 Mpps) ``` # 将线程固定到隔离核心 sudo ./oneida -W 4 -C 5 eth0 # 在编译时增加流表 gcc -O3 -DMAX_FLOWS=131072 -DFLOW_HASH_SIZE=32768 \ -o oneida oneida.c -lpcap -lm -lpthread # 使用 AF_PACKET 环(Linux) sudo ethtool -G eth0 rx 4096 # 增加套接字缓冲区 sudo sysctl -w net.core.rmem_max=134217728 ``` ### 低延迟 PCAP 回放 ``` ./oneida -n -t 0.35 large_capture.pcapng ``` ### 阈值调整指南 | 环境 | 建议的 `-t` 值 | |------|----------------| | 实验室/测试 | 0.35 | |局域网 | 0.45(默认) | | 面向互联网 | 0.55 | | 高噪声数据中心 | 0.65 | ## 版本历史 | 版本 | 关键变更 | |------|----------| | **v4.2** | TTL 方向修复、slot_valid 使用、死锁修复、uint32_t 池计数器、stat() 检测、capped sem_post、ICMP 支持、脏标志重新评分、SIGUSR1 统计、IP-ID 通道、DNS 隧道字符集/速率/类型、告警计数器 | | **v4.1** | 标志熵方向、过期分数重置、重传在槽位写入前、O(1) 序列号哈希集、信号驱动工作线程、slab 池、64 MB 内核环形缓冲区、每个流的告警冷却时间、纳秒时间戳、IPv4 分片检测 | | **v4.0** | 每个桶的读写锁、无锁 SPSC 环形缓冲区、CPU 亲和性、双向流键、基于 CoV 的 IP-ID、负载熵、突发规律性、方向性不对称、TCP 重传率 | ## 已知限制 - **仅支持 IPv4** — IPv6 数据包在解析器处静默丢弃 - **单工作线程** — 评分为单线程;在极高 PPS 下考虑按流哈希范围分片 - **无持久化** — 流状态仅在内存中;重启会清除所有流历史 - **加密流量** — 来自 TLS/QUIC 的高熵负载可能在合法流上产生较高的第 8 章分数;相应调整阈值 - **分片流** — 未实现重组;分片会递增计数器但排除在特征评分之外 ## 许可证 MIT 许可证 — 详情见 `LICENSE`。 ``` Copyright (c) 2026 Max Gecse ``` ``` ```
标签:API安全, Bing搜索, dns2tcp, dnscat2, DNS隧道, IP-ID调制, JSON输出, PCAP, SIEM集成, TCP UDP ICMP, TCP标志位滥用, TTL操纵, 包长度模式, 实时流量, 客户端加密, 开源安全工具, 性能调优, 方向不对称, 旁路检测, 熵检测, 碘信道, 突发模式, 统计信道, 网络隐写术, 被动监测, 逆向工程平台, 阈值告警, 隐写检测