极空间远程访问体系:四层递进的 NAT 穿透架构

2026/05/22

基于 T2 设备上的 zfrpc、zrps、frpc、nginx 配置分析 分析日期:2026-05-22


一、核心结论:四层递进式远程访问架构

极空间的远程访问不是单一方案,而是 四层递进 的混合架构,从最优到兜底依次尝试:

用户外网访问 *.direct.zspace.link 或 *.direct.ud.link
              │
     ┌───────┴────────┐
     │   DNS 解析      │
     │  (DDNS/zddns)  │
     └───────┬────────┘
              │
    ┌─────────▼─────────┐
    │ 1. P2P 直连 (最优) │  ← zrps + UPnP/STUN 打洞
    │  延迟最低,无中转   │
    └─────────┬─────────┘
              │ 失败
    ┌─────────▼─────────┐
    │ 2. zrps Relay 中转 │  ← 自研中继协议,设备互联
    │  极空间中继服务器    │     zconn 协议
    └─────────┬─────────┘
              │ 失败/特定场景
    ┌─────────▼─────────┐
    │ 3. frp 反向代理    │  ← 开源 frp 0.32.0
    │  极空间自建 frps   │     TCP 端口映射
    └─────────┬─────────┘
              │
    ┌─────────▼─────────┐
    │ 4. DDNS 直连 (兜底)│  ← 公网 IP + 端口映射
    │  zddns + UPnP     │
    └───────────────────┘

二、四层方案详解

第一层:P2P 直连(zrps + STUN + UPnP)

这是极空间的核心远程方案,自研程度最高。

关键组件:

组件路径作用
zrps/zspace/applications/services/zrps/zrpsP2P 连接管理与中继
zupnp/zspace/applications/services/zupnp/zupnpUPnP IGD 端口映射
STUN 探测proxy.zenithspace.net:3478NAT 类型检测、获取公网 IP

工作流程:

1. zupnp 通过 UPnP 协议向路由器申请端口映射
   将内网 5055/5056 映射到公网

2. zrps 向 proxy.zenithspace.net:3478 (STUN) 查询公网 IP 和 NAT 类型

3. 客户端连接时,zrps 尝试 UDP/TCP 打洞
   成功 → P2P 直连,延迟最低
   失败 → 进入 Relay 模式

zrps 配置关键项:

{
  "env": {
    "firewall": {
      "allow_ports": "tcp:5055,tcp:8050"    // 允许外部访问的端口
    },
    "port": {
      "p2p": "20000-30000"                   // P2P 打洞使用的端口范围
    }
  },
  "system": {
    "id": "/zspace/system/private/id",       // 设备唯一 ID
    "privkey": "/zspace/system/private/privkey",  // 设备私钥
    "pubkey": "/zspace/system/private/pubkey"     // 设备公钥
  }
}

zrps 监听端口:

端口用途
127.0.0.1:22345zrps API(速度测试、连接管理)
127.0.0.1:8041Relay 代理(跨设备中转)

第二层:Relay 中继(zconn 协议)

当 P2P 打洞失败时(对称 NAT 等场景),流量通过极空间的中继服务器转发。

zconn 协议(ZSpace Connection Protocol)是极空间自研的设备间通信协议,在 nginx 配置中有完整实现:

# 设备间连接路由
location /zconn/http/5056/ {
    # 解析目标设备 ID
    # 如果目标是自身 → 走本地 5056
    # 如果目标是其他设备 → 走 zrps relay 8041
    if target_nas_id ~= self_nas_id then
        port = 5056      # 本地
    else
        port = 8041      # relay 中转
    end
}

这意味着用户可以通过任意一台自己的极空间设备访问另一台,zrps 自动判断是否需要中继。

分享链接的跨设备路由:

# /redirect/v2/share/ — 分享链接
# 读取请求头 shareNasId,判断目标是本地还是远程
# 本地 → 8050 (go-baseset)
# 远程 → 8041 (zrps relay)

第三层:frp 反向代理(开源方案,兜底)

极空间部署了两套 frp 客户端:

方案 A:自研 zfrpc(优先)

路径:/usr/zfrpc/zfrpc 和 /zspace/applications/services/zfrp/zfrpc

方案 B:开源 frpc 0.32.0(兜底)

路径:/zspace/shell/tool/frpc/frpc_openwrt

配置文件 /zspace/shell/tool/frpc/frpc.ini(敏感字段已脱敏):

[common]
server_addr = <极空间自建 frps 服务器 IP>
server_port = 10050
token = <认证 token>

[ssh_<设备序列号>]             # SSH 隧道
type = tcp
local_ip = 127.0.0.1
local_port = 22
remote_port = 32xxx            # 外网通过该端口访问 SSH

[http_<设备序列号>]            # HTTP 隧道
type = tcp
local_ip = 127.0.0.1
local_port = 5055
remote_port = 52xxx            # 外网通过该端口访问 Web

