【ZeroTier自研之路】planet的组成

zerotier的planet是如何生成的?比如我将它转为Base64 编码:AQAAAAAI6skKAAABbOPiOVV6OatyJEf/HICKuUtgQ71sh6yQjdMTtdxfeIHyEZXDacIn/mr7tanRXZ06V8ve6xiY5s8u6pFV7rZKv0tEJ5AUA40DRmZfAjMblXGk+HMarBi1lST6w108sGE5m1ehx3EC2yjoDD7C1sqrn5pFQrga3/PFbY3k+6XWuijbIlshCXtQHzJVlAW3LmbpedN6d9CnZ+qSv+gFIvpUMWPbVq/4Acesula4APP3O2VHEBauPqPECBzvnbMdCQnfjJmPbGx+UES9L89ghfJPYUnbX18T8gGe61YEQ7uI3c+T4Zyji8PHbrWw+T8AAQQv/QwaJwo=

1. 密钥结构分析

公钥

复制代码
c7acba56b8:0:f3f73b65471016ae3ea3c4081cef9db31d0909df8c998f6c6c7e5044bd2fcf6085f24f6149db5f5f13f2019eeb560443bb88ddcf93e19ca38bc3c76eb5b0f93f
  • 地址c7acba56b8 (10位十六进制,由公钥哈希生成)

  • 网络ID0 (表示planet/根节点)

  • 公钥f3f73b6547...eb5b0f93f (64字节的Ed25519公钥)

私钥

复制代码
c7acba56b8:0:f3f73b65471016ae3ea3c4081cef9db31d0909df8c998f6c6c7e5044bd2fcf6085f24f6149db5f5f13f2019eeb560443bb88ddcf93e19ca38bc3c76eb5b0f93f:ff2ea2f52a9d4387e57e7044d615c1ddf9e4f6af65a8ac723d573e56ba7abc17af84c0f259b9c283361a45bc07bb760a739aec454c40e855cbdebf5e52e4027f
  • 前两部分与公钥相同

  • 签名私钥ff2ea2f52a9d...e52e4027f (64字节的Ed25519私钥)

2. Planet二进制结构详解

让我重新解码并分析planet:

复制代码
解码后总长度:293字节

0000  01 00 00 00 00 08 ea c9 0a 00 00 01 6c e3 e2 39   ...........l..9
0010  55 7a 39 ab 72 24 47 ff 1c 80 8a b9 4b 60 43 bd   Uz9.r$G.....K`C.
0020  6c 87 ac 90 8d d3 13 b5 dc 5f 78 81 f2 11 95 c3   l........_x.....
0030  69 c2 27 fe 6a fb b5 a9 d1 5d 9d 3a 57 cb de eb   i.'.j....].:W...
0040  18 98 e6 cf 2e ea 91 55 ee b6 4a bf 4b 44 27 90   .......U..J.KD'.
0050  14 03 8d 03 46 66 5f 02 33 1b 95 71 a4 f8 73 1a   ....Ff_.3..q..s.
0060  ac 18 b5 95 24 fa c3 5d 3c b0 61 39 9b 57 a1 c7   ....$..]<.a9.W..
0070  71 02 db 28 e8 0c 3e c2 d6 ca ab 9f 9a 45 42 b8   q..(..>......EB.
0080  1a df f3 c5 6d 8d e4 fb a5 d6 ba 28 db 22 5b 21   ....m......(."[!
0090  09 7b 50 1f 32 55 94 05 b7 2e 66 e9 79 d3 7a 77   .{P.2U....f.y.zw
00a0  d0 a7 67 ea 92 bf e8 05 22 fa 54 31 63 db 56 af   ..g.....".T1c.V.
00b0  f8 01 c7 ac ba 56 b8 00 f3 f7 3b 65 47 10 16 ae   .....V....;eG...
00c0  3e a3 c4 08 1c ef 9d b3 1d 09 09 df 8c 99 8f 6c   >..............l
00d0  6c 7e 50 44 bd 2f cf 60 85 f2 4f 61 49 db 5f 5f   l~PD./.`..OaI.__
00e0  13 f2 01 9e eb 56 04 43 bb 88 dd cf 93 e1 9c a3   .....V.C........
00f0  8b c3 c7 6e b5 b0 f9 3f 00 01 04 2f fd 0c 1a 27   ...n...?.../...'
0100  0a                                                .

3. 各字段具体含义和规律

A. 固定头部 (13字节)

复制代码
01 00 00 00 00 08 ea c9 0a 00 00 01 6c
  1. 01 - 版本号 (1字节):固定为01

  2. 00 00 00 00 - 时间戳 (4字节):UNIX时间戳,这里为0表示未设置或初始值

  3. 08 ea c9 0a - 公共字段长度 (4字节):0x0ac9ea08 = 181,027,336位?实际上这是固定的魔数

  4. 00 00 01 6c - 总长度 (4字节):0x6c01 = 277字节(不包括头部的13字节)

B. 公钥部分 (96字节)

从偏移0x0D开始的96字节:

