背景
我的博客是静态页面,托管在 Cloudflare Pages,域名解析也在 Cloudflare。 评论区用的是 Twikoo,后端单独部署在 Netlify Functions。
页面和评论是两条路:
blog.zery.cn -> Cloudflare Pages -> 博客页面 twikoo.zery.cn -> Netlify Function -> Twikoo 评论后端
后面才发现,这点很重要。因为评论区显示哪个 IP、显示不显示属地,主要看 twikoo.zery.cn 这个后端域名最后把什么 IP 交给了 Twikoo,和博客页面本身是不是走 IPv6、是不是套 CDN 不是一回事。
一开始以为是 CDN 的锅
最早的问题是评论 IP 属地会乱跳,有时是香港,有时是美国。这个现象很迷惑,因为手机没有挂代理,流量显示美国就明显不对了。
当时链路大概是:
访客 -> Cloudflare / 其他 CDN -> Netlify Function -> Twikoo
这种情况下,Netlify 有可能看到的是 CDN 节点 IP。然后Twikoo 拿节点 IP 去查属地,显示香港、美国就不奇怪了。
所以第一步先直接查验后端收到的 header。
const headers = [ 'cf-connecting-ip', 'x-real-ip', 'x-forwarded-for', 'x-nf-client-connection-ip', ]
手机访问时,看到过类似这样的结果:
{
"cf-connecting-ip": "2409:8938:****:****:****:****:****:****",
"x-forwarded-for": "2409:8938:****:****:****:****:****:****, 162.158.*.*, 50.18.*.*",
"x-nf-client-connection-ip": "162.158.*.*"
}
这里其实已经很清楚了。前面的 2409:... 是手机真实 IPv6,后面的 IPv4 是中间节点。
这时如果为了让属地显示出来,取 x-forwarded-for 后面的 IPv4,确实可能有结果,但它只是 CDN 或云平台节点的归属地。
关掉小黄云后,问题没有结束
后来把 Cloudflare 小黄云关了,按理说 CDN 节点这层干扰没了。
再看 header,变成了这样:
{
"cf-connecting-ip": "",
"x-forwarded-for": "2409:8938:****:****:****:****:****:****, 54.254.*.*",
"x-nf-client-connection-ip": "2409:8938:****:****:****:****:****:****"
}
这次 Netlify 拿到的已经是真实客户端 IP,但它是 IPv6。
问题就从“拿到的是不是本人 IP”,变成了“Twikoo 能不能查这个 IPv6 的属地”。实际表现是:Twikoo 对这个 IPv6 查不出来,于是评论区属地直接空了。
别人同样 Twikoo 却可以显示
对照了一个同样用 Twikoo 的站。奇了怪了,发现它能显示,但这不代表它一定改了 Twikoo 后端,比如额外加了 IPv6 属地库。
更可能的区别在 DNS。
它的评论后端没有 AAAA 记录,只能走 IPv4:
comment.example.com A x.x.x.x comment.example.com AAAA none
手机访问它的评论后端时,最后进后端的就是 IPv4。Twikoo 查 IPv4 没问题,属地自然能出来。
这也是我最后采用的办法:让评论后端只走 IPv4。
域名 DNS 怎么改
在 Cloudflare DNS 里改 twikoo 这条记录:
Type: A Name: twikoo IPv4 address: 75.2.60.5 Proxy status: DNS only
然后确认这几件事:
没有 AAAA 没有 CNAME 小黄云关闭
可以用 DNS-over-HTTPS 查一下,避免本地代理或者 Fake-IP 影响判断:
Invoke-RestMethod `
-Uri "https://cloudflare-dns.com/dns-query?name=twikoo.zery.cn&type=A" `
-Headers @{ accept = 'application/dns-json' }
Invoke-RestMethod `
-Uri "https://cloudflare-dns.com/dns-query?name=twikoo.zery.cn&type=AAAA" `
-Headers @{ accept = 'application/dns-json' }
这边最终期望是:
A 75.2.60.5 AAAA none
DNS 生效后,再用手机流量发一条新评论。
新的 header 应该接近这样:
{
"x-forwarded-for": "183.217.*.*, 3.1.*.*",
"x-nf-client-connection-ip": "183.217.*.*"
}
这时 Twikoo 拿到的是 IPv4,归属地就能正常显示。

评论区
评论加载中...