支持服务端加密

This commit is contained in:
lubeilin
2023-08-27 13:12:29 +08:00
parent 4a603f42ac
commit b0b32a5ea7
36 changed files with 2450 additions and 645 deletions

View File

@@ -38,36 +38,53 @@ jobs:
include:
- TARGET: i686-unknown-linux-musl # test in an alpine container on a mac
OS: ubuntu-latest
FEATURES: normal
- TARGET: x86_64-unknown-linux-gnu # tested in a debian container on a mac
OS: ubuntu-latest
FEATURES: ring-cipher
- TARGET: x86_64-unknown-linux-musl # test in an alpine container on a mac
OS: ubuntu-latest
FEATURES: ring-cipher
- TARGET: aarch64-unknown-linux-gnu # tested on aws t4g.nano
OS: ubuntu-latest
FEATURES: ring-cipher
- TARGET: aarch64-unknown-linux-musl # tested on aws t4g.nano in alpine container
OS: ubuntu-latest
FEATURES: normal
- TARGET: armv7-unknown-linux-gnueabihf # raspberry pi 2-3-4, not tested
OS: ubuntu-latest
FEATURES: ring-cipher
- TARGET: armv7-unknown-linux-musleabihf # raspberry pi 2-3-4, not tested
OS: ubuntu-latest
FEATURES: normal
- TARGET: arm-unknown-linux-gnueabihf # raspberry pi 0-1, not tested
OS: ubuntu-latest
FEATURES: ring-cipher
- TARGET: arm-unknown-linux-musleabihf # raspberry pi 0-1, not tested
OS: ubuntu-latest
FEATURES: normal
- TARGET: x86_64-apple-darwin # tested on a mac, is not properly signed so there are security warnings
OS: macos-latest
FEATURES: ring-cipher
- TARGET: aarch64-apple-darwin # tested on a mac, is not properly signed so there are security warnings
OS: macos-latest
FEATURES: ring-cipher
- TARGET: i686-pc-windows-msvc # tested on a windows machine
OS: windows-latest
FEATURES: ring-cipher
- TARGET: x86_64-pc-windows-msvc # tested on a windows machine
OS: windows-latest
FEATURES: ring-cipher
- TARGET: mipsel-unknown-linux-musl # openwrt
OS: ubuntu-latest
FEATURES: normal
# needs: test
runs-on: ${{ matrix.OS }}
env:
NAME: vnts # change with the name of your project
TARGET: ${{ matrix.TARGET }}
OS: ${{ matrix.OS }}
FEATURES: ${{ matrix.FEATURES }}
steps:
- uses: actions/checkout@v2
- name: Cargo cache
@@ -84,28 +101,51 @@ jobs:
# dependencies are only needed on ubuntu as that's the only place where
# we make cross-compilation
if [[ $OS =~ ^ubuntu.*$ ]]; then
sudo apt-get update && sudo apt-get install -qq crossbuild-essential-arm64 crossbuild-essential-armhf
sudo apt-get update && sudo apt-get install -qq crossbuild-essential-arm64 crossbuild-essential-armhf musl-tools gcc-mipsel-linux-gnu
fi
# some additional configuration for cross-compilation on linux
cat >>~/.cargo/config <<EOF
[target.x86_64-unknown-linux-musl]
rustflags = ["-C", "target-feature=+crt-static"]
[target.aarch64-unknown-linux-gnu]
linker = "aarch64-linux-gnu-gcc"
rustflags = ["-C", "target-feature=+crt-static"]
[target.aarch64-unknown-linux-musl]
linker = "aarch64-linux-gnu-gcc"
rustflags = ["-C", "target-feature=+crt-static"]
[target.armv7-unknown-linux-gnueabihf]
linker = "arm-linux-gnueabihf-gcc"
rustflags = ["-C", "target-feature=+crt-static"]
[target.armv7-unknown-linux-musleabihf]
linker = "arm-linux-gnueabihf-gcc"
rustflags = ["-C", "target-feature=+crt-static"]
[target.arm-unknown-linux-gnueabihf]
linker = "arm-linux-gnueabihf-gcc"
rustflags = ["-C", "target-feature=+crt-static"]
[target.arm-unknown-linux-musleabihf]
linker = "arm-linux-gnueabihf-gcc"
rustflags = ["-C", "target-feature=+crt-static"]
[target.mipsel-unknown-linux-musl]
linker = "mipsel-linux-gnu-gcc"
rustflags = ["-C", "target-feature=+crt-static"]
[target.x86_64-pc-windows-msvc]
rustflags = ["-C", "target-feature=+crt-static"]
[target.i686-pc-windows-msvc]
rustflags = ["-C", "target-feature=+crt-static"]
[target.x86_64-apple-darwin]
rustflags = ["-C", "target-feature=+crt-static"]
[target.aarch64-apple-darwin]
rustflags = ["-C", "target-feature=+crt-static"]
[target.i686-unknown-linux-musl]
rustflags = ["-C", "target-feature=+crt-static"]
[target.x86_64-unknown-linux-gnu]
rustflags = ["-C", "target-feature=+crt-static"]
EOF
- name: Install rust target
run: rustup target add $TARGET
- name: Run build
run: cargo build --release --verbose --target $TARGET
run: cargo build --release --verbose --target $TARGET --features $FEATURES
- name: List target
run: find ./target
- name: Compress

View File

@@ -1,6 +1,6 @@
[package]
name = "vnts"
version = "1.1.1"
version = "1.1.2"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
@@ -16,7 +16,10 @@ crossbeam = "0.8.2"
parking_lot = "0.12.1"
crossbeam-skiplist = "0.1"
rsa = "0.7.2"
rsa = {version="0.7.2", features = [] }
spki = {version="0.6.0",features=["fingerprint","alloc"]}
aes-gcm = {version="0.10.2", optional = true}
ring = {version="0.16.20", optional = true}
rand = "0.8.5"
sha2 ={version="0.10.6",features=["oid"]}
colored = "2.0.0"
@@ -29,6 +32,11 @@ protobuf = "3.2.0"
tokio = { version = "1.28.1", features = ["full"] }
async-trait = "0.1.71"
tokio-util = { version = "0.7.8", features = ["full"] }
[features]
default=["aes-gcm"]
ring-cipher=["ring"]
[build-dependencies]
protobuf-codegen = "3.2.0"
protoc-bin-vendored = "3.0.0"

View File

