NoAnyLoc 审计报告(AI读的)
一、项目功能
宿主机级“防送中”防火墙脚本(单文件 bash,1230 行,v2.3,纯 IPv4/IPv6 iptables + ipset,无其他依赖文件)。解决的问题:国内买家手机连代理节点时,GMS 等后台把周围 Wi-Fi BSSID/基站 ID 发给 geolocation.googleapis.com 等定位 API,Google 会把“海外 VPS IP + 中国 Wi-Fi MAC”关联起来,导致 VPS 的 IP 被 Google 判定为大陆位置(“送中”),IP 就废了。此脚本在母机(PVE/LXD 宿主机)的 FORWARD/OUTPUT 链上把所有定位 API 出网流量一票否决,覆盖母机下全部容器/小鸡,容器内用户无法绕过也清不掉。
功能清单:start/stop/restart/update/stats/test/uninstall 子命令 + 交互菜单;定时刷新 IP 池(systemd timer 默认 2h,无 systemd 退回 crontab);IP 原子热替换(ipset swap);拦截计数面板(读 iptables 计数器);“体检”功能(Google 跳转/底栏地区、YouTube countryCode、Cloudflare trace、自测拦截是否生效);自更新;卸载自清理。
二、实现机制(已逐行核实)
七层 SNI 熔断(核心巧思):对 Google 定位域名(与 Play 商店共享 Anycast IP,无法按 IP 拦)用 iptables -m string 在 443/80 报文里匹配 TLS Client Hello 的明文 SNI 字符串(geolocation.googleapis.com、.ls.apple.com 等 14 条),命中直接 REJECT + tcp-reset。所以敢拦 Google 定位而不误伤 Play。
四层 IPSet:对有独立 IP 的定位服务(Apple gs-loc、Mozilla MLS、微软、Skyhook 等 11 个域名)并发 dig 4 路公共 DNS 解析出 IP 填入 hash:ip 集合,TCP 回 RST、UDP/ICMP 回 port-unreachable。配置文件在 /etc/noanyloc/domains.conf,可自行增删;含 googleapis.com 的条目会被强制转入 SNI 引擎防止误杀 Play。
挂载点:iptables -I FORWARD 1 + iptables -I OUTPUT 1 跳转到自定义 NOANYLOC 链,不动 PVEFW/Docker/NAT 既有规则。
持久化:systemd oneshot(开机 start)+ timer(定时 update);ipset save 只备份自己两个集合。
失效保护:DNS 全挂时沿用本地缓存 IP,不空转。
三、后门审计结论:未发现后门
对全部 1230 行做了特征扫描 + 逐行人工过读(commit e3658d5,单提交,作者“大表哥”):
无反弹 shell / 隐匿通道:无 /dev/tcp、nc -e、socat、mkfifo、bash -i。
无凭据/敏感数据窃取:不碰 .ssh、authorized_keys、shadow、history、.netrc、任何 token/key;无任何 POST/上传(所有 curl 均为 -s 只读 GET)。
无混淆:无 base64/hex 编码载荷、无 eval。
所有外联均可解释:IP 查询(api.ipify.org/ip.sb/ipinfo.io——只取本机公网 IP 归属地展示)、体检探测(Google/YouTube/Cloudflare)、DNS 解析(1.1.1.1/8.8.8.8/9.9.9.9/OpenDNS)、自更新(raw.githubusercontent.com,备用镜像 ghfast.top)。无遥测、无上报。
apt 安装的只有 ipset/iptables/iproute2/curl/dnsutils/ca-certificates,无夹带。
持久化透明:只写自己的 3 个 systemd unit 和自己的 crontab 行,卸载时全部撤销并 rm -rf /etc/noanyloc + 删自身,干净。
自更新是唯一供应链风险面(今后新版可能变恶意),但有弱校验兜底:下载后必须同时含 NOANYLOC 和 check_os 字样才覆盖安装。这挡不住真正的恶意更新,只能挡内容错乱——这是所有“curl | bash”类工具的通病,不算本项目的后门。
四、非恶意的缺陷/风险(使用前须知)
SNI 匹配是裸字符串:--string "location.services.mozilla.com" 理论上可被证书指纹/非常规分片等手段规避,且拦截效果依赖客户端用明文 SNI(若走 ECH 或域名前置则失明)。IPSet 名单同理会随 DNS 解析漂移漏拦——所以才需要 2h 定时刷新。属于“尽力拦截”,不是 100% 铁闸,README 宣传有水分。
--algo bm 全端口 443/80 逐包扫串:规则 14 条 × 双栈,大流量宿主机上有可测的 CPU 软中断开销(README 声称“零损耗”不实);嫌耗性能可在菜单关掉 SNI(会失去 Google 定位拦截)。
裸字符串匹配误伤可能:任何 443 报文载荷中恰好含有这些子串都会被 RST(如 SNI 为 evil.locationhistory.example.com 会被 locationhistory 规则误杀),概率低但存在。
source ${CONFIG_FILE} 无校验:root 可写的本地文件,被本机其他 root 进程篡改可注入命令——本地威胁模型下无意义,仅记录。
统计口径:“拦截次数”=包计数不是“次数”,一次被拦的 HTTPS 会话重试会累计多包,面板数字偏乐观。
五、结论
功能与宣传一致,实现干净,没有后门、没有数据外传、没有隐藏持久化。风险仅在于 curl|bash 的固有供应链模式 + 未来版本不可控。若要在生产母机用,建议不用一键管道,clone 下来人工过一遍再 bash noanyloc.sh,并锁定版本不做在线升级;