☰
Lists 上游源监控体系:从 YAML 配置到自动化 PR 的全链路解析
2026/10/13 2:48:35 网站建设 项目流程
  • 网络安全

【免费下载链接】Lists

Primary Block Lists

项目地址:https://gitcode.com/gh_mirrors/lis/Lists
点击查看免费下载

本文基于 Lists 仓库的实现总结文档 UPSTREAM_IMPLEMENTATION_SUMMARY.md,完整解析该项目"上游威胁源监控(Upstream Source Monitoring)"子系统的设计与落地:如何仅通过编辑config/lists.yml即可声明式地引入外部威胁情报源,由 scripts/monitor_upstream.py 完成拉取、归一化、比对与分支提交,再由 upstream-monitor.yml 工作流每日自动生成带分级标签的 Pull Request。读完后,你可以独立配置上游源、读懂监控脚本的缓存与比对逻辑,并按仓库给出的测试清单安全地把该自动化跑通。

整体架构与组件构成

原始总结文档(完成于 2026-07-03,状态为 "Complete and Ready to Use")将该体系划分为四大交付物:配置系统、监控脚本、GitHub 自动化工作流,以及配套文档。四者职责分工如下:

组件文件职责
配置config/lists.yml、config/upstream-sources-example.yml定义全局监控参数与每个列表的上游源清单
监控脚本scripts/monitor_upstream.py拉取上游、归一化域名、比对本地列表、创建更新分支
自动化工作流.github/workflows/upstream-monitor.yml定时触发、创建 PR、打标签、生成汇总 Issue、错误上报
配套文档UPSTREAM_MONITORING.md、IMPROVEMENT_PLAN.md完整用户指南与 Phase 7.4 实施记录

从源码结构看,数据流是一条清晰的单向管道:

  1. 工作流在每天 02:00 UTC(cron0 2 * * *)触发,安装 requirements.txt 中的依赖(pyyaml、requests、PyGithub)后运行python scripts/monitor_upstream.py --all;
  2. 脚本读取 config/lists.yml,找出所有配置了upstream_sources的列表,逐个拉取并比对,把差异结果写入<列表名>.txt的更新分支;
  3. 脚本把每个列表的 PR 元数据(标题、分支名、新域名数、PR 正文)保存为pr_<列表名>.json;
  4. 工作流的github-script步骤扫描这些 JSON 文件,调用 GitHub API 创建 PR、按域名数量打标签,并生成一份汇总 Issue;
  5. 若脚本退出码非 0,工作流自动创建带needs-attention标签的错误 Issue,并上传完整日志 artifact。

这一设计的关键取舍是:脚本本身不直接调用 GitHub API 创建 PR,它只负责"生成分支 + 落盘 PR 描述",把 API 调用交给工作流的 Node 环境完成(见 monitor_upstream.py 中保存 PR 元数据的部分)。这样本地调试时脚本可以独立运行,CI 侧则统一拥有 token 与权限。

配置系统:全局参数与逐源参数两层设计

全局设置 settings.upstream

原始文档要求在 config/lists.yml 顶部的settings:段中加入全局监控配置,当前仓库的实际内容(config/lists.yml)即为:

settings: # Upstream monitoring configuration upstream: enabled: true check_frequency: "daily" auto_merge_threshold: 10 require_review_threshold: 100 cache_ttl: 86400

各参数含义与脚本中的读取逻辑:

参数当前值含义脚本中的使用位置
enabledtrue监控功能总开关配置层面的语义开关
check_frequency"daily"全局检查频率(daily / weekly / hourly)与工作流 cron 配合使用
auto_merge_threshold10新增域名 ≤ 该值时视为可自动合并的小变更generate_pr_body 中生成合并策略说明
require_review_threshold100新增域名 > 该值时强制人工审查PR 正文分级(≤10 / 11–100 / >100 三档)
cache_ttl86400(24 小时,单位秒)上游响应缓存有效期check_upstream_updates 中通过config.get("settings", {}).get("upstream", {}).get("cache_ttl", 86400)读取,缺省回退为 86400

逐列表的 upstream_sources 配置

每个列表可在自身定义下追加upstream_sources列表。以当前仓库 config/lists.yml 中的ads列表为例:

