Skip to content

Commit 8d3f60d

Browse files
VincentZyuwin11台式机VincentZyuwin11台式机
authored andcommitted
refactor: 移除无效的 --etw 回环捕获后端,同步更新三语文档
1 parent dbf06dd commit 8d3f60d

9 files changed

Lines changed: 47 additions & 163 deletions

File tree

docs/win_loopback.md

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Windows Loopback Traffic Monitoring: Why ETW Fails and Npcap Works
1+
# Windows Loopback Traffic Monitoring: Why Standard APIs Fail and Npcap Works
22

33
> **[📖 English](win_loopback.md)**
44
> **[📖 简体中文(大陆)](win_loopback.zh-cn.md)**
@@ -114,12 +114,13 @@ macOS inherits BSD's design philosophy: loopback is an ordinary network interfac
114114
115115
## winload's Solution
116116
117-
winload provides two Windows loopback capture backends:
117+
winload uses **Npcap** as its Windows loopback capture backend:
118118
119119
- **`--npcap` (recommended)**: Captures real loopback packets via Npcap's WFP callout. Accurate data.
120120
Requires [Npcap](https://npcap.com/#download) installed with "Support loopback traffic capture" enabled.
121121
122-
- **`--etw` (experimental)**: Polls counters via `GetIfEntry` API.
123-
Due to the Windows kernel deficiency described above, most versions return 0. **Essentially non-functional.** Kept only for completeness.
122+
> I previously experimented with polling `GetIfEntry` / `GetIfTable` counters directly, hoping to avoid the Npcap dependency. The result? Counters stubbornly stayed at 0 on every Windows version I tested. As detailed above, this is because the loopback pseudo-interface has no NDIS driver behind it — so there is simply nothing to count. I ended up removing that code path entirely. Thanks, Microsoft, for the *delightful* consistency.
124123
125-
On Linux / macOS, loopback traffic is obtained directly via the `sysinfo` crate — no extra flags needed.
124+
So yes — to monitor loopback traffic on Windows, you need to install a third-party driver. On Linux and macOS it just works out of the box, because those operating systems treated loopback as a real network device from the start. On Windows, the [Npcap](https://npcap.com/#download) project graciously fills the gap that the OS left behind.
125+
126+
On Linux / macOS, loopback traffic is obtained directly via the [`sysinfo`](https://crates.io/crates/sysinfo) crate — no extra flags needed.

docs/win_loopback.zh-cn.md

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Windows Loopback 流量监控:为什么 ETW 不行,Npcap 可以?
1+
# Windows Loopback 流量监控:为什么标准 API 不行,Npcap 可以?
22

33
> **[📖 English](win_loopback.md)**
44
> **[📖 简体中文(大陆)](win_loopback.zh-cn.md)**
@@ -129,12 +129,13 @@ Linux 的 `lo` 驱动在 loopback 路径上只多了几个函数调用——开
129129
130130
## winload 的解决方案
131131
132-
winload 提供两种 Windows loopback 捕获方式
132+
winload 使用 **Npcap** 作为 Windows loopback 捕获后端
133133
134134
- **`--npcap` (推荐)**: 通过 Npcap 的 WFP callout 捕获真实 loopback 数据包,数据准确。
135135
需要安装 [Npcap](https://npcap.com/#download),安装时勾选 "Support loopback traffic capture"。
136136
137-
- **`--etw` (实验性)**: 通过 `GetIfEntry` API 轮询计数器。
138-
由于上述 Windows 内核的功能缺失,大多数版本返回 0,**基本不可用**。仅作兼容保留。
137+
> 我曾经尝试过直接轮询 `GetIfEntry` / `GetIfTable` 计数器,希望能绕开 Npcap 依赖。结果呢?在我测试的每个 Windows 版本上,计数器都雷打不动地保持为 0。如上文所述,loopback 伪接口背后没有 NDIS 驱动,根本没有东西在计数。最终我删除了那部分代码。感谢微软一贯的 *稳定发挥*。
139138
140-
在 Linux / macOS 上,loopback 流量通过 `sysinfo` crate 直接获取,无需额外参数。
139+
所以是的——在 Windows 上监控回环流量,必须安装第三方驱动。而 Linux 和 macOS 上开箱即用,因为这些操作系统从一开始就把 loopback 当成真正的网络设备来对待。Windows 上则靠 [Npcap](https://npcap.com/#download) 项目填了操作系统留下的坑。
140+
141+
在 Linux / macOS 上,loopback 流量通过 [`sysinfo`](https://crates.io/crates/sysinfo) crate 直接获取,无需额外参数。

docs/win_loopback.zh-tw.md

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Windows Loopback 流量監控:為什麼 ETW 不行,Npcap 可以?
1+
# Windows Loopback 流量監控:為什麼標準 API 不行,Npcap 可以?
22

33
> **[📖 English](win_loopback.md)**
44
> **[📖 简体中文(大陆)](win_loopback.zh-cn.md)**
@@ -66,7 +66,7 @@ tcpip.sys 發送路徑
6666
短路環回到接收路徑
6767
```
6868

69-
这不是通过這不是通過 NDIS 層實現的,而是在更上層——WFP 是 `tcpip.sys` 內部的 hook 點。
69+
這不是透過 NDIS 層實現的,而是在更上層——WFP 是 `tcpip.sys` 內部的 hook 點。
7070

7171
所以 Npcap 安裝時需要選中 **"Support loopback traffic capture"**
7272
這會啟用 WFP callout 驅動,並創建 `NPF_Loopback` 虛擬適配器供 `pcap` 库使用。
@@ -129,12 +129,13 @@ Linux 的 `lo` 驅動程式在 loopback 路徑上只多了幾個函式呼叫—
129129
130130
## winload 的解決方案
131131
132-
winload 提供兩種 Windows loopback 擷取方式
132+
winload 使用 **Npcap** 作為 Windows loopback 擷取後端
133133
134134
- **`--npcap` (建議)**: 透過 Npcap 的 WFP callout 擷取真實的 loopback 封包,資料精準。
135135
需要安裝 [Npcap](https://npcap.com/#download),安裝時勾選 "Support loopback traffic capture"。
136136
137-
- **`--etw` (實驗性)**: 透過 `GetIfEntry` API 輪詢計數器。
138-
由於上述 Windows 核心的功能缺失,多數版本會回傳 0,**基本不可用**。僅為相容保留。
137+
> 我曾經嘗試過直接輪詢 `GetIfEntry` / `GetIfTable` 計數器,希望能繞過 Npcap 依賴。結果呢?在我測試的每個 Windows 版本上,計數器都紋絲不動地保持為 0。如上文所述,loopback 虛擬介面背後沒有 NDIS 驅動程式,根本沒有東西在計數。最終我刪除了那部分程式碼。感謝微軟一貫的 *穩定發揮*。
139138
140-
在 Linux / macOS 上,loopback 流量透過 `sysinfo` crate 直接取得,不需額外參數。
139+
所以是的——在 Windows 上監控回環流量,必須安裝第三方驅動程式。而 Linux 和 macOS 上開箱即用,因為這些作業系統從一開始就把 loopback 當成真正的網路裝置來對待。Windows 上則靠 [Npcap](https://npcap.com/#download) 專案填了作業系統留下的坑。
140+
141+
在 Linux / macOS 上,loopback 流量透過 [`sysinfo`](https://crates.io/crates/sysinfo) crate 直接取得,不需額外參數。

readme.md

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,6 @@ winload --npcap # Capture 127.0.0.1 loopback traffic (Windows, requires Npc
104104
| `--hide-separator` | Hide the separator line (row of equals signs) | off |
105105
| `--no-color` | Disable all TUI colors (monochrome mode) | off |
106106
| `--npcap` | **[Windows Rust Only]** Capture loopback traffic via Npcap (recommended) | off |
107-
| `--etw` | **[Windows Rust Only]** Poll loopback counters via GetIfEntry (experimental) | off |
108107
| `--debug-info` | **[Rust Only]** Print network interface debug info and exit ||
109108
| `-h`, `--help` | Print help (`--help --emoji` for emoji version!) ||
110109
| `-V`, `--version` | **[Rust Only]** Print version ||
@@ -122,22 +121,23 @@ winload --npcap # Capture 127.0.0.1 loopback traffic (Windows, requires Npc
122121

123122
Windows cannot report loopback traffic through standard APIs — this is a [functional deficiency in Windows' network stack](docs/win_loopback.md).
124123

125-
winload provides two workarounds:
124+
**To capture loopback traffic on Windows**, use the `--npcap` flag:
126125

127-
| Flag | Method | Status |
128-
|------|--------|--------|
129-
| `--npcap` | Npcap WFP callout driver |**Recommended** — accurate, real packet capture |
130-
| `--etw` | `GetIfEntry` API polling | ⚠️ Experimental — counters are 0 on most Windows versions |
126+
```bash
127+
winload --npcap
128+
```
129+
130+
This requires [Npcap](https://npcap.com/#download) installed with "Support loopback traffic capture" enabled during setup.
131131

132-
**To use `--npcap`**: Install [Npcap](https://npcap.com/#download) and enable "Support loopback traffic capture" during installation.
132+
> I previously tried polling Windows' own `GetIfEntry` API directly, but the counters are always 0 for loopback — there is simply no NDIS driver behind the loopback pseudo-interface to count anything. That code path has been removed.
133133
134134
> 📖 For a deep dive into why Windows loopback is broken, see [docs/win_loopback.md](docs/win_loopback.md)
135135
136136
On Linux and macOS, loopback traffic works out of the box — no extra flags needed.
137137

138138
## 🖼️ Previews
139-
#### preview of python impl
139+
#### Python Edition Preview
140140
![docs/preview-py.png](docs/preview-py.png)
141141

142-
#### preview of rust impl
142+
#### Rust Edition Preview
143143
![docs/preview-rust.png](docs/preview-rust.png)

readme.zh-cn.md

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,6 @@ winload --npcap # 捕获 127.0.0.1 回环流量 (Windows,需安装 Npcap)
104104
| `--hide-separator` | 隐藏分隔线(等于号一行) | 关闭 |
105105
| `--no-color` | 禁用所有 TUI 颜色(单色模式) | 关闭 |
106106
| `--npcap` | **[Windows Only]** 通过 Npcap 捕获回环流量(推荐) | 关闭 |
107-
| `--etw` | **[Windows Only]** 通过 GetIfEntry API 轮询回环计数器(实验性) | 关闭 |
108107
| `--debug-info` | **[Rust Only]** 打印网络接口调试信息后退出 ||
109108
| `-h`, `--help` | 打印帮助(`--help --emoji` 可查看 emoji 版!) ||
110109
| `-V`, `--version` | **[Rust Only]** 打印版本号 ||
@@ -122,14 +121,15 @@ winload --npcap # 捕获 127.0.0.1 回环流量 (Windows,需安装 Npcap)
122121

123122
Windows 无法通过标准 API 报告回环流量——这是 [Windows 网络栈的功能缺失](docs/win_loopback.zh-cn.md)
124123

125-
winload 提供两种解决方案
124+
**要在 Windows 上捕获回环流量**,使用 `--npcap` 参数
126125

127-
| 参数 | 方式 | 状态 |
128-
|------|------|------|
129-
| `--npcap` | Npcap WFP callout 驱动 |**推荐** — 数据准确,真实数据包捕获 |
130-
| `--etw` | `GetIfEntry` API 轮询 | ⚠️ 实验性 — 大多数 Windows 版本计数器为 0 |
126+
```bash
127+
winload --npcap
128+
```
129+
130+
需要安装 [Npcap](https://npcap.com/#download),安装时勾选 "Support loopback traffic capture"。
131131

132-
**使用 `--npcap`**: 安装 [Npcap](https://npcap.com/#download),安装时勾选"Support loopback traffic capture"
132+
> 我之前尝试过直接轮询 Windows 自带的 `GetIfEntry` API,但 loopback 的计数器始终为 0——loopback 伪接口背后根本没有 NDIS 驱动在计数。该代码路径已被移除
133133
134134
> 📖 深入了解 Windows 回环为何失效,请阅读 [docs/win_loopback.zh-cn.md](docs/win_loopback.zh-cn.md)
135135

readme.zh-tw.md

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,6 @@ winload --npcap # 擷取 127.0.0.1 回環流量 (Windows,需安裝 Npcap)
100100
| `--hide-separator` | 隱藏分隔線(等號一行) | 關閉 |
101101
| `--no-color` | 停用所有 TUI 顏色(單色模式) | 關閉 |
102102
| `--npcap` | **[Windows Only]** 透過 Npcap 擷取回環流量(建議) | 關閉 |
103-
| `--etw` | **[Windows Only]** 透過 GetIfEntry API 輪詢回環計數器(實驗性) | 關閉 |
104103
| `--debug-info` | **[Rust Only]** 列印網路介面除錯資訊後退出 ||
105104
| `-h`, `--help` | 列印說明(`--help --emoji` 可查看 emoji 版!) ||
106105
| `-V`, `--version` | **[Rust Only]** 列印版本號 ||
@@ -118,18 +117,19 @@ winload --npcap # 擷取 127.0.0.1 回環流量 (Windows,需安裝 Npcap)
118117

119118
Windows 無法透過標準 API 回報回環流量——這是 [Windows 網路堆疊的功能缺失](docs/win_loopback.zh-tw.md)
120119

121-
winload 提供兩種解決方案
120+
**要在 Windows 上擷取回環流量**,使用 `--npcap` 參數
122121

123-
| 參數 | 方式 | 狀態 |
124-
|------|------|------|
125-
| `--npcap` | Npcap WFP callout 驅動程式 |**建議** — 資料準確,真實封包擷取 |
126-
| `--etw` | `GetIfEntry` API 輪詢 | ⚠️ 實驗性 — 大多數 Windows 版本計數器為 0 |
122+
```bash
123+
winload --npcap
124+
```
125+
126+
需要安裝 [Npcap](https://npcap.com/#download),安裝時勾選 "Support loopback traffic capture"。
127127

128-
**使用 `--npcap`**: 安裝 [Npcap](https://npcap.com/#download),安裝時勾選"Support loopback traffic capture"
128+
> 我之前嘗試過直接輪詢 Windows 自帶的 `GetIfEntry` API,但 loopback 的計數器始終為 0——loopback 虛擬介面背後根本沒有 NDIS 驅動程式在計數。該程式碼路徑已被移除
129129
130130
> 📖 深入了解 Windows 回環為何失效,請閱讀 [docs/win_loopback.zh-tw.md](docs/win_loopback.zh-tw.md)
131131
132-
在 Linux 和 macOS 上,回環流量开箱即用,無需額外參數。
132+
在 Linux 和 macOS 上,回環流量開箱即用,無需額外參數。
133133

134134
## 🖼️ 預覽
135135
#### Python 版預覽

rust/Cargo.toml

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "winload"
3-
version = "0.1.6-beta.1"
3+
version = "0.1.6-beta.2"
44
edition = "2021"
55
description = "Network Load Monitor — nload-like TUI tool for Windows/Linux/macOS"
66
license = "MIT"
@@ -18,15 +18,10 @@ clap = { version = "4", features = ["derive"] }
1818

1919
[target.'cfg(windows)'.dependencies]
2020
pcap = { version = "2", optional = true }
21-
windows-sys = { version = "0.59", features = [
22-
"Win32_Foundation",
23-
"Win32_NetworkManagement_IpHelper",
24-
], optional = true }
2521

2622
[features]
27-
default = ["npcap", "etw"]
23+
default = ["npcap"]
2824
npcap = ["pcap"]
29-
etw = ["windows-sys"]
3025

3126
[profile.release]
3227
opt-level = 3

rust/src/loopback.rs

Lines changed: 1 addition & 101 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
//! Windows 本地回环流量捕获模块
22
//!
3-
//! 提供两种后端:
4-
//! - Npcap: 通过 pcap crate 捕获 \Device\NPF_Loopback 上的数据包
5-
//! - ETW: 通过 Event Tracing for Windows 获取网络事件 (实验性)
3+
//! 通过 Npcap (pcap crate) 捕获 \Device\NPF_Loopback 上的数据包。
64
//!
75
//! 此模块仅在 Windows 平台编译。非 Windows 平台下提供空实现。
86
@@ -44,8 +42,6 @@ pub enum LoopbackMode {
4442
None,
4543
/// 使用 Npcap (pcap) 捕获
4644
Npcap,
47-
/// 使用 ETW 捕获 (实验性)
48-
Etw,
4945
}
5046

5147
// ═══════════════════════════════════════════════════════════
@@ -178,96 +174,6 @@ pub mod platform {
178174
Npcap download: {NPCAP_URL}"
179175
))
180176
}
181-
182-
/// 启动 ETW 回环捕获
183-
///
184-
/// 实验性功能 — 使用 Windows GetIfEntry API 定时轮询 Loopback 接口统计。
185-
/// 注意: 标准 API 对 loopback 的计数器可能始终为 0,
186-
/// 但某些 Windows 版本/补丁下可能有效。
187-
#[cfg(feature = "etw")]
188-
pub fn start_etw(counters: LoopbackCounters) -> Result<String, String> {
189-
// 查找 loopback 接口的 dwIndex
190-
let loopback_idx = find_loopback_interface_index()?;
191-
let info_msg = format!("[etw] Found loopback interface index: {loopback_idx} (experimental, counters may be 0)");
192-
193-
thread::Builder::new()
194-
.name("etw-loopback".to_string())
195-
.spawn(move || {
196-
etw_poll_loop(loopback_idx, &counters);
197-
})
198-
.map_err(|e| format!("Failed to spawn ETW thread: {e}"))?;
199-
200-
Ok(info_msg)
201-
}
202-
203-
/// 通过 GetIfTable 遍历所有接口,找到 dwType == 24 (SOFTWARE_LOOPBACK) 的索引
204-
#[cfg(feature = "etw")]
205-
fn find_loopback_interface_index() -> Result<u32, String> {
206-
use windows_sys::Win32::NetworkManagement::IpHelper::{GetIfTable, MIB_IFTABLE};
207-
208-
unsafe {
209-
// 第一次调用获取所需 buffer 大小
210-
let mut size: u32 = 0;
211-
GetIfTable(std::ptr::null_mut(), &mut size, 0);
212-
213-
if size == 0 {
214-
return Err("GetIfTable returned size 0".to_string());
215-
}
216-
217-
// 分配 buffer 并第二次调用
218-
let mut buf: Vec<u8> = vec![0u8; size as usize];
219-
let table_ptr = buf.as_mut_ptr() as *mut MIB_IFTABLE;
220-
let ret = GetIfTable(table_ptr, &mut size, 0);
221-
if ret != 0 {
222-
return Err(format!("GetIfTable failed with error code: {ret}"));
223-
}
224-
225-
let num = (*table_ptr).dwNumEntries as usize;
226-
// table 字段是 [MIB_IFROW; 1],实际是变长数组
227-
let entries = std::slice::from_raw_parts((*table_ptr).table.as_ptr(), num);
228-
229-
for entry in entries {
230-
// IF_TYPE_SOFTWARE_LOOPBACK = 24
231-
if entry.dwType == 24 {
232-
return Ok(entry.dwIndex);
233-
}
234-
}
235-
236-
Err("No loopback interface found via GetIfTable".to_string())
237-
}
238-
}
239-
240-
/// 定时轮询 loopback 接口的 dwInOctets / dwOutOctets
241-
#[cfg(feature = "etw")]
242-
fn etw_poll_loop(if_index: u32, counters: &LoopbackCounters) {
243-
use windows_sys::Win32::NetworkManagement::IpHelper::{GetIfEntry, MIB_IFROW};
244-
245-
let poll_interval = std::time::Duration::from_millis(200);
246-
247-
loop {
248-
unsafe {
249-
let mut row: MIB_IFROW = std::mem::zeroed();
250-
row.dwIndex = if_index;
251-
252-
let ret = GetIfEntry(&mut row);
253-
if ret == 0 {
254-
// dwInOctets / dwOutOctets 是 u32 累计值
255-
// 对于 loopback,大多数 Windows 版本可能报告 0
256-
counters.bytes_recv.store(row.dwInOctets as u64, Ordering::Relaxed);
257-
counters.bytes_sent.store(row.dwOutOctets as u64, Ordering::Relaxed);
258-
}
259-
}
260-
261-
thread::sleep(poll_interval);
262-
}
263-
}
264-
265-
#[cfg(not(feature = "etw"))]
266-
pub fn start_etw(_counters: LoopbackCounters) -> Result<String, String> {
267-
Err("winload was compiled without ETW support (feature 'etw' disabled).\n\
268-
Recompile with: cargo build --features etw"
269-
.to_string())
270-
}
271177
}
272178

273179
// ═══════════════════════════════════════════════════════════
@@ -283,10 +189,4 @@ pub mod platform {
283189
On Linux/macOS, loopback traffic is natively available."
284190
.to_string())
285191
}
286-
287-
pub fn start_etw(_counters: LoopbackCounters) -> Result<String, String> {
288-
Err("--etw is only supported on Windows. \
289-
On Linux/macOS, loopback traffic is natively available."
290-
.to_string())
291-
}
292192
}

rust/src/main.rs

Lines changed: 1 addition & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -143,17 +143,8 @@ struct Args {
143143

144144
/// [Windows only] Use Npcap to capture loopback traffic (recommended)
145145
/// Requires Npcap installed: https://npcap.com/#download
146-
#[arg(long = "npcap", conflicts_with = "etw")]
146+
#[arg(long = "npcap")]
147147
npcap: bool,
148-
149-
/// [Windows only] Use GetIfEntry API to poll loopback traffic (experimental)
150-
/// WARNING: Most Windows versions report 0 for loopback counters, likely to fail.
151-
/// Windows loopback traffic is short-circuited inside tcpip.sys and bypasses
152-
/// the NDIS layer, so GetIfEntry counters are never updated.
153-
/// Recommend using --npcap instead. Npcap: https://npcap.com/#download
154-
/// Details: https://github.com/VincentZyuApps/winload/blob/main/docs/win_loopback.md
155-
#[arg(long = "etw", conflicts_with = "npcap")]
156-
etw: bool,
157148
}
158149

159150
// ─── App 状态 ──────────────────────────────────────────────
@@ -211,8 +202,6 @@ impl App {
211202

212203
let loopback_mode = if args.npcap {
213204
LoopbackMode::Npcap
214-
} else if args.etw {
215-
LoopbackMode::Etw
216205
} else {
217206
LoopbackMode::None
218207
};
@@ -286,7 +275,6 @@ fn run(terminal: &mut ratatui::DefaultTerminal, args: Args) -> io::Result<()> {
286275
let counters = LoopbackCounters::new();
287276
let result = match app.loopback_mode {
288277
LoopbackMode::Npcap => loopback::platform::start_npcap(counters.clone()),
289-
LoopbackMode::Etw => loopback::platform::start_etw(counters.clone()),
290278
LoopbackMode::None => unreachable!(),
291279
};
292280
match result {
@@ -390,8 +378,6 @@ nload-like TUI tool for Windows/Linux/macOS
390378
🪟 Windows Loopback:
391379
--npcap 🟢 Use Npcap to capture loopback traffic (recommended)
392380
📥 Download Npcap: https://npcap.com/#download
393-
--etw 🟡 Use GetIfEntry API (experimental, usually shows 0)
394-
⚠️ Most Windows versions report 0 for loopback counters
395381
396382
💬 Why? Windows loopback is short-circuited in tcpip.sys, bypassing NDIS,
397383
so counters stay 0. Npcap uses a WFP callout to intercept before the short-circuit.

0 commit comments

Comments
 (0)