Skip to content
Open
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
8 changes: 8 additions & 0 deletions ARCHITECTURE.md
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,14 @@ Cache properties:

CNAME chains need no separate map: the DNS DPI parser records the original *question* name, and the answer's A/AAAA records map directly to it. Capturing at the wire sees fewer signals than an eBPF socket-level approach (no app-to-stub traffic on `lo` unless captured, no D-Bus resolutions, no DoH/DoT plaintext); this is a known limitation.

#### Passive DNS Analytics

`network::dns_analytics::DnsAnalyticsTracker` is a separate bounded aggregate owned by `ConnectionTracker`. For captured unicast UDP DNS, it pairs each outgoing query with an incoming response using the host-oriented connection key and 16-bit transaction ID. Retransmissions refresh the pending entry, unmatched responses are ignored, and an unanswered query is finalized as a timeout after 10 seconds.

Completed transactions are retained for a rolling 60-second window. The tracker caps pending transactions at 4,096 and completed transactions at 8,192; capacity pressure is surfaced as a sampled indicator in the Host DNS view. Snapshots contain response-code and NODATA totals, latency percentiles and buckets, normalized question-name aggregates, and the DNS health classification used by Overview. `ConnectionTracker::clear()` resets both pending and completed DNS state.

Health is deliberately evidence based. NXDOMAIN counts as a normal resolver response, while SERVFAIL, REFUSED, other response codes, and timeouts count as operational failures. At least three failed observations are required for a failing or no-replies state. Degraded status requires either five completed observations with at least 20% operational failures, or five latency samples with p95 of at least 500 ms. No observed plaintext DNS remains unknown rather than healthy because encrypted DNS, caches, capture loss, and interface selection can hide activity.

### 6. Cleanup Thread

Removes inactive connections using smart, protocol-aware timeouts. This prevents memory leaks and keeps the connection list relevant. When `--pcap-export` is enabled, also streams connection metadata (PID, process name, timestamps) to a JSONL sidecar file as connections close.
Expand Down
8 changes: 8 additions & 0 deletions ARCHITECTURE.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,14 @@ flowchart LR

CNAME 链不需要单独的映射:DNS DPI 解析器记录的是原始*问题*名称,应答中的 A/AAAA 记录直接映射到它。在线路层捕获看到的信号比 eBPF 套接字层方案少(除非同时捕获 `lo`,否则看不到应用到 stub 的流量;看不到 D-Bus 解析;看不到 DoH/DoT 明文);这是已知限制。

#### 被动 DNS 分析

`network::dns_analytics::DnsAnalyticsTracker` 是由 `ConnectionTracker` 持有的独立有界汇总器。对于捕获到的单播 UDP DNS,它使用以本机为方向的连接键和 16 位事务 ID,将每个出站查询与入站响应配对。重传会刷新待处理项,无法匹配的响应会被忽略,查询在 10 秒内没有响应时会最终记为超时。

已完成事务保留在滚动 60 秒窗口中。追踪器最多保存 4,096 个待处理事务和 8,192 个已完成事务,容量压力会在 Host 的 DNS 视图中显示 sampled 标记。快照包含响应码与 NODATA 总数、延迟分位数与区间、规范化查询名称汇总,以及供 Overview 使用的 DNS 健康分类。`ConnectionTracker::clear()` 会同时重置待处理和已完成的 DNS 状态。

健康分类要求足够的观测证据。NXDOMAIN 算作解析器正常响应,SERVFAIL、REFUSED、其他响应码和超时算作运行失败。failing 或 no-replies 状态至少需要三次失败观测。degraded 状态需要至少五次已完成观测且运行失败率达到 20%,或者至少五个延迟样本且 p95 达到 500 ms。未观测到明文 DNS 时保持 unknown,而不会判定为健康,因为加密 DNS、缓存、捕获丢包和接口选择都可能隐藏活动。

### 6. 清理线程

使用智能的、协议感知的超时机制移除不活跃的连接。这防止内存泄漏并保持连接列表的相关性。当启用 `--pcap-export` 时,连接关闭时还会将连接元数据(PID、进程名、时间戳)流式写入 JSONL sidecar 文件。
Expand Down
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased]

### Added
- **Passive DNS Analytics**: the Host tab now shows rolling response codes,
timeouts, matched latency, question names, and DNS health, with a compact
health line in Overview
- **Host Socket Inventory**: the new Host tab shows TCP LISTEN sockets, UDP
BOUND endpoints, TCP state totals, observed RTT, process owners, and the
detailed interface table on Linux, macOS, FreeBSD, and Windows
Expand Down
5 changes: 3 additions & 2 deletions README.ja.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ RustNet は、各接続を所有するプロセス、通信量、状態、アプ