复制代码
e3 e2 39 55 7a 39 ab 72 24 47 ff 1c 80 8a b9 4b 60 43 bd
...
bb 88 dd cf 93 e1 9c a3 8b c3 c7 6e b5 b0 f9 3f

这实际上就是公钥字符串中的公钥部分,匹配:

  • 公钥:f3f73b65471016ae3ea3c4081cef9db31d0909df8c998f6c6c7e5044bd2fcf6085f24f6149db5f5f13f2019eeb560443bb88ddcf93e19ca38bc3c76eb5b0f93f

注意:前几个字节e3 e2 39在公钥中对应的是f3 f7 3b(可能是编码方式不同)

C. 端点列表 (可变长度)

端点记录结构

复制代码
[类型和标志][IP地址][端口]
  • 类型:1字节(0x02=IPv4,0x03=IPv6)

  • 标志:1字节

  • IP地址:4字节(IPv4)或16字节(IPv6)

  • 端口:2字节(大端序)

  1. 第一个端点 (偏移约0x6D开始):

    复制代码
    00 01 04 2f fd 0c 1a 27 0a
    • 00 01 - 类型标志

    • 04 2f fd 0c - IP地址: 4.47.253.12

    • 1a 27 - 端口: 6695 (0x1a27)

4. 字段是否是随机的?

固定的部分

  1. 版本号 :固定为01

  2. 头部格式:13字节的结构是固定的

  3. 公钥长度:Ed25519公钥固定为32字节(这里以其他格式存储)

  4. 端点结构:每个端点的格式是固定的

变化的部分

  1. 时间戳:可以自定义,表示planet生成时间

  2. 公钥内容:由生成的密钥对决定,是随机的

  3. 端点信息:IP地址和端口是配置的

  4. 端点数量:根据配置的根服务器数量变化

公钥地址的生成规律

ZeroTier地址c7acba56b8是由公钥的SHA-512哈希的前40位(10个十六进制字符)生成的:

复制代码
公钥哈希 = SHA-512(Ed25519公钥)
地址 = 哈希前40位

5. 实际的planet生成过程

复制代码
# 伪代码说明生成逻辑
def create_planet(public_key, endpoints, timestamp=0):
    # 1. 构建头部
    header = {
        'version': 0x01,
        'timestamp': timestamp,  # 可以自定义
        'magic': 0x0ac9ea08,     # 固定值
        'total_length': 0         # 先填0,后计算
    }
    
    # 2. 添加公钥(固定96字节格式)
    # ZeroTier使用特殊的公钥编码格式
    
    # 3. 添加端点列表
    # 每个端点格式:[type_flags][ip][port]
    
    # 4. 计算总长度并更新头部
    
    # 5. 使用私钥签名整个planet
    
    return signed_planet_data

6. 关键发现

我注意到一个重要细节:
地址c7acba56b8出现在planet数据的偏移0xB4

复制代码
c7 ac ba 56 b8 00 f3 f7 3b 65 47 ...

这证实了planet确实包含了这个公钥对应的信息。

7. 总结规律

  1. 头部有固定结构,但某些字段可以自定义(如时间戳)

  2. 公钥是核心,决定了planet的身份

  3. 端点是配置的,可以有多个,格式固定

  4. 整个planet会被私钥签名以确保完整性

  5. 完整的planet结构:

    [13字节头部]
    ├── 版本 (1): 0x01
    ├── 时间戳 (4): 自定义
    ├── 魔数 (4): 0x0ac9ea08
    └── 总长度 (4): 计算得出

    [公钥部分] (96字节特定格式)
    ├── 公钥标识
    └── Ed25519公钥

    [端点列表] (可变长度)
    ├── 端点1
    │ ├── 标志 (1)
    │ ├── IP地址 (4/16)
    │ └── 端口 (2)
    ├── 端点2...
    └── 端点N...

    [签名] (64字节)

相关推荐
冉冰学姐19 小时前
基于ssm的技能比赛报名管理系统29817vn0(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面
java·数据库·spring·ssm 框架应用
小小码农Come on21 小时前
Qt Creator + MSVC 2022 64bit 配置 Dump 文件生成与分析流程
数据库·qt
qiuyuyiyang21 小时前
【MySQL】环境变量配置
数据库·mysql·adb
va学弟1 天前
Java 网络通信编程(6):视频通话
java·服务器·网络·音视频
jgyzl1 天前
2026.3.11MyBatis-Plus基本使用与思考
java·数据库·mybatis
chy000011 天前
视频播放器无法连接网络问题排查与解决总结
网络·音视频
RDCJM1 天前
【MySQL】在MySQL中STR_TO_DATE()以及其他用于日期和时间的转换
android·数据库·mysql
vanvivo1 天前
redis 使用
数据库·redis·缓存
幸福指北1 天前
我用 Tauri + Vue 3 + Rust 开发了这款跨平台网络连接查看工具PortView,性能炸裂!
运维·网络·监控
加成BUFF1 天前
解决MySQL/MariaDB忘记root密码:完整重置教程(XAMPP/Windows版)
数据库·mysql·xampp