lists: ads: description: "Ad serving domains" category: advertising status: stable upstream_sources: - url: "https://raw.githubusercontent.com/ShadowWhisperer/BlockLists/refs/heads/master/Lists/Ads" format: domains trusted: true update_frequency: daily - url: "https://media.githubusercontent.com/media/zachlagden/Pi-hole-Optimized-Blocklists/main/lists/advertising.txt" format: hosts trusted: true update_frequency: daily

脚本侧通过 UpstreamSource 数据类承载这些字段。对照 check_upstream_updates 中的解析代码,可以确认每个字段的默认值(原始文档未列全,这是源码级补充):

字段类型默认值说明
url必填—上游块列表的完整 URL
format字符串domains上游格式:hosts/domains/adguard/dnsmasq
trusted布尔False是否受信;未显式声明时按"不信任"处理,属保守默认
update_frequency字符串dailydaily/weekly/hourly
filter_comments布尔True跳过以#开头的注释行
filter_category可选None面向多类别列表的过滤标记(示例配置中ads、tracking有使用)
max_domains可选None单源域名上限,防止超大合并

config/upstream-sources-example.yml 提供了可直接复制粘贴的现成配置:覆盖abuse、crypto、fraud、malware、phishing、ransomware、scam等安全类列表,以及ads、gambling、porn、tracking等内容/隐私类列表,并逐条注明了格式与频率建议(例如 ransomware 的 RansomwareTracker 源特意标注trusted: false # Requires manual review)。文件末尾还附有字段速查表与"如何并入 lists.yml"的分步说明(CONFIGURATION OPTIONS EXPLAINED 段)。

四种上游格式如何被识别

format字段声明上游文件格式,实际解析由 src/normalize.py 完成。normalize_line 内置了四组正则(正则定义处),能同时识别0.0.0.0 domain/127.0.0.1 domain(hosts)、||domain^(adguard)、server=/domain/与address=/domain/0.0.0.0(dnsmasq)以及裸域名(domains),统一输出小写域名。这意味着即便个别源的实际格式与声明略有出入,只要落入上述模式之一即可被正确解析;对不符合任何模式的行则静默丢弃并返回None。

monitor_upstream.py 核心机制深读

原始文档将该脚本概括为"600+ 行"(当前为 645 行),下面按其内部调用链逐段展开。

智能缓存:MD5 哈希文件名 + mtime 判定 TTL

缓存是文档强调的核心特性("Smart Caching - Reduces bandwidth and respects upstream servers")。实现上:

  • 缓存文件路径由 URL 的 MD5 哈希生成:get_cache_path()返回TEMP_DIR / "upstream_cache_<md5>.txt"(get_cache_path)。TEMP_DIR来自 src/config.py,默认为系统/tmp,可用环境变量TEMP_DIR覆盖;
  • 缓存有效性由文件 mtime 与cache_ttl比较判定(is_cache_valid),未过期则直接parse_file_to_set读缓存,命中时输出Using cached data for ...;
  • 每次成功抓取后,原文整体写入缓存文件(fetch_upstream_domains),后续比对基于缓存内容重新解析,而非复用解析结果——这保证了filter_comments、max_domains等参数调整后无需清缓存即可生效。

命令行侧另有--no-cache参数可强制绕过缓存重新抓取(见下文 CLI 一节)。

抓取与域名上限

抓取使用requests.get(url, timeout=30, headers={"User-Agent": "BlockListProject-Upstream-Monitor/1.0"}),显式声明 User-Agent 并设置了 30 秒超时(抓取代码)。任何RequestException都会被捕获、打印错误并返回空集合,随后该源记为error="Failed to fetch upstream domains"的UpdateResult(错误分支),不会中断其他源的处理。

max_domains上限的生效细节值得注意(限流代码):当解析出的域名数超过上限时,脚本先对域名集合排序,再取前 N 个(set(sorted(domains)[:max_domains]))。排序保证多次运行截断结果一致,避免每次 PR 的"新增集合"随机漂移。

与本地列表比对:只增不删 + 排除名单

比对逻辑在 compare_with_local 中,包含两个关键设计决策:

其一,永不建议删除域名。函数签名声明返回(new_domains, removed_domains),但removed_domains恒为空集,源码注释(L198-L199、L225-L231)解释了原因:本地列表中的域名可能来自多个上游源、手工添加或社区贡献,仅凭"某上游源里没有了"就建议删除会误伤。这也解释了 PR 模板中 "Removed domains: 0" 恒成立的原因。

其二,排除名单(exclusions)在比对前介入。load_exclusions 读取config/exclusions/<列表名>.txt,把其中的域名从上游集合中扣除后再计算差集。这套机制与 config/exclusions/README.md 描述的流程闭环:被人工判定为误报、经 scripts/remove_domain.py 移除的域名会自动写入对应排除文件,从而"上游再出现也不会被自动加回来"。仓库中已存在ads.txt、malware.txt、tracking.txt等 7 个排除文件(见 config/exclusions/)。

比对结果new_domains = upstream_domains - local_domains即该源建议新增的域名集合,本地文件不存在时按空集合处理。

分支创建与多格式再生成

真正落盘更新时,create_pr_branch 依次执行:

  1. 清理旧分支:git branch -r扫描所有upstream-update/<列表名>/前缀的远程分支并逐个删除,避免堆积历史分支(L406-L436);
  2. 新建时间戳分支:命名格式upstream-update/<列表名>/<YYYYMMDD-HHMMSS>;
  3. 重写列表文件:合并existing_domains | all_new_domains后排序,以 hosts 格式(0.0.0.0 <domain>)写入<列表名>.txt,并带上 "Updated by upstream monitoring" 头注释(L461-L474);
  4. 再生成全部输出格式:调用python3 build.py --list <列表名>(L476-L491),由 build.py 按 config/lists.yml 中formats:段定义同步产出alt-version(domains)、adguard(ags)、dnsmasq-version(dnsmasq)等各目录下的对应文件。若该步失败仅告警不中断,注释说明格式可由 CI 兜底再生成;
  5. 提交并推送:commit message 为chore: update <列表名> from upstream sources,附新增域名数量;
  6. 落盘 PR 元数据:非 dry-run 且有新增时,把{list_name, title, branch, new_domains, body}写入TEMP_DIR/pr_<列表名>.json(L621-L631),供工作流的 github-script 步骤消费。

PR 正文与三档合并策略

generate_pr_body 生成的 PR 描述包含:汇总统计(列表名、新增/移除数、检查的源数)、每个源的明细(URL、上游总数、新增数,≤20 个时全量列出、否则抽样 10 个)、一个 4 项的验证清单(类别相关性、误报、校验通过、构建成功),以及按新增总量划分的合并策略三档:

新增域名数PR 中标注工作流附加标签
≤ 10Auto-merge eligiblesize:small+auto-merge-candidate
11–100Manual review recommendedsize:medium
> 100Manual review requiredsize:large+needs-review

所有 PR 固定携带automation与upstream-update两个基础标签(github-script 中的标签逻辑)。

命令行用法

脚本入口 main() 定义的完整参数集为(原始文档仅列了--list/--all/--dry-run,此处按源码补全):

# 检查单个列表(可加 --dry-run 只报告不建 PR) python scripts/monitor_upstream.py --list ads --dry-run # 检查所有配置了上游源的列表 python scripts/monitor_upstream.py --all --dry-run # 正式运行:创建分支并落盘 PR 元数据(去掉 --dry-run) python scripts/monitor_upstream.py --all # 忽略缓存强制重新抓取 python scripts/monitor_upstream.py --all --no-cache

参数约束:--list(-l)与--all(-a)必须至少指定其一,否则parser.error直接报错退出(L550-L551);--all模式下脚本自动过滤出配置了upstream_sources的列表(L558-L563)。运行结束会打印全局汇总(各列表新增/移除数、总计),dry-run 模式下明确输出 "No PRs created" 提示。

GitHub Actions 工作流逐段解析

.github/workflows/upstream-monitor.yml 与原始文档描述的七步流程一一对应,且比文档多出了两个细节:

触发与输入(L3-L18):除cron: '0 2 * * *'每日定时外,workflow_dispatch提供两个手动输入——list_name(指定单个列表,留空则全量)与dry_run(布尔,默认 false)。权限声明为contents、pull-requests、issues三项写权限(L20-L23)。

执行步骤(L26-L81):

  1. actions/checkout@v4且fetch-depth: 0(完整历史,脚本要清理旧远程分支);
  2. actions/setup-python@v5安装 Python 3.12 +pip install -r requirements.txt;
  3. actions/setup-node@v4安装 Node 24(供 github-script 使用);
  4. 以github-actions[bot]身份配置 git;
  5. 运行监控脚本,shell 侧用set +e容错、tee /tmp/monitor_output.log留存日志,并把退出码与error=true/false写入步骤输出,供后续步骤的if:条件分流。

PR 创建(L83-L190):github-script 步骤扫描/tmp/pr_*.json(即脚本写入的元数据),逐文件创建 PR(base 固定main)、按域名数追加标签、记录创建结果;随后把所有 PR 汇总成一张 Markdown 表格创建 "Upstream Updates Summary" Issue(标签automation、report),并写 Job Summary 表格。日志中list_name为空且dry_run=true时该步骤整体跳过。

错误与日志(L192-L235):脚本失败时自动创建 "Upstream Monitor Failed" Issue(标签automation、error、needs-attention),正文附带日志尾部 2000 字符与四条排查建议;Upload logs步骤以if: always()保证无论成败都上传monitor-logs-<run_id>artifact,保留 7 天。

快速上手:四步启用监控

这一节完整继承原始文档的 "How to Get Started" 流程。

Step 1 — 为列表添加上游源:编辑 config/lists.yml,在目标列表定义下(status:之后)加入upstream_sources段,可参考 config/upstream-sources-example.yml 中"copy-paste ready"的段落。原始文档给出的最小示例:

lists: ads: description: "Ad serving domains" category: advertising status: stable upstream_sources: # 新增这一段 - url: "https://adaway.org/hosts.txt" format: hosts trusted: true update_frequency: daily

Step 2 — 补齐全局设置:确认settings.upstream段存在且取值合理(当前仓库已就绪,见上文全局参数表)。

Step 3 — 手工验证:

# dry-run 单列表测试 python scripts/monitor_upstream.py --list ads --dry-run # 校验 YAML 语法 python -c "import yaml; yaml.safe_load(open('config/lists.yml'))"

检查输出中各源的 Upstream / Local / New 统计是否符合预期。

Step 4 — 启用自动化:工作流文件已在仓库中,提交并推送含上游源配置的改动后,次日 02:00 UTC 自动生效;也可在 Actions 面板选择 "Upstream Source Monitor" 通过 Run workflow 手动触发(可指定list_name或开启dry_run)。

推荐的起步源与类别对齐

原始文档给出的"高价值、低风险"起步组合为:

lists: malware: upstream_sources: - url: "https://urlhaus.abuse.ch/downloads/hostfile/" format: hosts trusted: true update_frequency: daily phishing: upstream_sources: - url: "https://phishing.army/download/phishing_army_blocklist.txt" format: domains trusted: true update_frequency: daily ads: upstream_sources: - url: "https://adaway.org/hosts.txt" format: hosts trusted: true update_frequency: weekly

文档同时给出当前仓库的类别对齐表,确保域名进入正确的列表:

类别列表目的
Securityabuse, crypto, fraud, malware, phishing, ransomware, scam防护威胁
Advertisingads拦截广告域
Contentgambling, porn, piracy, drugs, vaping内容类别过滤
Privacytracking拦截跟踪与分析
Socialfacebook, twitter, tiktok, whatsapp社交平台屏蔽
Gamingfortnite游戏相关屏蔽
Telemetryadobe, smart-tv遥测与激活拦截

对照当前 config/lists.yml,实际已启用上游源的是 8 个列表(ads、crypto、fraud、gambling、malware、porn、scam、tracking),合计 12 个源,来源以 ShadowWhisperer/BlockLists、Pi-hole-Optimized-Blocklists 与 hagezi/dns-blocklists 为主。而示例配置文件中还收录了 URLhaus、AdAway、phishing.army、Spam404、frogeye 等更多备选源,原始文档标注其覆盖了 23 个受信源、10 个列表——两者差异说明示例文件是"候选池",lists.yml是"已启用子集",可按需增删。

预期效果与自定义选项

原始文档对上线效果的描述(作为预期参考,而非实测数据):首周以小型 PR 为主(每列表 5–15 个域名),约 80% 的变更落在自动合并阈值内(≤10 域名),单次全量运行 2–5 分钟;UPSTREAM_MONITORING.md 的 Statistics 段进一步给出无缓存抓取约 5–10 秒/源、缓存命中 <1 秒/源、PR 生成 <30 秒等参考值。

三个常用自定义入口:

# 1. 调整全局检查频率 settings: upstream: check_frequency: "weekly" # 由 daily 改为 weekly # 2. 收紧或放宽自动合并阈值 settings: upstream: auto_merge_threshold: 5 # 保守:≤5 才允许自动合并 # auto_merge_threshold: 20 # 激进
# 3. 修改工作流触发节奏(.github/workflows/upstream-monitor.yml) on: schedule: - cron: '0 2 * * *' # 每天 02:00 UTC(现值) # - cron: '0 2 * * 1' # 改为每周一 02:00 UTC

测试清单与实操守则

原始文档的上线前测试清单,结合源码行为补充了验证要点:

  • 给一个测试列表添加一个上游源
  • 运行python scripts/monitor_upstream.py --list <name> --dry-run
  • 确认输出中的 Upstream / Local / New 三项统计正确(New = 上游集合 − 本地集合,且已扣除config/exclusions/中域名)
  • 检查输出无✗ Error fetching报错
  • 验证 YAML 语法:python -c "import yaml; yaml.safe_load(open('config/lists.yml'))"
  • 提交并推送改动
  • 在 Actions 面板手动触发一次工作流
  • 确认有差异时 PR 已创建(分支名upstream-update/<列表>/前缀、旧分支已清理)
  • 检查 PR 正文的源明细、验证清单与合并策略档位,以及标签是否符合域名数
  • CI 通过后合并测试 PR

DO / DON'T 守则(原文档原样继承,并附源码依据):

  • ✅ 从一两个受信源起步;✅ 测试时多用--dry-run;✅ 首周密切关注每个 PR;✅ 为大规模源设置max_domains(截断逻辑见上文);✅ 大变更人工审查;✅ 记录每个源的信任理由。
  • ❌ 立即添加不受信源并开自动合并(源码默认trusted: False,正是此精神);❌ 把所有源设为 auto-merge;❌ 忽略构建失败(build.py再生成失败会告警);❌ 跳过测试直接上生产;❌ 无谓地关闭缓存;❌ 不必要的hourly频率。

故障排查与后续规划

UPSTREAM_MONITORING.md 的故障排查章节与脚本实现可相互印证,四类常见问题:

  1. 源 URL 不可达:症状为✗ Error fetching或 PR 明细中出现⚠️ Error: Failed to fetch upstream domains(对应 UpdateResult.error 字段),排查 URL、限流与 Actions 日志(monitor-logs-*artifact);
  2. 变更量过大:优先为该源配置max_domains,或拆分大源,其次核对该源格式声明是否正确;
  3. 误报:把源标记trusted: false、向源上游反馈,并借助 config/exclusions/ 排除机制固化人工裁决结果;
  4. 缓存导致检测滞后:用--no-cache强制刷新,或删除TEMP_DIR下upstream_cache_*.txt缓存文件。

原始文档"Future Enhancements"部分列出的计划项(与 IMPROVEMENT_PLAN.md Phase 7.4 一致):VirusTotal API 信誉检查、基于 last-seen 的增量更新、源健康监控、IP 列表(.ip文件)支持、持续失败源的自动下线、定期健康报告。这些能力在当前 monitor_upstream.py 中尚未实现,属于规划中的增强方向。

相关文件索引

文件说明
UPSTREAM_IMPLEMENTATION_SUMMARY.md本文档所依据的实现总结
UPSTREAM_MONITORING.md完整用户指南(架构、格式表、合并策略、排错)
scripts/monitor_upstream.py监控脚本主实现(645 行)
.github/workflows/upstream-monitor.yml定时/手动触发的自动化工作流
config/lists.yml当前生效的全局参数与已启用上游源
config/upstream-sources-example.yml备选上游源示例与字段速查
src/normalize.py四种格式的域名归一化实现
src/config.pyPROJECT_ROOT/TEMP_DIR/CONFIG_DIR路径约定
config/exclusions/README.md排除名单机制说明
IMPROVEMENT_PLAN.mdPhase 7.4 实施记录与后续规划
  • 网络安全

【免费下载链接】Lists

Primary Block Lists

项目地址:https://gitcode.com/gh_mirrors/lis/Lists
点击查看免费下载

相关推荐

上一篇:DeepChem分子指纹选型指南:ECFP vs FCFP实测对比,一篇讲清怎么选
下一篇:ESP-IDF FAT 文件系统(FatFs)完全指南:挂载、配置、分区生成与性能优化

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询