changed the packet document

This commit is contained in:
asxalex 2024-02-27 10:36:51 +08:00
parent cd4fc9b218
commit b7adef51e8
8 changed files with 200 additions and 18 deletions

View File

@ -28,6 +28,7 @@ sdlan协议的总体格式如下
* `from_sn`: `0x0020`,表示这个数据包是从服务端发送过来的。
* `socket`: `0x0040`表示这个数据包里面包含了有用的socket信息通常在服务端转发的时候有用
* `v6_info`: `0x0080`,表示这个数据包里面包含了ipv6信息专门用在packet数据包里面目前只有这个数据包使用了该标识
最后的pc表示后面数据包的类型目前数据包类型如下
@ -35,11 +36,24 @@ sdlan协议的总体格式如下
* `1` —— `register super`,表示客户端像服务端发送的注册请求
* `2` —— `packet`表示客户端向服务端或者客户端发送给客户端发送的来自tun的数据包。
* `3` —— `register`数据包,表示客户端之间打洞请求消息
* `4` —— `register_ack`数据包,表示客户端之间打洞请求消息
* ... TODO
* `4` —— `register_ack`数据包表示客户端之间打洞ACK消息
* `5` —— `register_super_ack`数据包表示可以对节节点进行授权返回对应的ip地址等信息
* `6` —— `register_super_acknowledge`数据包,表示对`register_super`的一般返回,只是告诉客户端:服务端收到他的注册请求了
* `7` —— `register_super_nak`数据包,表示服务端不接受该客户端的上线请求,客户端应该直接退出
* `8` —— `unregister_super`数据包,客户端告诉服务端,客户端自己要下线了。
* `9` —— `query_info`数据包客户端向服务端查询对端的ip信息
* `10` —— `peer_info`数据包服务端向客户端返回对端的ip等信息。
## 4. 消息体
消息提根据协议头中的pc不同拥有不同的结构结构体在json化之后添加到消息体的位置。
消息提根据协议头中的pc不同拥有不同的结构结构体在json化之后需要加密的数据包进行加密然后将内容添加到消息体的位置。
其中RegisterSuper, RegisterSuperACK, RegisterSuperAcknowledge, RegisterSuperNAK这几个消息在发送和接收的时候消息提内容没有进行加密直接是json序列化之后的内容为了提高安全性服务端和客户端在实际编写的时候可以商量一个预置的aes密钥这几个消息类型就用这个密钥进行加解密
在服务端返回RegisterSuperACK的时候会有`enctypted_key``header_key`。这两个字段为使用客户端rsa公钥加密之后的两个aes密钥。
其中:
* `encrypted_key`用于加密PACKET数据包中的data流量也就是用于加密tun网卡的流量。
* `header_key`用于加密之后传输的结构本身比如客户端在向服务端发送一个PACKET数据包的时候在将json序列化之后再将序列化之后的内容使用`header_key`aes再加密一次然后放到消息提的位置。
### 4.1. RegisterSuper包类型
`register super`pc为1表示客户端像服务端发送的注册请求该请求每隔15-20秒发送一次RegisterSuper的json结构如下该结构没有用aes加密为了安全以后如果没有加密的结构体可以预置一个32为aes密钥
@ -105,6 +119,13 @@ sdlan协议的总体格式如下
// 如果family为10则v6有用一个16字节的数组表示ipv6地址
"v6": [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16]
},
// 如果对端有ipv6则填写该结构否则就省略
"v6_info": {
// ipv6的端口
"port": $uint16,
// v6
"v6": [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16]
}
// data为二进制的字节数组为aes加密之后的tun流量。
"data": []
}
@ -114,16 +135,34 @@ sdlan协议的总体格式如下
在发送packet数据包之前消息体部分的数据为json化之后的packet使用`header_pass`进行aes加密后的二进制数据。
在客户端收到PACKET消息的时候如果数据包来自服务端转发过来的则可以向sock字段表示的对端信息发送register消息
在实际发送的时候为了效率packet数据包被直接打包成二进制进行处理。二进制规则如下
1. 在消息头的`flags`里面会给相应的标志位置位比如如果有sock信息则flags会有`SOCKET`标识,如果有`ipv6`信息,则会有`v6_info`标识。
2. 消息体序列化`src_ip`,大端序表示`uint32`的来源ip地址
2. 消息体序列化`dst_ip`,大端序表示`uint32`的目的ip地址
3. 如果消息头的`socket`置位了接下来就是序列化sock信息
1. 一个字节的family
2. 2个字节大端序的`uint16`)端口号
1. 如果family是2表示是ipv4则接下来是4个字节的ipv4
2. 如果family是10表示是ipv6目前不会有这种情况只是为了兼容以后服务端也支持ipv6的情况则接下来是16个字节的ipv6地址
4. 如果消息头的`v6_info`置位了则接下来就是ipv6信息
1. 2个字节大端序的`uint16`ipv6端口号
2. 16个字节的ipv6地址
5. 之后是`network_pass`加密后的二进制tun接口的流量数据。
### 4.3. Register数据包
`register`pc为3客户端向另一个客户端发送打洞请求的数据包。json格式如下
`register`pc为3客户端向另一个客户端发送打洞请求的数据包。在完全不知情的情况下当一个客户端需要向另一个客户端发送数据的时候tun接口的流量发送端首先查看自己是否知道对方的地址此时不知道发送端就向服务端发起一个QueryInfo的数据包同时发送端的tun数据包首先通过服务端中转到对端客户端一方面发送端在收到QueryInfo的返回PeerInfo数据包的时候会向接收端发起一个或者一系列Register数据包另一方面接收端在收到Packet数据包之后也会发起一个或者一系列Register数据包。两边同时发起Register进行打洞当有一个数据包能被正确接收则马上返回RegisterACK数据包两边打洞成功。在json格式如下
```json
{
// 源ip
"cookie": $uint32,
// 源tun ip
"src_ip": $uint32,
// 目的ip
// 目的tun ip
"dst_ip": $uint32,
// supernode转发时开到的发送者的外网ip信息
// supernode转发时开到的发送者的外网ip信息,发送的时候,不需要填写
"sock": {
// family表示客户端的ip协议版本2表示ipv410表示ipv6
"family": 2|10,
@ -134,18 +173,33 @@ sdlan协议的总体格式如下
// 如果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,
pc为4,结构如下:
```json
{
// 匹配Register
"cookie": $uint32,
// 源tun ip
"src_ip": $uint32,
// 目的tun ip
"dst_ip": &uint32,
// 发送者的外网ip信息
"sock": {
// family表示客户端的ip协议版本2表示ipv410表示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]
}
}
```
### 4.5. RegisterSuperACK数据包
pc为5。在服务端收到registersuper之后如果服务端判断该节点已经授权而且是刚上线就会返回一个RegisterSuperACK告知该节点ip信息。另外如果在服务端界面上进行操作将本来没有授权的节点进行授权或者将已将寂静授权的节点转移到另一个网络里面服务端也会主动向客户端发送一个RegisterSuperAck消息将客户端需要的信息新网络的加密aes等主动告诉客户端。
@ -196,7 +250,7 @@ RegisterSuperAcknowledge的消息格式如下该结构没有用aes加密
}
```
### 4.6. RegisterSuperNAK数据包
### 4.7. RegisterSuperNAK数据包
服务端在节点发送RegisterSuper时候如果该数据包里面的初始验证信息等无效则会直接返回RegisterSuperNAK消息此时客户端应该直接退出。
量外如果服务端判断到比如一个用户最多可以创建10个客户端但是这个节点是第11个了在收到该客户端的RegisterSuper以后和会直接返回RegisterSuperNAK消息客户端同样应该直接退出。
@ -208,4 +262,64 @@ RegisterSuperNAK结构如下该结构没有用aes加密
// 来自registerSuper消息的cookie
"cookie": $uint32,
}
```
```
### 4.8. UnregisterSuper数据包
当客户端没有收到RegisterSuperNAK的情况下没有被服务端拒绝接入在客户端结束之前可以发送UnregisterSuper数据包该数据包告诉服务端客户端将要下线了可以将这个客户端的相关信息删除了。
UnregisterSuper数据包结构如下
```json
{
// 客户端被分配的ip如果没有分配到则设置为0
"src_ip": $uint32
}
```
### 4.9. QueryInfo数据包
在发送端发送数据包PACKET消息的时候如果对方ip找不到没有打洞则会发起一个QueryInfo数据包服务端在收到相应信息之后会返回锁查找的接收端的信息PEERINFO数据包发送端收到PEERINFO之后便发起Register进行打洞。
结构如下:
```json
{
// 自身tun ip
"src_ip": $uint32,
// 需要查找的目标的tun ip
"dst_ip": $uint32,
}
```
### 4.10. PeerInfo数据包
PeerInfo结构如下
```json
{
// 标识为暂时没有用都填写0
"flag": $uint16,
// 之前发起短的tun ip
"src_ip": $uint32,
// 目标的tun ip
"dst_ip": $uint32,
// 需要查找的对端的外网通信信息
"sock": {
// family表示客户端的ip协议版本2表示ipv410表示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]
},
// 朝兆的对端的ipv6信息如果有的话
"v6_info": {
// 端口
"port": $uint16,
// v6地址
"v6": [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16]
}
}
```

