GeoIP 与 GeoSite 数据库更新指南:分流规则失准的根源与解决
解释 GeoIP、GeoSite 数据库在规则匹配中的角色,演示手动替换与配置内自动更新两种方式,并分析数据库过旧导致分流错误的典型表现与验证方法。
Clash 与 mihomo 内核的分流规则并不完全依赖手写的域名或 IP 段,大量常用规则实际引用了两类离线数据库:GeoIP 与 GeoSite。它们把海量 IP 段和域名归类打包,规则文件只需要写一行 GEOIP,CN 或引用一个规则集,就能覆盖成千上万条实际地址。这带来了配置上的简洁,但也埋了一个容易被忽视的隐患——数据库本身是有时效性的,过旧的数据库会让原本正确的规则悄悄失准。
GeoIP 与 GeoSite 到底存了什么
这两类数据库解决的是同一个问题的两个维度:一个按 IP 归类,一个按域名归类。理解它们的差异,是排查分流异常的前提。
| 维度 | GeoIP | GeoSite |
|---|---|---|
| 存储内容 | IP 地址段与所属国家/地区代码的映射 | 域名与业务分类标签的映射 |
| 常见文件 | Country.mmdb / geoip.metadb | geosite.dat / GeoSite.dat |
| 典型规则写法 | GEOIP,CN,DIRECT | RULE-SET,geosite-google,PROXY |
| 更新触发原因 | IP 段重新分配、云厂商机房迁移 | 新域名上线、CDN 域名变更 |
mihomo 内核在启动时会把这两类数据库加载进内存,之后每一次连接匹配规则,都会去查表——查一个 IP 属于哪个国家,或者一个域名归属哪个分类。数据库里没有的内容,自然无法命中对应规则,只能继续往下匹配,通常会落到规则表最后的 MATCH 兜底策略上,而这往往和期望的出口不一致。
数据库过旧会带来哪些具体症状
数据库老化不会报错,也不会在界面上提示"请更新",它是一种沉默的偏差,只能通过分流结果的异常反推出来。以下是几种高频表现:
- 新上线的服务被误判为国内地址:某些云服务商会把新申请的 IP 段划归特定地区,如果 GeoIP 数据库没有及时收录这次划分,新服务的连接可能被
GEOIP,CN规则错误地判定为境内 IP,走了直连,导致连接超时或访问失败。 - 规则集写对了但完全不命中:引用某个分类的 GeoSite 规则集(例如按流媒体或社交应用分类),如果该分类近期新增了域名而数据库未更新,新增域名会绕过规则集,落到默认策略,表现为"同一个应用,部分功能走代理,部分直连"。
- 国内网站偶发性走代理:反过来,如果某个 IP 段被云厂商收回或转让给境外主体,旧数据库仍标记为境内,会导致本该直连的网站被错误地推入代理出口,速度明显变慢。
- 延迟测试正常但实际访问异常:节点延迟测试走的是固定测速地址,不经过完整的域名/IP 分流判断,所以数据库过旧引发的问题往往在节点测速阶段完全不可见,只有真实访问业务域名时才会暴露。
如果最近没有改动过任何规则或订阅,但某些网站突然分流异常,先怀疑 GeoIP/GeoSite 数据库版本,而不是急着重写规则——多数情况下规则本身没有问题。
手动替换数据库文件
手动替换是最直接、最可控的方式,适合排查阶段确认问题,或者对自动更新机制不放心的场景。核心步骤只有三步:找到内核的数据目录、下载最新数据库文件、重启内核使其重新加载。
- 确认数据目录位置:mihomo 内核默认会在其工作目录下查找
Country.mmdb与geosite.dat(或对应的.metadb格式)。桌面端一般在配置目录同级,iOS 客户端通常在应用内的规则/数据管理页面单独列出这两项,不需要手动定位文件系统路径。 - 获取最新数据库:数据库随 mihomo 相关开源项目的规则集仓库持续维护并发布更新,发布节奏通常是数周一次,遇到 IP 段大范围调整或热门域名迁移时会有针对性的补丁版本。
- 替换并重启:用新文件覆盖旧文件后,必须完整重启内核(重载配置通常不会重新加载数据库文件),否则内存中仍是旧版本的映射表,替换动作不会生效。
如果客户端提供了图形化的"更新 GeoIP/GeoSite"按钮,优先使用该入口,它会自动处理文件校验与重启流程,比手动操作文件系统更不容易出错。
配置内自动更新的两种方式
手动替换终究是被动的,更推荐的是在配置里开启自动更新,让内核按周期自查。mihomo 提供了两层可以分别设置的更新机制。
第一层:内核级 GeoIP/GeoSite 自动更新
这一层控制的是内核内置的地理数据库本身,在配置文件顶层设置:
geodata-mode: true
geo-auto-update: true
geo-update-interval: 24
geox-url:
geoip: "https://example-mirror.invalid/country.mmdb"
geosite: "https://example-mirror.invalid/geosite.dat"
geo-update-interval 的单位是小时,决定内核每隔多久检查一次远端是否有新版本;geox-url 可以指向自建或第三方镜像地址,加速下载或规避访问不稳定的问题。开启后无需人工干预,内核会在后台静默完成更新。
第二层:规则集(rule-providers)的独立更新
如果分流规则用的是外部规则集而不是内核内置的 GeoSite 分类,更新周期要单独在每个 rule-provider 里声明:
rule-providers:
reject-list:
type: http
behavior: domain
url: "https://example-mirror.invalid/reject.txt"
path: ./rules/reject.yaml
interval: 86400
interval 单位是秒,86400 即一天一次。规则集与内核自带的 GeoIP/GeoSite 是两套独立的更新通道,只开启一边并不能覆盖另一边,这也是"更新了数据库但规则仍然不准"的常见原因之一。
自动更新依赖客户端在后台保持运行或按计划唤醒,长期不启动客户端的设备,建议结合手动更新入口定期检查一次。
更新后如何验证生效
替换文件或改完配置之后,不要凭感觉判断"应该好了",而是走一套可复现的验证流程。
- 查看启动日志:内核重启时会打印数据库加载信息,包括文件路径与记录条数,如果日志里出现下载失败或文件校验异常的提示,说明更新并未真正落地,规则仍在用旧数据。
- 用已知边界地址测试:挑选一个最近确认发生过归属变化的域名或 IP,分别在更新前后测试其分流结果,如果出口策略发生了预期中的变化,说明新数据库确实被加载并参与了匹配。
- 核对规则集条目数:部分客户端的规则管理界面会显示每个规则集当前包含的域名或 IP 条数,更新前后条数明显变化,是数据库确实刷新的直接证据。
- 清空连接缓存后重测:一些内核会对已建立的连接结果做短时缓存,验证前先断开重连或重启客户端,避免被旧缓存结果干扰判断。
验证环节看似繁琐,但比"更新完就当结束"更能避免反复排查同一个问题——数据库相关的分流异常往往隐蔽且滞后,提前建立一套验证习惯,能省下大量后续的日志翻查时间。
规划一个可持续的更新节奏
对绝大多数使用场景而言,开启内核级自动更新并设置 12~24 小时的检查间隔已经足够,没有必要追求分钟级的实时同步,GeoIP 与 GeoSite 数据库的上游发布节奏本身也不支持这种频率。如果观察到分流问题反复出现在同一类服务上,更值得做的是针对性地检查该分类对应的规则集来源是否仍在维护,而不是无限缩短更新间隔。数据库更新只是分流准确性的其中一环,配合定期查看运行日志、留意规则匹配结果,才能把偶发的分流偏差控制在最小范围。