@@ -10,4 +10,10 @@ Options:
--netmask <NETMASK> 子网掩码,例如 --netmask 255.255.255.0
-h, --help Print help
```
默认情况服务日志输出在 './log/'下,可通过编写'./log/log4rs.yaml'文件自定义日志配置,参考[log4rs](https://github.com/estk/log4rs)
## 说明
1. 修改服务端密钥后,客户端要重启才能正常链接(修改密钥后无法自动重连)
2. 服务端密钥用于加密客户端和服务端之间传输的数据(使用rsa+aes256gcm加密)可以防止token被中间人窃取如果客户端显示的密钥指纹和服务端的不一致则表示可能有中间人攻击
3. 服务端密钥在'./key/'目录下,可以替换成自定义的密钥对
4. 客户端的密码用于加密客户端之间传输的数据
5. 默认情况服务日志输出在 './log/'下,可通过编写'./log/log4rs.yaml'文件自定义日志配置,参考[log4rs](https://github.com/estk/log4rs)

View File

@@ -3,12 +3,12 @@ use std::{fmt, io};
/// 地址解析协议由IP地址找到MAC地址
/// https://www.ietf.org/rfc/rfc6747.txt
/*
0 2 4 5 6 8 10 (字节)
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 硬件类型|协议类型|硬件地址长度|协议地址长度|操作类型|
| 源MAC地址 | 源ip地址 |
| 目的MAC地址 | 目的ip地址 |
*/
0 2 4 5 6 8 10 (字节)
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 硬件类型|协议类型|硬件地址长度|协议地址长度|操作类型|
| 源MAC地址 | 源ip地址 |
| 目的MAC地址 | 目的ip地址 |
*/
pub struct ArpPacket<B> {
buffer: B,
@@ -119,4 +119,4 @@ impl<B: AsRef<[u8]>> fmt::Debug for ArpPacket<B> {
.field("target_protocol_addr", &self.target_protocol_addr())
.finish()
}
}
}

View File

@@ -1 +1 @@
pub mod arp;
pub mod arp;

View File

@@ -1,2 +1,2 @@
pub mod packet;
pub mod protocol;
pub mod protocol;

View File

@@ -1,13 +1,13 @@
use std::{fmt, io};
use crate::ethernet::protocol::Protocol;
use std::{fmt, io};
/// 以太网帧协议
/// https://www.ietf.org/rfc/rfc894.txt
/*
0 6 12 14 (字节)
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 目的地址 | 源地址 | 类型 |
*/
0 6 12 14 (字节)
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 目的地址 | 源地址 | 类型 |
*/
pub struct EthernetPacket<B> {
pub buffer: B,
}
@@ -74,4 +74,4 @@ impl<B: AsRef<[u8]>> fmt::Debug for EthernetPacket<B> {
.field("payload", &self.payload())
.finish()
}
}
}

View File

@@ -102,7 +102,7 @@ impl From<u16> for Protocol {
0x88f7 => Ptp,
0x8902 => Cfm,
0x9100 => QinQ,
n => Unknown(n),
n => Unknown(n),
}
}
}
@@ -112,30 +112,30 @@ impl Into<u16> for Protocol {
use self::Protocol::*;
match self {
Ipv4 => 0x0800,
Arp => 0x0806,
WakeOnLan => 0x0842,
Trill => 0x22f3,
DecNet => 0x6003,
Rarp => 0x8035,
AppleTalk => 0x809b,
Aarp => 0x80f3,
Ipx => 0x8137,
Qnx => 0x8204,
Ipv6 => 0x86dd,
FlowControl => 0x8808,
CobraNet => 0x8819,
Mpls => 0x8847,
MplsMulticast => 0x8848,
Ipv4 => 0x0800,
Arp => 0x0806,
WakeOnLan => 0x0842,
Trill => 0x22f3,
DecNet => 0x6003,
Rarp => 0x8035,
AppleTalk => 0x809b,
Aarp => 0x80f3,
Ipx => 0x8137,
Qnx => 0x8204,
Ipv6 => 0x86dd,
FlowControl => 0x8808,
CobraNet => 0x8819,
Mpls => 0x8847,
MplsMulticast => 0x8848,
PppoeDiscovery => 0x8863,
PppoeSession => 0x8864,
Vlan => 0x8100,
PBridge => 0x88a8,
Lldp => 0x88cc,
Ptp => 0x88f7,
Cfm => 0x8902,
QinQ => 0x9100,
Unknown(n) => n,
PppoeSession => 0x8864,
Vlan => 0x8100,
PBridge => 0x88a8,
Lldp => 0x88cc,
Ptp => 0x88f7,
Cfm => 0x8902,
QinQ => 0x9100,
Unknown(n) => n,
}
}
}

View File

@@ -1,8 +1,8 @@
use std::{fmt, io};
use byteorder::{BigEndian, ReadBytesExt};
use crate::cal_checksum;
use crate::icmp::{Code, Kind};
use crate::ip::ipv4::packet::IpV4Packet;
use byteorder::{BigEndian, ReadBytesExt};
use std::{fmt, io};
/// icmp 协议
/* https://www.rfc-editor.org/rfc/rfc792
@@ -67,7 +67,7 @@ impl<B: AsRef<[u8]>> IcmpPacket<B> {
| Kind::TimestampReply
| Kind::InformationRequest
| Kind::InformationReply => {
let ide =u16::from_be_bytes(self.buffer.as_ref()[4..6].try_into().unwrap());
let ide = u16::from_be_bytes(self.buffer.as_ref()[4..6].try_into().unwrap());
let seq = u16::from_be_bytes(self.buffer.as_ref()[6..8].try_into().unwrap());
HeaderOther::Identifier(ide, seq)
}
@@ -121,11 +121,11 @@ impl<B: AsRef<[u8]>> fmt::Debug for IcmpPacket<B> {
} else {
"icmp::Packet!"
})
.field("kind", &self.kind())
.field("code", &self.code())
.field("checksum", &self.checksum())
.field("payload", &self.payload())
.finish()
.field("kind", &self.kind())
.field("code", &self.code())
.field("checksum", &self.checksum())
.field("payload", &self.payload())
.finish()
}
}

View File

@@ -1,17 +1,17 @@
use std::{fmt, io};
use std::net::Ipv4Addr;
use crate::cal_checksum;
use std::net::Ipv4Addr;
use std::{fmt, io};
/// igmp v1
/* https://datatracker.ietf.org/doc/html/rfc1112
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|Version| Type | Unused | Checksum |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Group Address |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|Version| Type | Unused | Checksum |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Group Address |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
/// v1版本的报文
pub struct IgmpV1Packet<B> {
pub buffer: B,
@@ -43,7 +43,7 @@ impl Into<u8> for IgmpV1Type {
match self {
IgmpV1Type::Query => 0x11,
IgmpV1Type::ReportV1 => 0x12,
IgmpV1Type::Unknown(v) => v
IgmpV1Type::Unknown(v) => v,
}
}
}
@@ -114,4 +114,4 @@ impl<B: AsRef<[u8]>> fmt::Debug for IgmpV1Packet<B> {
.field("group_address", &self.group_address())
.finish()
}
}
}

View File

@@ -1,18 +1,18 @@
use std::{fmt, io};
use std::net::Ipv4Addr;
use crate::cal_checksum;
use std::net::Ipv4Addr;
use std::{fmt, io};
/// igmp v2
/* https://www.rfc-editor.org/rfc/rfc2236.html
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Type | Max Resp Time | Checksum |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Group Address |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Type | Max Resp Time | Checksum |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Group Address |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
/// v2版本的报文
pub struct IgmpV2Packet<B> {
@@ -48,7 +48,7 @@ impl Into<u8> for IgmpV2Type {
IgmpV2Type::Query => 0x11,
IgmpV2Type::ReportV2 => 0x16,
IgmpV2Type::LeaveV2 => 0x17,
IgmpV2Type::Unknown(v) => v
IgmpV2Type::Unknown(v) => v,
}
}
}

View File

@@ -1,5 +1,5 @@
use std::{fmt, io};
use std::net::Ipv4Addr;
use std::{fmt, io};
use crate::cal_checksum;
@@ -116,7 +116,7 @@ impl Into<u8> for IgmpV3Type {
match self {
IgmpV3Type::Query => 0x11,
IgmpV3Type::ReportV3 => 0x22,
IgmpV3Type::Unknown(v) => v
IgmpV3Type::Unknown(v) => v,
}
}
}
@@ -203,7 +203,7 @@ impl<B: AsRef<[u8]> + AsMut<[u8]>> IgmpV3QueryPacket<B> {
self.buffer.as_mut()[2..4].copy_from_slice(&checksum.to_be_bytes())
}
pub fn set_qrv(&mut self, qrv: u8) {
self.buffer.as_mut()[8] = (self.buffer.as_ref()[8]&(!0x07)) | (qrv & 0x07)
self.buffer.as_mut()[8] = (self.buffer.as_ref()[8] & (!0x07)) | (qrv & 0x07)
}
pub fn set_qqic(&mut self, qqic: u8) {
self.buffer.as_mut()[9] = qqic
@@ -349,7 +349,10 @@ impl<B: AsRef<[u8]>> IgmpV3ReportPacket<B> {
return None;
}
if let Ok(record) = IgmpV3RecordPacket::new(&buf[start..]) {
let end = start + 8 + record.aux_data_len() as usize * 4 + record.source_number() as usize * 4;
let end = start
+ 8
+ record.aux_data_len() as usize * 4
+ record.source_number() as usize * 4;
if end > len {
return None;
}
@@ -364,7 +367,6 @@ impl<B: AsRef<[u8]>> IgmpV3ReportPacket<B> {
}
}
/// group record
pub struct IgmpV3RecordPacket<B> {
pub buffer: B,
@@ -488,4 +490,4 @@ impl<B: AsRef<[u8]>> fmt::Debug for IgmpV3RecordPacket<B> {
.field("auxiliary_data", &self.auxiliary_data())
.finish()
}
}
}

View File

@@ -2,7 +2,7 @@ pub mod igmp_v1;
pub mod igmp_v2;
pub mod igmp_v3;
#[derive(Debug,Copy, Clone,Eq, PartialEq)]
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub enum IgmpType {
/// 0x11 所有组224.0.0.1或者特定组
Query,
@@ -40,7 +40,7 @@ impl Into<u8> for IgmpType {
IgmpType::ReportV2 => 0x16,
IgmpType::ReportV3 => 0x22,
IgmpType::LeaveV2 => 0x17,
IgmpType::Unknown(v) => v
IgmpType::Unknown(v) => v,
}
}
}
}

View File

@@ -1,6 +1,5 @@
use std::{fmt, io};
use std::net::Ipv4Addr;
use std::{fmt, io};
use crate::cal_checksum;
use crate::ip::ipv4::protocol::Protocol;

View File

@@ -1,4 +1,4 @@
#[derive(Eq, PartialEq,Ord, PartialOrd, Copy, Clone, Debug)]
#[derive(Eq, PartialEq, Ord, PartialOrd, Copy, Clone, Debug)]
pub enum Protocol {
///
Hopopt,

View File

@@ -1,5 +1,5 @@
use std::io;
use ipv4::packet::IpV4Packet;
use std::io;
pub mod ipv4;

View File

@@ -3,13 +3,13 @@ use std::net::Ipv4Addr;
use byteorder::BigEndian;
use byteorder::ReadBytesExt;
pub mod arp;
pub mod ethernet;
pub mod icmp;
pub mod igmp;
pub mod ip;
pub mod tcp;
pub mod udp;
pub mod ethernet;
pub mod arp;
// pub enum IpUpperLayer<B> {
// UDP(UdpPacket<B>),
// Unknown(B),

View File

@@ -1,5 +1,5 @@
use std::{fmt, io};
use std::net::Ipv4Addr;
use std::{fmt, io};
use crate::tcp::Flags;
@@ -58,7 +58,11 @@ impl<B: AsRef<[u8]>> TcpPacket<B> {
buffer,
}
}
pub fn new(source_ip: Ipv4Addr, destination_ip: Ipv4Addr, buffer: B) -> io::Result<TcpPacket<B>> {
pub fn new(
source_ip: Ipv4Addr,
destination_ip: Ipv4Addr,
buffer: B,
) -> io::Result<TcpPacket<B>> {
let packet = TcpPacket::unchecked(source_ip, destination_ip, buffer);
if packet.buffer.as_ref().len() < 20 {

View File

@@ -1,5 +1,5 @@
use std::{fmt, io};
use std::net::Ipv4Addr;
use std::{fmt, io};
/// udp协议
///
@@ -60,7 +60,11 @@ impl<B: AsRef<[u8]>> UdpPacket<B> {
buffer,
}
}
pub fn new(source_ip: Ipv4Addr, destination_ip: Ipv4Addr, buffer: B) -> io::Result<UdpPacket<B>> {
pub fn new(
source_ip: Ipv4Addr,
destination_ip: Ipv4Addr,
buffer: B,
) -> io::Result<UdpPacket<B>> {
if buffer.as_ref().len() < 8 {
Err(io::Error::from(io::ErrorKind::InvalidData))?;
}

View File

@@ -0,0 +1,109 @@
use std::io;
use aes_gcm::aead::consts::{U12, U16};
use aes_gcm::aead::generic_array::GenericArray;
use aes_gcm::{AeadInPlace, Aes256Gcm, Key, KeyInit, Nonce, Tag};
use rand::RngCore;
use crate::cipher::finger::Finger;
use crate::protocol::{body::SecretBody, body::ENCRYPTION_RESERVED, NetPacket};
#[derive(Clone)]
pub struct Aes256GcmCipher {
cipher: Aes256Gcm,
finger: Finger,
}
impl Aes256GcmCipher {
pub fn new(key: [u8; 32], finger: Finger) -> Self {
let key: &Key<Aes256Gcm> = &key.into();
Self {
cipher: Aes256Gcm::new(key),
finger,
}
}
pub fn decrypt_ipv4<B: AsRef<[u8]> + AsMut<[u8]>>(
&self,
net_packet: &mut NetPacket<B>,
) -> io::Result<()> {
if !net_packet.is_encrypt() {
//未加密的数据直接丢弃
return Err(io::Error::new(io::ErrorKind::Other, "not encrypt"));
}
if net_packet.payload().len() < ENCRYPTION_RESERVED {
log::error!("数据异常,长度小于{}", ENCRYPTION_RESERVED);
return Err(io::Error::new(io::ErrorKind::Other, "data err"));
}
let mut nonce_raw = [0; 12];
nonce_raw[0..4].copy_from_slice(&net_packet.source().octets());
nonce_raw[4..8].copy_from_slice(&net_packet.destination().octets());
nonce_raw[8] = net_packet.protocol().into();
nonce_raw[9] = net_packet.transport_protocol();
nonce_raw[10] = net_packet.is_gateway() as u8;
nonce_raw[11] = net_packet.source_ttl();
let nonce: &GenericArray<u8, U12> = Nonce::from_slice(&nonce_raw);
let mut secret_body = SecretBody::new(net_packet.payload_mut())?;
let tag = secret_body.tag();
if tag.len() != 16 {
return Err(io::Error::new(io::ErrorKind::Other, "tag err"));
}
let finger = self.finger.calculate_finger(&nonce_raw, &secret_body);
if &finger != secret_body.finger() {
return Err(io::Error::new(io::ErrorKind::Other, "finger err"));
}
let tag: GenericArray<u8, U16> = Tag::clone_from_slice(tag);
if let Err(e) =
self.cipher
.decrypt_in_place_detached(nonce, &[], secret_body.body_mut(), &tag)
{
return Err(io::Error::new(
io::ErrorKind::Other,
format!("解密失败:{}", e),
));
}
net_packet.set_encrypt_flag(false);
net_packet.set_data_len(net_packet.data_len() - ENCRYPTION_RESERVED)?;
return Ok(());
}
/// net_packet 必须预留足够长度
/// data_len是有效载荷的长度
/// 返回加密后载荷的长度
pub fn encrypt_ipv4<B: AsRef<[u8]> + AsMut<[u8]>>(
&self,
net_packet: &mut NetPacket<B>,
) -> io::Result<()> {
if net_packet.reserve() < ENCRYPTION_RESERVED {
return Err(io::Error::new(io::ErrorKind::Other, "too short"));
}
let mut nonce_raw = [0; 12];
nonce_raw[0..4].copy_from_slice(&net_packet.source().octets());
nonce_raw[4..8].copy_from_slice(&net_packet.destination().octets());
nonce_raw[8] = net_packet.protocol().into();
nonce_raw[9] = net_packet.transport_protocol();
nonce_raw[10] = net_packet.is_gateway() as u8;
nonce_raw[11] = net_packet.source_ttl();
let nonce: &GenericArray<u8, U12> = Nonce::from_slice(&nonce_raw);
net_packet.set_data_len(net_packet.data_len() + ENCRYPTION_RESERVED)?;
let mut secret_body = SecretBody::new(net_packet.payload_mut())?;
secret_body.set_random(rand::thread_rng().next_u32());
return match self
.cipher
.encrypt_in_place_detached(nonce, &[], secret_body.body_mut())
{
Ok(tag) => {
secret_body.set_tag(tag.as_slice())?;
let finger = self.finger.calculate_finger(&nonce_raw, &secret_body);
secret_body.set_finger(&finger)?;
net_packet.set_encrypt_flag(true);
Ok(())
}
Err(e) => Err(io::Error::new(
io::ErrorKind::Other,
format!("加密失败:{}", e),
)),
};
}
}

52
src/cipher/finger.rs Normal file
View File

@@ -0,0 +1,52 @@
use std::io;
use sha2::Digest;
use crate::protocol::{body::SecretBody, body::ENCRYPTION_RESERVED, NetPacket};
#[derive(Clone)]
pub struct Finger {
token: String,
}
impl Finger {
pub fn new(token: String) -> Self {
Finger { token }
}
pub fn check_finger<B: AsRef<[u8]>>(&self, net_packet: &NetPacket<B>) -> io::Result<()> {
if !net_packet.is_encrypt() {
//未加密的数据直接丢弃
return Err(io::Error::new(io::ErrorKind::Other, "not encrypt"));
}
if net_packet.payload().len() < ENCRYPTION_RESERVED {
log::error!("数据异常,长度小于{}", ENCRYPTION_RESERVED);
return Err(io::Error::new(io::ErrorKind::Other, "data err"));
}
let mut nonce_raw = [0; 12];
nonce_raw[0..4].copy_from_slice(&net_packet.source().octets());
nonce_raw[4..8].copy_from_slice(&net_packet.destination().octets());
nonce_raw[8] = net_packet.protocol().into();
nonce_raw[9] = net_packet.transport_protocol();
nonce_raw[10] = net_packet.is_gateway() as u8;
nonce_raw[11] = net_packet.source_ttl();
let secret_body = SecretBody::new(net_packet.payload())?;
let finger = self.calculate_finger(&nonce_raw, &secret_body);
if &finger != secret_body.finger() {
return Err(io::Error::new(io::ErrorKind::Other, "finger err"));
}
Ok(())
}
pub fn calculate_finger<B: AsRef<[u8]>>(
&self,
nonce_raw: &[u8; 12],
secret_body: &SecretBody<B>,
) -> [u8; 12] {
let mut hasher = sha2::Sha256::new();
hasher.update(secret_body.body());
hasher.update(nonce_raw);
hasher.update(secret_body.tag());
hasher.update(&self.token);
let key: [u8; 32] = hasher.finalize().into();
return key[20..].try_into().unwrap();
}
}

13
src/cipher/mod.rs Normal file
View File

@@ -0,0 +1,13 @@
#[cfg(not(feature = "ring-cipher"))]
mod aes_gcm_cipher;
mod finger;
#[cfg(feature = "ring-cipher")]
mod ring_cipher;
mod rsa_cipher;
#[cfg(not(feature = "ring-cipher"))]
pub use aes_gcm_cipher::Aes256GcmCipher;
pub use finger::Finger;
#[cfg(feature = "ring-cipher")]
pub use ring_cipher::Aes256GcmCipher;
pub use rsa_cipher::RsaCipher;

143
src/cipher/ring_cipher.rs Normal file
View File

@@ -0,0 +1,143 @@
use crate::cipher::Finger;
use rand::RngCore;
use ring::aead;
use ring::aead::{LessSafeKey, UnboundKey};
use std::io;
use crate::protocol::body::{SecretBody, ENCRYPTION_RESERVED};
use crate::protocol::NetPacket;
#[derive(Clone)]
pub struct Aes256GcmCipher {
pub(crate) cipher: AesGcmEnum,
pub(crate) finger: Finger,
}
pub enum AesGcmEnum {
AesGCM128(LessSafeKey, [u8; 16]),
AesGCM256(LessSafeKey, [u8; 32]),
}
impl Clone for AesGcmEnum {
fn clone(&self) -> Self {
match &self {
AesGcmEnum::AesGCM128(_, key) => {
let c =
LessSafeKey::new(UnboundKey::new(&aead::AES_128_GCM, key.as_slice()).unwrap());
AesGcmEnum::AesGCM128(c, *key)
}
AesGcmEnum::AesGCM256(_, key) => {
let c =
LessSafeKey::new(UnboundKey::new(&aead::AES_256_GCM, key.as_slice()).unwrap());
AesGcmEnum::AesGCM256(c, *key)
}
}
}
}
impl Aes256GcmCipher {
pub fn new(key: [u8; 32], finger: Finger) -> Self {
let cipher = LessSafeKey::new(UnboundKey::new(&aead::AES_256_GCM, &key).unwrap());
Self {
cipher: AesGcmEnum::AesGCM256(cipher, key),
finger,
}
}
pub fn decrypt_ipv4<B: AsRef<[u8]> + AsMut<[u8]>>(
&self,
net_packet: &mut NetPacket<B>,
) -> io::Result<()> {
if !net_packet.is_encrypt() {
//未加密的数据直接丢弃
return Err(io::Error::new(io::ErrorKind::Other, "not encrypt"));
}
if net_packet.payload().len() < ENCRYPTION_RESERVED {
log::error!("数据异常,长度小于{}", ENCRYPTION_RESERVED);
return Err(io::Error::new(io::ErrorKind::Other, "data err"));
}
let mut nonce_raw = [0; 12];
nonce_raw[0..4].copy_from_slice(&net_packet.source().octets());
nonce_raw[4..8].copy_from_slice(&net_packet.destination().octets());
nonce_raw[8] = net_packet.protocol().into();
nonce_raw[9] = net_packet.transport_protocol();
nonce_raw[10] = net_packet.is_gateway() as u8;
nonce_raw[11] = net_packet.source_ttl();
let nonce = aead::Nonce::assume_unique_for_key(nonce_raw);
let mut secret_body = SecretBody::new(net_packet.payload_mut())?;
let tag = secret_body.tag();
if tag.len() != 16 {
return Err(io::Error::new(io::ErrorKind::Other, "tag err"));
}
let finger = self.finger.calculate_finger(&nonce_raw, &secret_body);
if &finger != secret_body.finger() {
return Err(io::Error::new(io::ErrorKind::Other, "finger err"));
}
let rs = match &self.cipher {
AesGcmEnum::AesGCM128(cipher, _) => {
cipher.open_in_place(nonce, aead::Aad::empty(), secret_body.en_body_mut())
}
AesGcmEnum::AesGCM256(cipher, _) => {
cipher.open_in_place(nonce, aead::Aad::empty(), secret_body.en_body_mut())
}
};
if let Err(e) = rs {
return Err(io::Error::new(
io::ErrorKind::Other,
format!("解密失败:{}", e),
));
}
net_packet.set_encrypt_flag(false);
net_packet.set_data_len(net_packet.data_len() - ENCRYPTION_RESERVED)?;
return Ok(());
}
/// net_packet 必须预留足够长度
/// data_len是有效载荷的长度
/// 返回加密后载荷的长度
pub fn encrypt_ipv4<B: AsRef<[u8]> + AsMut<[u8]>>(
&self,
net_packet: &mut NetPacket<B>,
) -> io::Result<()> {
let mut nonce_raw = [0; 12];
nonce_raw[0..4].copy_from_slice(&net_packet.source().octets());
nonce_raw[4..8].copy_from_slice(&net_packet.destination().octets());
nonce_raw[8] = net_packet.protocol().into();
nonce_raw[9] = net_packet.transport_protocol();
nonce_raw[10] = net_packet.is_gateway() as u8;
nonce_raw[11] = net_packet.source_ttl();
let nonce = aead::Nonce::assume_unique_for_key(nonce_raw);
let data_len = net_packet.data_len() + ENCRYPTION_RESERVED;
net_packet.set_data_len(data_len)?;
let mut secret_body = SecretBody::new(net_packet.payload_mut())?;
secret_body.set_random(rand::thread_rng().next_u32());
let rs = match &self.cipher {
AesGcmEnum::AesGCM128(cipher, _) => {
cipher.seal_in_place_separate_tag(nonce, aead::Aad::empty(), secret_body.body_mut())
}
AesGcmEnum::AesGCM256(cipher, _) => {
cipher.seal_in_place_separate_tag(nonce, aead::Aad::empty(), secret_body.body_mut())
}
};
return match rs {
Ok(tag) => {
let tag = tag.as_ref();
if tag.len() != 16 {
return Err(io::Error::new(
io::ErrorKind::Other,
format!("加密tag长度错误:{}", tag.len()),
));
}
secret_body.set_tag(tag)?;
let finger = self.finger.calculate_finger(&nonce_raw, &secret_body);
secret_body.set_finger(&finger)?;
net_packet.set_encrypt_flag(true);
Ok(())
}
Err(e) => Err(io::Error::new(
io::ErrorKind::Other,
format!("加密失败:{}", e),
)),
};
}
}

146
src/cipher/rsa_cipher.rs Normal file
View File

@@ -0,0 +1,146 @@
use std::io;
use std::path::PathBuf;
use std::sync::Arc;
use crate::protocol::body::RsaSecretBody;
use crate::protocol::NetPacket;
use rsa::pkcs8::der::Decode;
use rsa::pkcs8::{DecodePrivateKey, EncodePrivateKey, EncodePublicKey, LineEnding};
use rsa::{RsaPrivateKey, RsaPublicKey};
use sha2::Digest;
#[derive(Clone)]
pub struct RsaCipher {
inner: Arc<Inner>,
}
struct Inner {
private_key: RsaPrivateKey,
public_key_der: Vec<u8>,
}
impl RsaCipher {
pub fn new() -> io::Result<Self> {
let priv_key_path = PathBuf::from("key/private_key.pem");
let private_key = if priv_key_path.exists() {
let key = std::fs::read_to_string(priv_key_path)?;
let private_key = match RsaPrivateKey::from_pkcs8_pem(&key) {
Ok(private_key) => private_key,
Err(e) => {
return Err(io::Error::new(
io::ErrorKind::Other,
format!("'key/private_key.pem' content error {}", e),
));
}
};
private_key
} else {
let path = PathBuf::from("key");
if !path.exists() {
std::fs::create_dir(path)?;
}
let mut rng = rand::thread_rng();
let bits = 2048;
let private_key = match RsaPrivateKey::new(&mut rng, bits) {
Ok(private_key) => private_key,
Err(e) => {
return Err(io::Error::new(
io::ErrorKind::Other,
format!("failed to generate a key {}", e),
));
}
};
match private_key.write_pkcs8_pem_file(priv_key_path, LineEnding::CRLF) {
Ok(_) => {}
Err(e) => {
return Err(io::Error::new(
io::ErrorKind::Other,
format!("failed to write to file 'key/private_key.pem' {}", e),
));
}
};
private_key
};
let public_key = RsaPublicKey::from(&private_key);
match public_key.write_public_key_pem_file("key/public_key.pem", LineEnding::CRLF) {
Ok(_) => {}
Err(e) => {
return Err(io::Error::new(
io::ErrorKind::Other,
format!("failed to write to file 'key/public_key.pem' {}", e),
));
}
};
let public_key_der = match public_key.to_public_key_der() {
Ok(public_key_der) => public_key_der.to_vec(),
Err(e) => {
return Err(io::Error::new(
io::ErrorKind::Other,
format!("to_public_key_der failed {}", e),
));
}
};
let inner = Inner {
private_key,
public_key_der,
};
Ok(Self {
inner: Arc::new(inner),
})
}
pub fn finger(&self) -> io::Result<String> {
match rsa::pkcs8::SubjectPublicKeyInfo::from_der(&self.inner.public_key_der) {
Ok(spki) => match spki.fingerprint_base64() {
Ok(finger) => Ok(finger),
Err(e) => Err(io::Error::new(
io::ErrorKind::Other,
format!("fingerprint_base64 error {}", e),
)),
},
Err(e) => Err(io::Error::new(
io::ErrorKind::Other,
format!("from_der error {}", e),
)),
}
}
pub fn public_key(&self) -> &[u8] {
&self.inner.public_key_der
}
}
impl RsaCipher {
pub fn decrypt<B: AsRef<[u8]>>(
&self,
net_packet: &NetPacket<B>,
) -> io::Result<RsaSecretBody<Vec<u8>>> {
match self
.inner
.private_key
.decrypt(rsa::PaddingScheme::PKCS1v15Encrypt, net_packet.payload())
{
Ok(rs) => {
let mut nonce_raw = [0; 12];
nonce_raw[0..4].copy_from_slice(&net_packet.source().octets());
nonce_raw[4..8].copy_from_slice(&net_packet.destination().octets());
nonce_raw[8] = net_packet.protocol().into();
nonce_raw[9] = net_packet.transport_protocol();
nonce_raw[10] = net_packet.is_gateway() as u8;
nonce_raw[11] = net_packet.source_ttl();
let secret_body = RsaSecretBody::new(rs)?;
let mut hasher = sha2::Sha256::new();
hasher.update(secret_body.body());
hasher.update(nonce_raw);
let key: [u8; 32] = hasher.finalize().into();
if secret_body.finger() != &key[16..] {
return Err(io::Error::new(io::ErrorKind::Other, "finger err"));
}
Ok(secret_body)
}
Err(e) => Err(io::Error::new(
io::ErrorKind::Other,
format!("decrypt failed {}", e),
)),
}
}
}

View File

@@ -4,14 +4,16 @@ use std::net::Ipv4Addr;
use std::path::PathBuf;
use std::sync::Arc;
use crate::cipher::RsaCipher;
use crate::service::{start_tcp, start_udp};
use clap::Parser;
use tokio::net::{TcpListener, UdpSocket};
use crate::service::{start_tcp, start_udp};
pub mod error;
pub mod proto;
pub mod protocol;
pub mod service;
mod cipher;
mod error;
mod proto;
mod protocol;
mod service;
/// 默认网关信息
const GATEWAY: Ipv4Addr = Ipv4Addr::new(10, 26, 0, 1);
@@ -52,7 +54,8 @@ fn log_init() {
let log_config = log_path.join("log4rs.yaml");
if !log_config.exists() {
if let Ok(mut f) = std::fs::File::create(&log_config) {
let _ = f.write_all(b"refresh_rate: 30 seconds
let _ = f.write_all(
b"refresh_rate: 30 seconds
appenders:
rolling_file:
kind: rolling_file
@@ -74,7 +77,8 @@ appenders:
root:
level: info
appenders:
- rolling_file");
- rolling_file",
);
}
}
let _ = log4rs::init_file(log_config, Default::default());
@@ -82,49 +86,76 @@ root:
#[tokio::main]
async fn main() {
log_init();
let args = StartArgs::parse();
let port = args.port.unwrap_or(29871);
println!("端口{}", port);
let port = args.port.unwrap_or(29872);
println!("端口: {}", port);
let white_token = if let Some(white_token) = args.white_token {
Some(HashSet::from_iter(white_token.into_iter()))
} else {
None
};
println!("token白名单{:?}", white_token);
println!("token白名单: {:?}", white_token);
let gateway = if let Some(gateway) = args.gateway {
gateway.parse::<Ipv4Addr>().expect("网关错误必须为有效的ipv4地址")
match gateway.parse::<Ipv4Addr>() {
Ok(ip) => ip,
Err(e) => {
log::error!("网关错误必须为有效的ipv4地址 gateway={},e={}", gateway, e);
panic!("网关错误必须为有效的ipv4地址")
}
}
} else {
GATEWAY
};
println!("网关{:?}", gateway);
println!("网关: {:?}", gateway);
if gateway.is_unspecified() {
println!("网关地址无效");
log::error!("网关错误必须为有效的ipv4地址 gateway={}", gateway);
return;
}
if gateway.is_broadcast() {
println!("网关错误,不能为广播地址");
log::error!("网关错误,不能为广播地址 gateway={}", gateway);
return;
}
if gateway.is_multicast() {
println!("网关错误,不能为组播地址");
log::error!("网关错误,不能为组播地址 gateway={}", gateway);
return;
}
if !gateway.is_private() {
println!("Warning 不是一个私有地址:{:?}将有可能和公网ip冲突", gateway);
println!(
"Warning 不是一个私有地址:{:?}将有可能和公网ip冲突",
gateway
);
log::warn!("网关错误,不是一个私有地址 gateway={}", gateway);
}
let netmask = if let Some(netmask) = args.netmask {
netmask.parse::<Ipv4Addr>().expect("子网掩码错误必须为有效的ipv4地址")
match netmask.parse::<Ipv4Addr>() {
Ok(ip) => ip,
Err(e) => {
log::error!(
"子网掩码错误必须为有效的ipv4地址 netmask={},e={}",
netmask,
e
);
panic!("子网掩码错误必须为有效的ipv4地址")
}
}
} else {
NETMASK
};
println!("子网掩码{:?}", netmask);
if netmask.is_broadcast() || netmask.is_unspecified() || !(!u32::from_be_bytes(netmask.octets()) + 1).is_power_of_two() {
println!("子网掩码: {:?}", netmask);
if netmask.is_broadcast()
|| netmask.is_unspecified()
|| !(!u32::from_be_bytes(netmask.octets()) + 1).is_power_of_two()
{
println!("子网掩码错误");
log::error!("子网掩码错误 netmask={}", netmask);
return;
}
let broadcast = (!u32::from_be_bytes(netmask.octets()))
| u32::from_be_bytes(gateway.octets());
let broadcast = (!u32::from_be_bytes(netmask.octets())) | u32::from_be_bytes(gateway.octets());
let broadcast = Ipv4Addr::from(broadcast);
let config = ConfigInfo {
port,
@@ -133,33 +164,38 @@ async fn main() {
broadcast,
netmask,
};
log_init();
log::info!("config:{:?}",config);
let rsa = match RsaCipher::new() {
Ok(rsa) => {
println!("密钥指纹: {}", rsa.finger().unwrap());
Some(rsa)
}
Err(e) => {
log::error!("获取密钥错误:{:?}", e);
panic!("获取密钥错误:{}", e);
}
};
log::info!("config:{:?}", config);
let udp = match UdpSocket::bind(format!("0.0.0.0:{}", port)).await {
Ok(udp) => { Arc::new(udp) }
Ok(udp) => Arc::new(udp),
Err(e) => {
log::warn!("udp启动失败:{:?}",e);
panic!("{:?}", e);
log::warn!("udp启动失败:{:?}", e);
panic!("udp启动失败:{}", e);
}
};
log::info!("监听udp端口:{:?}",udp.local_addr().unwrap());
println!("监听udp端口:{:?}", udp.local_addr().unwrap());
log::info!("监听udp端口: {:?}", udp.local_addr().unwrap());
println!("监听udp端口: {:?}", udp.local_addr().unwrap());
let tcp = match TcpListener::bind(format!("0.0.0.0:{}", port)).await {
Ok(tcp) => { tcp }
Ok(tcp) => tcp,
Err(e) => {
log::warn!("tcp启动失败:{:?}",e);
panic!("{:?}", e);
log::warn!("tcp启动失败:{:?}", e);
panic!("tcp启动失败:{:?}", e);
}
};
log::info!("监听tcp端口:{:?}",tcp.local_addr().unwrap());
println!("监听tcp端口:{:?}", tcp.local_addr().unwrap());
log::info!("监听tcp端口: {:?}", tcp.local_addr().unwrap());
println!("监听tcp端口: {:?}", tcp.local_addr().unwrap());
let config = config.clone();
let main_udp = udp.clone();
let tcp_config = config.clone();
tokio::spawn(async move {
if let Err(e) = start_tcp(tcp, main_udp, tcp_config).await {
log::warn!("tcp任务结束:{:?}",e);
}
});
start_udp(udp, config).await;
tokio::spawn(start_tcp(tcp, main_udp, tcp_config, rsa.clone()));
start_udp(udp, config, rsa.clone()).await;
}

View File

@@ -25,6 +25,462 @@
/// of protobuf runtime.
const _PROTOBUF_VERSION_CHECK: () = ::protobuf::VERSION_3_2_0;
#[derive(PartialEq,Clone,Default,Debug)]
// @@protoc_insertion_point(message:HandshakeRequest)
pub struct HandshakeRequest {
// message fields
// @@protoc_insertion_point(field:HandshakeRequest.version)
pub version: ::std::string::String,
// @@protoc_insertion_point(field:HandshakeRequest.secret)
pub secret: bool,
// special fields
// @@protoc_insertion_point(special_field:HandshakeRequest.special_fields)
pub special_fields: ::protobuf::SpecialFields,
}
impl<'a> ::std::default::Default for &'a HandshakeRequest {
fn default() -> &'a HandshakeRequest {
<HandshakeRequest as ::protobuf::Message>::default_instance()
}
}
impl HandshakeRequest {
pub fn new() -> HandshakeRequest {
::std::default::Default::default()
}
fn generated_message_descriptor_data() -> ::protobuf::reflect::GeneratedMessageDescriptorData {
let mut fields = ::std::vec::Vec::with_capacity(2);
let mut oneofs = ::std::vec::Vec::with_capacity(0);
fields.push(::protobuf::reflect::rt::v2::make_simpler_field_accessor::<_, _>(
"version",
|m: &HandshakeRequest| { &m.version },
|m: &mut HandshakeRequest| { &mut m.version },
));
fields.push(::protobuf::reflect::rt::v2::make_simpler_field_accessor::<_, _>(
"secret",
|m: &HandshakeRequest| { &m.secret },
|m: &mut HandshakeRequest| { &mut m.secret },
));
::protobuf::reflect::GeneratedMessageDescriptorData::new_2::<HandshakeRequest>(
"HandshakeRequest",
fields,
oneofs,
)
}
}
impl ::protobuf::Message for HandshakeRequest {
const NAME: &'static str = "HandshakeRequest";
fn is_initialized(&self) -> bool {
true
}
fn merge_from(&mut self, is: &mut ::protobuf::CodedInputStream<'_>) -> ::protobuf::Result<()> {
while let Some(tag) = is.read_raw_tag_or_eof()? {
match tag {
10 => {
self.version = is.read_string()?;
},
16 => {
self.secret = is.read_bool()?;
},
tag => {
::protobuf::rt::read_unknown_or_skip_group(tag, is, self.special_fields.mut_unknown_fields())?;
},
};
}
::std::result::Result::Ok(())
}
// Compute sizes of nested messages
#[allow(unused_variables)]
fn compute_size(&self) -> u64 {
let mut my_size = 0;
if !self.version.is_empty() {
my_size += ::protobuf::rt::string_size(1, &self.version);
}
if self.secret != false {
my_size += 1 + 1;
}
my_size += ::protobuf::rt::unknown_fields_size(self.special_fields.unknown_fields());
self.special_fields.cached_size().set(my_size as u32);
my_size
}
fn write_to_with_cached_sizes(&self, os: &mut ::protobuf::CodedOutputStream<'_>) -> ::protobuf::Result<()> {
if !self.version.is_empty() {
os.write_string(1, &self.version)?;
}
if self.secret != false {
os.write_bool(2, self.secret)?;
}
os.write_unknown_fields(self.special_fields.unknown_fields())?;
::std::result::Result::Ok(())
}
fn special_fields(&self) -> &::protobuf::SpecialFields {
&self.special_fields
}
fn mut_special_fields(&mut self) -> &mut ::protobuf::SpecialFields {
&mut self.special_fields
}
fn new() -> HandshakeRequest {
HandshakeRequest::new()
}
fn clear(&mut self) {
self.version.clear();
self.secret = false;
self.special_fields.clear();
}
fn default_instance() -> &'static HandshakeRequest {
static instance: HandshakeRequest = HandshakeRequest {
version: ::std::string::String::new(),
secret: false,
special_fields: ::protobuf::SpecialFields::new(),
};
&instance
}
}
impl ::protobuf::MessageFull for HandshakeRequest {
fn descriptor() -> ::protobuf::reflect::MessageDescriptor {
static descriptor: ::protobuf::rt::Lazy<::protobuf::reflect::MessageDescriptor> = ::protobuf::rt::Lazy::new();
descriptor.get(|| file_descriptor().message_by_package_relative_name("HandshakeRequest").unwrap()).clone()
}
}
impl ::std::fmt::Display for HandshakeRequest {
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
::protobuf::text_format::fmt(self, f)
}
}
impl ::protobuf::reflect::ProtobufValue for HandshakeRequest {
type RuntimeType = ::protobuf::reflect::rt::RuntimeTypeMessage<Self>;
}
#[derive(PartialEq,Clone,Default,Debug)]
// @@protoc_insertion_point(message:HandshakeResponse)
pub struct HandshakeResponse {
// message fields
// @@protoc_insertion_point(field:HandshakeResponse.version)
pub version: ::std::string::String,
// @@protoc_insertion_point(field:HandshakeResponse.secret)
pub secret: bool,
// @@protoc_insertion_point(field:HandshakeResponse.public_key)
pub public_key: ::std::vec::Vec<u8>,
// @@protoc_insertion_point(field:HandshakeResponse.key_finger)
pub key_finger: ::std::string::String,
// special fields
// @@protoc_insertion_point(special_field:HandshakeResponse.special_fields)
pub special_fields: ::protobuf::SpecialFields,
}
impl<'a> ::std::default::Default for &'a HandshakeResponse {
fn default() -> &'a HandshakeResponse {
<HandshakeResponse as ::protobuf::Message>::default_instance()
}
}
impl HandshakeResponse {
pub fn new() -> HandshakeResponse {
::std::default::Default::default()
}
fn generated_message_descriptor_data() -> ::protobuf::reflect::GeneratedMessageDescriptorData {
let mut fields = ::std::vec::Vec::with_capacity(4);
let mut oneofs = ::std::vec::Vec::with_capacity(0);
fields.push(::protobuf::reflect::rt::v2::make_simpler_field_accessor::<_, _>(
"version",
|m: &HandshakeResponse| { &m.version },
|m: &mut HandshakeResponse| { &mut m.version },
));
fields.push(::protobuf::reflect::rt::v2::make_simpler_field_accessor::<_, _>(
"secret",
|m: &HandshakeResponse| { &m.secret },
|m: &mut HandshakeResponse| { &mut m.secret },
));
fields.push(::protobuf::reflect::rt::v2::make_simpler_field_accessor::<_, _>(
"public_key",
|m: &HandshakeResponse| { &m.public_key },
|m: &mut HandshakeResponse| { &mut m.public_key },
));
fields.push(::protobuf::reflect::rt::v2::make_simpler_field_accessor::<_, _>(
"key_finger",
|m: &HandshakeResponse| { &m.key_finger },
|m: &mut HandshakeResponse| { &mut m.key_finger },
));
::protobuf::reflect::GeneratedMessageDescriptorData::new_2::<HandshakeResponse>(
"HandshakeResponse",
fields,
oneofs,
)
}
}
impl ::protobuf::Message for HandshakeResponse {
const NAME: &'static str = "HandshakeResponse";
fn is_initialized(&self) -> bool {
true
}
fn merge_from(&mut self, is: &mut ::protobuf::CodedInputStream<'_>) -> ::protobuf::Result<()> {
while let Some(tag) = is.read_raw_tag_or_eof()? {
match tag {
10 => {
self.version = is.read_string()?;
},
16 => {
self.secret = is.read_bool()?;
},
26 => {
self.public_key = is.read_bytes()?;
},
34 => {
self.key_finger = is.read_string()?;
},
tag => {
::protobuf::rt::read_unknown_or_skip_group(tag, is, self.special_fields.mut_unknown_fields())?;
},
};
}
::std::result::Result::Ok(())
}
// Compute sizes of nested messages
#[allow(unused_variables)]
fn compute_size(&self) -> u64 {
let mut my_size = 0;
if !self.version.is_empty() {
my_size += ::protobuf::rt::string_size(1, &self.version);
}
if self.secret != false {
my_size += 1 + 1;
}
if !self.public_key.is_empty() {
my_size += ::protobuf::rt::bytes_size(3, &self.public_key);
}
if !self.key_finger.is_empty() {
my_size += ::protobuf::rt::string_size(4, &self.key_finger);
}
my_size += ::protobuf::rt::unknown_fields_size(self.special_fields.unknown_fields());
self.special_fields.cached_size().set(my_size as u32);
my_size
}
fn write_to_with_cached_sizes(&self, os: &mut ::protobuf::CodedOutputStream<'_>) -> ::protobuf::Result<()> {
if !self.version.is_empty() {
os.write_string(1, &self.version)?;
}
if self.secret != false {
os.write_bool(2, self.secret)?;
}
if !self.public_key.is_empty() {
os.write_bytes(3, &self.public_key)?;
}
if !self.key_finger.is_empty() {
os.write_string(4, &self.key_finger)?;
}
os.write_unknown_fields(self.special_fields.unknown_fields())?;
::std::result::Result::Ok(())
}
fn special_fields(&self) -> &::protobuf::SpecialFields {
&self.special_fields
}
fn mut_special_fields(&mut self) -> &mut ::protobuf::SpecialFields {
&mut self.special_fields
}
fn new() -> HandshakeResponse {
HandshakeResponse::new()
}
fn clear(&mut self) {
self.version.clear();
self.secret = false;
self.public_key.clear();
self.key_finger.clear();
self.special_fields.clear();
}
fn default_instance() -> &'static HandshakeResponse {
static instance: HandshakeResponse = HandshakeResponse {
version: ::std::string::String::new(),
secret: false,
public_key: ::std::vec::Vec::new(),
key_finger: ::std::string::String::new(),
special_fields: ::protobuf::SpecialFields::new(),
};
&instance
}
}
impl ::protobuf::MessageFull for HandshakeResponse {
fn descriptor() -> ::protobuf::reflect::MessageDescriptor {
static descriptor: ::protobuf::rt::Lazy<::protobuf::reflect::MessageDescriptor> = ::protobuf::rt::Lazy::new();
descriptor.get(|| file_descriptor().message_by_package_relative_name("HandshakeResponse").unwrap()).clone()
}
}
impl ::std::fmt::Display for HandshakeResponse {
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
::protobuf::text_format::fmt(self, f)
}
}
impl ::protobuf::reflect::ProtobufValue for HandshakeResponse {
type RuntimeType = ::protobuf::reflect::rt::RuntimeTypeMessage<Self>;
}
#[derive(PartialEq,Clone,Default,Debug)]
// @@protoc_insertion_point(message:SecretHandshakeRequest)
pub struct SecretHandshakeRequest {
// message fields
// @@protoc_insertion_point(field:SecretHandshakeRequest.token)
pub token: ::std::string::String,
// @@protoc_insertion_point(field:SecretHandshakeRequest.key)
pub key: ::std::vec::Vec<u8>,
// special fields
// @@protoc_insertion_point(special_field:SecretHandshakeRequest.special_fields)
pub special_fields: ::protobuf::SpecialFields,
}
impl<'a> ::std::default::Default for &'a SecretHandshakeRequest {
fn default() -> &'a SecretHandshakeRequest {
<SecretHandshakeRequest as ::protobuf::Message>::default_instance()
}
}
impl SecretHandshakeRequest {
pub fn new() -> SecretHandshakeRequest {
::std::default::Default::default()
}
fn generated_message_descriptor_data() -> ::protobuf::reflect::GeneratedMessageDescriptorData {
let mut fields = ::std::vec::Vec::with_capacity(2);
let mut oneofs = ::std::vec::Vec::with_capacity(0);
fields.push(::protobuf::reflect::rt::v2::make_simpler_field_accessor::<_, _>(
"token",
|m: &SecretHandshakeRequest| { &m.token },
|m: &mut SecretHandshakeRequest| { &mut m.token },
));
fields.push(::protobuf::reflect::rt::v2::make_simpler_field_accessor::<_, _>(
"key",
|m: &SecretHandshakeRequest| { &m.key },
|m: &mut SecretHandshakeRequest| { &mut m.key },
));
::protobuf::reflect::GeneratedMessageDescriptorData::new_2::<SecretHandshakeRequest>(
"SecretHandshakeRequest",
fields,
oneofs,
)
}
}
impl ::protobuf::Message for SecretHandshakeRequest {
const NAME: &'static str = "SecretHandshakeRequest";
fn is_initialized(&self) -> bool {
true
}
fn merge_from(&mut self, is: &mut ::protobuf::CodedInputStream<'_>) -> ::protobuf::Result<()> {
while let Some(tag) = is.read_raw_tag_or_eof()? {
match tag {
10 => {
self.token = is.read_string()?;
},
18 => {
self.key = is.read_bytes()?;
},
tag => {
::protobuf::rt::read_unknown_or_skip_group(tag, is, self.special_fields.mut_unknown_fields())?;
},
};
}
::std::result::Result::Ok(())
}
// Compute sizes of nested messages
#[allow(unused_variables)]
fn compute_size(&self) -> u64 {
let mut my_size = 0;
if !self.token.is_empty() {
my_size += ::protobuf::rt::string_size(1, &self.token);
}
if !self.key.is_empty() {
my_size += ::protobuf::rt::bytes_size(2, &self.key);
}
my_size += ::protobuf::rt::unknown_fields_size(self.special_fields.unknown_fields());
self.special_fields.cached_size().set(my_size as u32);
my_size
}
fn write_to_with_cached_sizes(&self, os: &mut ::protobuf::CodedOutputStream<'_>) -> ::protobuf::Result<()> {
if !self.token.is_empty() {
os.write_string(1, &self.token)?;
}
if !self.key.is_empty() {
os.write_bytes(2, &self.key)?;
}
os.write_unknown_fields(self.special_fields.unknown_fields())?;
::std::result::Result::Ok(())
}
fn special_fields(&self) -> &::protobuf::SpecialFields {
&self.special_fields
}
fn mut_special_fields(&mut self) -> &mut ::protobuf::SpecialFields {
&mut self.special_fields
}
fn new() -> SecretHandshakeRequest {
SecretHandshakeRequest::new()
}
fn clear(&mut self) {
self.token.clear();
self.key.clear();
self.special_fields.clear();
}
fn default_instance() -> &'static SecretHandshakeRequest {
static instance: SecretHandshakeRequest = SecretHandshakeRequest {
token: ::std::string::String::new(),
key: ::std::vec::Vec::new(),
special_fields: ::protobuf::SpecialFields::new(),
};
&instance
}
}
impl ::protobuf::MessageFull for SecretHandshakeRequest {
fn descriptor() -> ::protobuf::reflect::MessageDescriptor {
static descriptor: ::protobuf::rt::Lazy<::protobuf::reflect::MessageDescriptor> = ::protobuf::rt::Lazy::new();
descriptor.get(|| file_descriptor().message_by_package_relative_name("SecretHandshakeRequest").unwrap()).clone()
}
}
impl ::std::fmt::Display for SecretHandshakeRequest {
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
::protobuf::text_format::fmt(self, f)
}
}
impl ::protobuf::reflect::ProtobufValue for SecretHandshakeRequest {
type RuntimeType = ::protobuf::reflect::rt::RuntimeTypeMessage<Self>;
}
#[derive(PartialEq,Clone,Default,Debug)]
// @@protoc_insertion_point(message:RegistrationRequest)
pub struct RegistrationRequest {
@@ -43,6 +499,8 @@ pub struct RegistrationRequest {
pub virtual_ip: u32,
// @@protoc_insertion_point(field:RegistrationRequest.allow_ip_change)
pub allow_ip_change: bool,
// @@protoc_insertion_point(field:RegistrationRequest.client_secret)
pub client_secret: bool,
// special fields
// @@protoc_insertion_point(special_field:RegistrationRequest.special_fields)
pub special_fields: ::protobuf::SpecialFields,
@@ -60,7 +518,7 @@ impl RegistrationRequest {
}
fn generated_message_descriptor_data() -> ::protobuf::reflect::GeneratedMessageDescriptorData {
let mut fields = ::std::vec::Vec::with_capacity(7);
let mut fields = ::std::vec::Vec::with_capacity(8);
let mut oneofs = ::std::vec::Vec::with_capacity(0);
fields.push(::protobuf::reflect::rt::v2::make_simpler_field_accessor::<_, _>(
"token",
@@ -97,6 +555,11 @@ impl RegistrationRequest {
|m: &RegistrationRequest| { &m.allow_ip_change },
|m: &mut RegistrationRequest| { &mut m.allow_ip_change },
));
fields.push(::protobuf::reflect::rt::v2::make_simpler_field_accessor::<_, _>(
"client_secret",
|m: &RegistrationRequest| { &m.client_secret },
|m: &mut RegistrationRequest| { &mut m.client_secret },
));
::protobuf::reflect::GeneratedMessageDescriptorData::new_2::<RegistrationRequest>(
"RegistrationRequest",
fields,
@@ -136,6 +599,9 @@ impl ::protobuf::Message for RegistrationRequest {
56 => {
self.allow_ip_change = is.read_bool()?;
},
64 => {
self.client_secret = is.read_bool()?;
},
tag => {
::protobuf::rt::read_unknown_or_skip_group(tag, is, self.special_fields.mut_unknown_fields())?;
},
@@ -169,6 +635,9 @@ impl ::protobuf::Message for RegistrationRequest {
if self.allow_ip_change != false {
my_size += 1 + 1;
}
if self.client_secret != false {
my_size += 1 + 1;
}
my_size += ::protobuf::rt::unknown_fields_size(self.special_fields.unknown_fields());
self.special_fields.cached_size().set(my_size as u32);
my_size
@@ -196,6 +665,9 @@ impl ::protobuf::Message for RegistrationRequest {
if self.allow_ip_change != false {
os.write_bool(7, self.allow_ip_change)?;
}
if self.client_secret != false {
os.write_bool(8, self.client_secret)?;
}
os.write_unknown_fields(self.special_fields.unknown_fields())?;
::std::result::Result::Ok(())
}
@@ -220,6 +692,7 @@ impl ::protobuf::Message for RegistrationRequest {
self.version.clear();
self.virtual_ip = 0;
self.allow_ip_change = false;
self.client_secret = false;
self.special_fields.clear();
}
@@ -232,6 +705,7 @@ impl ::protobuf::Message for RegistrationRequest {
version: ::std::string::String::new(),
virtual_ip: 0,
allow_ip_change: false,
client_secret: false,
special_fields: ::protobuf::SpecialFields::new(),
};
&instance
@@ -514,6 +988,8 @@ pub struct DeviceInfo {
pub virtual_ip: u32,
// @@protoc_insertion_point(field:DeviceInfo.device_status)
pub device_status: u32,
// @@protoc_insertion_point(field:DeviceInfo.client_secret)
pub client_secret: bool,
// special fields
// @@protoc_insertion_point(special_field:DeviceInfo.special_fields)
pub special_fields: ::protobuf::SpecialFields,
@@ -531,7 +1007,7 @@ impl DeviceInfo {
}
fn generated_message_descriptor_data() -> ::protobuf::reflect::GeneratedMessageDescriptorData {
let mut fields = ::std::vec::Vec::with_capacity(3);
let mut fields = ::std::vec::Vec::with_capacity(4);
let mut oneofs = ::std::vec::Vec::with_capacity(0);
fields.push(::protobuf::reflect::rt::v2::make_simpler_field_accessor::<_, _>(
"name",
@@ -548,6 +1024,11 @@ impl DeviceInfo {
|m: &DeviceInfo| { &m.device_status },
|m: &mut DeviceInfo| { &mut m.device_status },
));
fields.push(::protobuf::reflect::rt::v2::make_simpler_field_accessor::<_, _>(
"client_secret",
|m: &DeviceInfo| { &m.client_secret },
|m: &mut DeviceInfo| { &mut m.client_secret },
));
::protobuf::reflect::GeneratedMessageDescriptorData::new_2::<DeviceInfo>(
"DeviceInfo",
fields,
@@ -575,6 +1056,9 @@ impl ::protobuf::Message for DeviceInfo {
24 => {
self.device_status = is.read_uint32()?;
},
32 => {
self.client_secret = is.read_bool()?;
},
tag => {
::protobuf::rt::read_unknown_or_skip_group(tag, is, self.special_fields.mut_unknown_fields())?;
},
@@ -596,6 +1080,9 @@ impl ::protobuf::Message for DeviceInfo {
if self.device_status != 0 {
my_size += ::protobuf::rt::uint32_size(3, self.device_status);
}
if self.client_secret != false {
my_size += 1 + 1;
}
my_size += ::protobuf::rt::unknown_fields_size(self.special_fields.unknown_fields());
self.special_fields.cached_size().set(my_size as u32);
my_size
@@ -611,6 +1098,9 @@ impl ::protobuf::Message for DeviceInfo {
if self.device_status != 0 {
os.write_uint32(3, self.device_status)?;
}
if self.client_secret != false {
os.write_bool(4, self.client_secret)?;
}
os.write_unknown_fields(self.special_fields.unknown_fields())?;
::std::result::Result::Ok(())
}
@@ -631,6 +1121,7 @@ impl ::protobuf::Message for DeviceInfo {
self.name.clear();
self.virtual_ip = 0;
self.device_status = 0;
self.client_secret = false;
self.special_fields.clear();
}
@@ -639,6 +1130,7 @@ impl ::protobuf::Message for DeviceInfo {
name: ::std::string::String::new(),
virtual_ip: 0,
device_status: 0,
client_secret: false,
special_fields: ::protobuf::SpecialFields::new(),
};
&instance
@@ -1107,33 +1599,41 @@ impl PunchNatType {
}
static file_descriptor_proto_data: &'static [u8] = b"\
\n\rmessage.proto\"\xd6\x01\n\x13RegistrationRequest\x12\x14\n\x05token\
\x18\x01\x20\x01(\tR\x05token\x12\x1b\n\tdevice_id\x18\x02\x20\x01(\tR\
\x08deviceId\x12\x12\n\x04name\x18\x03\x20\x01(\tR\x04name\x12\x17\n\x07\
is_fast\x18\x04\x20\x01(\x08R\x06isFast\x12\x18\n\x07version\x18\x05\x20\
\x01(\tR\x07version\x12\x1d\n\nvirtual_ip\x18\x06\x20\x01(\x07R\tvirtual\
Ip\x12&\n\x0fallow_ip_change\x18\x07\x20\x01(\x08R\rallowIpChange\"\xb3\
\x02\n\x14RegistrationResponse\x12\x1d\n\nvirtual_ip\x18\x01\x20\x01(\
\x07R\tvirtualIp\x12'\n\x0fvirtual_gateway\x18\x02\x20\x01(\x07R\x0evirt\
ualGateway\x12'\n\x0fvirtual_netmask\x18\x03\x20\x01(\x07R\x0evirtualNet\
mask\x12\x14\n\x05epoch\x18\x04\x20\x01(\rR\x05epoch\x125\n\x10device_in\
fo_list\x18\x05\x20\x03(\x0b2\x0b.DeviceInfoR\x0edeviceInfoList\x12\x1b\
\n\tpublic_ip\x18\x06\x20\x01(\x07R\x08publicIp\x12\x1f\n\x0bpublic_port\
\x18\x07\x20\x01(\rR\npublicPort\x12\x1f\n\x0bpublic_ipv6\x18\x08\x20\
\x01(\x0cR\npublicIpv6\"d\n\nDeviceInfo\x12\x12\n\x04name\x18\x01\x20\
\x01(\tR\x04name\x12\x1d\n\nvirtual_ip\x18\x02\x20\x01(\x07R\tvirtualIp\
\x12#\n\rdevice_status\x18\x03\x20\x01(\rR\x0cdeviceStatus\"Y\n\nDeviceL\
ist\x12\x14\n\x05epoch\x18\x01\x20\x01(\rR\x05epoch\x125\n\x10device_inf\
o_list\x18\x02\x20\x03(\x0b2\x0b.DeviceInfoR\x0edeviceInfoList\"\xa2\x02\
\n\tPunchInfo\x12$\n\x0epublic_ip_list\x18\x02\x20\x03(\x07R\x0cpublicIp\
List\x12\x1f\n\x0bpublic_port\x18\x03\x20\x01(\rR\npublicPort\x12*\n\x11\
public_port_range\x18\x04\x20\x01(\rR\x0fpublicPortRange\x12(\n\x08nat_t\
ype\x18\x05\x20\x01(\x0e2\r.PunchNatTypeR\x07natType\x12\x14\n\x05reply\
\x18\x06\x20\x01(\x08R\x05reply\x12\x19\n\x08local_ip\x18\x07\x20\x01(\
\x07R\x07localIp\x12\x1d\n\nlocal_port\x18\x08\x20\x01(\rR\tlocalPort\
\x12(\n\x10public_ipv6_list\x18\t\x20\x03(\x0cR\x0epublicIpv6List*'\n\
\x0cPunchNatType\x12\r\n\tSymmetric\x10\0\x12\x08\n\x04Cone\x10\x01b\x06\
proto3\
\n\rmessage.proto\"D\n\x10HandshakeRequest\x12\x18\n\x07version\x18\x01\
\x20\x01(\tR\x07version\x12\x16\n\x06secret\x18\x02\x20\x01(\x08R\x06sec\
ret\"\x83\x01\n\x11HandshakeResponse\x12\x18\n\x07version\x18\x01\x20\
\x01(\tR\x07version\x12\x16\n\x06secret\x18\x02\x20\x01(\x08R\x06secret\
\x12\x1d\n\npublic_key\x18\x03\x20\x01(\x0cR\tpublicKey\x12\x1d\n\nkey_f\
inger\x18\x04\x20\x01(\tR\tkeyFinger\"@\n\x16SecretHandshakeRequest\x12\
\x14\n\x05token\x18\x01\x20\x01(\tR\x05token\x12\x10\n\x03key\x18\x02\
\x20\x01(\x0cR\x03key\"\xfb\x01\n\x13RegistrationRequest\x12\x14\n\x05to\
ken\x18\x01\x20\x01(\tR\x05token\x12\x1b\n\tdevice_id\x18\x02\x20\x01(\t\
R\x08deviceId\x12\x12\n\x04name\x18\x03\x20\x01(\tR\x04name\x12\x17\n\
\x07is_fast\x18\x04\x20\x01(\x08R\x06isFast\x12\x18\n\x07version\x18\x05\
\x20\x01(\tR\x07version\x12\x1d\n\nvirtual_ip\x18\x06\x20\x01(\x07R\tvir\
tualIp\x12&\n\x0fallow_ip_change\x18\x07\x20\x01(\x08R\rallowIpChange\
\x12#\n\rclient_secret\x18\x08\x20\x01(\x08R\x0cclientSecret\"\xb3\x02\n\
\x14RegistrationResponse\x12\x1d\n\nvirtual_ip\x18\x01\x20\x01(\x07R\tvi\
rtualIp\x12'\n\x0fvirtual_gateway\x18\x02\x20\x01(\x07R\x0evirtualGatewa\
y\x12'\n\x0fvirtual_netmask\x18\x03\x20\x01(\x07R\x0evirtualNetmask\x12\
\x14\n\x05epoch\x18\x04\x20\x01(\rR\x05epoch\x125\n\x10device_info_list\
\x18\x05\x20\x03(\x0b2\x0b.DeviceInfoR\x0edeviceInfoList\x12\x1b\n\tpubl\
ic_ip\x18\x06\x20\x01(\x07R\x08publicIp\x12\x1f\n\x0bpublic_port\x18\x07\
\x20\x01(\rR\npublicPort\x12\x1f\n\x0bpublic_ipv6\x18\x08\x20\x01(\x0cR\
\npublicIpv6\"\x89\x01\n\nDeviceInfo\x12\x12\n\x04name\x18\x01\x20\x01(\
\tR\x04name\x12\x1d\n\nvirtual_ip\x18\x02\x20\x01(\x07R\tvirtualIp\x12#\
\n\rdevice_status\x18\x03\x20\x01(\rR\x0cdeviceStatus\x12#\n\rclient_sec\
ret\x18\x04\x20\x01(\x08R\x0cclientSecret\"Y\n\nDeviceList\x12\x14\n\x05\
epoch\x18\x01\x20\x01(\rR\x05epoch\x125\n\x10device_info_list\x18\x02\
\x20\x03(\x0b2\x0b.DeviceInfoR\x0edeviceInfoList\"\xa2\x02\n\tPunchInfo\
\x12$\n\x0epublic_ip_list\x18\x02\x20\x03(\x07R\x0cpublicIpList\x12\x1f\
\n\x0bpublic_port\x18\x03\x20\x01(\rR\npublicPort\x12*\n\x11public_port_\
range\x18\x04\x20\x01(\rR\x0fpublicPortRange\x12(\n\x08nat_type\x18\x05\
\x20\x01(\x0e2\r.PunchNatTypeR\x07natType\x12\x14\n\x05reply\x18\x06\x20\
\x01(\x08R\x05reply\x12\x19\n\x08local_ip\x18\x07\x20\x01(\x07R\x07local\
Ip\x12\x1d\n\nlocal_port\x18\x08\x20\x01(\rR\tlocalPort\x12(\n\x10public\
_ipv6_list\x18\t\x20\x03(\x0cR\x0epublicIpv6List*'\n\x0cPunchNatType\x12\
\r\n\tSymmetric\x10\0\x12\x08\n\x04Cone\x10\x01b\x06proto3\
";
/// `FileDescriptorProto` object which was a source for this generated file
@@ -1151,7 +1651,10 @@ pub fn file_descriptor() -> &'static ::protobuf::reflect::FileDescriptor {
file_descriptor.get(|| {
let generated_file_descriptor = generated_file_descriptor_lazy.get(|| {
let mut deps = ::std::vec::Vec::with_capacity(0);
let mut messages = ::std::vec::Vec::with_capacity(5);
let mut messages = ::std::vec::Vec::with_capacity(8);
messages.push(HandshakeRequest::generated_message_descriptor_data());
messages.push(HandshakeResponse::generated_message_descriptor_data());
messages.push(SecretHandshakeRequest::generated_message_descriptor_data());
messages.push(RegistrationRequest::generated_message_descriptor_data());
messages.push(RegistrationResponse::generated_message_descriptor_data());
messages.push(DeviceInfo::generated_message_descriptor_data());

205
src/protocol/body.rs Normal file
View File

@@ -0,0 +1,205 @@
use std::{fmt, io};
pub const ENCRYPTION_RESERVED: usize = 32;
/* aes_gcm加密数据体
0 15 31
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 数据体 |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| random(32) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| tag(32) |
| tag(32) |
| tag(32) |
| tag(32) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| finger(32) |
| finger(32) |
| finger(32) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
finger用于快速校验数据是否被修改上层可使用token、协议头参与计算finger
确保服务端和客户端都能感知修改(服务端不能解密也能校验指纹)
*/
pub struct SecretBody<B> {
buffer: B,
}
impl<B: AsRef<[u8]>> SecretBody<B> {
pub fn new(buffer: B) -> io::Result<SecretBody<B>> {
let len = buffer.as_ref().len();
// 不能大于udp最大载荷长度
if len < 32 || len > 65535 - 20 - 8 - 12 {
return Err(io::Error::new(
io::ErrorKind::InvalidData,
"length overflow",
));
}
Ok(SecretBody { buffer })
}
pub fn data(&self) -> &[u8] {
let end = self.buffer.as_ref().len() - 32;
&self.buffer.as_ref()[..end]
}
pub fn random(&self) -> u32 {
let end = self.buffer.as_ref().len() - 16 - 12;
u32::from_be_bytes(self.buffer.as_ref()[end - 4..end].try_into().unwrap())
}
pub fn body(&self) -> &[u8] {
let end = self.buffer.as_ref().len() - 16 - 12;
&self.buffer.as_ref()[..end]
}
pub fn tag(&self) -> &[u8] {
let end = self.buffer.as_ref().len() - 12;
&self.buffer.as_ref()[end - 16..end]
}
pub fn finger(&self) -> &[u8] {
let end = self.buffer.as_ref().len();
&self.buffer.as_ref()[end - 12..end]
}
pub fn buffer(&self) -> &[u8] {
self.buffer.as_ref()
}
}
impl<B: AsRef<[u8]> + AsMut<[u8]>> SecretBody<B> {
pub fn set_data(&mut self, data: &[u8]) -> io::Result<()> {
let end = self.buffer.as_ref().len() - 32;
if end - 4 != data.len() {
return Err(io::Error::new(io::ErrorKind::InvalidData, "end-4 != data.len"));
}
self.buffer.as_mut()[..end].copy_from_slice(data);
Ok(())
}
pub fn set_random(&mut self, random: u32) {
let end = self.buffer.as_ref().len() - 16 - 12;
self.buffer.as_mut()[end - 4..end].copy_from_slice(&random.to_be_bytes());
}
pub fn set_tag(&mut self, tag: &[u8]) -> io::Result<()> {
if tag.len() != 16 {
return Err(io::Error::new(io::ErrorKind::InvalidData, "tag.len != 16"));
}
let end = self.buffer.as_ref().len() - 12;
self.buffer.as_mut()[end - 16..end].copy_from_slice(tag);
Ok(())
}
pub fn set_finger(&mut self, finger: &[u8]) -> io::Result<()> {
if finger.len() != 12 {
return Err(io::Error::new(io::ErrorKind::InvalidData, "finger.len != 12"));
}
let end = self.buffer.as_ref().len();
self.buffer.as_mut()[end - 12..end].copy_from_slice(finger);
Ok(())
}
pub fn data_mut(&mut self) -> &mut [u8] {
let end = self.buffer.as_ref().len() - 32;
&mut self.buffer.as_mut()[..end]
}
/// 数据部分
pub fn body_mut(&mut self) -> &mut [u8] {
let end = self.buffer.as_ref().len() - 12 - 16;
&mut self.buffer.as_mut()[..end]
}
pub fn tag_mut(&mut self) -> &mut [u8] {
let end = self.buffer.as_ref().len() - 12;
&mut self.buffer.as_mut()[end - 16..end]
}
/// 数据部分+tag部分
pub fn en_body_mut(&mut self) -> &mut [u8] {
let end = self.buffer.as_ref().len() - 12;
&mut self.buffer.as_mut()[..end]
}
pub fn buffer_mut(&mut self) -> &mut [u8] {
self.buffer.as_mut()
}
}
impl<B: AsRef<[u8]>> fmt::Debug for SecretBody<B> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("SecretBody")
.field("random", &self.random())
.field("body", &self.body())
.field("tag", &self.tag())
.finish()
}
}
/* rsa加密数据体
0 15 31
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 数据体(n) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| random(32) |
| random(32) |
| random(32) |
| random(32) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| finger(32) |
| finger(32) |
| finger(32) |
| finger(32) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
pub struct RsaSecretBody<B> {
buffer: B,
}
impl<B: AsRef<[u8]>> RsaSecretBody<B> {
pub fn new(buffer: B) -> io::Result<RsaSecretBody<B>> {
let len = buffer.as_ref().len();
// 不能大于udp最大载荷长度
if len < 32 || len > 65535 - 20 - 8 - 12 {
return Err(io::Error::new(
io::ErrorKind::InvalidData,
"length overflow",
));
}
Ok(RsaSecretBody { buffer })
}
pub fn data(&self) -> &[u8] {
let end = self.buffer.as_ref().len() - 32;
&self.buffer.as_ref()[..end]
}
pub fn random(&self) -> &[u8] {
let end = self.buffer.as_ref().len() - 16;
&self.buffer.as_ref()[end - 16..end]
}
pub fn body(&self) -> &[u8] {
let end = self.buffer.as_ref().len() - 16;
&self.buffer.as_ref()[..end]
}
pub fn finger(&self) -> &[u8] {
let end = self.buffer.as_ref().len() - 16;
&self.buffer.as_ref()[end..]
}
pub fn buffer(&self) -> &[u8] {
&self.buffer.as_ref()
}
}
impl<B: AsRef<[u8]> + AsMut<[u8]>> RsaSecretBody<B> {
pub fn set_random(&mut self, random: &[u8]) -> io::Result<()> {
if random.len() != 16 {
return Err(io::Error::new(io::ErrorKind::InvalidData, "random.len != 16"));
}
let end = self.buffer.as_ref().len() - 16;
self.buffer.as_mut()[end - 16..end].copy_from_slice(random);
Ok(())
}
pub fn random_mut(&mut self) -> &mut [u8] {
let end = self.buffer.as_ref().len() - 16;
&mut self.buffer.as_mut()[end - 16..end]
}
pub fn set_finger(&mut self, finger: &[u8]) -> io::Result<()> {
if finger.len() != 16 {
return Err(io::Error::new(io::ErrorKind::InvalidData, "finger.len != 16"));
}
let end = self.buffer.as_ref().len();
self.buffer.as_mut()[end - 16..end].copy_from_slice(finger);
Ok(())
}
}

View File

@@ -7,6 +7,7 @@ pub enum Protocol {
AddressExhausted,
IpAlreadyExists,
InvalidIp,
NoKey,
Other(u8),
}
@@ -18,6 +19,7 @@ impl From<u8> for Protocol {
3 => Self::AddressExhausted,
4 => Self::IpAlreadyExists,
5 => Self::InvalidIp,
6 => Self::NoKey,
val => Self::Other(val),
}
}
@@ -31,6 +33,7 @@ impl Into<u8> for Protocol {
Protocol::AddressExhausted => 3,
Protocol::IpAlreadyExists => 4,
Protocol::InvalidIp => 5,
Protocol::NoKey => 6,
Protocol::Other(val) => val,
}
}
@@ -42,6 +45,7 @@ pub enum InErrorPacket<B> {
AddressExhausted,
IpAlreadyExists,
InvalidIp,
NoKey,
OtherError(ErrorPacket<B>),
}
@@ -53,6 +57,7 @@ impl<B: AsRef<[u8]>> InErrorPacket<B> {
Protocol::AddressExhausted => Ok(InErrorPacket::AddressExhausted),
Protocol::IpAlreadyExists => Ok(InErrorPacket::IpAlreadyExists),
Protocol::InvalidIp => Ok(InErrorPacket::InvalidIp),
Protocol::NoKey => Ok(InErrorPacket::NoKey),
Protocol::Other(_) => Ok(InErrorPacket::OtherError(ErrorPacket::new(buffer)?)),
}
}

View File

@@ -3,8 +3,6 @@ use std::net::Ipv4Addr;
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
pub enum Protocol {
Icmp,
Igmp,
Ipv4,
Ipv4Broadcast,
Unknown(u8),
@@ -13,8 +11,6 @@ pub enum Protocol {
impl From<u8> for Protocol {
fn from(value: u8) -> Self {
match value {
1 => Protocol::Icmp,
2 => Protocol::Igmp,
4 => Protocol::Ipv4,
201 => Protocol::Ipv4Broadcast,
val => Protocol::Unknown(val),
@@ -25,8 +21,6 @@ impl From<u8> for Protocol {
impl Into<u8> for Protocol {
fn into(self) -> u8 {
match self {
Protocol::Icmp => 1,
Protocol::Igmp => 2,
Protocol::Ipv4 => 4,
Protocol::Ipv4Broadcast => 201,
Protocol::Unknown(val) => val,
@@ -34,18 +28,18 @@ impl Into<u8> for Protocol {
}
}
pub struct BroadcastPacketEnd<B> {
pub struct BroadcastPacket<B> {
buffer: B,
}
impl<B: AsRef<[u8]>> BroadcastPacketEnd<B> {
impl<B: AsRef<[u8]>> BroadcastPacket<B> {
pub fn unchecked(buffer: B) -> Self {
Self { buffer }
}
pub fn new(buffer: B) -> io::Result<Self> {
let len = buffer.as_ref().len();
let packet = Self::unchecked(buffer);
if len < 1 || packet.len() != len {
if len < 2 + 4 || packet.addr_num() == 0 {
Err(io::Error::new(
io::ErrorKind::InvalidData,
"InvalidData",
@@ -56,31 +50,36 @@ impl<B: AsRef<[u8]>> BroadcastPacketEnd<B> {
}
}
impl<B: AsRef<[u8]>> BroadcastPacketEnd<B> {
pub fn len(&self) -> usize {
1 + self.num() as usize * 4
}
pub fn num(&self) -> u8 {
let len = self.buffer.as_ref().len();
self.buffer.as_ref()[len - 1]
impl<B: AsRef<[u8]>> BroadcastPacket<B> {
pub fn addr_num(&self) -> u8 {
self.buffer.as_ref()[1]
}
/// 已经发送给了这些地址
/// 从尾往头拿
pub fn addresses(&self) -> Vec<Ipv4Addr> {
let num = self.num() as usize;
let num = self.addr_num() as usize;
let mut list = Vec::with_capacity(num);
let buf = self.buffer.as_ref();
let mut offset = buf.len() + 4 - 2;
let mut offset = 1;
for _ in 0..num {
offset -= 4;
list.push(Ipv4Addr::new(buf[offset - 3], buf[offset - 2], buf[offset - 1], buf[offset]));
list.push(Ipv4Addr::new(buf[offset], buf[offset + 1], buf[offset + 2], buf[offset + 3]));
offset += 4;
}
list
}
pub fn data(&self) -> io::Result<&[u8]> {
let start = 1 + self.addr_num() as usize * 4;
if start > self.buffer.as_ref().len() {
Err(io::Error::new(
io::ErrorKind::InvalidData,
"InvalidData",
))
} else {
Ok(&self.buffer.as_ref()[start..])
}
}
}
impl<B: AsRef<[u8]> + AsMut<[u8]>> BroadcastPacketEnd<B> {
/// 从头往尾放
impl<B: AsRef<[u8]> + AsMut<[u8]>> BroadcastPacket<B> {
pub fn set_address(&mut self, addr: &[Ipv4Addr]) -> io::Result<()> {
let buf = self.buffer.as_mut();
if buf.len() < 1 + addr.len() * 4 || addr.len() > u8::MAX as usize {
@@ -89,15 +88,28 @@ impl<B: AsRef<[u8]> + AsMut<[u8]>> BroadcastPacketEnd<B> {
"InvalidData",
))
} else {
let mut offset = 0;
buf[0] = addr.len() as u8;
let mut offset = 1;
for ip in addr {
buf[offset..offset + 4].copy_from_slice(&ip.octets());
offset += 4;
}
self.buffer.as_mut()[offset] = addr.len() as u8;
Ok(())
}
}
pub fn set_data(&mut self, data: &[u8]) -> io::Result<()> {
let num = self.addr_num() as usize;
let start = 1 + 4 * num;
let buf = self.buffer.as_mut();
if start > buf.len() || start + data.len() != buf.len() {
return Err(io::Error::new(
io::ErrorKind::InvalidData,
"InvalidData",
));
}
buf[start..].copy_from_slice(data);
Ok(())
}
}

View File

@@ -1,11 +1,12 @@
use std::net::Ipv4Addr;
use std::{fmt, io};
use std::net::Ipv4Addr;
use crate::protocol::body::ENCRYPTION_RESERVED;
/*
0 15 31
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 版本(8) | 协议(8) | 上层协议(8) | 初始ttl(4) | 生存时间(4) |
|e|s|unused| 版本(4) | 协议(8) | 上层协议(8) | 初始ttl(4) | 生存时间(4) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 源ip地址(32) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
@@ -13,8 +14,11 @@ use std::{fmt, io};
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 数据体 |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
e为是否加密标志s为服务端通信包标志
*/
pub mod body;
pub mod control_packet;
pub mod error_packet;
pub mod service_packet;
@@ -91,32 +95,70 @@ pub const MAX_SOURCE: u8 = 0b11110000;
#[derive(Copy, Clone)]
pub struct NetPacket<B> {
data_len: usize,
buffer: B,
}
impl<B: AsRef<[u8]>> NetPacket<B> {
pub fn new(buffer: B) -> io::Result<NetPacket<B>> {
let len = buffer.as_ref().len();
// 不能大于udp最大载荷长度
if len < 12 || len > 65535 - 20 - 8 {
let data_len = buffer.as_ref().len();
Self::new0(data_len, buffer)
}
pub fn new_encrypt(buffer: B) -> io::Result<NetPacket<B>> {
if 12 + ENCRYPTION_RESERVED > buffer.as_ref().len() {
return Err(io::Error::new(
io::ErrorKind::InvalidData,
"length overflow",
));
}
Ok(NetPacket { buffer })
//加密需要预留32字节
let data_len = buffer.as_ref().len() - ENCRYPTION_RESERVED;
Self::new0(data_len, buffer)
}
pub fn new0(data_len: usize, buffer: B) -> io::Result<NetPacket<B>> {
if data_len > buffer.as_ref().len() {
return Err(io::Error::new(
io::ErrorKind::InvalidData,
"length overflow",
));
}
// 不能大于udp最大载荷长度
if data_len < 12 || buffer.as_ref().len() > 65535 - 20 - 8 {
return Err(io::Error::new(
io::ErrorKind::InvalidData,
"length overflow",
));
}
Ok(NetPacket { data_len, buffer })
}
pub fn buffer(&self) -> &[u8] {
&self.buffer.as_ref()[..self.data_len]
}
pub fn raw_buffer(&self) -> &[u8] {
self.buffer.as_ref()
}
pub fn data_len(&self) -> usize {
self.data_len
}
pub fn reserve(&self) -> usize {
self.buffer.as_ref().len() - self.data_len
}
pub fn into_buffer(self) -> B {
self.buffer
}
}
impl<B: AsRef<[u8]>> NetPacket<B> {
/// 数据加密
pub fn is_encrypt(&self) -> bool {
self.buffer.as_ref()[0] & 0x80 == 0x80
}
/// 网关通信的标识
pub fn is_gateway(&self) -> bool {
self.buffer.as_ref()[0] & 0x50 == 0x50
}
pub fn version(&self) -> Version {
Version::from(self.buffer.as_ref()[0])
Version::from(self.buffer.as_ref()[0] & 0x0F)
}
pub fn protocol(&self) -> Protocol {
Protocol::from(self.buffer.as_ref()[1])
@@ -139,16 +181,31 @@ impl<B: AsRef<[u8]>> NetPacket<B> {
Ipv4Addr::from(tmp)
}
pub fn payload(&self) -> &[u8] {
&self.buffer.as_ref()[12..]
&self.buffer.as_ref()[12..self.data_len]
}
}
impl<B: AsRef<[u8]> + AsMut<[u8]>> NetPacket<B> {
pub fn buffer_mut(&mut self)->&mut [u8]{
pub fn buffer_mut(&mut self) -> &mut [u8] {
self.buffer.as_mut()
}
pub fn set_encrypt_flag(&mut self, is_encrypt: bool) {
if is_encrypt {
self.buffer.as_mut()[0] = self.buffer.as_ref()[0] | 0x80
} else {
self.buffer.as_mut()[0] = self.buffer.as_ref()[0] & 0x7F
};
}
pub fn set_gateway_flag(&mut self, is_gateway: bool) {
if is_gateway {
self.buffer.as_mut()[0] = self.buffer.as_ref()[0] | 0x50
} else {
self.buffer.as_mut()[0] = self.buffer.as_ref()[0] & 0xBF
};
}
pub fn set_version(&mut self, version: Version) {
self.buffer.as_mut()[0] = version.into();
let v: u8 = version.into();
self.buffer.as_mut()[0] = (self.buffer.as_ref()[0] & 0xF0) | (0x0F & v);
}
pub fn set_protocol(&mut self, protocol: Protocol) {
self.buffer.as_mut()[1] = protocol.into();
@@ -171,11 +228,22 @@ impl<B: AsRef<[u8]> + AsMut<[u8]>> NetPacket<B> {
pub fn set_destination(&mut self, destination: Ipv4Addr) {
self.buffer.as_mut()[8..12].copy_from_slice(&destination.octets());
}
pub fn set_payload(&mut self, payload: &[u8]) {
self.buffer.as_mut()[12..payload.len() + 12].copy_from_slice(payload);
pub fn set_payload(&mut self, payload: &[u8]) -> io::Result<()> {
if self.data_len - 12 != payload.len() {
return Err(io::Error::new(io::ErrorKind::InvalidData, "data_len - 12 != payload.len"));
}
self.buffer.as_mut()[12..self.data_len].copy_from_slice(payload);
Ok(())
}
pub fn payload_mut(&mut self) -> &mut [u8] {
&mut self.buffer.as_mut()[12..]
&mut self.buffer.as_mut()[12..self.data_len]
}
pub fn set_data_len(&mut self, data_len: usize) -> io::Result<()> {
if data_len > self.buffer.as_ref().len() || data_len < 12 {
return Err(io::Error::new(io::ErrorKind::InvalidData, "data_len invalid"));
}
self.data_len = data_len;
Ok(())
}
}

View File

@@ -8,6 +8,11 @@ pub enum Protocol {
PollDeviceList,
/// 推送设备列表
PushDeviceList,
/// 和服务端握手
HandshakeRequest,
HandshakeResponse,
SecretHandshakeRequest,
SecretHandshakeResponse,
Unknown(u8),
}
@@ -18,6 +23,10 @@ impl From<u8> for Protocol {
2 => Self::RegistrationResponse,
3 => Self::PollDeviceList,
4 => Self::PushDeviceList,
5 => Self::HandshakeRequest,
6 => Self::HandshakeResponse,
7 => Self::SecretHandshakeRequest,
8 => Self::SecretHandshakeResponse,
val => Self::Unknown(val),
}
}
@@ -30,6 +39,10 @@ impl Into<u8> for Protocol {
Self::RegistrationResponse => 2,
Self::PollDeviceList => 3,
Self::PushDeviceList => 4,
Self::HandshakeRequest => 5,
Self::HandshakeResponse => 6,
Self::SecretHandshakeRequest => 7,
Self::SecretHandshakeResponse => 8,
Self::Unknown(val) => val,
}
}

View File

@@ -1,13 +1,13 @@
use std::collections::{HashMap, HashSet};
use std::net::Ipv4Addr;
use std::sync::Arc;
use crate::error::*;
use moka::sync::Cache;
use packet::igmp::igmp_v2::IgmpV2Packet;
use packet::igmp::igmp_v3::{IgmpV3RecordType, IgmpV3ReportPacket};
use packet::igmp::IgmpType;
use parking_lot::RwLock;
use moka::sync::Cache;
use std::collections::{HashMap, HashSet};
use std::net::Ipv4Addr;
use std::sync::Arc;
use std::time::Duration;
use crate::error::*;
lazy_static::lazy_static! {
//组播缓存 30分钟 (token,group_address) -> members
@@ -16,9 +16,9 @@ lazy_static::lazy_static! {
// (token,group_address,member_ip)
static ref MULTICAST_MEMBER:Cache<(String,Ipv4Addr,Ipv4Addr), ()> = Cache::builder()
.time_to_idle(Duration::from_secs(20*60)).eviction_listener(|k:Arc<(String,Ipv4Addr,Ipv4Addr)>,_,cause|{
if cause==moka::notification::RemovalCause::Replaced{
return;
}
if cause==moka::notification::RemovalCause::Replaced{
return;
}
log::info!("MULTICAST_MEMBER eviction {:?}", k);
if let Some(v) = MULTICAST.get(&(k.0.clone(),k.1)){
let mut lock = v.write();
@@ -116,7 +116,8 @@ pub fn handle(buf: &[u8], token: &String, source: Ipv4Addr) -> Result<()> {
guard.members.insert(source);
guard.map.insert(source, (true, HashSet::from_iter(src)));
drop(guard);
MULTICAST_MEMBER.insert((token.clone(), multicast_addr, source), ());
MULTICAST_MEMBER
.insert((token.clone(), multicast_addr, source), ());
}
}
}
@@ -140,20 +141,18 @@ pub fn handle(buf: &[u8], token: &String, source: Ipv4Addr) -> Result<()> {
//在已有源的基础上,接收目标源,如果是排除模式,则删除;是包含模式则添加
match group_record.source_addresses() {
None => {}
Some(src) => {
match guard.map.get_mut(&source) {
None => {}
Some((is_include, set)) => {
for ip in src {
if *is_include {
set.insert(ip);
} else {
set.remove(&ip);
}
Some(src) => match guard.map.get_mut(&source) {
None => {}
Some((is_include, set)) => {
for ip in src {
if *is_include {
set.insert(ip);
} else {
set.remove(&ip);
}
}
}
}
},
}
drop(guard);
MULTICAST_MEMBER.insert((token.clone(), multicast_addr, source), ());
@@ -162,20 +161,18 @@ pub fn handle(buf: &[u8], token: &String, source: Ipv4Addr) -> Result<()> {
//在已有源的基础上,不接收目标源
match group_record.source_addresses() {
None => {}
Some(src) => {
match guard.map.get_mut(&source) {
None => {}
Some((is_include, set)) => {
for ip in src {
if *is_include {
set.remove(&ip);
} else {
set.insert(ip);
}
Some(src) => match guard.map.get_mut(&source) {
None => {}
Some((is_include, set)) => {
for ip in src {
if *is_include {
set.remove(&ip);
} else {
set.insert(ip);
}
}
}
}
},
}
drop(guard);
MULTICAST_MEMBER.insert((token.clone(), multicast_addr, source), ());
@@ -188,4 +185,4 @@ pub fn handle(buf: &[u8], token: &String, source: Ipv4Addr) -> Result<()> {
IgmpType::Unknown(_) => {}
}
Ok(())
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,56 +1,65 @@
use std::collections::HashMap;
use std::net::SocketAddr;
use moka::sync::Cache;
use std::time::Duration;
use std::net::{IpAddr, Ipv4Addr, SocketAddr};
use std::sync::Arc;
use std::time::Duration;
use crossbeam_skiplist::SkipMap;
use moka::sync::Cache;
use parking_lot::RwLock;
use tokio::sync::mpsc::Sender;
mod udp_service;
mod tcp_service;
mod common;
pub use udp_service::start_udp;
pub use tcp_service::start_tcp;
pub use udp_service::start_udp;
use crate::cipher::Aes256GcmCipher;
mod common;
mod tcp_service;
mod udp_service;
lazy_static::lazy_static! {
//七天不连接则回收ip
static ref DEVICE_ID_SESSION:Cache<(String,String),()> = Cache::builder()
.time_to_idle(Duration::from_secs(60*60*24*7)).eviction_listener(|k:Arc<(String,String)>,_,cause|{
if cause!=moka::notification::RemovalCause::Expired{
return;
}
static ref DEVICE_ID_SESSION:Cache<(String,String),i64> = Cache::builder()
.time_to_idle(Duration::from_secs(60*60*24*7)).eviction_listener(|k:Arc<(String,String)>,id:i64,cause|{
if cause!=moka::notification::RemovalCause::Expired{
return;
}
log::info!("DEVICE_ID_SESSION eviction {:?}", k);
if let Some(v) = VIRTUAL_NETWORK.get(&k.0){
let mut lock = v.write();
lock.virtual_ip_map.remove(&k.1);
lock.epoch+=1;
if let Some(dev) = lock.virtual_ip_map.get(&k.1){
if dev.id==id{
lock.virtual_ip_map.remove(&k.1);
lock.epoch+=1;
}
}
}
}).build();
//七天没有用户则回收网段缓存
static ref VIRTUAL_NETWORK:Cache<String, Arc<RwLock<VirtualNetwork>>> = Cache::builder()
.time_to_idle(Duration::from_secs(60*60*24*7)).build();
static ref DEVICE_ADDRESS:SkipMap<(String,u32), PeerLink> = SkipMap::new();
static ref DEVICE_ADDRESS:SkipMap<(String,u32), (PeerLink,Context)> = SkipMap::new();
static ref TCP_AES:SkipMap<SocketAddr,Aes256GcmCipher> = SkipMap::new();
static ref UDP_AES:Cache<SocketAddr,Aes256GcmCipher> = Cache::builder()
.time_to_idle(Duration::from_secs(20)).build();
//udp专用 10秒钟没有收到消息则判定为掉线
// 地址 -> 注册信息
static ref UDP_SESSION:Cache<SocketAddr,Context> = Cache::builder()
.time_to_idle(Duration::from_secs(10)).eviction_listener(|_,context:Context,cause|{
if cause!=moka::notification::RemovalCause::Expired{
return;
}
log::info!("UDP_SESSION eviction {:?}", context);
if cause!=moka::notification::RemovalCause::Expired{
return;
}
log::info!("UDP_SESSION eviction token={},virtual_ip={},device_id={},id={}", context.token,context.virtual_ip,context.device_id,context.id);
if let Some(v) = VIRTUAL_NETWORK.get(&context.token){
let mut lock = v.write();
if let Some(mut item) = lock.virtual_ip_map.get_mut(&context.device_id){
if let Some(item) = lock.virtual_ip_map.get_mut(&context.device_id){
if item.id!=context.id{
return;
}
item.status = PeerDeviceStatus::Offline;
DEVICE_ADDRESS.remove(&(context.token,context.virtual_ip));
lock.epoch+=1;
}
lock.epoch+=1;
}
}).build();
}
@@ -61,13 +70,27 @@ pub enum PeerLink {
Udp(SocketAddr),
}
#[derive(Clone, Debug)]
#[derive(Clone)]
pub struct Context {
token: String,
virtual_ip: u32,
id: i64,
device_id: String,
client_secret: bool,
address: SocketAddr,
}
impl Default for Context {
fn default() -> Self {
Context {
token: "".to_string(),
virtual_ip: 0,
id: 0,
device_id: "".to_string(),
client_secret: false,
address: SocketAddr::new(IpAddr::V4(Ipv4Addr::UNSPECIFIED), 0),
}
}
}
#[derive(Clone, Debug)]
@@ -83,6 +106,7 @@ pub struct DeviceInfo {
ip: u32,
name: String,
status: PeerDeviceStatus,
client_secret: bool,
}
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
@@ -104,7 +128,7 @@ impl From<u8> for PeerDeviceStatus {
fn from(value: u8) -> Self {
match value {
0 => PeerDeviceStatus::Online,
_ => PeerDeviceStatus::Offline
_ => PeerDeviceStatus::Offline,
}
}
}
}

View File

@@ -3,80 +3,124 @@ use std::net::SocketAddr;
use std::sync::Arc;
use tokio::io::{AsyncReadExt, AsyncWriteExt};
use tokio::net::{TcpListener, UdpSocket};
use tokio::net::tcp::OwnedReadHalf;
use tokio::net::{TcpListener, UdpSocket};
use tokio::sync::mpsc::{channel, Sender};
use crate::ConfigInfo;
use crate::service::main_service::{Context, DEVICE_ADDRESS, PeerDeviceStatus, VIRTUAL_NETWORK};
use crate::cipher::{Aes256GcmCipher, RsaCipher};
use crate::service::main_service::common::handle;
use crate::service::main_service::{
Context, PeerDeviceStatus, DEVICE_ADDRESS, TCP_AES, VIRTUAL_NETWORK,
};
use crate::ConfigInfo;
pub async fn start_tcp(tcp: TcpListener, main_udp: Arc<UdpSocket>, config: ConfigInfo) -> io::Result<()> {
pub async fn start_tcp(
tcp: TcpListener,
main_udp: Arc<UdpSocket>,
config: ConfigInfo,
rsa_cipher: Option<RsaCipher>,
) {
loop {
let (stream, addr) = match tcp.accept().await {
Ok(rs) => { rs }
Ok(rs) => rs,
Err(e) => {
log::warn!("tcp accept err:{:?}",e);
log::warn!("tcp accept err:{:?}", e);
continue;
}
};
log::info!("tcp连接 {}",addr);
log::info!("tcp连接 {}", addr);
let (r, mut w) = stream.into_split();
let (sender, mut receiver) = channel::<Vec<u8>>(100);
tokio::spawn(async move {
while let Some(mut data) = receiver.recv().await {
if data.len() >= 4 {
let len = data.len() - 4;
data[2] = (len >> 8) as u8;
data[3] = (len & 0xFF) as u8;
if let Err(e) = w.write_all(&data).await {
log::info!("发送失败,链接终止:{:?},{:?}",addr,e);
break;
}
let mut head = [0; 4];
while let Some(data) = receiver.recv().await {
let len = data.len();
head[2] = (len >> 8) as u8;
head[3] = (len & 0xFF) as u8;
if let Err(e) = w.write_all(&head).await {
log::info!("发送失败,链接终止:{:?},{:?}", addr, e);
}
if let Err(e) = w.write_all(&data).await {
log::info!("发送失败,链接终止:{:?},{:?}", addr, e);
break;
}
}
let _ = w.shutdown().await;
});
let main_udp = main_udp.clone();
let config = config.clone();
let rsa_cipher = rsa_cipher.clone();
tokio::spawn(async move {
let mut context = Context {
token: "".to_string(),
virtual_ip: 0,
id: 0,
device_id: "".to_string(),
};
if let Err(e) = tcp_handle(&mut context, config, r, addr, sender, main_udp).await {
log::info!("接收失败,链接终止:{:?},{:?}",addr,e);
let mut context: Option<Context> = None;
let mut aes_gcm_cipher: Option<Aes256GcmCipher> = None;
if let Err(e) = tcp_handle(
rsa_cipher,
&mut aes_gcm_cipher,
&mut context,
config,
r,
addr,
sender,
main_udp,
)
.await
{
log::info!("接收失败,链接终止:{:?},{:?}", addr, e);
}
if context.virtual_ip != 0 && context.id != 0 {
TCP_AES.remove(&addr);
if let Some(context) = context {
if let Some(v) = VIRTUAL_NETWORK.get(&context.token) {
let mut lock = v.write();
if let Some(mut item) = lock.virtual_ip_map.get_mut(&context.device_id) {
if let Some(item) = lock.virtual_ip_map.get_mut(&context.device_id) {
if item.id != context.id {
return;
}
item.status = PeerDeviceStatus::Offline;
DEVICE_ADDRESS.remove(&(context.token, context.virtual_ip));
lock.epoch += 1;
}
lock.epoch += 1;
}
}
});
}
}
async fn tcp_handle(context: &mut Context, config: ConfigInfo, mut read: OwnedReadHalf, addr: SocketAddr, sender: Sender<Vec<u8>>, main_udp: Arc<UdpSocket>) -> io::Result<()> {
async fn tcp_handle(
rsa_cipher: Option<RsaCipher>,
aes_gcm_cipher: &mut Option<Aes256GcmCipher>,
context: &mut Option<Context>,
config: ConfigInfo,
mut read: OwnedReadHalf,
addr: SocketAddr,
sender: Sender<Vec<u8>>,
main_udp: Arc<UdpSocket>,
) -> io::Result<()> {
let mut head = [0; 4];
let mut buf = [0; 10240];
loop {
read.read_exact(&mut buf[..4]).await?;
let len = 4 + (((buf[2] as u16) << 8) | buf[3] as u16) as usize;
read.read_exact(&mut buf[4..len]).await?;
if let Err(e) = handle(context, &main_udp, &mut buf[..len], addr, &config, Some(&sender)).await {
log::info!("tcp数据处理失败:{:?},{:?}",addr,e);
read.read_exact(&mut head).await?;
let len = (((head[2] as u16) << 8) | head[3] as u16) as usize;
if len < 12 || len > buf.len() {
return Err(io::Error::new(
io::ErrorKind::InvalidData,
"length overflow",
));
}
read.read_exact(&mut buf[..len]).await?;
if let Err(e) = handle(
&rsa_cipher,
aes_gcm_cipher,
context,
&main_udp,
&mut buf[..len],
addr,
&config,
Some(&sender),
)
.await
{
log::info!("tcp数据处理失败:{:?},{:?}", addr, e);
}
}
}

View File

@@ -1,31 +1,42 @@
use std::sync::Arc;
use crate::cipher::RsaCipher;
use tokio::net::UdpSocket;
use crate::ConfigInfo;
use crate::service::main_service::{Context, UDP_SESSION};
use crate::service::main_service::common::handle;
use crate::service::main_service::{UDP_AES, UDP_SESSION};
use crate::ConfigInfo;
pub async fn start_udp(main_udp: Arc<UdpSocket>, config: ConfigInfo) {
pub async fn start_udp(
main_udp: Arc<UdpSocket>,
config: ConfigInfo,
rsa_cipher: Option<RsaCipher>,
) {
loop {
let mut buf = vec![0u8; 10240];
match main_udp.recv_from(&mut buf[4..]).await {
match main_udp.recv_from(&mut buf).await {
Ok((len, addr)) => {
let main_udp = main_udp.clone();
let config = config.clone();
let mut context = UDP_SESSION.get(&addr).unwrap_or_else(|| {
Context {
token: "".to_string(),
virtual_ip: 0,
id: 0,
device_id: "".to_string(),
}
});
let rsa_cipher = rsa_cipher.clone();
let mut context = UDP_SESSION.get(&addr);
let mut aes = UDP_AES.get(&addr);
tokio::spawn(async move {
match handle(&mut context, &main_udp, &mut buf[..len + 4], addr, &config, None).await {
match handle(
&rsa_cipher,
&mut aes,
&mut context,
&main_udp,
&mut buf[..len],
addr,
&config,
None,
)
.await
{
Ok(_) => {}
Err(e) => {
log::info!("udp数据处理失败:{:?},{:?}",addr,e);
log::info!("udp数据处理失败:{:?},{:?}", addr, e);
}
}
});
@@ -35,4 +46,4 @@ pub async fn start_udp(main_udp: Arc<UdpSocket>, config: ConfigInfo) {
}
}
}
}
}