rithinkrishnakv/jobless-router
GitHub: rithinkrishnakv/jobless-router
实时 BGP 零信任威胁情报引擎,监听全球路由数据流,通过 RPKI 验证、意图评分和基线偏差检测识别路由劫持与泄露。
Stars: 0 | Forks: 0
[](https://github.com/rithinkrishnakv/jobless-router/actions/workflows/tests.yml)
[](LICENSE)
[](https://www.python.org/)
[](https://ris-live.ripe.net/)
[](#advisory-mitigation-playbook)
[](#what-it-actually-does)
一个实时的 BGP 零信任威胁情报引擎。它监听全球
路由数据流,针对实时 RPKI 对路由公告进行密码学验证,
并**评估意图** —— 是无意的错误配置、蓄意的路由泄露,
还是针对性的拦截企图 —— 而不仅仅是标记为“RPKI invalid”
就停止。
## 它的实际作用
1. **AS-path 遍历** —— 指出确切的“共谋”上游传输
提供商,这些提供商从其源端接收了错误路由并在
未经过滤的情况下继续传播。
2. **意图启发式** —— 两个独立的 0-100 分评分:
- *Fat-finger*(误操作):宽泛且过度碎片化的 prefix,RPKI `INVALID_LENGTH`。
- *针对性 MITM*:高度具体的 prefix,命中受监视的关键服务,
与合法持有者没有任何业务关系,破坏了
[valley-free routing](https://en.wikipedia.org/wiki/Valley-free_routing)
(Gao-Rexford 属性,RFC 7908 依赖它来定义路由泄露),或者
伴随 AS-path 投毒。
3. **BGP community 解码** —— 标记 RFC 1997/7999 知名 community,
包括 blackhole (RTBH) community,这样由运营商有意发布的
缓解路由就不会被错误分类为劫持。
4. **AS-path 投毒检测** —— 区分良性的自我前缀追加
(流量工程)和植入路径中间的非源 ASN,以绕过
特定网络自身的环路预防机制。
5. **基线偏差检测** —— 学习哪些源 ASN 和上游
之前合法地宣告过每个 prefix,从而即使在没有
RPKI ROA 可以通过密码学验证判定为无效时,也能捕捉到泄露。
(RPKI ROA 的覆盖率仍然远不及路由表的一半 —— 沉默
并不代表无辜。)
6. **影响范围估算** —— 计算有多少个不同的、地理分布广泛的
RIPE RIS 路由收集器看到了相同的错误路由,作为一个可靠的、
可衡量的传播样本(PeeringDB 描述的是对等关系,
而不是实时的 RIB 状态,因此它实际上无法回答“互联网中有多大比例
接受了这个路由” —— 而这可以做到)。
7. **惯犯跟踪** —— 一个小型的 sqlite 账本,记录每个 ASN 累计的
不良路由时间,而不仅仅是事件计数。
8. **Certificate Transparency 交叉检查** —— 可选地轮询 `crt.sh`
以查找在事件窗口附近颁发的可疑证书,这是一种跨层信号,
可以区分“路由泄露”和“有人试图进行 MITM TLS。”
9. **建议缓解手册** —— 生成 RTBH 文本、一条 BGP Flowspec
(RFC 8955)规则,以及 Cisco/Juniper/Arista 的 ACL 配置供人工
审查。它刻意绝不开启实时的 BGP 会话或自动推送配置
—— 在*自动化*缓解中出现误报,导致合法流量被黑洞的速度
可能比劫持本身还要快。
10. **运行鲁棒性** —— 将 websocket 接收器和
评分 pipeline 作为独立的、通过队列连接的生产者/消费者任务运行,
因此缓慢的处理(RPKI 查询等)绝不会延迟
socket 的排空 —— 这很可能是早期测试中观察到 ping-timeout
断开连接的原因之一。在瞬时断开时通过退避机制自动重新连接
而不是直接崩溃,可选地通过 SOCKS5
代理(`--proxy socks5://host:port`);将 RPKI 查询缓存几分钟,
这样重复看到相同的路由就不会频繁请求
RIPEstat;`--debug` 显示每个事件的评分,无论是否被标记,因此
沉默是可验证的,而不仅仅是被盲目信任的。
## 快速开始
```
git clone https://github.com/rithinkrishnakv/jobless-router.git
cd jobless-router
pip install -r requirements.txt
# 离线演示 —— 六个脚本化场景,零网络依赖:
python run.py --replay sample_events.jsonl
# 对检测逻辑本身进行健全性检查:
python tests/test_demo.py
# 真实场景 —— 连接到 RIPE RIS Live 的公共 websocket firehose,
# 无需 API key。需要正常的出站互联网访问。
python run.py --live
# 缩小范围到一个 prefix 或一个 collector,而不是完整的全局 firehose,
# 和/或查看每个事件的 score,即使它没有被标记:
python run.py --live --prefix 1.1.1.0/24
python run.py --live --host rrc00 --debug
# 捕获从受监控的 block 中划分出的 sub-prefix(真实的 hijack 模式):
python run.py --live --prefix 1.0.0.0/8 --more-specific
# 通过 SOCKS5 代理,并为不稳定网络设置更宽松的 keepalive 容差:
python run.py --live --host rrc00 --proxy socks5://127.0.0.1:1080 --ping-timeout 30
```
## 内置演示 (`sample_events.jsonl`)
六个预设的、符合 RIS-Live 格式的事件,无需连接网络
即可端到端测试每个子系统:
| # | 场景 | 验证内容 |
|---|---|---|
| A | 干净的路由,用于建立基线 | 工具在合法流量上保持沉默 |
| B | 宽泛的 `/16`,`INVALID_LENGTH` | Fat-finger 启发式正确触发 |
| C | 监视列表中的 `/24`,恶意源,无关联关系 | 针对性 MITM 启发式正确触发 |
| D | 路径中间重复出现非源 ASN | AS-path 投毒检测器捕捉到它,提升 MITM 分数 |
| E | 带有 `65535:666` blackhole community 的 `/32` | Community 解码抑制了误报 |
| F | 与 A 相同的 prefix,新源,完全没有 ROA | 基线偏差捕捉到 RPKI 无法察觉的泄露 |
除了一个 watchlist 示例 Cloudflare 的公共 `1.1.1.0/24` 解析器(仅用于展示 watchlist 机制的工作原理,并非声称发生了任何真实事件)外,
使用的每个 prefix 均来自 IANA 保留的文档范围(RFC 5737:
`192.0.2.0/24`, `198.51.100.0/24`, `203.0.113.0/24`)。所有的“恶意”
和“客户”ASN 都在 IANA 的私有使用范围内(64512–65534)。
## 在生产环境中替换为真实数据
- **AS 关系**:`data/sample_as_relationships.txt` 是一个微小的、
手动构建的说明性子集。要进行真实的 valley-free 检查,请从
[CAIDA 的 AS 关系项目](https://publicdata.caida.org/datasets/as-relationships/serial-2/)
下载实际的数据集(相同的 `as1|as2|relationship` 格式),并将 `--relationships` 指向它。
- **Watchlist**:使用对你真正重要的 prefix 编辑 `data/watchlist.json`。
- **RPKI**:`jobless_router/rpki.py` 调用 RIPEstat 免费的
`rpki-validation` API —— 不需要密钥,只需正常的互联网访问。
- **持久化**:传入 `--db-dir /some/real/path` 而不是默认的
`:memory:`,这样基线和惯犯数据库在重启后依然存在。
## 架构
```
firehose.py (producer: receives off the websocket, pushes to a queue)
|
v
asyncio.Queue
|
v
run.py (consumer) --> engine.py --(orchestrates)--> rpki.py (cached)
|--> path_analysis.py (traversal + poisoning)
|--> relationships.py (valley-free / Gao-Rexford)
|--> communities.py (RFC1997/7999 decoding)
|--> baseline.py (sqlite, learns "normal")
|--> blast_radius.py (multi-collector sampling, bounded)
|--> heuristics.py (intent scoring)
|--> threat_db.py (sqlite, repeat offenders)
|--> ct_correlation.py (crt.sh cross-check)
|--> mitigation.py (advisory playbook text)
`--> report.py (markdown rendering)
```
生产者和消费者作为独立的 asyncio 任务运行,因此缓慢的评分
pipeline 绝不会延迟 websocket 本身的排空。任何一个任务
崩溃都会立即显现(`asyncio.wait(..., FIRST_EXCEPTION)`),
而不是在另一个任务继续运行时默默死去。
## 关于范围和诚实的说明
标签:BGP, Python, RPKI, 威胁情报, 开发者工具, 无后门, 网络安全, 计算机取证, 路由监控, 逆向工具, 隐私保护