#2986·OpenList

[BUG] PikPak 上传 no such host:OSS endpoint 落在 .net 侧(无任何 DNS 记录),附取证与已验证修法

Author: WolfeOvOCreated Aug 28, 2026Updated Sep 6, 2026

请确认以下事项

  • 我已确认阅读并同意 AGPL-3.0 第15条。
  • 我已确认阅读并同意 AGPL-3.0 第16条。
  • 我确认我的描述清晰,语法礼貌,能帮助开发者快速定位问题,并符合社区规则。
  • 我已确认阅读了 OpenList 文档。
  • 我已确认没有重复的问题或讨论。
  • 我已确认是 OpenList 的问题,而不是其他原因(例如网络,依赖或操作)。
  • 我认为此问题必须由 OpenList 处理,而非第三方。
  • 我已确认这个问题在最新版本中没有被修复。
  • 我没有阅读这个清单,只是闭眼选中了所有的复选框,请关闭这个 Issue。

OpenList 版本(必填)

v4.2.5

使用的存储驱动(必填)

PikPak(账号挂载,非 PikPakShare)

问题描述(必填)

上传文件到 PikPak 挂载时失败,报被分配到一个 DNS 中不存在的上传节点域名:

failed put /PikPak/: Post "http://vip-lixian-07.mypikpak.net/upload_tmp%2F<key>?uploads":
failed to resolve host: vip-lixian-07.mypikpak.net: lookup vip-lixian-07.mypikpak.net on 127.0.0.11:53: no such host

这与已关闭的 #2431 属于同一类问题(#2431 被以「偶发」结案,但在我的环境里是稳定必然失败, 每次上传都复现),相关 PR #2862 仍处于 open。

本 issue 的目的:补充可复现的 DNS/OSS 取证,并说明 #2862 的剥前缀方案只能覆盖 .com 那一种 endpoint 形态、对 .net 形态无效,同时给出一个已验证可用的修法。

根因

PikPak 的 files 接口在 resumable.params 中返回:

  • bucket = vip-lixian-07
  • endpoint = vip-lixian-07.mypikpak.net

drivers/pikpak/util.go 里两处上传都把它交给 aliyun OSS SDK:

