家里宽带只有公网 IPv6、没有公网 IPv4,出门在外遇到纯 IPv4 的网络(公司内网、部分酒店、老热点)就打不开家里的 Lucky / Emby。这篇文章记录我用一台阿里云杭州 VPS + Realm 四层转发做的方案:有 IPv6 就直连家里,没 IPv6 才走 VPS 中转,VPS 只当一根「透明管道」,证书和域名分流全部留在家里。
一、目标与架构
核心诉求有四条:
1、同一个域名,有 IPv6 的网络直连家庭宽带,跑满家宽上行,不消耗 VPS 带宽;
2、纯 IPv4 的网络自动回落到 VPS,由 VPS 通过 IPv6 回源到家里的 Lucky;
3、家里不额外常驻穿透客户端(不要 frpc 那种心跳进程);
4、一套配置支持多个域名、多个服务。
┌─ 有 IPv6 的客户端 ──(AAAA)──→ 家庭宽带 IPv6:8443 ─┐
DNS 双栈解析 ──────┤ ├─→ Lucky ─→ 内网服务
└─ 只有 IPv4 的客户端 ─(A)──→ 阿里云 VPS:8443 ─Realm─┘
(VPS 通过 IPv6 回源到家庭 DDNS 域名:8443)
关键点:Realm 做的是四层 TCP 透传,不解密 TLS、不碰证书,Lucky 依然是唯一的 TLS 终点和域名分流点。
二、为什么是这套方案
1、四种中转思路的取舍
| 方案 | 思路 | 评价 |
|---|---|---|
| DNS 双栈 + VPS IPv6 回源 | A 记录指 VPS、AAAA 指家庭,VPS 四层转发回家庭 IPv6 | ✅ 最终选择:无家庭端常驻进程、开销最低、直连时零成本 |
| FRP 穿透 | frps + frpc 长连接隧道 | 成熟,但家里要多跑一个守护进程,且默认所有流量都绕 VPS 小水管;端口不对等时才必需 |
| WireGuard / Tailscale 组网 | VPS 与家组虚拟内网,再反代 | 最安全,适合只在自有设备上管理;但要装客户端、组网配置繁琐 |
| Cloudflare 回源 | CF 边缘节点 IPv6 回源家庭 | 国内访问绕海外,延迟抖动明显,不适合 |
一句话选型:VPS 有公网 IPv6 → 双栈 + 回源;VPS 只有 IPv4 → 只能上 FRP。
2、四层转发工具:Realm / GOST / Nginx
| 工具 | 内存 | 动态 DNS 重解析 | 定位 |
|---|---|---|---|
| Realm | 1~3 MB(Rust) | ✅ 原生 schedule = “30s” 定时重解析 | 纯四层转发,专为此场景而生 |
| GOST | 15~30 MB(Go) | ✅ 每次建连重查 DNS | 多协议万金油,日后想加混淆/WSS 更方便 |
| Nginx | 30~60 MB+ | ⚠️ 需 resolver + 变量写法,否则只解析一次 | 七层反代重型武器,拿来纯透传大材小用 |
选 Realm 的决定性理由:家宽 IPv6 前缀24~48 小时会变一次,如果转发进程只在启动时解析一次域名,一次重拨就让中转彻底失效。Realm 的 schedule 能自动跟着变,且实测常驻内存 2.3 MB。
三、前置条件
1、一台阿里云杭州 ECS(本文以 Debian/Ubuntu 为例,root 操作);
2、该实例已开通 IPv6 出网能力(VPC + 网卡免费分配 IPv6,并开通 IPv6 公网带宽);
3、家里的 Lucky 已能正常工作:DDNS 会更新 AAAA、有可用证书、Web 规则监听如 8443;
4、家庭侧光猫/路由器放行对应端口的 IPv6 入站;
5、一个域名(本文用 example.com 代指,回源域名用 v6.example.net)。
四、动手实操
Step 0 确认 VPS 能走 IPv6(最容易漏的一步)
ip -6 addr show # 是否有 2408: 开头的公网 IPv6
ping6 -c 3 2400:3200::1 # 阿里 DNS 的 v6 地址
curl -6 -sI https://ipv6.google.com | head -1
不通就先去控制台开通 IPv6 公网带宽——这一步没做,后面 Realm 永远连不上家里。
Step 1 阿里云安全组放行端口
路径:ECS 实例 → 安全组 → 配置规则 → 入方向 → 手动添加
协议类型:TCP
端口范围:8443(业务)、16601(Lucky 控制台,按需)
授权对象:0.0.0.0/0
注意:阿里云安全组是独立于系统防火墙的一道墙,系统的 ufw/firewalld 放行了但安全组没放,一样连不上。
Step 2 安装 Realm
cd /tmp
curl -LO https://github.com/zhboner/realm/releases/latest/download/realm-x86_64-unknown-linux-musl.tar.gz
tar -xvf realm-x86_64-unknown-linux-musl.tar.gz
chmod +x realm
mv realm /usr/local/bin/
mkdir -p /etc/realm
realm -v # 能输出版本号即成功
ARM 机器(比如倚天实例)把文件名里的 x86_64 换成 aarch64。
Step 3 写配置 /etc/realm/config.toml
[network]
no_tcp_check = false
# 业务端口:VPS 8443 → 家里 Lucky 8443
[[endpoints]]
listen = "0.0.0.0:8443"
remote = "v6.example.net:8443"
schedule = "30s"
# Lucky 控制台(可选,建议也走中转)
[[endpoints]]
listen = "0.0.0.0:16601"
remote = "v6.example.net:16601"
schedule = "30s"
要点:
1、listen 端口必须与家里 Lucky 的监听端口一致,原因见下面 5.2;
2、remote 填只解析 AAAA 的回源域名,原因见下面这条坑;
3、schedule 是灵魂参数:每 30 秒重解析一次,家宽 IPv6 变了自动跟上,无需重启。
⚠️ 回源域名必须是「纯净」的 AAAA 记录
如果给 *.example.com 同时加了 A 和 AAAA,那 v6.example.com 也会继承泛解析的 A 记录(指向 VPS 自己),Realm 可能解析到 VPS 本机端口,形成自环。稳妥做法二选一:
① 回源域名用另一个域名(如 v6.example.net),只加 AAAA;
② 或保留独立 AAAA 记录,并确认该子域不被泛解析的 A 记录覆盖(先用 dig A v6.example.com 验证为空)。
新版 Realm 启动日志里会打印 ipv6-only 选项,可强制只连 IPv6,具体键名以你所用版本文档为准。
Step 4 systemd 常驻
cat <<'EOF' > /etc/systemd/system/realm.service
[Unit]
Description=realm
After=network.target network-online.target
Wants=network-online.target
[Service]
Type=simple
User=root
ExecStart=/usr/local/bin/realm -c /etc/realm/config.toml
Restart=on-failure
RestartSec=5s
[Install]
WantedBy=multi-user.target
EOF
systemctl daemon-reload
systemctl enable --now realm
systemctl status realm
正常的启动日志长这样:
Active: active (running) ...
Memory: 2.3M
realm[xxxx]: dns: mode=ipv4_and_ipv6, protocol=tcp+udp, min-ttl=0, max-ttl=86400, cache-size=32
realm[xxxx]: inited: 0.0.0.0:8443 -> [v6.example.net:8443]; options: ipv6-only=false, ...
看到 inited: … -> [v6.example.net:8443] 就说明监听与回源映射已经建立。
Step 5 域名双栈解析
主访问域名(*.example.com)——两条记录并存:
| 类型 | 主机记录 | 值 | 谁维护 |
|---|---|---|---|
| AAAA | * | 家庭宽带 IPv6 | Lucky DDNS 自动更新 |
| A | * | 阿里云 VPS 公网 IPv4 | 固定不变 |
回源域名(v6.example.net)——只加 AAAA:
| 类型 | 主机记录 | 值 | 谁维护 |
|---|---|---|---|
| AAAA | v6 | 家庭宽带 IPv6 | Lucky DDNS 自动更新 |
Lucky 侧的 DDNS 任务域名列表直接填 *.example.com 和 v6.example.net 即可,泛解析省掉逐个服务配置。
⚠️ Cloudflare 用户必须关掉小黄云:代理模式会把两条记录都变成 CF 的 Anycast IP,客户端就再也无法自己决定走 IPv6 直连了,必须设为 DNS only。
Step 6 验证链路
① VPS 端口在听
ss -tulpn | grep 8443
# 0.0.0.0:8443 LISTEN ... users:(("realm",pid=...))
② 造一个纯 IPv4 环境(手机和公司网往往都已经是 IPv6,会直接直连,测不出中转)
Windows:网卡属性 → 取消勾选「Internet 协议版本 6 (TCP/IPv6)」→ 刷新浏览器访问。
③ 判断到底走了哪条路
· 看 Lucky 日志(最直观):来源 client_ip / direct_ip 是客户端自己的 IPv6(如手机蜂窝 240e:…)→ IPv6 直连;是阿里云机房的 IPv6 段(2408:…)→ 走了 VPS 中转。
· 看 VPS 连接:ss -tuna | grep 8443,直连时没有任何 ESTAB;中转时会出现成对连接(客户端 IPv4 → VPS,VPS → 家庭 IPv6)。
· VPS 抓包:tcpdump -nn -i any port 8443,页面刷新一片安静 = 直连;疯狂刷包 = 中转。
· 浏览器侧:F12 → Network → 打开 Remote Address 列,[…]:8443 是 v6,VPS_IP:8443 是中转。
五、几个必须知道的技术细节
1、客户端凭什么「优先 IPv6」?
不需要任何客户端配置,靠的是操作系统的 Happy Eyeballs(RFC 8305):同时查 A / AAAA,优先向 AAAA 发 SYN,并挂一个 100~300 ms 的计时器;IPv6 秒通则全速直连,没有 IPv6 或握手超时才无感切到 A 记录(VPS)。实测手机蜂窝网络和公司网络都命中了 AAAA,直接打回家里的光猫。
2、两端端口必须一模一样
DNS 只负责把域名翻译成 IP,不能按端口分流。所以「IPv6 直连」和「VPS 中转」必须用同一个端口(本文统一 8443)。想做到「外面用标准 443、家里用 8443」这种端口不对等,四层双栈方案做不到,只能退回 FRP 做端口重映射。
3、真实客户端 IP 会丢
Realm 是四层透传,Lucky 看到的来源永远是阿里云 VPS 的 IPv6,拿不到访客真实 IPv4。个人管理场景无影响;要记真实 IP 就得换 Nginx + X-Forwarded-For 或启用 PROXY Protocol。
4、未备案域名的现实问题(国内节点)
· DNS 解析本身不会被拦,可以正常指向阿里云;
· 被拦的是流量层的 HTTP/HTTPS 握手:80/443 会被扫 Host / TLS SNI,命中未备案域名就 RST 或弹拦截页;
· 高位端口(如 8443)+ 纯 IP 直访在实践中通常能过,但机房 DPI 对非标端口的 TLS SNI 同样有识别能力,随时可能失效;
· 长期解法:正经 ICP 备案;或把中转机换成香港/新加坡等境外轻量 VPS(免备案,且一般双栈齐全,本方案直接可用)。
5、家宽侧别忘的两件事
· 光猫/路由器要放行该端口的 IPv6 入站(很多光猫默认全拦);
· Lucky 取 IPv6 时优先取网卡前缀地址(240e: 段),不要取临时地址/隐私地址,否则 DDNS 一直在变。
六、多域名 / 多服务的写法
Realm 是四层工具,看不懂 SNI,不需要在 VPS 上区分域名——让它当一根盲管道,域名分流交给家里的 Lucky:
[network]
no_tcp_check = false
# 所有域名(example.com / example2.com / …)共用这一条 8443 通道
[[endpoints]]
listen = "0.0.0.0:8443"
remote = "v6.example.net:8443"
schedule = "30s"
[[endpoints]]
listen = "0.0.0.0:16601"
remote = "v6.example.net:16601"
schedule = "30s"
DNS 侧每个域名各配一套 A + AAAA(泛解析),Lucky 侧给每个域名配好证书与 Web 规则(监听统一 8443)。之后新增第 N 个域名,VPS 配置一行都不用改。
只有当你希望不同域名走 VPS 时使用不同端口(12443 / 28443)时,才需要给每个域名加一条 [[endpoints]]。
七、排坑清单
| 症状 | 原因 | 处理 |
|---|---|---|
| activating (auto-restart),日志 status=0/SUCCESS 后立刻退出 | config.toml 为空或语法错,Realm 找不到 endpoint 直接退出 | 前台跑 /usr/local/bin/realm -c /etc/realm/config.toml 看报错;确认有 [[endpoints]] 段 |
| 中转全挂,家里 IPv6 变了之后一直连不上 | 回源域名被泛解析的 A 记录污染,或解析缓存过期 | dig AAAA/A v6.example.net 核对只回 AAAA;保留 schedule = “30s” |
| 有 IPv6 却总走 VPS,速度只有几 Mbps | 两端端口不一致 / Cloudflare 开了小黄云 | 端口统一;CF 改 DNS only |
| 域名能 ping 通但浏览器打不开 | 安全组没放行 / 光猫拦 IPv6 入站 / 家宽无 IPv6 出网 | 逐段查:安全组 → 系统防火墙 → 光猫 → curl -g -6 ‘https://[240e:…]:8443’ |
| 访问偶发 RST / 拦截页 | 未备案域名被 DPI 命中 | 换高位端口 + 纯 IP 应急;长期备案或换境外中转 |
| 测试总测不出中转 | 手机 5G 和公司网其实都有 IPv6 | 手动禁用网卡 IPv6 再测 |
八、效果
· 有 IPv6 时:手机 5G、家里 Wi-Fi、多数公司网络 → 直连家宽,延迟就是物理光纤延迟,跑满上行,VPS 流量为 0;
· 纯 IPv4 时:一次 TCP 透传,多一跳 VPS,管理后台、Emby 海报墙这种场景体感差别极小(受限于 VPS 3~5 Mbps 出口,大文件传输会慢,所以只当中转应急);
· 资源占用:VPS 上 Realm 常驻内存约 2.3 MB,无长连接、无心跳、无僵尸隧道;
· 维护成本:家宽 IPv6 变了,30 秒内自动重解析;VPS 重启也只是少一条应急通道。
一句话总结:让 DNS 决定走哪条路,让 Realm 当透明管道,让 Lucky 只管证书和分流。
本文整理自与 Gemini 的一次方案推演对话,并结合实际部署中的踩坑做了修正。