- TCP、UDP、QUIC 接続とプロセスの対応付け。詳細には PID、実行ファイル、ユーザー/グループ名、照合の信頼度、全プラットフォーム共通の親プロセスチェーン(上限あり)を表示
- HTTP、TLS/SNI、DNS、SSH、QUIC などの深層パケット解析
- TCP、QUIC ハンドシェイク、DNS 応答、ICMP エコーの往復時間(RTT)と、TCP の再送・順序入れ替わりをリアルタイム表示
- Host タブに TCP LISTEN ソケット、UDP BOUND エンドポイント、TCP 状態集計、観測 RTT、所有プロセス、インターフェース統計を表示
- TCP、QUIC ハンドシェイク、DNS 応答、ICMP エコーの往復時間(RTT)と、TCP の再送・順序入れ替わりをリアルタイム表示。DNS の応答コード、タイムアウト、レイテンシ分位点、質問名、ヘルス状態も受動的に集計
- Host タブに TCP LISTEN ソケット、UDP BOUND エンドポイント、TCP 状態集計、観測 RTT、所有プロセス、インターフェース統計、DNS 分析を表示
- `port:`、`process:`、`sni:`、`state:` などのフィルター
- 注釈付き PCAPNG、PCAP と JSONL sidecar、JSON ログの出力
- ローカル GeoIP データベースによる国、ASN、都市情報
Expand Down Expand Up @@ -114,6 +114,7 @@ rustnet --pcapng-export capture.pcapng # 注釈付き PCAPNG を出力
| `a` | プロセス単位のグループ表示 |
| `Space` | 選択したプロセスグループを展開または折りたたむ |
| `t` | 終了済み接続の表示を切り替え |
| `d` | Overview ではホスト名/IP、Activity では送信/受信を切り替え、Host では DNS 分析を開く |
| `i` | Overview では System 情報を切り替え、Host ではインターフェース表示に切り替える |
| `r` | 表示、並び替え、フィルターをリセット |
| `h` | 現在のタブに対応したヘルプオーバーレイを表示または閉じる |
Expand Down
7 changes: 4 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
- **Deep packet inspection**: Identify HTTP, HTTPS/TLS with SNI, DNS, SSH, FTP, QUIC, MQTT, BitTorrent, STUN, NTP, mDNS, LLMNR, DHCP, SNMP, SSDP, and NetBIOS, without external dissectors.
- **Annotated PCAPNG export**: `--pcapng-export` writes a Wireshark-ready capture with process, PID, direction, DPI/SNI, and GeoIP embedded as per-packet comments. Open it in Wireshark and every packet already names its owning process, with no post-processing. Classic `--pcap-export` with a JSONL sidecar for offline correlation is also available.
- **Security sandboxing**: Landlock (Linux 5.13+), Seatbelt (macOS), token privilege drop + job-object child-process block (Windows). Drops privileges immediately after libpcap initializes. See [SECURITY.md](SECURITY.md).
- **Network analytics**: Real-time round-trip times for TCP, QUIC handshakes, DNS responses, and ICMP echo, plus TCP retransmission, out-of-order, and fast-retransmit detection.
- **Network analytics**: Real-time round-trip times for TCP, QUIC handshakes, DNS responses, and ICMP echo, plus TCP retransmission, out-of-order, and fast-retransmit detection. Passive DNS analytics add response codes, timeouts, latency percentiles, question names, and a compact health signal.
- **Smart connection lifecycle**: Protocol-aware timeouts with white → yellow → red staleness indicators. Toggle `t` to keep historic (closed) connections visible for forensics.
- **Vim/fzf-style filtering**: `port:`, `src:`, `dst:`, `sni:`, `process:`, `state:`, `proto:`, plus regex via `/(?i)pattern/`.
- **GeoIP enrichment**: Country lookups via local MaxMind GeoLite2. No network calls.
Expand Down Expand Up @@ -84,8 +84,9 @@ RustNet combines process-level traffic accounting with real-time network interfa
- **Overview Tab**: Shows active interfaces with current rates, errors, and drops
- **Activity Tab** (press `3`): Ranks processes by Egress (TX) or Ingress (RX), including retained and rolling traffic, rates, shares, connections, and destinations
- **Security Workflow**: Sort by Egress, identify an unexpected uploader, then inspect its top remote peer and retained traffic even after the connection closes
- **Host Tab** (press `5`): Shows TCP LISTEN sockets, UDP BOUND endpoints, aggregated TCP states, observed RTT, and process ownership
- **Host Tab** (press `5`): Shows TCP LISTEN sockets, UDP BOUND endpoints, aggregated TCP states, observed RTT, process ownership, and passive DNS analytics
- **Interface Details** (press `i` on Host): Shows comprehensive metrics for every interface
- **DNS Details** (press `d` on Host): Shows a rolling outcome summary, matched response latency, and the most active question names
- **Cross-Platform**: Linux (sysfs), macOS/FreeBSD (getifaddrs), Windows (GetIfTable2 API)
- **Smart Filtering**: Windows automatically excludes virtual/filter adapters