frp 服务器是极空间自建的 frps(frp server),不是公网 frp 服务。

每条隧道以设备 ID 命名,远程端口按规则分配(SSH 和 HTTP 各一个)。


第四层:DDNS + UPnP(传统兜底)


三、远程访问域名体系

域名用途TLS
*.direct.zspace.link用户远程访问主域名Let’s Encrypt 证书
*.direct.ud.link备用域名同证书
proxy.zenithspace.netSTUN/信令服务器-

证书由 zbasic 服务自动申请和管理:

ssl_certificate     /zspace/applications/services/zbasic/data/new_fullchain.pem
ssl_certificate_key /zspace/applications/services/zbasic/data/new_priv.key

四、Nginx 远程访问入口(5056 端口)

5056 端口是远程访问的统一 HTTPS 入口,配置极其复杂,集成了所有远程功能:

:5056 (HTTPS)
  │
  ├── /v2/*                    → go-baseset (:8050)   核心 API
  ├── /zconn/http/5056/*       → 设备间连接路由        跨设备访问
  ├── /redirect/v2/share/*     → 分享链接跨设备路由
  ├── /syncthing/*             → Syncthing (:8385)   文件同步
  ├── /docker/api/*            → zdocker (:9123)      Docker 管理
  ├── /hdmiapi/*               → HDMI 输出 (:20124)
  ├── /netdisk/*               → 网盘 (:5300)
  ├── /wps/*                   → WPS 文档
  ├── /ws                      → WebSocket (:8001)
  ├── /settings                → 系统设置 (动态路由)
  ├── @dynamic_proxy           → Lua 动态代理(远程访问白名单)
  │
  └── /                        → 默认转发到 :8020 (PC Web)

动态代理机制

# remote_access.conf
if ($dynamic_proxy_target) {
    return 418;   # 触发 @dynamic_proxy 错误页处理
}

location @dynamic_proxy {
    proxy_pass $dynamic_proxy_target;  # Lua 动态设置目标
}

Lua 脚本 rewrite_token.lua 在此处做 token 认证 + 动态路由:


五、设备身份与安全

设备唯一标识

每台极空间在出厂时烧录唯一 ID,格式为 <型号代码><序列号>(如 T020 开头即 T2 型号),主机名也从 ID 派生(形如 T2-xxxx)。

密钥体系

/zspace/system/private/
├── id          ← 设备唯一 ID
├── privkey     ← 设备私钥(用于 zrps P2P 加密)
└── pubkey      ← 设备公钥(用于服务端验证设备身份)

多层认证

层级机制位置
传输加密TLS (Let’s Encrypt)nginx 5056
Token 认证rewrite_token.luanginx Lua
密码二次验证auth_pwdcheck.lua敏感操作(格式化等)
设备认证公私钥对zrps P2P 握手
frp 认证tokenfrpc.ini
远程访问白名单RemoteAccessWhiteList.jsonzrps

六、NAT 穿透技术栈

┌────────────────────────────────────────┐
│           极空间云服务                    │
│                                        │
│  proxy.zenithspace.net:3478 (STUN)     │
│  frp server (自建 frps)                │
│  zrps relay server (中继)              │
│                                        │
└────────────┬───────────────────────────┘
             │
    ┌────────┴────────┐
    │   用户家庭网络    │
    │                 │
    │  ┌───────────┐  │
    │  │  zupnp     │──┼──► 路由器 UPnP 端口映射
    │  └───────────┘  │
    │  ┌───────────┐  │
    │  │  zrps      │──┼──► P2P 打洞 / Relay 选择
    │  └───────────┘  │
    │  ┌───────────┐  │
    │  │  frpc      │──┼──► frps 反向代理 (兜底)
    │  └───────────┘  │
    │  ┌───────────┐  │
    │  │  zddns     │──┼──► DDNS 域名更新
    │  └───────────┘  │
    └─────────────────┘

STUN 协议 (proxy.zenithspace.net:3478):


七、设备间互联(zconn 协议亮点)

5056 端口 nginx 配置中最精彩的部分是 zconn 协议——实现了设备间透明路由:

用户 --→ 设备A (5056) --zconn--> 设备B (8041 relay 或直连)

典型场景:


八、总结

极空间的远程访问不是简单套用某个开源方案,而是一个精心设计的四层递进系统:

层方案自研程度延迟适用场景
1P2P 直连 (zrps + STUN + UPnP)高(自研 zrps)最低NAT 类型兼容
2Relay 中继 (zconn 协议)高(自研协议)中对称 NAT
3frp 反向代理低(开源 frp + 自研 zfrpc)中兜底
4DDNS 直连低(标准方案)取决于网络有公网 IP

其中 zrps + zconn 是技术含量最高的部分,实现了:

这套架构的设计思路是:优先 P2P 省带宽,不行走 Relay,再不行兜底 frp,绝不会连不上。