113 lines
4.8 KiB
Markdown
113 lines
4.8 KiB
Markdown
# sdlan交互协议
|
||
sdlan协议的总体格式如下:
|
||
|
||
```
|
||
+-----------+------------+--------+----------+
|
||
| 2字节的长度 | 2字节消息id | 消息头 | 消息体 |
|
||
+-----------+------------+--------+----------+
|
||
```
|
||
|
||
## 1. 长度
|
||
2字节长度包含后面的所有字节的长度(不包括自身)
|
||
|
||
## 2. 消息id
|
||
用于匹配请求和响应,占用2字节,目前可以都先填写0
|
||
|
||
## 3. 消息头
|
||
在sdlan中,有一个common头使用二进制协议,消息头主要包含了协议版本,消息来源id(从哪个节点发出的节点标识),消息ttl,以及一些协议的flag(flag标志以后可以扩充)
|
||
|
||
消息头二进制格式如下:
|
||
|
||
```
|
||
+---------+----+-----+------+-----+
|
||
| version | id | ttl | flag | pc |
|
||
+---------+----+-----+------+-----+
|
||
```
|
||
|
||
其中,version占用一个字节,用于标识协议版本。id用于唯一标识某个客户端,为长度为32字节的uuid,之后的ttl占用一个字节,当ttl为0,则直接丢弃该数据包。后面的flag占用2字节,用于标识数据包属性,目前拥有的标识如下:
|
||
|
||
* `from_sn`: `0x0020`,表示这个数据包是从服务端发送过来的。
|
||
* `socket`: `0x0040`,表示这个数据包里面包含了有用的socket信息(通常在服务端转发的时候有用)。
|
||
|
||
最后的pc表示后面数据包的类型,目前数据包类型如下:
|
||
|
||
* `0` —— `invalid pkt type`,表示无效的数据包类型
|
||
* `1` —— `register super`,表示客户端像服务端发送的注册请求
|
||
* `2` —— `packet`,表示客户端向服务端(或者客户端发送给客户端)发送的来自tun的数据包。
|
||
* `3` —— `register`数据包,表示客户端之间打洞请求消息
|
||
* `4` —— `register_ack`数据包,表示客户端之间打洞请求消息
|
||
* ... TODO
|
||
|
||
## 4. 消息体
|
||
消息提根据协议头中的pc不同,拥有不同的结构,结构体在json化之后,添加到消息体的位置。
|
||
|
||
### 4.1. RegisterSuper包类型
|
||
`register super`,pc为1,表示客户端像服务端发送的注册请求,该请求每隔15-20秒发送一次,RegisterSuper的json结构如下:
|
||
|
||
```json
|
||
|
||
```
|
||
|
||
### 4.2. Packet数据包
|
||
`packet`,pc为2,表示客户端向服务端(或者客户端发送给客户端)发送的来自tun的数据包。packet数据包的json化之后的结构如下:
|
||
|
||
```json
|
||
{
|
||
// 来源ip
|
||
"src_ip": $uint32,
|
||
// 目的ip
|
||
"dst_ip": $uint32,
|
||
// sock信息, sock信息包含了来自客户端的信息
|
||
// 通常客户端发送一个packet数据包的时候,不需要携带这个信息。
|
||
// 而在服务端收到一个packet的数据包的时候,在转发的时候,会将客户端的信息放入这个结构,然后发送给需要转发的客户端。所以在客户端收到转发的packet数据包的时候,可以通过这个sock结构,得知发送的客户端的端口信息。在sock结构有用的时候,flags中的socket(0x0040)标识也会被置位。
|
||
"sock": {
|
||
// family表示客户端的ip协议版本,2表示ipv4,10表示ipv6
|
||
"family": 2|10,
|
||
// 客户端开放的端口, u16
|
||
"port": $uint16,
|
||
// 如果family为2,则v4有用,一个四字节的数组,表示ipv4
|
||
"v4": [1,2,3,4],
|
||
// 如果family为10,则v6有用,一个16字节的数组,表示ipv6地址
|
||
"v6": [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16]
|
||
},
|
||
// data为二进制的字节数组,为aes加密之后的tun流量。
|
||
"data": []
|
||
}
|
||
```
|
||
|
||
其中,`src_ip`为tun的ip数据包的来源ip,`dst_ip`为tun的ip数据包的目的ip。均为大端序的32位无符号整数。`sock`为转发时由sn填充的发送客户端的信息,发送短不需要处理。`data`为tun的数据流量,使用`network_pass`进行加密后的二进制数据。
|
||
|
||
在发送packet数据包之前,消息体部分的数据,为json化之后的packet使用`header_pass`进行aes加密后的二进制数据。
|
||
|
||
### 4.3. Register数据包
|
||
`register`,pc为3,客户端向另一个客户端发送打洞请求的数据包。json格式如下:
|
||
|
||
```json
|
||
{
|
||
// 源ip
|
||
"src_ip": $uint32,
|
||
// 目的ip
|
||
"dst_ip": $uint32,
|
||
// supernode转发时开到的发送者的外网ip信息
|
||
"sock": {
|
||
// family表示客户端的ip协议版本,2表示ipv4,10表示ipv6
|
||
"family": 2|10,
|
||
// 客户端开放的端口, u16
|
||
"port": $uint16,
|
||
// 如果family为2,则v4有用,一个四字节的数组,表示ipv4
|
||
"v4": [1,2,3,4],
|
||
// 如果family为10,则v6有用,一个16字节的数组,表示ipv6地址
|
||
"v6": [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16]
|
||
},
|
||
// 发送者的tun的ip信息
|
||
"dev_addr": {
|
||
// tun设备的ip,大端序的32位无符号
|
||
"net_addr": $uint32,
|
||
// 子网掩码1的位数,一般为24
|
||
"net_bit_len": $uint8,
|
||
},
|
||
}
|
||
```
|
||
|
||
### 4.4. RegisterACK数据包
|
||
pc为4 |