树莓派ipv6穿透网站
把树莓派扔进 IPv6 环境里,树莓它能直接拿到一个公网地址。穿透这不是网站什么黑科技,是树莓 IPv6 的设计本意——地址多到用不完,每台设备都能有自己的穿透门牌号。问题在于,网站运营商给你的树莓那串前缀,通常每 24 小时或者每次重拨都会变。穿透你昨天记下的网站 240e:390:... 开头的地址,今天可能就失效了。树莓所以真正要解决的穿透,不是网站“能不能通”,而是树莓“怎么让域名始终指向那台派”。
先确认你的穿透派到底有没有 IPv6
SSH 进去,敲 ip -6 addr show。网站如果看到 scope global 的地址,且不是 fe80:: 开头,恭喜,你已经有公网 IPv6 了。但别急着高兴——很多家用路由器默认开启 IPv6 防火墙,外部流量根本进不来。我手头这台华硕 AX86U,默认策略就是“允许内网出、阻止外网入”。你得手动放行。
放行方式分两种。如果你的路由器支持 IPv6 防火墙规则,直接加一条:允许目标端口 443 或 22 的入站连接。如果不支持,那就把派设为 DMZ 主机——粗暴,但有效。代价是派完全暴露在公网扫描之下,所以 SSH 别用密码,换密钥。
DDNS 是绕不开的坎
IPv6 地址太长,没人记得住。你需要一个域名,加上动态解析。Cloudflare 的 API 是最省事的方案,免费,TTL 可以设到 60 秒。写个 Python 脚本,每 5 分钟跑一次:读取 ip -6 addr 里的全局地址,调 Cloudflare API 更新 AAAA 记录。
但这里有个坑:树莓派可能有多个 IPv6 地址。一个来自 SLAAC 的临时隐私地址,一个稳定的 EUI-64 地址。你要取的是后者——通常以 240e 或 2409 开头,接口标识不是随机的。用 ip -6 addr show dev eth0 | grep 'scope global' | grep -v 'temporary' 过滤。临时地址每几小时换一次,拿它做 DDNS 纯属自找麻烦。
curl -s -X PUT "https://api.cloudflare.com/client/v4/zones/ZONE_ID/dns_records/RECORD_ID" \ -H "Authorization: Bearer TOKEN" \ -H "Content-Type: application/json" \ --data '{ "type":"AAAA","name":"pi.example.com","content":"'$NEW_IP'","ttl":60}' 把这段塞进 crontab,*/5 * * * *。跑通之后,dig AAAA pi.example.com 应该返回你派上的地址。
HTTPS 和反代
直接暴露 80 端口太糙。Caddy 是首选——自动申请 Let's Encrypt 证书,配置两行搞定。但 Let's Encrypt 的 HTTP-01 验证需要 80 端口可达,而 IPv6 环境下有些运营商会封 80。那就用 DNS-01 验证,Cloudflare 插件支持。
Caddyfile 长这样:
pi.example.com { reverse_proxy localhost:8080 } 重启 Caddy,证书自动签发。现在你从外面访问 https://pi.example.com,流量直接打到派上的 8080 服务。全程不经过任何内网穿透工具,没有 frp,没有 ngrok,没有 Tailscale。就是纯 IPv6 直连。
实际体验和坑
我在移动宽带下测试,延迟比走 IPv4 中转低了 20ms 左右。但问题也很明显:公司网络、部分公共 WiFi 根本没开 IPv6。这时候你的域名解析出来是 AAAA,客户端连不上,直接超时。解决办法是同时保留 IPv4 的穿透方案作为 fallback,或者用 Cloudflare 的代理模式——它同时支持双栈接入。
另一个坑是前缀变化。有些运营商不只是换地址,连前缀长度都变。比如从 /64 变成 /56,你路由器下的设备地址全变。DDNS 脚本得能处理这种情况,不能只替换接口标识部分。
树莓派本身功耗低,常年跑着不心疼。但 SD 卡容易坏,建议把日志和 DDNS 脚本放 tmpfs,或者挂个 U 盘。我第一块卡就是这么写坏的——每天几百次 API 调用,三个月后文件系统只读。
这套方案适合谁?有 IPv6 公网、愿意折腾、不想把流量交给第三方穿透服务的人。如果你家宽带只有 IPv4 内网地址,那还是老老实实 frp 或者 WireGuard 吧。IPv6 穿透不是万能药,它只是把“没有公网 IP”这个问题,换成了“有公网 IPv6 但对方不一定能连”。