Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions src/agentsight/AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,8 @@ eBPF Probes → Event → Parser → ParsedMessage → Aggregator → Aggregated

| 模块 | 位置 | 职责 | 关键类型 |
|------|------|------|----------|
| **Probes** | `src/probes/` | eBPF 探针管理 | `Probes`, `ProbesPoller`, `SslSniff`, `ProcMon`, `FileWatch` |
| **Event** | `src/event.rs` | 统一事件枚举 | `Event::{Ssl, Proc, ProcMon, FileWatch}` |
| **Probes** | `src/probes/` | eBPF 探针管理 | `Probes`, `ProbesPoller`, `SslSniff`, `ProcMon`, `FileWatch`, `FileWriteProbe`, `UdpDns`, `TcpSniff` |
| **Event** | `src/event.rs` | 统一事件枚举 | `Event::{Ssl, Proc, ProcMon, FileWatch, FileWrite, UdpDns}` |
| **Parser** | `src/parser/` | 协议解析(HTTP/1.x, HTTP/2, SSE, ProcTrace) | `Parser`, `ParsedMessage` |
| **Aggregator** | `src/aggregator/` | 请求-响应关联 | `Aggregator`, `AggregatedResult` |
| **Analyzer** | `src/analyzer/` | Token/审计/消息分析 | `Analyzer`, `AnalysisResult` |
Expand Down Expand Up @@ -62,6 +62,9 @@ eBPF Probes → Event → Parser → ParsedMessage → Aggregator → Aggregated
| proctrace | `src/bpf/proctrace.bpf.c` | tracepoint on execve 捕获命令行参数 |
| procmon | `src/bpf/procmon.bpf.c` | 进程创建/退出事件(Agent 发现) |
| filewatch | `src/bpf/filewatch.bpf.c` | 监控 .jsonl 文件打开事件 |
| filewrite | `src/bpf/filewrite.bpf.c` | fentry on vfs_write 捕获 .jsonl 写入内容 |
| udpdns | `src/bpf/udpdns.bpf.c` | fentry on udp_sendmsg 捕获 DNS 查询(域名→IP)|
| tcpsniff | `src/bpf/tcpsniff.bpf.c` | fentry on tcp_recvmsg/sendmsg 捕获明文 HTTP 流量 |

构建时 `build.rs` 通过 `libbpf-cargo` 自动生成 eBPF skeleton。

Expand Down
45 changes: 44 additions & 1 deletion src/agentsight/docs/design-docs/ebpf-probes.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

## Overview

AgentSight 使用 4 个 eBPF 探针从内核态捕获数据,所有探针共享同一个 ring buffer 和 `traced_processes` BPF map,由 `Probes` 管理器统一协调。
AgentSight 使用 7 个 eBPF 探针从内核态捕获数据,所有探针共享同一个 ring buffer 和 `traced_processes` BPF map,由 `Probes` 管理器统一协调。

## Probe Architecture

Expand All @@ -13,6 +13,9 @@ graph TB
PT[proctrace.bpf.c<br/>tracepoint: sched_process_exec]
PM[procmon.bpf.c<br/>tracepoint: sched_process_exec/fork/exit]
FW[filewatch.bpf.c<br/>tracepoint: do_sys_open]
FWR[filewrite.bpf.c<br/>fentry: vfs_write]
UD[udpdns.bpf.c<br/>fentry: udp_sendmsg]
TS[tcpsniff.bpf.c<br/>fentry: tcp_recvmsg/sendmsg]
end

subgraph Shared["Shared BPF Maps"]
Expand All @@ -24,8 +27,13 @@ graph TB
PT -->|write| RB
PM -->|write| RB
FW -->|write| RB
FWR -->|write| RB
UD -->|write| RB
TS -->|write| RB
SSL -->|lookup| TM
FW -->|lookup| TM
FWR -->|lookup| TM
UD -->|lookup| TM

subgraph Userspace["User Space"]
P[Probes Poller Thread]
Expand Down Expand Up @@ -87,6 +95,39 @@ graph TB

**Purpose**: Monitor Agent processes opening .jsonl files for auxiliary Agent session identification.

### 5. filewrite — File Write Capture

- **BPF Type**: fentry
- **Attach Point**: `vfs_write`
- **Filter**: Only PIDs in `traced_processes` writing to `.jsonl` files
- **Output**: `filewrite_event_t` (pid, filename, written content)
- **Source**: `src/bpf/filewrite.bpf.c`, `src/bpf/filewrite.h`
- **Userspace**: `src/probes/filewrite.rs`

**Purpose**: Capture written .jsonl content to recover responseId → sessionId mappings.

### 6. udpdns — DNS Query Capture

- **BPF Type**: fentry
- **Attach Point**: `udp_sendmsg`
- **Filter**: PIDs in `traced_processes`, UDP destination port 53
- **Output**: `udpdns_event_t` (queried domain)
- **Source**: `src/bpf/udpdns.bpf.c`, `src/bpf/udpdns.h`
- **Userspace**: `src/probes/udpdns.rs`

