rekurt/prt

GitHub: rekurt/prt

prt 是一款用 Rust 编写的实时终端网络端口监控工具,通过交互式 TUI 替代 lsof、ss 等传统命令,提供连接追踪、容器感知、告警和 SSH 隧道管理等功能。

Stars: 2 | Forks: 0

# prt **为你的终端设计的实时网络端口监控工具**
prt demo

[![Crates.io](https://img.shields.io/crates/v/prt.svg)](https://crates.io/crates/prt) [![下载量](https://img.shields.io/crates/d/prt.svg)](https://crates.io/crates/prt) [![CI](https://static.pigsec.cn/wp-content/uploads/repos/2026/06/b185394609021856.svg)](https://github.com/rekurt/prt/actions/workflows/ci.yml) [![许可证: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE) [![Rust](https://img.shields.io/badge/rust-1.75%2B-orange.svg)](https://www.rust-lang.org) [![docs.rs](https://docs.rs/prt-core/badge.svg)](https://docs.rs/prt-core) [English](README.md) | [Русский](README.ru.md) | [中文](README.zh.md)
## 什么是 prt? `prt` 可以实时在你的终端中显示哪些进程正在占用你机器上的网络端口。你可以把它看作是一个实时的、交互式的 `lsof -i` / `ss -tlnp`,并且带有颜色、过滤功能和进程树。 ## 为什么选择 prt? 像 `lsof`、`ss` 和 `netstat` 这样的传统工具提供的是静态快照,当你读到它时就已经过时了。`prt` 为你提供了一个**实时、自动刷新的终端 UI**,并带有变更追踪功能,让你可以: - **实时查看连接的出现和消失**(绿色 = 新建,红色 = 正在关闭) - **瞬间发现端口冲突** —— 不再需要通过 `lsof -i :8080` 瞎猜 - **检测可疑活动** —— 异常连接会自动被标记为 `[!]` - **直接在 TUI 中一键封禁恶意 IP** - **调试容器化应用** —— 查看每个端口属于哪个 Docker/Podman 容器 - **即时追踪 syscall** —— 无需离开 TUI 即可附加 strace/dtruss - **监控带宽** —— header 栏会显示全系统的网络吞吐量 - **设置告警** —— 当特定端口开放或进程超出连接限制时收到通知 ## prt vs lsof vs ss vs netstat | 功能 | `prt` | `lsof -i` | `ss -tlnp` | `netstat -tlnp` | |---------|:-----:|:---------:|:----------:|:---------------:| | 实时自动刷新 | **是** | 否 | 否 | 否 | | 变更追踪 (新建/消失) | **是** | 否 | 否 | 否 | | 彩色输出 | **是** | 否 | 否 | 否 | | 交互式过滤 | **是** | 否 | 否 | 否 | | 进程树 | **是** | 否 | 否 | 否 | | 已知端口名称 (170+) | **是** | 部分 | 部分 | 部分 | | 可疑连接检测 | **是** | 否 | 否 | 否 | | 容器感知 (Docker) | **是** | 否 | 否 | 否 | | 带宽监控 | **是** | 否 | 否 | 否 | | 防火墙快速封禁 | **是** | 否 | 否 | 否 | | 附加 Strace/dtruss | **是** | 否 | 否 | 否 | | 创建 SSH 隧道 | **是** | 否 | 否 | 否 | | 告警规则 (TOML 配置) | **是** | 否 | 否 | 否 | | 导出为 JSON/CSV | **是** | 否 | 否 | 否 | | 用于脚本的 NDJSON 流 | **是** | 否 | 否 | 否 | | 多语言 (EN/RU/ZH) | **是** | 否 | 否 | 否 | | macOS + Linux | **是** | macOS/Linux | Linux | Linux | | 无依赖 (单一二进制文件) | **是** | 系统 | 系统 | 系统 | ## 功能 ### 带有变更追踪的实时表格 主视图在一个可排序、可过滤的表格中显示所有活动的网络连接。列包括端口、服务名称、协议、状态、PID、进程名称和用户。新连接会闪烁**绿色**;已关闭的连接会褪色为**红色** 5 秒钟后再消失。表格每 2 秒自动刷新一次。 ### 已知端口数据库 `Service` 列将众所周知的端口号映射为人类可读的名称 —— http (80)、ssh (22)、postgres (5432) 等约 170 种。你可以在 `~/.config/prt/config.toml` 中覆盖或扩展自定义名称: ``` [known_ports] 3000 = "my-app" 9090 = "prometheus" ``` ### 连接老化 每个连接都会追踪其 `first_seen` 时间戳。超过 1 小时的 ESTABLISHED 连接会高亮显示为黄色;超过 24 小时的会显示为红色。CLOSE_WAIT 连接始终显示为红色,因为它们表明可能存在资源泄漏。 ### 可疑连接检测器 连接将被扫描异常情况,并标记为 `[!]`: - **非 root 用户使用特权端口** —— 非 root 进程监听在小于 1024 的端口上 - **脚本占用敏感端口** —— Python、Perl、Ruby 或 Node.js 监听在 22、80 或 443 端口 - **root 用户向高端口发起外连** —— root 进程与大于 1024 的远程端口建立了连接 按 `/` 然后输入 `!` 仅显示可疑条目。 ### 容器感知 如果 Docker 或 Podman 正在运行,`Container` 列将显示每个进程所属的容器。当没有检测到容器时,该列会自动隐藏以节省空间。解析使用批处理的 `docker ps` + `docker inspect` 调用,具有 2 秒的超时时间,以避免阻塞 TUI。 ### 带宽估算 header 栏显示全系统网络吞吐量:`▼ 1.2 MB/s ▲ 340 KB/s`。在 Linux 上读取 `/proc/net/dev`,或在 macOS 上读取 `netstat -ib`。速率是根据刷新周期之间的增量计算的。 ### 进程树 按 `Enter` 或 `d` 打开详情面板,然后按 `1` 查看所选进程的完整父级链(例如 `launchd → nginx → worker`)。通过遍历 PPID 关系构建。 ### 区块 `Tab` / `Shift+Tab` 在三个顶层区块之间循环切换。活动区块会在 header 中高亮显示。 | 区块 | 默认内容 | 子标签页 (`[` / `]`) | |---------|-----------------|----------------------| | **Connections** | 端口表 + 底部详情面板(使用 `Enter` / `d` 切换) | — | | **Processes** | 所选条目的进程详情 (CWD、CPU %、RSS、打开的文件、环境变量、所有连接、进程树) | 详情 ⇄ 拓扑 | | **SSH** | 保存的主机和活动的隧道集中在一处 | 主机 ⇄ 隧道 | Connections 表格下方的 **Details** 面板是一个统一的视图, 结合了绑定类型、网络接口、远程地址、状态、cmdline、相关 端口以及进程树 —— 无需切换标签页。 Processes 中的 **Topology** 子标签页会为整个工作集绘制 ASCII 树状图 `process → :local_port → remote`。 所有可滚动的视图都支持 `j`/`k` 和 `g`/`G`。 ### 操作菜单 (`Space`) 对所选条目的几乎所有操作都可以通过按 `Space` 打开的一个上下文弹出菜单来执行: - **杀死进程**(也直接绑定到 `K`) - **复制行**(也直接绑定到 `c`) / **复制 PID** - **封禁远程 IP** —— `iptables -A INPUT -s -j DROP` (Linux) / `pfctl -t prt_blocked -T add ` (macOS)。状态栏会显示撤销 命令。需要 sudo。 - **追踪 syscall** —— `strace -p -e trace=network -f` (Linux) 或 `dtruss -p ` (macOS,需要禁用 SIP 或拥有 root 权限)。重新运行即可分离。 - **SSH 转发** —— 打开隧道表单,让你可以选择本地端口、 远程目标和主机别名。 该菜单仅显示对当前条目有效的操作 —— 当没有 远程地址时,封禁和转发将被隐藏。 ### SSH 区块 `SSH` 聚合了两个子标签页: - **Hosts** —— 从 `~/.ssh/config` 以及 `~/.config/prt/config.toml` 中的 `[[ssh_hosts]]` 条目解析的只读列表。按 `Enter` 打开预填了主机别名的隧道表单。 - **Tunnels** —— 具有实时状态的运行中隧道:🟢 存活,🟡 启动中, 🔴 失败(失败状态将保持可见,直到你进行处理)。 按键:`n` 新建 · `e` 编辑 · `K` 杀死 · `r` 重启 · `s` 保存到配置。 隧道表单会进行**行内验证**(输入时错误的字段会变红),支持 **编辑模式**(按 Enter 会替换现有隧道),并且 **保护 Esc 键** —— 丢弃一个非空表单需要在 1.5 秒 内按第二次 Esc。 ### 告警规则 在 `~/.config/prt/config.toml` 中定义规则,以便在满足特定条件时收到通知: ``` [[alerts]] port = 22 action = "bell" # terminal bell on new SSH connections [[alerts]] process = "python" state = "LISTEN" action = "highlight" # highlight row in yellow [[alerts]] connections_gt = 100 action = "bell" # alert when a process exceeds 100 connections ``` 告警仅在出现 NEW 条目时触发(而不是在每个刷新周期)。可用的条件:`port`、`process`、`state`、`connections_gt`。操作:`bell`、`highlight`。 ### NDJSON 流 ``` prt --json | jq '.process.name' ``` 每个刷新周期向 stdout 输出每个连接的一个 JSON 对象。优雅地处理 SIGPIPE(当通过管道传递给 `head` 时不会发生 panic)。无 TUI 初始化 —— 对脚本和 pipeline 安全。 ### 监控模式 ``` prt watch 3000 8080 5432 ``` 显示特定端口 UP/DOWN 状态的紧凑型非 TUI 显示器。在状态改变时发出 BEL (`\x07`)。当连接到 TTY 时支持 ANSI 颜色,通过管道传递时为纯文本。 ``` :3000 ● UP nginx (1234) since 42s :8080 ○ DOWN since 7m :5432 ● UP postgres (567) since 42s ``` ### 导出 ``` prt --export json # JSON snapshot of all connections prt --export csv # CSV snapshot ``` ### 多语言界面 支持英语、俄语和中文。语言解析顺序: 1. `--lang en|ru|zh` CLI flag(最高优先级) 2. `PRT_LANG` 环境变量 3. 系统区域设置自动检测 4. 英语(后备) 在 TUI 中按 `L` 即可在运行时切换语言 —— 无需重启。 ## 安装 ``` cargo install prt ```
从源码构建 ``` git clone https://github.com/rekurt/prt.git cd prt make install # or: cargo install --path crates/prt ``` **环境要求:** Rust 1.75+ · macOS 10.15+ 或带有 `/proc` 的 Linux · `lsof` (macOS —— 预装)
## 用法 ``` prt # launch TUI prt --lang ru # Russian interface prt --export json # export snapshot to JSON prt --export csv # export snapshot to CSV prt --json # NDJSON streaming to stdout prt watch 80 443 5432 # compact port watch mode sudo prt # run as root (see all processes) ``` ## 键盘快捷键 **导航:** **全局:** | 按键 | 操作 | |-----|--------| | `?` | 帮助 (速查表) | | `q` | 退出 | | `Tab` / `Shift+Tab` | 下一个 / 上一个区块 (Connections \| Processes \| SSH) | | `Space` | 操作菜单 (杀死 / 复制 / 封禁 / 追踪 / 转发) | | `/` | 搜索与过滤 (`!` = 仅显示可疑) | | `Esc` | 关闭模态框 · 按两次可清除激活的过滤器 | | `r` | 刷新 | | `s` | Sudo 提示 | | `L` | 循环切换语言 | | `j`/`k` `↑`/`↓` `g`/`G` | 移动 / 滚动 · 跳转到顶部 / 底部 | **直接快捷键 (任何区块):** | 按键 | 操作 | |-----|--------| | `K` / `Del` | 杀死所选进程 | | `c` | 复制行到剪贴板 | **Connections 区块:** | 按键 | 操作 | |-----|--------| | `Enter` / `d` | 切换底部详情面板 | | `o` / `O` | 下一个排序列 / 反向排序 | **Processes 区块:** | 按键 | 操作 | |-----|--------| | `[` / `]` | 切换子标签页 (Detail \| Topology) | **SSH 区块:** | 按键 | 操作 | |-----|--------| | `[` / `]` | 切换子标签页 (Hosts \| Tunnels) | | Hosts: `Enter` | 从所选主机新建隧道 | | Hosts: `r` | 重新加载 `~/.ssh/config` 和 prt 配置 | | Tunnels: `n` | 打开新建隧道表单 | | Tunnels: `e` 编辑所选隧道 (提交时杀死 + 重生) | | Tunnels: `K` | 杀死所选隧道 | | Tunnels: `r` | 重启所选隧道 | | Tunnels: `s` | 将活动隧道保存到配置 | ## 配置 创建 `~/.config/prt/config.toml`: ``` # 覆盖已知端口名称 [known_ports] 3000 = "my-app" 9090 = "prometheus" # Alert rules [[alerts]] port = 22 action = "bell" [[alerts]] process = "python" state = "LISTEN" action = "highlight" [[alerts]] connections_gt = 100 action = "bell" ``` ## 架构 ``` crates/ ├── prt-core/ # Core library (platform-independent) │ ├── model.rs # PortEntry, TrackedEntry, ViewMode, ProcessesTab, SshTab, ActionItem │ ├── config.rs # TOML config loading (~/.config/prt/) │ ├── known_ports.rs # Well-known port → service name database │ ├── core/ │ │ ├── scanner.rs # scan → diff → sort → filter → export │ │ ├── session.rs # Refresh cycle state machine │ │ ├── killer.rs # SIGTERM / SIGKILL │ │ ├── alerts.rs # Alert rule evaluation │ │ ├── suspicious.rs # Suspicious connection heuristics │ │ ├── bandwidth.rs # System-wide RX/TX rate tracking │ │ ├── container.rs # Docker/Podman container resolution │ │ ├── namespace.rs # Network namespace grouping (Linux) │ │ ├── process_detail.rs # CWD, env, files, CPU, RSS │ │ └── firewall.rs # iptables/pfctl block/unblock │ ├── i18n/ # EN / RU / ZH, AtomicU8-backed runtime switching │ └── platform/ │ ├── macos.rs # lsof + batch ps (2 calls/cycle) │ └── linux.rs # /proc via procfs └── prt/ # TUI binary (ratatui + crossterm + clap) ├── app.rs # App state, main loop, caching ├── ui.rs # ViewMode-based rendering, fullscreen views ├── input.rs # Key dispatch by view mode ├── stream.rs # NDJSON streaming mode ├── watch.rs # Port watch mode ├── tracer.rs # Strace/dtruss session management └── forward.rs # SSH tunnel manager ``` **数据流:** ``` platform::scan_ports() → Session::refresh() → diff_entries() New / Unchanged / Gone (with first_seen carry-forward) → enrich() service names, suspicious flags, containers → retain() remove Gone after 5s → bandwidth.sample() RX/TX delta since previous cycle → sort_entries() by current SortState App::refresh() → alerts::evaluate() fire bell/highlight alerts → filter_indices() user's search query → UI renders ViewMode-based routing ``` | 平台 | 方法 | 性能 | |----------|--------|-------------| | **macOS** | `lsof -F` 结构化输出 | 每个扫描周期 2 次 `ps` 调用(批量) | | **Linux** | 通过 `procfs` 访问 `/proc/net/` | 零子进程开销 | ## 高投资回报率用例 (超越基础监控) ### 1) 部署前网络回归防护 在部署前后运行 `prt --json` 并对比连接配置文件差异。 这能捕获意外的新出口路径、错误的绑定地址以及隐藏的副作用。 ``` prt --json | jq -c '{pid: .process.pid, name: .process.name, local: .local_addr, remote: .remote_addr, state: .state}' ``` ### 2) 终端内的实时事件响应循环 无需离开 TUI 即可使用可疑过滤 + 封禁 + 追踪: 1. `/` 然后按 `!` 仅显示可疑项 2. 按 `b` 封禁远程 IP 3. 按 `t` 附加 strace/dtruss 并检查行为 这提供了一个快速的“观察 → 隔离 -> 检查”工作流。 ### 3) 容器端口暴露审计 在容器密集的主机上,切换到 **Processes → Topology**(按 `Tab` 到 Processes,再按 `]` 到 Topology)以发现 意外的暴露(例如,调试端口、管理 API、意外的公开绑定)。 ### 4) 运行时功能开关验证 在功能推出期间,追踪启用某个开关是否会引入新的出站 连接或状态变动(`SYN_SENT`、`CLOSE_WAIT` 激增等)。 ### 5) 针对脚本密集型服务的轻量级主机金丝雀 对于重度使用 Python/Node/Ruby 的技术栈,可疑启发式算法 + 告警可以作为一种 廉价的金丝雀,用于监测敏感端口上的异常监听行为。 ## 开发 ``` cargo build --workspace # build everything cargo test --workspace # run all tests cargo clippy --workspace # lint cargo fmt --all -- --check # format check cargo bench -p prt-core # criterion benchmarks ``` 请参阅 [CONTRIBUTING.md](CONTRIBUTING.md) 了解指南。 ## 常见问题 ### 如何查看所有进程?某些端口显示为“unknown”。 使用 `sudo prt` 运行以查看其他用户拥有的进程。在没有 root 权限的情况下,操作系统会隐藏不属于你的 PID。 ### prt 可以在 Windows 上运行吗? 暂时不行。`prt` 目前支持 **macOS** (10.15+) 和 **Linux** (带有 `/proc`)。Windows 支持已在 issue 追踪器中记录。 ### prt 与 `htop` 或 `btop` 有什么区别? `htop`/`btop` 是通用的进程监控器。`prt` 则专门针对**网络连接和端口** —— 显示哪个进程正在使用哪个端口,追踪连接生命周期,检测异常,并提供网络特定的操作(防火墙封禁、strace、SSH 隧道)。 ### 我可以在脚本和 pipeline 中使用 prt 吗? 可以!使用 `prt --json` 输出 NDJSON 流,`prt --export json|csv` 获取快照,或者使用 `prt watch ` 进行简单的 UP/DOWN 监控。所有非 TUI 模式在通过管道传递时都能完美运行。 ### 如何添加自定义端口名称? 编辑 `~/.config/prt/config.toml`: ``` [known_ports] 3000 = "my-frontend" 8080 = "my-api" 9090 = "prometheus" ``` ### 在生产环境中使用 prt 安全吗? 默认情况下,`prt` 是一个**只读的诊断工具**。破坏性操作(杀死进程、封禁 IP、附加 strace)始终需要明确的确认。TUI 绝不会在未经你批准的情况下修改系统状态。 ## Star History [![Star History Chart](https://api.star-history.com/svg?repos=rekurt/prt&type=Date)](https://star-history.com/#rekurt/prt&Date) ## 许可证 [MIT](LICENSE)
**如果 `prt` 对你有用,可以考虑在 GitHub 上给它点个 star!** [![GitHub stars](https://img.shields.io/github/stars/rekurt/prt?style=social)](https://github.com/rekurt/prt)
标签:Python安全, Rust, 内存分配, 可视化界面, 系统工具, 终端UI, 网络流量审计, 请求拦截, 跨平台, 运维监控, 通知系统