go
// UploadByOSS (util.go:422)
ossClient, err := netutil.NewOSSClient(params.Endpoint, ...)
// UploadByMultipart (util.go:455)
if ossClient, err = netutil.NewOSSClient(params.Endpoint, ...); err != nil {

OSS SDK 默认 virtual-hosted 风格,会把请求打到 <bucket>.<endpoint>。 而 mypikpak.net 这一侧任何子域都没有 DNS 记录,因此无论是否剥掉节点前缀都必然 no such host

bash
# 目标 hostname:5 家公共 DNS 结果一致
$ for d in 8.8.8.8 1.1.1.1 223.5.5.5 119.29.29.29 9.9.9.9; do
    dig @$d vip-lixian-07.mypikpak.net | grep -o "status: [A-Z]*"; done
status: NXDOMAIN
status: NXDOMAIN
status: NXDOMAIN
status: NXDOMAIN
status: NXDOMAIN

# 不存在泛解析(随便一个子域同样 NXDOMAIN)
$ dig @8.8.8.8 zzzrandom123.mypikpak.net | grep -o "status: [A-Z]*"
status: NXDOMAIN

# 权威 NS 明确返回 NXDOMAIN(不是解析器问题)
$ dig @8.8.8.8 vip-lixian-07.mypikpak.net | grep -A1 "AUTHORITY SECTION"
;; AUTHORITY SECTION:
mypikpak.net.   586  IN  SOA  ns1.alidns.com. hostmaster.hichina.com. ...

# apex 本身能解析,但它是 nginx 网关,不是 OSS 端点
$ dig +short @8.8.8.8 mypikpak.net
43.160.170.196
$ curl -s -D- -o /dev/null -X POST "http://mypikpak.net/upload_tmp%2Fprobe?uploads"
HTTP/1.1 301 Moved Permanently
Location: https://mypikpak.net/upload_tmp%2Fprobe?uploads
via: 23.140.244.74, 23.140.244.74
# 响应体为 nginx 的 301 页面,无任何 x-oss-* 头

节点前缀本身是真实存在的,但它属于 .com 一侧,并且被 OSS 认作 CNAME 绑定桶:

bash
$ dig @8.8.8.8 vip-lixian-07.mypikpak.com
vip-lixian-07.mypikpak.com. 600 IN CNAME vip-lixian-07.oss-ap-southeast-1.aliyuncs.com.
vip-lixian-07.oss-ap-southeast-1.aliyuncs.com. 60 IN A 47.79.49.2
vip-lixian-07.oss-ap-southeast-1.aliyuncs.com. 60 IN A 47.79.49.3
vip-lixian-07.oss-ap-southeast-1.aliyuncs.com. 60 IN A 47.79.49.4

# .com 主机名被 OSS 正确当作 vhost 解析:403 AccessDenied(仅缺凭据),
# 响应里没有 <BucketName>,说明桶已解析成功,不是「桶不存在」
$ curl -s -D- -X POST "https://vip-lixian-07.mypikpak.com/upload_tmp%2Fprobe?uploads"
HTTP/1.1 403 Forbidden
Server: AliyunOSS
x-oss-request-id: 6A91C54C0A93063234AB990F

<?xml version="1.0" encoding="UTF-8"?>
<Error>
  <Code>AccessDenied</Code>
  <Message>Anonymous user has no right to access this object.</Message>
  <HostId>vip-lixian-07.mypikpak.com</HostId>
  <EC>0003-00000002</EC>
</Error>

关于 PR #2862:能修 .com 变体,但修不了 .net 变体

需要先说明清楚:#2862 的思路对 #2431 报告的那个 case 是有效的,我不是来否定它的。 但服务端返回的 endpoint 至少有两种形态,剥前缀只对其中一种奏效:

服务端返回的 endpoint #2862 剥前缀后 SDK 拼出的 host 解析结果
upload-a10b.mypikpak.com(#2431) mypikpak.com vip-lixian-07.mypikpak.com ✅ NOERROR
vip-lixian-07.mypikpak.net(本例) mypikpak.net vip-lixian-07.mypikpak.net ❌ NXDOMAIN

第二行的结果与 v4.2.5 现有的 if Platform == "android" { params.Endpoint = "mypikpak.net" } 完全等价,因此 .net 这种返回值在 #2862 合并后依然会失败。

换句话说,问题的关键不在于「有没有节点前缀」,而在于落到哪个顶级域.com 一侧的 <bucket>.mypikpak.com 有 CNAME 且被 OSS 认作绑定桶,.net 一侧没有任何子域记录。

另外,「把 *.mypikpak.net 在本地 DNS/hosts 指向 OSS IP」这类绕行同样不可行 —— 强制指过去后 OSS 会退化成 path-style 解析,把对象 key 的第一段当成桶名:

bash
$ curl -s -X POST --resolve "vip-lixian-07.mypikpak.net:80:47.79.49.2" \
    "http://vip-lixian-07.mypikpak.net/upload_tmp%2Fprobe?uploads"
<Error><Code>NoSuchBucket</Code>
  <BucketName>upload_tmp</BucketName>
  <HostId>vip-lixian-07.mypikpak.net</HostId></Error>

建议修法

把 OSS endpoint 换到 .com 一侧,不再区分 platform:

go
params := resp.Resumable.Params
params.Endpoint = "mypikpak.com"

这样 SDK 拼出 vip-lixian-07.mypikpak.com,既可解析、又被 OSS 认作 CNAME 绑定桶。

影响范围:普通上传与分片上传都会失败

UploadByOSS(≤10MB)与 UploadByMultipart(>10MB)使用 params.Endpoint, 因此这不是「仅大文件受影响」。我的日志里两条路径都有真实失败记录,可通过请求形态区分:

  • Put "http://.../upload_tmp%2F<key>"(无 ?uploads)→ UploadByOSSbucket.PutObject
  • Post "http://.../upload_tmp%2F<key>?uploads"UploadByMultipartInitiateMultipartUpload

小文件在实践中较少暴露,可能是因为常命中秒传(resp.Resumable == nil 时直接返回,不走 OSS)。

日志(必填)

普通上传路径(UploadByOSS,注意是 Put 且无 ?uploads):

ERRO[2026-08-20 06:04:48] failed put /PikPak/: Put "http://vip-lixian-07.mypikpak.net/upload_tmp%2F012ADE5B9AD146E828D8F4E6513BAF9CA265301D_1787205892715198485": failed to resolve host: vip-lixian-07.mypikpak.net: lookup vip-lixian-07.mypikpak.net on 127.0.0.11:53: no such host

分片上传路径(UploadByMultipartPost + ?uploads):

ERRO[2026-08-28 16:23:53] failed put /PikPak/: Post "http://vip-lixian-07.mypikpak.net/upload_tmp%2FE9E033F252F36419DDCAE3E559824F2A2108E6CB_1787934249207321649?uploads": failed to resolve host: vip-lixian-07.mypikpak.net: lookup vip-lixian-07.mypikpak.net on 127.0.0.11:53: no such host

127.0.0.11:53 是 Docker 内置 DNS;已验证在宿主机及 5 家公共 DNS 上结果一致,见上文。)

配置文件内容(必填)

存储驱动配置(已脱敏):

json
{
  "mount_path": "/PikPak",
  "driver": "PikPak",
  "addition": {
    "platform": "android",
    "root_folder_id": "",
    "disable_media_link": false
  }
}

platformandroidwebpc 均无法规避此问题:android 分支把 endpoint 改写为 mypikpak.net 后拼回去仍是不存在的域名;切换到 web/pc 在我的环境下会触发 ErrorCode: 4002 captcha_invalid / captcha_token expired 使存储变为不健康状态。

验证情况

我在本地按上述建议改动(params.Endpoint = "mypikpak.com")自行编译 v4.2.5 后, 先在隔离实例上验证,再上线验证,上传恢复正常:

  • 20 MiB:PUT 返回 code=200
  • 120 MiB:PUT 返回 code=200,耗时 38.0s(约 3.16 MiB/s)
  • fs/listrefresh:true 回读,云端 size = 125829120,与本地文件字节数完全一致

如果维护者认可这个方向,我可以提一个 PR。

复现链接(可选)

AI生成内容(可选)

  • 本 Issue 包含 AI 辅助整理的内容(取证命令与结论均由我在真实环境执行并核对)。