# porteye **Repository Path**: tomlen/porteye ## Basic Information - **Project Name**: porteye - **Description**: 端口暴露自查镜 — 本机视角 vs 外部视角, 幻影端口差集报告, 零依赖单文件 CLI - **Primary Language**: Unknown - **License**: MIT - **Default Branch**: main - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-09-21 - **Last Updated**: 2026-09-22 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # porteye [简体中文](README.md) | [Gitee](https://gitee.com/tomlen/porteye) **端口暴露自查镜** —— 你的端口在「本机视角」和「外部视角」是两张不一样的图。porteye 把两张图摆在一起,差集就是问题。 零依赖单文件 CLI,Python 3 标准库,拷走就能跑。macOS / Linux / Windows 通吃。 ## 解决什么问题 * 防火墙挡住了你以为开着的端口 → **本机 netstat 显示监听 ≠ 外部可达**,安全自查最经典的错觉 * 新起一个服务绑了 `0.0.0.0` → **没人知道暴露面变了**,diff 基线一跑就响(退出码 0/2,直接接 cron/CI) * `nmap` 只给外面视角、`netstat` 只给本机视角 → **expose 子命令做差集**:幻影端口(挡住了)、可见端口(真暴露)、外部端口(NAT/容器映射进来的)三分类 * 扫描脚本随手写越界端口 → **fail-loud 拒绝**,`0` 和 `65536` 直接报错不静默跳过 ## 快速使用 ``` python3 porteye.py local # 本机监听全景(含进程名) python3 porteye.py target # 外部视角:扫 TOP103 端口 python3 porteye.py expose <本机内网IP> # 招牌命令:双视角差集报告 python3 porteye.py baseline # 保存当前暴露面为基线 python3 porteye.py diff 基线.json # 对比,新增暴露退出码 2 ``` | 你想 | 你跑 | | --- | --- | | 看本机有哪些端口在听、谁在听 | `local`(wildcard 端口带 `!` 标记) | | 检查服务器从外面能看到什么 | `target `(或 `--ports 80,443,8000-8100`) | | 我这些监听端口外面到底能不能打通 | `expose <本机内网IP>` | | 以后暴露面一变我就要知道 | `baseline` 存基线 → cron 挂 `diff`,退出码 2=变了 | | 全量扫描 65535 个端口 | 加 `--full`(约几分钟,256 并发) | ## expose 报告怎么读 ``` == porteye expose report == local listening : 37 ports (wildcard 16) remote visible : 0 ports [VISIBLE] 外部可达的本地服务 ← 真暴露面,攻击者眼里只有这些 [PHANTOM] 本机在听, 外部不可达 ← 幻影端口:防火墙/安全组/绑定策略挡住了 [OUTSIDE] 远端开放但本机未见 ← NAT/容器端口映射进来的,注意背后是谁 ``` 一句话:**对着 netstat 自我感觉良好,是暴露面管理的第一大错觉。** 以 VISIBLE 为准。 ## 设计要点 * **fail-loud**:端口规格越界直接 ValueError,不静默跳过——漏扫一个端口比报错更危险 * **探前必并**:expose 自动把本机 wildcard 监听并进探测清单,幻影无从漏报 * **退出码即接口**:diff 退出码 0(无变化)/ 2(有变化),shell/cron/CI 直接用,`--json` 出机读格式 * **只读探测**:全程只发 TCP connect 和读系统表,不改任何配置 * **四条不变量**:INV1 幻影⊆本机监听 / INV2 diff 双向互斥完备 / INV3 端口域 [1,65535] / INV4 `--json` 输出可解析且含固定键——`tests/test_porteye.py` 17 项自测逐条验证 ## 跨平台取数 | 平台 | 来源 | | --- | --- | | macOS | `lsof -nP -iTCP -sTCP:LISTEN`(带进程名),netstat 兜底 | | Linux | 直接读 `/proc/net/tcp{,6}`,不需要 netstat 二进制 | | Windows | `netstat -ano -p tcp` | ## 自测 ``` python3 tests/test_porteye.py # TOTAL 17 PASS 17 FAIL 0 (含真实端口起服→探测→diff 检出的全链路实测) ``` ## 适用边界(一句大实话) expose 的「外部视角」需要一个**另一台机器的位置**来探测——在同机回环上跑,防火墙视角是缺席的。跨机跑(同网段另一台机器/跳板机)才是它的完整形态。TCP 全连接扫描对IDS明显的目标会留日志,生产环境先打报告再动手。 ## License MIT