DreadpiratePickles/lantern-lan

GitHub: DreadpiratePickles/lantern-lan

一款局域网设备发现与清单管理工具,通过 MAC 厂商识别和随机化感知帮助防御者快速发现网络中的未知设备。

Stars: 0 | Forks: 0

# 🏮 Lantern LAN ### 映射局域网 · 识别供应商 · 揪出陌生设备 ![python](https://img.shields.io/badge/python-3.11%2B-3776AB?logo=python&logoColor=white) ![license](https://img.shields.io/badge/license-MIT-blueviolet) ![tests](https://img.shields.io/badge/tests-30%20passing-brightgreen) ![interface](https://img.shields.io/badge/interface-CLI%20%2B%20Web-22c55e) ![packet%20capture](https://img.shields.io/badge/packet%2520capture-Scapy-0e83cd) ![transmits](https://img.shields.io/badge/transmits-nothing%20by%20default-success) *你的网络上最可怕的设备,就是你叫不出名字的那些。*
Lantern LAN 构建并维护本地 IPv4 网络上的设备清单,通过供应商提示丰富每个 MAC 地址的信息,记录它之前检测到的设备,并将*未知*设备放在你最显眼的地方——无论是在带有颜色区分的终端视图中,还是在本地 Web 仪表板中。 它是一个**用于你拥有或明确授权评估的网络的防御性工具。**它只做一件切实有效的事:帮助家庭实验室或小型办公室的防御者回答“谁在我的 Wi-Fi 上,其中是否有新出现或意外的设备?”——相比于假设那个神秘的 MAC 地址可能没什么问题,这是迈向网络卫生管理成本更低的第一步。 ## 为什么开发它 家庭和小型办公网络会在不知不觉中积累设备:一个新的智能插座、客人的手机、室友的游戏机,偶尔还会出现一些你并没有放置的设备。单纯的 `arp -a` 转储就像是一堵十六进制的墙。Lantern LAN 将其转化为一份运行记录,包含防御者真正需要的三样东西: 1. **供应商归属** — OUI 查询将 `b8:27:eb:…` 转换为“Raspberry Pi”。 2. **随机化感知** — 现代手机为了保护隐私会轮换*随机* MAC 地址。Lantern LAN 会检测到这些(本地管理位)并将它们归入独立的平静的 `randomized` 状态,这样你的手机就不会在“unknown”视图中引发虚警淹没。剩下被标记为 **unknown** 的才是真正无法识别的、全球分配的地址——这才是值得关注的情况。 3. **记忆功能** — 首次发现/最后发现的时间戳和信任标志会在多次扫描中持久化存储于 SQLite 中,因此“刚刚出现”是一个可见的信号,而不是你需要自己去重建的东西。 ## 工作原理(数据流) ``` ┌──────────────┐ scan ───────► │ scanner.py │ active ARP sweep (Scapy) of a private CIDR │ │ └─ falls back to passive `ip neigh` cache └──────┬───────┘ (Linux) if Scapy/permissions unavailable │ Device(ip, mac, vendor, source) ▼ ┌──────────────┐ │ oui.py │ MAC → vendor + classify_mac(): │ │ universal / randomized / multicast / invalid └──────┬───────┘ ▼ ┌──────────────┐ │ store.py │ SQLite upsert. Preserves trust marks and │ │ first_seen across re-scans; computes a └──────┬───────┘ display status per device. │ ┌─────────┴──────────┐ ▼ ▼ ┌──────────────┐ ┌──────────────┐ │ cli.py │ │ app.py │ Flask dashboard (127.0.0.1), │ rich tables │ │ templates/ │ strangers float to the top. └──────────────┘ └──────────────┘ ``` **状态是推导出来的,而不是存储的** — 信任级别最高,其次是带有未知供应商的隐私随机化 MAC,状态为 `randomized`,然后是无法识别的全局 OUI 为 `unknown`,否则为 `known`: | 状态 | 颜色 | 含义 | | ------------ | ------- | ------------------------------------------------------------- | | `unknown` | 红色 | 无法识别的**全球分配** OUI。请注意这些。 | | `randomized` | 黄色 | 本地管理/隐私随机化 MAC(通常是手机)。 | | `known` | 青色 | 从本地 OUI 表中识别出的供应商。 | | `trusted` | 绿色 | 你明确标记为受信任的设备。 | `•new` 徽章标记仅被检测到过一次(未再次观察到)的设备。 **内置的发现保护机制:** 扫描范围被限制在 `/20`(4096 个主机),仅限 IPv4,并且**默认拒绝非私有地址空间** — 防御性清单工具不应该对公共互联网进行 ARP 扫描。 ## 设置 ``` cd lantern-lan python -m venv .venv # Linux/macOS: source .venv/bin/activate # Windows: .venv\Scripts\activate pip install -r requirements.txt pip install -e . cp .env.example .env # optional: defaults for DB path, CIDR, host/port ``` 在 Kali / Parrot 上,主动 ARP 扫描需要 packet 工具,并且通常需要 root 权限: ``` sudo apt install -y python3-scapy tcpdump ``` 将 `src` 添加到路径中即可直接运行,无需安装: ``` PYTHONPATH=src python -m lantern_lan.cli --help ``` ## 使用方法 全局标志(位于子命令之前):`--db PATH`(SQLite 清单,环境变量 `LANTERN_LAN_DB`)和 `--plain` / `--no-color`(同时也会自动响应 `NO_COLOR` 和非 TTY 输出)。 ### `scan` — 发现设备并保存 主动 ARP 扫描**私有** CIDR 并保存结果。因为这会发送数据包,所以需要经过授权确认才能执行。 ``` # 提示进行 YES 确认,然后进行扫描: sudo lantern-lan scan --cidr 192.168.1.0/24 # 非交互式(scripts/cron):预先断言授权: sudo lantern-lan scan --cidr 192.168.1.0/24 --yes # ...或者在环境中设置 LANTERN_LAN_ASSUME_AUTHORIZED=1。 # 被动模式:读取主机的 neighbor cache 而不是发送 ARP(无需同意): lantern-lan scan --ip-neigh-only # 机器可读,stdout 上无额外修饰: lantern-lan scan --cidr 192.168.1.0/24 --yes --json ``` 标志:`--cidr`, `--timeout`, `--interface`, `--ip-neigh-only`, `--yes/--i-am-authorized`, `--allow-public-range`, `--json`. 示例输出: ``` ┌───────────────────── 🏮 lantern-lan ─────────────────────┐ │ map the LAN · name the vendors · surface the strangers │ └────────────────────────── scan ──────────────────────────┘ scan · 192.168.1.0/24 · via scapy ┌──────────────┬──────────────┬───────────────────┬──────────────┬────────┐ │ Status │ IP │ MAC │ Vendor │ Source │ ├──────────────┼──────────────┼───────────────────┼──────────────┼────────┤ │ UNKNOWN •new │ 192.168.1.47 │ 00:11:22:33:44:55 │ Unknown │ scapy │ │ RANDOM •new │ 192.168.1.23 │ de:ad:be:ef:00:01 │ Unknown │ scapy │ │ OK │ 192.168.1.10 │ b8:27:eb:aa:bb:cc │ Raspberry Pi │ scapy │ │ TRUSTED │ 192.168.1.1 │ 44:d9:e7:11:22:33 │ Ubiquiti │ scapy │ └──────────────┴──────────────┴───────────────────┴──────────────┴────────┘ ┌─────────────────── inventory ────────────────────┐ │ 1 unknown 1 randomized 1 trusted 4 total │ └──────────────────────────────────────────────────┘ saved 4 device(s) → lantern_lan.sqlite3 1 new ``` ### `devices` — 显示已保存的清单 陌生设备优先(unknown → randomized → known → trusted),在每个类别内按 IP 排序。 ``` lantern-lan devices # pretty table + summary lantern-lan devices --unknown-only # only red/unknown rows lantern-lan devices --watch # live-refreshing view (Ctrl-C to exit) lantern-lan devices --json # pure JSON for scripting ``` 标志:`--json`, `--unknown-only`, `--watch`, `--interval SECONDS`. ### `trust` — 将设备标记为受信任(或撤销信任) 接受任何常见的 MAC 格式(`:`, `-`, `.`,任何大小写)。报告是否实际匹配到了记录。 ``` lantern-lan trust b8:27:eb:aa:bb:cc lantern-lan trust B8-27-EB-AA-BB-CC --remove ``` ### `forget` — 从清单中移除设备 适用于那些已经彻底离开、你不想让它继续残留的设备。 ``` lantern-lan forget de:ad:be:ef:00:01 ``` ### `serve` — Web 仪表板 默认绑定到 `127.0.0.1:5063`。具有相同的三态视图,并为每个设备提供一个 Trust/Untrust 按钮。 ``` lantern-lan serve # http://127.0.0.1:5063 lantern-lan serve --host 127.0.0.1 --port 8080 ``` 标志:`--host`, `--port`, `--debug`. 如果你绑定到 localhost 之外(仪表板没有身份验证)或启用了 `--debug`(如果可以被访问到,Werkzeug 调试器会导致远程代码执行),CLI 会发出强烈的警告。 **退出代码:** `0` 成功 · `1` 错误 · `2` 拒绝执行(未经授权的扫描)。 ## 安全与授权 - **仅限已授权目标。** 主动扫描会向范围内的每个主机发送 ARP 数据包。仅对你拥有或明确授权评估的网络运行此操作。如果没有明确的 `--yes` / 交互式 `YES` / `LANTERN_LAN_ASSUME_AUTHORIZED=1`,`scan` 子命令将拒绝执行。 - **默认为私有范围。** 除非你添加 `--allow-public-range`(并且你仍需获得授权),否则将拒绝公共/非 RFC1918 的 CIDR。 - **扫描大小限制。** 任何大于 `/20` 的范围都会作为可能的误操作被拒绝。 - **被动回退即为被动。** `--ip-neigh-only` 仅读取你本机现有的邻居缓存;它不发送任何内容,因此无需授权。 - **仪表板默认仅限本地。** 绑定到 `127.0.0.1`;它没有登录功能,所以请保持在此地址。更改状态的 POST 请求会进行 same-origin 检查,输入会被验证,并且设置了保守的响应头——这是安全带,而不是一把锁。 - **输出中无敏感信息。** 该工具仅存储 MAC/IP/供应商/时间戳;不会记录任何敏感信息。 ## 开发与测试 快速、确定、无网络依赖、无 sleeps: ``` cd lantern-lan PYTHONPATH=src python -m pytest -q ``` 测试套件涵盖了 MAC 分类(randomized vs. universal vs. multicast)、私有范围/大小 CIDR 保护、基于 CIDR 过滤的邻居缓存回退、清单状态推导、跨多次重新扫描的信任/首次发现的持久性、CLI 授权确认和 JSON 纯度,以及 Flask 的输入验证 / same-origin / 响应头加固。 ### 项目结构 ``` lantern-lan/ src/lantern_lan/ scanner.py # Scapy ARP sweep + passive `ip neigh` fallback, CIDR guards oui.py # local MAC→vendor table + MAC classification store.py # SQLite inventory, trust flags, status derivation cli.py # scan · devices · trust · forget · serve (+ rich rendering) app.py # Flask dashboard (hardened) ui.py # shared theme / console / banner templates/ tests/ ``` ### 扩展供应商表 `oui.py` 提供了一组精选的常见 OUI。将你环境的前缀添加到 `OUI_PREFIXES` 中。如需完整覆盖,请接入下载好的 IEEE `oui.txt` — `lookup_vendor` 边界已经将调用者与数据所在的具体位置隔离开来(有关升级路径,请参阅文件中的 `# ponytail:` 注释)。 ``` --- ## 🏷️ 为什么叫 "Lantern LAN"? Hold up a lantern, see who's in the room. Finding devices is the easy half — any scanner does that. The half that actually matters is telling a genuinely unknown host apart from an iPhone doing MAC-address randomisation, because to a naive scanner those look identical, and a tool that cries wolf about your colleague's phone every morning is a tool you will stop reading by Thursday. --- ## 🔬 这个工具是如何构建的 > One of ten defensive tools rebuilt to a single standard — *understand, reimagine, > build the CLI, harden, document, verify*. The goal was never to change what these > tools **are**, but to take each one as far as it could honestly go on correctness, > safety and the experience of the person actually running it at 2am. **Purpose.** A LAN device mapper that no longer just lists MACs but *reasons* about them: it tells a genuinely-unknown globally-assigned device apart from an expected privacy-randomized phone, remembers what it has seen, and puts the strangers front-and-center — all behind an authorized-networks-only gate. **How it works.** An active ARP scan (or a passive neighbor-cache read) discovers devices; each MAC is classified by its OUI and the locally-administered bit, then reconciled against a persistent SQLite inventory that tracks first-seen and trusted state. Unknowns sort to the top. **Standout CLI.** A color-coded status column (unknown=red, randomized=yellow, known=cyan, trusted=green), an inventory summary panel whose border turns red when unknowns are present, a `•new` badge for first-seen devices, and a `--watch` live-refreshing table via `rich.Live`. **Key improvements.** *Functional:* MAC-randomization detection (the locally-administered bit) splits expected privacy MACs from genuinely-unknown global OUIs, cutting false positives; a `forget` subcommand prunes stale devices; `trust` now validates the MAC in any format and reports whether a row actually changed; the CIDR-filtered neighbor-cache fallback no longer leaks devices from other subnets; fixed leaking SQLite connections (matters for the long-lived Flask process); hostname is preserved across re-scans. *Security:* the consent gate on active ARP scans (`--yes` / interactive / `LANTERN_LAN_ASSUME_AUTHORIZED=1`, exit 2); private-range-only by default (`--allow-public-range` to override) with a /20 scan-size cap; the passive `--ip-neigh-only` path needs no consent (it sends nothing); strict MAC validation and a same-origin Origin/Referer check on `POST /trust` to block cross-site trust flips. **Example.** ```bash PYTHONPATH=src python -m lantern_lan.cli --db demo.sqlite3 devices ``` ## ⚖️ 授权使用与安全准则 **这些是用于你拥有或明确授权评估的系统、文件、网络和人员的防御性工具。** 在运行任何内容之前,请阅读以下声明: - **授权不是可选项。** 钓鱼演练、网络扫描、IP 信誉查询和 Web 应用探测都会触及他人的系统或数据。请先获得书面授权。一些工具在确认授权之前*拒绝执行任何操作*(`--yes`, `--authorized-training`, `--i-have-authorization`, `--i-am-authorized` 等)。 - **默认安全。** 每个 Web UI 都绑定到 `127.0.0.1` (loopback)。出站流量、实时发送和主动扫描都需要显式的标志才能执行——试运行、被动模式,或者拒绝并警告始终是默认设置。 - **防止意外自损。** Flask `--debug`(Werkzeug 交互式调试器在任何 traceback 上均可被用于远程代码执行)会受到强烈的警告,并且在 loopback 之外被完全拒绝。不受信任的输入会有大小限制、经过验证并被无效化处理,因此带有恶意的文件或日志行既不会导致你的终端崩溃,也不会被接管。 - **输出中无敏感信息。** API key 保留在 request header 中,密码来源于环境变量,并且不会记录或打印任何敏感信息。 这些不是攻击性工具。它们不包含任何漏洞利用、凭证收集器或 payload。如果某个工具*可能*被滥用,它的构造设计也会使其能够抵抗这种滥用。 ## 🧪 开发 ``` python -m venv .venv && source .venv/bin/activate pip install -e . pytest -q # 30 tests, no network, no sleeps lantern-lan --help ``` ## 📄 许可证 基于 **MIT License** 发布。详见 [LICENSE](LICENSE)。
防御性工具。无漏洞利用,无 payload,无凭证收集器。
标签:Docker 部署, Python, Scapy, 局域网发现, 插件系统, 无后门, 网络设备监控, 网络运维, 资产盘点, 逆向工具