View File

@ -89,6 +89,12 @@ pub enum PacketType {
PKTRegisterSuperACK,
PKTRegisterSuperAcknowledge,
PKTRegisterSuperNAK,
PKTUnregisterSuper,
// 客户端向服务端发送另一个客户端的信息
PKTQueryPeer,
// 服务端向客户端返回消息
PKTPeerInfo,
}
impl std::convert::From<u8> for PacketType {
@ -102,6 +108,9 @@ impl std::convert::From<u8> for PacketType {
5 => Self::PKTRegisterSuperACK,
6 => Self::PKTRegisterSuperAcknowledge,
7 => Self::PKTRegisterSuperNAK,
8 => Self::PKTUnregisterSuper,
9 => Self::PKTQueryPeer,
10 => Self::PKTPeerInfo,
_ => Self::PKTInvalid,
}
}
@ -118,6 +127,9 @@ impl PacketType {
Self::PKTRegisterSuperACK => 5,
Self::PKTRegisterSuperAcknowledge => 6,
Self::PKTRegisterSuperNAK => 7,
Self::PKTUnregisterSuper => 8,
Self::PKTQueryPeer => 9,
Self::PKTPeerInfo => 10,
}
}
}

View File

@ -21,3 +21,12 @@ pub use register_super_acknowledge::*;
mod register_super_nak;
pub use register_super_nak::*;
mod unregister_super;
pub use unregister_super::*;
mod query_peer;
pub use query_peer::*;
mod peer_info;
pub use peer_info::*;

