【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字节)

相关推荐
策知道2 小时前
2026年北京政府工作报告产业指标深度解析
大数据·数据库·人工智能·搜索引擎·政务
Traced back2 小时前
# C# WinForms 数据库清理系统基础知识与避坑指南
开发语言·数据库·c#
慎思知行2 小时前
Discord中创建机器人的流程
linux·服务器·机器人
云边有个稻草人2 小时前
金仓 VS MongoDB:国产数据库凭什么成为MongoDB平替首选?
数据库·mongodb·国产数据库·金仓·kingbasees sql
yqcoder2 小时前
uni-app 之 下拉刷新
运维·服务器·uni-app
huohaiyu3 小时前
IP协议详解
服务器·网络·tcp/ip
DarkAthena3 小时前
【GaussDB】排查创建索引后查询数据行数发生变化的问题
数据库·sql·gaussdb
MengFly_3 小时前
Compose 脚手架 Scaffold 完全指南
android·java·数据库
PPPPickup3 小时前
application.yml或者yaml文件不显示绿色问题
java·数据库·spring