**Purpose**: Resolve configured HTTPS/HTTP domain patterns to IPs at runtime for SSL/TCP attach filtering.

### 7. tcpsniff — Plaintext HTTP Capture

- **BPF Type**: fentry/fexit
- **Attach Point**: `tcp_recvmsg` / `tcp_sendmsg`
- **Filter**: Configured destination IP/port targets (`tcp_targets`)
- **Output**: reuses the sslsniff `probe_SSL_data_t` event format
- **Source**: `src/bpf/tcpsniff.bpf.c`
- **Userspace**: `src/probes/tcpsniff.rs`

**Purpose**: Capture plaintext (non-TLS) HTTP traffic to configured endpoints, e.g. internal MaaS gateways.

## Shared Resource Design

### Ring Buffer (events_rb)
Expand All @@ -99,6 +140,8 @@ All probes share one ring buffer, distinguished by `common_event_hdr.source` fie
| 2 (EVENT_SOURCE_SSL) | sslsniff event | `SslEvent::from_bpf()` |
| 3 (EVENT_SOURCE_PROCMON) | procmon event | `procmon::Event::from_bytes()` |
| 4 (EVENT_SOURCE_FILEWATCH) | filewatch event | `FileWatchEvent::from_bytes()` |
| 5 (EVENT_SOURCE_FILEWRITE) | filewrite event | `FileWriteEvent::from_bytes()` |
| 6 (EVENT_SOURCE_UDPDNS) | udpdns event | `UdpDnsEvent::from_bytes()` |

**Implementation**: `src/probes/probes.rs:Probes::run()` lines 137-193 — single thread polls ring buffer, dispatches by source field into `Event` enum.

Expand Down
7 changes: 5 additions & 2 deletions src/agentsight/integration-tests/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@
|------|------|
| `RULES.md` | 测试环境、部署流程、通用规则 |
| `TEMPLATE.md` | 新建测试用例的模板 |
| `test_sni.md` | TLS SNI 探针加载与域名匹配 |
| `test_hermes_sni.md` | 通过 SNI 捕获 Hermes agent(dashscope.aliyuncs.com) |
| `test_dns.md` | UDP DNS 探针:域名→IP 解析捕获 |
| `test_hermes_dns.md` | 通过 DNS 捕获 Hermes agent(dashscope.aliyuncs.com) |
| `test_http.md` | 明文 HTTP(tcpsniff)流量捕获 |
| `test_connection_scanner.md` | 连接扫描器:活跃连接发现 |
| `test_ffi_integration.md` | C FFI API 集成 |
| `test_claude_code.md` | Claude Code BoringSSL 探针、SSE thinking/tool_use 解析、msg_id 会话关联 |
3 changes: 1 addition & 2 deletions src/agentsight/src/aggregator/http2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,11 @@
//! by their stream_id and correlating request (client->server) with response (server->client)
//! to form complete HTTP/2 request/response pairs.

use std::collections::HashMap;
use std::num::NonZeroUsize;
use lru::LruCache;
use crate::config::DEFAULT_CONNECTION_CAPACITY;
use crate::parser::http2::ParsedHttp2Frame;
use crate::parser::sse::{SseParser, SSEParser};
use crate::parser::sse::SSEParser;
use crate::aggregator::http::ConnectionId;
use crate::aggregator::result::AggregatedResult;
use crate::chrome_trace::{ChromeTraceEvent, ToChromeTraceEvent, ns_to_us};
Expand Down
2 changes: 1 addition & 1 deletion src/agentsight/src/aggregator/unified.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use super::http::{ConnectionId, ConnectionState, HttpConnectionAggregator};
use super::http2::Http2StreamAggregator;
use super::proctrace::ProcessEventAggregator;
use super::result::AggregatedResult;
use crate::chrome_trace::{export_trace_events, ToChromeTraceEvent};
use crate::chrome_trace::export_trace_events;
use crate::parser::{ParseResult, ParsedMessage};

/// Unified aggregator for all event types
Expand Down
2 changes: 1 addition & 1 deletion src/agentsight/src/analyzer/message/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -390,7 +390,7 @@ mod tests {

#[test]
fn test_full_url_paths() {
let parser = MessageParser::new();
let _parser = MessageParser::new();

// Should work with full URLs too
assert!(MessageParser::is_llm_api_path(
Expand Down
3 changes: 1 addition & 2 deletions src/agentsight/src/analyzer/token/extractor/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ mod anthropic;
mod utils;

use serde_json::Value;
use super::data::{TokenData, MessageTokenData, ResponseTokenData};
use super::data::TokenData;

/// Extract token data from JSON request/response bodies
///
Expand Down Expand Up @@ -79,4 +79,3 @@ pub enum Provider {
}

// Re-export utility functions for internal use
pub use utils::extract_model_from_json;
Loading
Loading