12
src/packet/peer_info.rs Normal file
View File

@ -0,0 +1,12 @@
use serde::{Deserialize, Serialize};
use crate::peer::SdlanSock;
#[derive(Serialize, Deserialize)]
pub struct PeerInfo {
// query peer some flag.
pub flag: u16,
pub src_ip: u32,
pub dst_ip: u32,
pub sock: SdlanSock,
}

15
src/packet/query_peer.rs Normal file
View File

@ -0,0 +1,15 @@
use serde::{Deserialize, Serialize};
use crate::peer::SdlanSock;
#[derive(Serialize, Deserialize)]
pub struct QueryPeer {
// query peer some flag.
pub flag: u16,
// 询问人的ip
pub src_ip: u32,
// 询问对方的ip
pub dst_ip: u32,
// sock信息用于转发
pub sock: Option<SdlanSock>,
}

View File

@ -4,6 +4,7 @@ use crate::peer::{IpSubnet, SdlanSock};
#[derive(Serialize, Deserialize)]
pub struct Register {
pub cookie: u32,
// 源ip
pub src_ip: u32,
// 目的ip
@ -11,5 +12,5 @@ pub struct Register {
// supernode转发时开到的发送者的外网ip信息
pub sock: Option<SdlanSock>,
// 发送者的tun的ip信息
pub dev_addr: IpSubnet,
// pub dev_addr: IpSubnet,
}

View File

@ -0,0 +1,13 @@
use serde::{Deserialize, Serialize};
use crate::peer::SdlanSock;
pub struct RegisterACK {
pub cookie: u32,
// 返回方的tun接口的ip地址
pub src_ip: u32,
// 发送Register的客户端的tun ip地址
pub dst_ip: u32,
//
pub sock: Option<SdlanSock>,
}

View File

@ -0,0 +1,6 @@
use serde::{Deserialize, Serialize};
#[derive(Serialize, Deserialize)]
pub struct UnregisterSuper {
pub src_ip: u32,
}