Expand Down Expand Up @@ -217,7 +218,7 @@ See [INSTALL.md](INSTALL.md) for detailed permission setup and [USAGE.md](USAGE.
| `Esc` | Go back or clear filter |
| `c` | Copy remote address |
| `p` | Toggle service names/ports |
| `d` | Toggle hostnames/IPs on Overview or Egress/Ingress on Activity |
| `d` | Toggle hostnames/IPs on Overview, Egress/Ingress on Activity, or open DNS on Host |
| `s` `S` | Cycle sort columns / toggle direction |
| `a` | Toggle process grouping |
| `Space` | Expand/collapse process group |
Expand Down
7 changes: 4 additions & 3 deletions README.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
- **深度包检测**:无需外部解析器即可识别 HTTP、带 SNI 的 HTTPS/TLS、DNS、SSH、FTP、QUIC、MQTT、BitTorrent、STUN、NTP、mDNS、LLMNR、DHCP、SNMP、SSDP 及 NetBIOS。
- **带注释的 PCAPNG 导出**:`--pcapng-export` 可写出能直接用 Wireshark 打开的捕获文件,并将进程、PID、方向、DPI/SNI 和 GeoIP 作为逐包注释嵌入。每个数据包都会直接标明所属进程,无需后处理。也可使用经典的 `--pcap-export` 配合 JSONL sidecar 进行离线关联。
- **安全沙箱**:Linux 5.13+ 使用 Landlock,macOS 使用 Seatbelt,Windows 通过 token 降权 + job-object 阻止子进程创建。libpcap 初始化完成后立即丢弃特权。详见 [SECURITY.zh-CN.md](SECURITY.zh-CN.md)。
- **网络分析**:实时统计 TCP、QUIC 握手、DNS 响应及 ICMP 回显的往返时延,并检测 TCP 重传、乱序包和快重传。
- **网络分析**:实时统计 TCP、QUIC 握手、DNS 响应及 ICMP 回显的往返时延,并检测 TCP 重传、乱序包和快重传。被动 DNS 分析还会汇总响应码、超时、延迟分位数、查询名称和简洁的健康状态。
- **智能连接生命周期**:按协议设置超时,以白 → 黄 → 红的颜色指示过期程度。按 `t` 可保留历史(已关闭)连接以便事后追溯。
- **Vim / fzf 风格过滤**:支持 `port:`、`src:`、`dst:`、`sni:`、`process:`、`state:`、`proto:`,以及 `/(?i)pattern/` 形式的正则。
- **GeoIP 增强**:基于本地 MaxMind GeoLite2 数据库查询国家信息,不发起任何网络请求。
Expand Down Expand Up @@ -84,8 +84,9 @@ RustNet 将进程级流量计量与实时网络接口统计整合在一起:
- **概览标签页**:展示当前活跃的接口,包含速率、错误数与丢包数
- **活动标签页**(按 `3`):按出站 (TX) 或入站 (RX) 查看进程排名,包括保留流量与滚动流量、速率、占比、连接数和目的地
- **安全工作流**:按出站流量排序,找出异常上传进程,然后检查其流量最大的远端对端;即使连接关闭,仍可查看保留流量
- **主机标签页**(按 `5`):显示 TCP LISTEN 套接字、UDP BOUND 端点、TCP 状态汇总、观测 RTT 和所属进程
- **主机标签页**(按 `5`):显示 TCP LISTEN 套接字、UDP BOUND 端点、TCP 状态汇总、观测 RTT、所属进程和被动 DNS 分析
- **接口详情**(在主机标签页按 `i`):显示各接口完整指标表格
- **DNS 详情**(在主机标签页按 `d`):显示滚动响应结果、匹配响应延迟和最活跃的查询名称
- **跨平台**:Linux(sysfs)、macOS / FreeBSD(getifaddrs)、Windows(GetIfTable2 API)
- **智能过滤**:Windows 上自动剔除虚拟 / 过滤类适配器

Expand Down Expand Up @@ -215,7 +216,7 @@ rustnet --pcapng-export capture.pcapng # 导出带注释的 PCAPNG
| `Esc` | 返回或清除过滤器 |
| `c` | 复制远端地址 |
| `p` | 在服务名与端口之间切换 |
| `d` | 在概览中切换主机名/IP,或在活动标签页切换出站/入站 |
| `d` | 在概览中切换主机名/IP,在活动标签页切换出站/入站,或在主机标签页打开 DNS 分析 |
| `s` `S` | 切换排序列 / 切换排序方向 |
| `a` | 切换按进程分组 |
| `Space` | 展开 / 折叠进程分组 |
Expand Down
32 changes: 30 additions & 2 deletions USAGE.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ This guide covers detailed usage of RustNet, including command-line options, key
- [Network Statistics Panel](#network-statistics-panel)
- [Process Activity](#process-activity)
- [Host Socket Inventory](#host-socket-inventory)
- [Passive DNS Analytics](#passive-dns-analytics)
- [Interface Statistics](#interface-statistics)
- [Connection Lifecycle & Visual Indicators](#connection-lifecycle--visual-indicators)
- [Logging](#logging)
Expand Down Expand Up @@ -738,10 +739,13 @@ Press `r` to reset all view settings at once:

## Network Statistics Panel

The Network Statistics panel appears on the right side of the interface, below the Traffic panel. It provides real-time TCP connection quality metrics derived directly from packet capture analysis, making it platform-independent across Linux, macOS, Windows, and FreeBSD.
The Network Statistics panel appears in the right-side system panel between Statistics and Traffic. It provides passive DNS health and real-time TCP connection quality metrics derived directly from packet capture analysis, making it platform-independent across Linux, macOS, Windows, and FreeBSD.

### Available Metrics

**DNS Health**
Summarizes the last 60 seconds of captured unicast DNS activity. It distinguishes normal responses, degraded service, operational failures, and queries that received no reply. A responsive line also includes p95 response time when matched samples are available. No observed DNS traffic is reported as `not observed`, not as healthy.

**TCP Retransmits**
Detects when a TCP segment is retransmitted due to packet loss or timeout. RustNet identifies retransmissions by analyzing TCP sequence numbers: when a packet arrives with a sequence number lower than expected, it indicates the original packet was lost and is being resent.

Expand Down Expand Up @@ -856,7 +860,30 @@ The inventory refreshes every 5 seconds. Process ownership is best effort becaus
| FreeBSD | `sockstat -s` for native TCP states plus UDP socket rows |
| Windows | IP Helper owner tables from `GetExtendedTcpTable` and `GetExtendedUdpTable` |

Press `i` for Interfaces and `s` to return to Sockets. Left and right arrow keys switch between the two views.
Press `i` for Interfaces, `d` for DNS, and `s` to return to Sockets. Left and right arrow keys cycle through all three views.

## Passive DNS Analytics

Press `5` for Host, then `d` to open DNS analytics. The view summarizes captured unicast UDP DNS traffic over a rolling 60-second window:

- **Outcomes**: lookup, answer, pending, timeout, NOERROR, NXDOMAIN, NODATA, SERVFAIL, REFUSED, and other response-code counts
- **Response time**: p50, p95, maximum, and latency buckets for responses paired by connection and transaction ID
- **Question names**: normalized query name and type with lookup, NXDOMAIN, failure, and p95 latency totals

Queries become timeouts after 10 seconds without a matching response. A retransmitted query with the same connection and transaction ID remains one logical lookup and restarts that timeout. Press `o` to sort question names by lookups, NXDOMAIN, failures, or p95 latency. The arrow keys, Page Up, Page Down, and mouse wheel scroll the table.

The DNS health state uses enough recent evidence to avoid alarming on a single packet:

- `not observed`: no captured DNS lookup is in the rolling window
- `checking`: queries are pending or fewer than three completed lookups are inconclusive
- `responsive`: at least one NOERROR or NXDOMAIN response was observed without a degradation threshold being crossed
- `degraded`: at least five completed lookups have a 20% operational failure rate, or at least five latency samples have p95 of 500 ms or more
- `failing`: at least three completed lookups produced no NOERROR or NXDOMAIN response
- `no replies`: no response was captured and at least three lookups timed out

NXDOMAIN is a valid resolver response, so it does not by itself make DNS unhealthy. Operational failures include SERVFAIL, REFUSED, other response codes, and timeouts.

This is passive evidence, not an active DNS probe. DNS over HTTPS, DNS over TLS, cached answers, and traffic not present on the selected capture interface are not visible. Missing replies can also indicate capture loss or asymmetric routing. If capture stops, Overview reports DNS health as unknown. Pressing `x` to clear captured state also resets these DNS aggregates.

## Interface Statistics

Expand All @@ -866,6 +893,7 @@ RustNet provides real-time network interface statistics across all supported pla

**Overview Tab (Main Screen):**
- Interface stats appear in the right panel below Network Stats
- Network Stats includes the compact rolling DNS health line
- Shows up to 3 active interfaces with current rates
- Displays: `InterfaceName: X KB/s ↓ / Y KB/s ↑`
- Shows cumulative totals: `Errors (Total): N Drops (Total): M`
Expand Down
Loading