diff --git a/docs/protocol.md b/docs/protocol.md index 6c381e7..e22b62b 100644 --- a/docs/protocol.md +++ b/docs/protocol.md @@ -42,12 +42,47 @@ sdlan协议的总体格式如下: 消息提根据协议头中的pc不同,拥有不同的结构,结构体在json化之后,添加到消息体的位置。 ### 4.1. RegisterSuper包类型 -`register super`,pc为1,表示客户端像服务端发送的注册请求,该请求每隔15-20秒发送一次,RegisterSuper的json结构如下: +`register super`,pc为1,表示客户端像服务端发送的注册请求,该请求每隔15-20秒发送一次,RegisterSuper的json结构如下(该结构没有用aes加密,为了安全,以后如果没有加密的结构体,可以预置一个32为aes密钥): ```json +{ + "pass": "初始密钥,用于最初始的简单验证, 目前固定为`encrypt!`", + // 客户端自己随机生成的整数,用于匹配RegisterSuper和RegisterSuperACK, RegisterSuperNAK, RegisterSuperAcknowledge + "cookie": $uint32, + // sock在客户端发送时不需要填写,在Supernode之间转发的时候,会带上这个,表示客户端的信息。 + "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] + }, + // 客户端自己的ipv6信息,如果没有ipv6,则不用填写 + "v6_info": { + // 客户端的ipv6的端口 + "port": $uint16, + // 客户端的ipv6地址 + "v6": [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16], + }, + // 客户端tun设备的ip信息 + "dev_addr": { + // 客户端的tun的ip地址,如果没有ip(第一次上线等情况),则填写0 + "net_addr": $uint32, + // 子网掩码的位数,一般为24, 如果没有ip,则填写0 + "net_bit_len": $uint8, + }, + // 客户端自己的公钥,在服务端返回加密的aes密钥时,会使用这个公钥加密 + "pub_key": "", + // 字符串,用于标识一个用户的id,或者一个由用户生成的token + "token": "", +} ``` + ### 4.2. Packet数据包 `packet`,pc为2,表示客户端向服务端(或者客户端发送给客户端)发送的来自tun的数据包。packet数据包的json化之后的结构如下: @@ -110,4 +145,67 @@ sdlan协议的总体格式如下: ``` ### 4.4. RegisterACK数据包 -pc为4 \ No newline at end of file +pc为4, + +### 4.5. RegisterSuperACK数据包 +pc为5。在服务端收到registersuper之后,如果服务端判断该节点已经授权,而且是刚上线,就会返回一个RegisterSuperACK,告知该节点ip信息。另外,如果在服务端界面上进行操作,将本来没有授权的节点进行授权,或者将已将寂静授权的节点,转移到另一个网络里面,服务端也会主动向客户端发送一个RegisterSuperAck消息,将客户端需要的信息(新网络的加密aes等)主动告诉客户端。 + +RegisterSuperACK的消息格式如下(暂时该结构没有加密,以后可以将该结构整个用客户端的rsa公钥加密): + +```json +{ + // 匹配RegisterSuper + "cookie": $uint32, + + // 服务端看来的该客户端的外网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": { + // 客户端分配到的ip地址 + "net_addr": $uint32, + // 客户端分配到的ip地址的掩码位数 + "net_bit_len": $uint8, + }, + // rsa加密之后的加密头的aes密钥 + "header_key": "", + // rsa加密之后的tun流量的加密aes密钥 + "encrypted_key": "", + // 多久之后,客户端应该再发起RegisterSuper消息,暂时可以忽略 + "lifetime": $int16 +} +``` + +### 4.6. RegisterSuperAcknowledge数据包 +在服务端收到registersuper之后,如果服务端判断该节点已经授权,而且不是第一次收到该节点的RegisterSuper消息(这个时候,该RegisterSuper消息类似于心跳数据包了),就会返回一个RegisterSuperAcknowledge,告知该节点:服务端已经收到你的消息了。另外,如果服务端判断该节点没有授权,也会返回一个RegisterSuperAcknowledge消息,这个时候,可以理解为:服务端收到你的消息了,但是你没有授权,我这边不会给你分配ip,你就这样等着吧。 + +RegisterSuperAcknowledge的消息格式如下(该结构没有用aes加密): + +```json +{ + // 来自registerSuper消息的cookie + "cookie": $uint32, +} +``` + +### 4.6. RegisterSuperNAK数据包 +服务端在节点发送RegisterSuper时候,如果该数据包里面的初始验证信息等无效,则会直接返回RegisterSuperNAK消息,此时客户端应该直接退出。 + +量外,如果服务端判断到,比如一个用户最多可以创建10个客户端,但是这个节点是第11个了,在收到该客户端的RegisterSuper以后,和会直接返回RegisterSuperNAK消息,客户端同样应该直接退出。 + +RegisterSuperNAK结构如下(该结构没有用aes加密): + +```json +{ + // 来自registerSuper消息的cookie + "cookie": $uint32, +} +``` \ No newline at end of file diff --git a/src/config.rs b/src/config.rs index ae55984..87355e1 100644 --- a/src/config.rs +++ b/src/config.rs @@ -19,3 +19,6 @@ pub enum SDLanSNOPER { pub const AF_INET: u8 = 2; pub const AF_INET6: u8 = 10; + +pub const SDLAN_VERSION: u8 = 1; +pub const SDLAN_DEFAULT_TTL: u8 = 2; diff --git a/src/packet/common.rs b/src/packet/common.rs index 99b640f..c841eeb 100644 --- a/src/packet/common.rs +++ b/src/packet/common.rs @@ -85,8 +85,10 @@ pub enum PacketType { PKTRegister, // 打洞消息ACK PKTRegisterACK, - + // RegisterSuperACK, PKTRegisterSuperACK, + PKTRegisterSuperAcknowledge, + PKTRegisterSuperNAK, } impl std::convert::From for PacketType { @@ -98,6 +100,8 @@ impl std::convert::From for PacketType { 3 => Self::PKTRegister, 4 => Self::PKTRegisterACK, 5 => Self::PKTRegisterSuperACK, + 6 => Self::PKTRegisterSuperAcknowledge, + 7 => Self::PKTRegisterSuperNAK, _ => Self::PKTInvalid, } } @@ -112,6 +116,8 @@ impl PacketType { Self::PKTRegister => 3, Self::PKTRegisterACK => 4, Self::PKTRegisterSuperACK => 5, + Self::PKTRegisterSuperAcknowledge => 6, + Self::PKTRegisterSuperNAK => 7, } } } diff --git a/src/packet/mod.rs b/src/packet/mod.rs index f45a093..a29cb06 100644 --- a/src/packet/mod.rs +++ b/src/packet/mod.rs @@ -15,3 +15,9 @@ pub use register_ack::*; mod register_super_ack; pub use register_super_ack::*; + +mod register_super_acknowledge; +pub use register_super_acknowledge::*; + +mod register_super_nak; +pub use register_super_nak::*; diff --git a/src/packet/register_super_acknowledge.rs b/src/packet/register_super_acknowledge.rs new file mode 100644 index 0000000..5c61599 --- /dev/null +++ b/src/packet/register_super_acknowledge.rs @@ -0,0 +1,6 @@ +use serde::{Deserialize, Serialize}; + +#[derive(Debug, Serialize, Deserialize)] +pub struct RegisterSuperAcknowledge { + pub cookie: u32, +} diff --git a/src/packet/register_super_nak.rs b/src/packet/register_super_nak.rs new file mode 100644 index 0000000..3a0100e --- /dev/null +++ b/src/packet/register_super_nak.rs @@ -0,0 +1,6 @@ +use serde::{Deserialize, Serialize}; + +#[derive(Serialize, Deserialize)] +pub struct RegisterSuperNAK { + pub cookie: u32, +} diff --git a/src/utils/myrsa.rs b/src/utils/myrsa.rs index 3fb0293..c4352a2 100644 --- a/src/utils/myrsa.rs +++ b/src/utils/myrsa.rs @@ -7,7 +7,6 @@ use rsa::pkcs8::EncodePublicKey; use rsa::{Pkcs1v15Encrypt, RsaPrivateKey, RsaPublicKey}; use std::io::Read; -use std::sync::Arc; pub fn gen_rsa_keys() { let mut rng = rand::thread_rng();