Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c8d0f3850f | ||
|
|
b846f54d79 | ||
|
|
bb7b1d23af | ||
|
|
9e700b3094 | ||
|
|
38f28e313c | ||
|
|
63f03fb11f | ||
|
|
cf7854906f | ||
|
|
78ae5f3036 | ||
|
|
c412a256b8 | ||
|
|
94def558fc | ||
|
|
25e9c523d3 | ||
|
|
a009d06000 | ||
|
|
675e0c52ff | ||
|
|
dc4219753a | ||
|
|
c003b9acbb | ||
|
|
f4869ebd1d | ||
|
|
de4f42537d | ||
|
|
b9ebe80ef3 | ||
|
|
ea5ba750d4 | ||
|
|
b594afce16 |
+42
-25
@@ -2,7 +2,8 @@ name: Rust
|
||||
|
||||
on:
|
||||
push:
|
||||
pull_request:
|
||||
tags:
|
||||
- '*'
|
||||
|
||||
env:
|
||||
CARGO_TERM_COLOR: always
|
||||
@@ -13,23 +14,23 @@ defaults:
|
||||
shell: bash
|
||||
|
||||
jobs:
|
||||
# test:
|
||||
# runs-on: ubuntu-latest
|
||||
# steps:
|
||||
# - uses: actions/checkout@v2
|
||||
# - name: Init submodules
|
||||
# uses: snickerbockers/submodules-init@v4
|
||||
# - name: Cargo cache
|
||||
# uses: actions/cache@v2
|
||||
# with:
|
||||
# path: |
|
||||
# ~/.cargo/registry
|
||||
# ./target
|
||||
# key: test-cargo-registry
|
||||
# - name: List
|
||||
# run: find ./
|
||||
# - name: Run tests
|
||||
# run: cargo test --verbose
|
||||
# test:
|
||||
# runs-on: ubuntu-latest
|
||||
# steps:
|
||||
# - uses: actions/checkout@v2
|
||||
# - name: Init submodules
|
||||
# uses: snickerbockers/submodules-init@v4
|
||||
# - name: Cargo cache
|
||||
# uses: actions/cache@v2
|
||||
# with:
|
||||
# path: |
|
||||
# ~/.cargo/registry
|
||||
# ./target
|
||||
# key: test-cargo-registry
|
||||
# - name: List
|
||||
# run: find ./
|
||||
# - name: Run tests
|
||||
# run: cargo test --verbose
|
||||
|
||||
build:
|
||||
strategy:
|
||||
@@ -39,20 +40,28 @@ jobs:
|
||||
include:
|
||||
- TARGET: i686-unknown-linux-musl # test in an alpine container on a mac
|
||||
OS: ubuntu-latest
|
||||
- TARGET: x86_64-unknown-linux-gnu # tested in a debian container on a mac
|
||||
OS: ubuntu-latest
|
||||
- TARGET: x86_64-unknown-linux-musl # test in an alpine container on a mac
|
||||
OS: ubuntu-latest
|
||||
- TARGET: aarch64-unknown-linux-gnu # tested on aws t4g.nano
|
||||
OS: ubuntu-latest
|
||||
- TARGET: aarch64-unknown-linux-musl # tested on aws t4g.nano in alpine container
|
||||
OS: ubuntu-latest
|
||||
- TARGET: armv7-unknown-linux-gnueabihf # raspberry pi 2-3-4, not tested
|
||||
OS: ubuntu-latest
|
||||
- TARGET: armv7-unknown-linux-musleabihf # raspberry pi 2-3-4, not tested
|
||||
OS: ubuntu-latest
|
||||
- TARGET: arm-unknown-linux-gnueabihf # raspberry pi 0-1, not tested
|
||||
OS: ubuntu-latest
|
||||
- TARGET: arm-unknown-linux-musleabihf # raspberry pi 0-1, not tested
|
||||
OS: ubuntu-latest
|
||||
- TARGET: x86_64-apple-darwin # tested on a mac, is not properly signed so there are security warnings
|
||||
OS: macos-latest
|
||||
- TARGET: x86_64-pc-windows-msvc # tested on a windows machine
|
||||
OS: windows-latest
|
||||
- TARGET: i686-pc-windows-msvc # tested on a windows machine
|
||||
OS: windows-latest
|
||||
- TARGET: x86_64-pc-windows-msvc # tested on a windows machine
|
||||
OS: windows-latest
|
||||
# needs: test
|
||||
runs-on: ${{ matrix.OS }}
|
||||
env:
|
||||
@@ -77,15 +86,20 @@ 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 install -qq crossbuild-essential-arm64 crossbuild-essential-armhf
|
||||
sudo apt-get update && sudo apt-get install -qq crossbuild-essential-arm64 crossbuild-essential-armhf
|
||||
fi
|
||||
|
||||
# some additional configuration for cross-compilation on linux
|
||||
cat >>~/.cargo/config <<EOF
|
||||
[target.aarch64-unknown-linux-gnu]
|
||||
linker = "aarch64-linux-gnu-gcc"
|
||||
[target.aarch64-unknown-linux-musl]
|
||||
linker = "aarch64-linux-gnu-gcc"
|
||||
[target.armv7-unknown-linux-gnueabihf]
|
||||
linker = "arm-linux-gnueabihf-gcc"
|
||||
[target.armv7-unknown-linux-musleabihf]
|
||||
linker = "arm-linux-gnueabihf-gcc"
|
||||
[target.arm-unknown-linux-gnueabihf]
|
||||
linker = "arm-linux-gnueabihf-gcc"
|
||||
[target.arm-unknown-linux-musleabihf]
|
||||
linker = "arm-linux-gnueabihf-gcc"
|
||||
EOF
|
||||
@@ -117,7 +131,6 @@ jobs:
|
||||
name: switch-desktop
|
||||
path: |
|
||||
./artifacts
|
||||
|
||||
# deploys to github releases on tag
|
||||
deploy:
|
||||
if: startsWith(github.ref, 'refs/tags/')
|
||||
@@ -132,6 +145,10 @@ jobs:
|
||||
- name: List
|
||||
run: find ./artifacts
|
||||
- name: Release
|
||||
uses: softprops/action-gh-release@v1
|
||||
uses: svenstaro/upload-release-action@v2
|
||||
with:
|
||||
files: ./artifacts/*.tar.gz
|
||||
repo_token: ${{ secrets.YOURTOKEN }}
|
||||
file: ./artifacts/*.tar.gz
|
||||
tag: ${{ github.ref }}
|
||||
overwrite: true
|
||||
file_glob: true
|
||||
@@ -4,13 +4,13 @@
|
||||
将不同网络下的多个设备虚拟到一个局域网下
|
||||
|
||||
|
||||
### 示例:
|
||||
### 快速使用:
|
||||
|
||||
1. 指定一个token,在多台设备上运行该程序,例如:
|
||||
```shell
|
||||
# linux上
|
||||
root@DESKTOP-0BCHNIO:/opt# ./switch-desktop start --token 123456
|
||||
# 在另一台linux上使用nohup后台运行,不在命令行指定配置时,将在home/.switch/config文件中读取配置
|
||||
# 在另一台linux上使用nohup后台运行,不在命令行指定配置时,将在home/.switch_desktop/config文件中读取配置
|
||||
[root@izj6cemne76ykdzkataftfz switch]# nohup ./switch-desktop start &
|
||||
# windows上
|
||||
D:\switch\bin_v1>switch-desktop.exe start --token 123456
|
||||
@@ -49,6 +49,7 @@
|
||||
1. 和远程桌面(如mstsc)搭配,超低延迟的体验
|
||||
2. 安装samba服务,共享磁盘
|
||||
3. 搭配公网服务器nginx反向代理,在公网访问本地文件
|
||||
4. 点对网(结合启动参数'--in-ip'和'--out-ip')
|
||||
|
||||
|
||||
### 使用须知
|
||||
@@ -68,7 +69,8 @@
|
||||
- Mac
|
||||
- Linux
|
||||
- Windows
|
||||
- 依赖 wintun.dll(https://www.wintun.net/)
|
||||
- 使用tun网卡 依赖wintun.dll(https://www.wintun.net/)
|
||||
- 使用tap网卡 依赖tap-windows(https://build.openvpn.net/downloads/releases/)
|
||||
|
||||
### 特性
|
||||
- IP层数据转发
|
||||
@@ -78,6 +80,7 @@
|
||||
- 点对点穿透
|
||||
- 服务端中继转发
|
||||
- 客户端中继转发
|
||||
- IP代理
|
||||
|
||||
### Todo
|
||||
- 支持安卓
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "switch-desktop"
|
||||
version = "1.0.2"
|
||||
version = "1.0.4"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
@@ -13,7 +13,7 @@ console = "0.15.2"
|
||||
dirs = "4.0.0"
|
||||
log = "0.4.17"
|
||||
log4rs = "1.2.0"
|
||||
#tokio = { version = "1.24.1", features = ["full"] }
|
||||
tokio = { version = "1.28.1", features = ["full"] }
|
||||
chrono = "0.4.23"
|
||||
|
||||
serde = "1.0"
|
||||
|
||||
@@ -1,19 +1,17 @@
|
||||
use std::io;
|
||||
use crate::config::SWITCH_HOME_PATH;
|
||||
use std::path::PathBuf;
|
||||
use crate::config::get_home;
|
||||
|
||||
#[cfg(target_os = "windows")]
|
||||
pub fn log_service_init() -> io::Result<()> {
|
||||
log_init_("switch-service.log")
|
||||
log_init_(crate::config::get_win_server_home().join("switch-service.log"))
|
||||
}
|
||||
|
||||
pub fn log_init() -> io::Result<()> {
|
||||
log_init_("switch-desktop.log")
|
||||
log_init_(get_home().join("switch-desktop.log"))
|
||||
}
|
||||
pub fn log_init_(file_name:&str) -> io::Result<()> {
|
||||
let home = SWITCH_HOME_PATH.lock().clone();
|
||||
let home = if let Some(home) = home {
|
||||
home
|
||||
} else {
|
||||
return Err(io::Error::new(io::ErrorKind::Other, "not found"));
|
||||
};
|
||||
|
||||
fn log_init_(file_name: PathBuf) -> io::Result<()> {
|
||||
let stderr = log4rs::append::console::ConsoleAppender::builder()
|
||||
.target(log4rs::append::console::Target::Stderr)
|
||||
.build();
|
||||
@@ -22,7 +20,7 @@ pub fn log_init_(file_name:&str) -> io::Result<()> {
|
||||
.encoder(Box::new(log4rs::encode::pattern::PatternEncoder::new(
|
||||
"{d(%+)(utc)} [{f}:{L}] {h({l})} {M}:{m}{n}\n",
|
||||
)))
|
||||
.build(home.join(file_name))?;
|
||||
.build(file_name)?;
|
||||
match log4rs::Config::builder()
|
||||
.appender(log4rs::config::Appender::builder().build("logfile", Box::new(logfile)))
|
||||
.appender(
|
||||
|
||||
+275
-115
@@ -1,7 +1,7 @@
|
||||
use std::fs::{File, OpenOptions};
|
||||
use std::io;
|
||||
use std::io::{Read, Write};
|
||||
use std::net::{SocketAddr, ToSocketAddrs};
|
||||
use std::net::{Ipv4Addr, SocketAddr, ToSocketAddrs};
|
||||
use std::path::PathBuf;
|
||||
|
||||
use lazy_static::lazy_static;
|
||||
@@ -11,6 +11,19 @@ use serde::{Deserialize, Serialize};
|
||||
use crate::StartArgs;
|
||||
|
||||
pub mod log_config;
|
||||
lazy_static! {
|
||||
pub static ref SWITCH_HOME_PATH: Mutex<Option<PathBuf>> = Mutex::new(None);
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
pub fn get_win_server_home() -> PathBuf {
|
||||
SWITCH_HOME_PATH.lock().as_ref().unwrap().clone()
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
pub fn set_win_server_home(home: PathBuf) {
|
||||
let _ = SWITCH_HOME_PATH.lock().insert(home);
|
||||
}
|
||||
|
||||
pub struct StartConfig {
|
||||
pub tap: bool,
|
||||
@@ -19,27 +32,73 @@ pub struct StartConfig {
|
||||
pub server: SocketAddr,
|
||||
pub nat_test_server: Vec<SocketAddr>,
|
||||
pub device_id: String,
|
||||
pub in_ips: Vec<(u32, u32, Ipv4Addr)>,
|
||||
pub out_ips: Vec<(u32, u32, Ipv4Addr)>,
|
||||
#[cfg(any(unix))]
|
||||
pub off_command_server: bool,
|
||||
}
|
||||
|
||||
fn ips_parse(ips: &Vec<String>) -> Result<Vec<(u32, u32, Ipv4Addr)>, String> {
|
||||
let mut in_ips_c = vec![];
|
||||
for x in ips {
|
||||
let mut split = x.split(",");
|
||||
let net = if let Some(net) = split.next() {
|
||||
net
|
||||
} else {
|
||||
return Err("参数错误".to_string());
|
||||
};
|
||||
let ip = if let Some(ip) = split.next() {
|
||||
ip
|
||||
} else {
|
||||
return Err("参数错误".to_string());
|
||||
};
|
||||
let ip = if let Ok(ip) = ip.parse::<Ipv4Addr>() {
|
||||
ip
|
||||
} else {
|
||||
return Err("参数错误".to_string());
|
||||
};
|
||||
let mut split = net.split("/");
|
||||
let dest = if let Some(dest) = split.next() {
|
||||
dest
|
||||
} else {
|
||||
return Err("参数错误".to_string());
|
||||
};
|
||||
let mask = if let Some(mask) = split.next() {
|
||||
mask
|
||||
} else {
|
||||
return Err("参数错误".to_string());
|
||||
};
|
||||
let dest = if let Ok(dest) = dest.parse::<Ipv4Addr>() {
|
||||
dest
|
||||
} else {
|
||||
return Err("参数错误".to_string());
|
||||
};
|
||||
let mask = if let Ok(m) = mask.parse::<u32>() {
|
||||
let mut mask = 0 as u32;
|
||||
for i in 0..m {
|
||||
mask = mask | (1 << (31 - i));
|
||||
}
|
||||
mask
|
||||
} else {
|
||||
return Err("参数错误".to_string());
|
||||
};
|
||||
in_ips_c.push((u32::from_be_bytes(dest.octets()), mask, ip));
|
||||
}
|
||||
Ok(in_ips_c)
|
||||
}
|
||||
|
||||
pub fn default_config(start_args: StartArgs) -> Result<StartConfig, String> {
|
||||
println!("========参数配置========");
|
||||
let args_config = read_config();
|
||||
let tap = start_args.tap.unwrap_or_else(|| {
|
||||
if let Some(c) = &args_config {
|
||||
c.tap
|
||||
} else {
|
||||
false
|
||||
}
|
||||
});
|
||||
let tap = start_args.tap;
|
||||
if tap {
|
||||
println!("use tap");
|
||||
} else {
|
||||
println!("use tun");
|
||||
}
|
||||
if args_config.is_none() && start_args.token.is_none() {
|
||||
if start_args.token.is_none() {
|
||||
return Err("找不到token(Token not found)".to_string());
|
||||
}
|
||||
let token = start_args.token.unwrap_or_else(|| args_config.as_ref().unwrap().token.clone()).trim().to_string();
|
||||
let token = start_args.token.unwrap();
|
||||
if token.is_empty() {
|
||||
return Err("token不能为空(Token cannot be empty)".to_string());
|
||||
}
|
||||
@@ -48,11 +107,6 @@ pub fn default_config(start_args: StartArgs) -> Result<StartConfig, String> {
|
||||
}
|
||||
println!("token:{:?}", token);
|
||||
let name = start_args.name.unwrap_or_else(|| {
|
||||
if let Some(c) = &args_config {
|
||||
if !c.name.is_empty() {
|
||||
return c.name.clone();
|
||||
}
|
||||
}
|
||||
os_info::get().to_string()
|
||||
});
|
||||
let name = name.trim();
|
||||
@@ -63,11 +117,6 @@ pub fn default_config(start_args: StartArgs) -> Result<StartConfig, String> {
|
||||
};
|
||||
println!("name:{:?}", name);
|
||||
let device_id = start_args.device_id.unwrap_or_else(|| {
|
||||
if let Some(c) = &args_config {
|
||||
if !c.device_id.is_empty() {
|
||||
return c.device_id.clone();
|
||||
}
|
||||
}
|
||||
if let Ok(Some(mac_address)) = mac_address::get_mac_address() {
|
||||
mac_address.to_string()
|
||||
} else {
|
||||
@@ -78,12 +127,27 @@ pub fn default_config(start_args: StartArgs) -> Result<StartConfig, String> {
|
||||
return Err("设备id不能为空并且长度不能大于64字符(The device id cannot be empty and the length cannot be greater than 64 characters)".to_string());
|
||||
}
|
||||
println!("device_id:{:?}", device_id);
|
||||
let in_ips = start_args.in_ip.unwrap_or_else(|| {
|
||||
vec![]
|
||||
});
|
||||
let out_ips = start_args.out_ip.unwrap_or_else(|| {
|
||||
vec![]
|
||||
});
|
||||
println!("in_ips:{:?}", in_ips);
|
||||
let in_ips_c = if let Ok(in_ips_c) = ips_parse(&in_ips) {
|
||||
in_ips_c
|
||||
} else {
|
||||
return Err("in_ips 参数错误 示例:--in_ip 192.168.10.0/24,10.26.0.3".to_string());
|
||||
};
|
||||
println!("out_ips:{:?}", out_ips);
|
||||
let out_ips_c = if let Ok(out_ips_c) = ips_parse(&out_ips) {
|
||||
out_ips_c
|
||||
} else {
|
||||
return Err("out_ips 参数错误 示例:--out_ip 192.168.10.0/24,192.168.0.5".to_string());
|
||||
};
|
||||
|
||||
|
||||
let server = match start_args.server.unwrap_or_else(|| {
|
||||
if let Some(c) = &args_config {
|
||||
if !c.server.is_empty() {
|
||||
return c.server.clone();
|
||||
}
|
||||
}
|
||||
"nat1.wherewego.top:29871".to_string()
|
||||
}).to_socket_addrs() {
|
||||
Ok(mut server) => {
|
||||
@@ -99,11 +163,6 @@ pub fn default_config(start_args: StartArgs) -> Result<StartConfig, String> {
|
||||
};
|
||||
println!("中继服务器:{:?}", server);
|
||||
let nat_test_server = start_args.nat_test_server.unwrap_or_else(|| {
|
||||
if let Some(c) = &args_config {
|
||||
if !c.nat_test_server.is_empty() {
|
||||
return c.nat_test_server.join(",");
|
||||
}
|
||||
}
|
||||
"nat1.wherewego.top:35061,nat1.wherewego.top:35062,nat2.wherewego.top:35061,nat2.wherewego.top:35062".to_string()
|
||||
}).split(",").flat_map(|a| a.to_socket_addrs()).flatten()
|
||||
.collect::<Vec<_>>();
|
||||
@@ -118,19 +177,128 @@ pub fn default_config(start_args: StartArgs) -> Result<StartConfig, String> {
|
||||
server,
|
||||
nat_test_server,
|
||||
device_id,
|
||||
in_ips: in_ips_c,
|
||||
out_ips: out_ips_c,
|
||||
#[cfg(any(unix))]
|
||||
off_command_server: start_args.off_command_server,
|
||||
};
|
||||
println!("========参数配置========");
|
||||
Ok(base_config)
|
||||
}
|
||||
|
||||
lazy_static! {
|
||||
static ref CONFIG: Mutex<Option<ArgsConfig>> = Mutex::new(None);
|
||||
pub static ref SWITCH_HOME_PATH: Mutex<Option<PathBuf>> = Mutex::new(None);
|
||||
pub fn read_config_file(config_path: PathBuf) -> Result<StartConfig, String> {
|
||||
println!("========读取配置文件========");
|
||||
let args_config = if let Ok(config) = read_config(config_path) {
|
||||
config
|
||||
} else {
|
||||
return Err("读取配置文件失败".to_string());
|
||||
};
|
||||
|
||||
let tap = args_config.tap;
|
||||
if tap {
|
||||
println!("use tap");
|
||||
} else {
|
||||
println!("use tun");
|
||||
}
|
||||
let token = args_config.token;
|
||||
if token.is_empty() {
|
||||
return Err("token不能为空(Token cannot be empty)".to_string());
|
||||
}
|
||||
if token.len() > 64 {
|
||||
return Err("token不能超过64字符(Token cannot exceed 64 characters)".to_string());
|
||||
}
|
||||
println!("token:{:?}", token);
|
||||
let name = args_config.name;
|
||||
let name = name.trim();
|
||||
let name = if name.len() > 64 {
|
||||
name[..64].to_string()
|
||||
} else {
|
||||
name.to_string()
|
||||
};
|
||||
println!("name:{:?}", name);
|
||||
let device_id = if !args_config.device_id.is_empty() {
|
||||
args_config.device_id
|
||||
} else {
|
||||
if let Ok(Some(mac_address)) = mac_address::get_mac_address() {
|
||||
mac_address.to_string()
|
||||
} else {
|
||||
"".to_string()
|
||||
}
|
||||
};
|
||||
if device_id.is_empty() || device_id.len() > 64 {
|
||||
return Err("设备id不能为空并且长度不能大于64字符(The device id cannot be empty and the length cannot be greater than 64 characters)".to_string());
|
||||
}
|
||||
println!("device_id:{:?}", device_id);
|
||||
let in_ips = args_config.in_ips;
|
||||
let out_ips = args_config.out_ips;
|
||||
println!("in_ips:{:?}", in_ips);
|
||||
let in_ips_c = if let Ok(in_ips_c) = ips_parse(&in_ips) {
|
||||
in_ips_c
|
||||
} else {
|
||||
return Err("in_ips 参数错误 示例:--in_ip 192.168.10.0/24,10.26.0.3".to_string());
|
||||
};
|
||||
println!("out_ips:{:?}", out_ips);
|
||||
let out_ips_c = if let Ok(out_ips_c) = ips_parse(&out_ips) {
|
||||
out_ips_c
|
||||
} else {
|
||||
return Err("out_ips 参数错误 示例:--out_ip 192.168.10.0/24,192.168.0.5".to_string());
|
||||
};
|
||||
let server = match {
|
||||
if !args_config.server.is_empty() {
|
||||
args_config.server
|
||||
} else {
|
||||
"nat1.wherewego.top:29871".to_string()
|
||||
}
|
||||
}.to_socket_addrs()
|
||||
{
|
||||
Ok(mut server) => {
|
||||
if let Some(addr) = server.next() {
|
||||
addr
|
||||
} else {
|
||||
return Err("中继服务器地址错误( Relay server address error)".to_string());
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
return Err(format!("中继服务器地址错误( Relay server address error) :{:?}", e));
|
||||
}
|
||||
};
|
||||
println!("中继服务器:{:?}", server);
|
||||
let nat_test_server = if args_config.nat_test_server.is_empty() {
|
||||
vec!["nat1.wherewego.top:35061".to_string(), "nat1.wherewego.top:35062".to_string(), "nat2.wherewego.top:35061".to_string(), "nat2.wherewego.top:35062".to_string()]
|
||||
} else {
|
||||
args_config.nat_test_server
|
||||
}.iter().flat_map(|a| a.to_socket_addrs()).flatten()
|
||||
.collect::<Vec<_>>();
|
||||
if nat_test_server.is_empty() {
|
||||
return Err("NAT检测服务地址错误(NAT detection service address error)".to_string());
|
||||
}
|
||||
println!("NAT探测服务器:{:?}", nat_test_server);
|
||||
let base_config = StartConfig {
|
||||
tap,
|
||||
name,
|
||||
token,
|
||||
server,
|
||||
nat_test_server,
|
||||
device_id,
|
||||
in_ips: in_ips_c,
|
||||
out_ips: out_ips_c,
|
||||
#[cfg(any(unix))]
|
||||
off_command_server: args_config.off_command_server,
|
||||
};
|
||||
println!("========参数配置========");
|
||||
Ok(base_config)
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
pub struct RuntimeData {
|
||||
#[serde(default = "default_pid")]
|
||||
pub pid: u32,
|
||||
pub command_port: Option<u16>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
pub struct ArgsConfig {
|
||||
#[serde(default = "default_tap")]
|
||||
#[serde(default = "default_false")]
|
||||
pub tap: bool,
|
||||
#[serde(default = "default_version")]
|
||||
pub version: String,
|
||||
@@ -138,18 +306,22 @@ pub struct ArgsConfig {
|
||||
pub token: String,
|
||||
#[serde(default = "default_str")]
|
||||
pub name: String,
|
||||
pub command_port: Option<u16>,
|
||||
#[serde(default = "default_str")]
|
||||
pub server: String,
|
||||
#[serde(default = "default_vec")]
|
||||
pub nat_test_server: Vec<String>,
|
||||
#[serde(default = "default_str")]
|
||||
pub device_id: String,
|
||||
#[serde(default = "default_pid")]
|
||||
pub pid: u32,
|
||||
#[serde(default = "default_vec")]
|
||||
pub in_ips: Vec<String>,
|
||||
#[serde(default = "default_vec")]
|
||||
pub out_ips: Vec<String>,
|
||||
#[cfg(any(unix))]
|
||||
#[serde(default = "default_false")]
|
||||
pub off_command_server: bool,
|
||||
}
|
||||
|
||||
fn default_tap() -> bool {
|
||||
fn default_false() -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
@@ -169,77 +341,61 @@ fn default_pid() -> u32 {
|
||||
0
|
||||
}
|
||||
|
||||
impl ArgsConfig {
|
||||
pub fn new(tap: bool, token: String, name: String, server: SocketAddr,
|
||||
nat_test_server: &Vec<SocketAddr>, device_id: String, ) -> Self {
|
||||
Self {
|
||||
tap,
|
||||
version: "1.0".to_string(),
|
||||
token,
|
||||
name,
|
||||
command_port: None,
|
||||
server: server.to_string(),
|
||||
nat_test_server: nat_test_server.iter().map(|v| v.to_string()).collect::<Vec<String>>(),
|
||||
device_id,
|
||||
pid: 0,
|
||||
}
|
||||
}
|
||||
}
|
||||
// impl ArgsConfig {
|
||||
// pub fn new(tap: bool, token: String, name: String, server: SocketAddr,
|
||||
// nat_test_server: &Vec<SocketAddr>, device_id: String,
|
||||
// in_ips: Vec<(u32, u32, Ipv4Addr)>, out_ips: Vec<(u32, u32, Ipv4Addr)>, ) -> Self {
|
||||
//
|
||||
// Self {
|
||||
// tap,
|
||||
// version: "1.0".to_string(),
|
||||
// token,
|
||||
// name,
|
||||
// command_port: None,
|
||||
// server: server.to_string(),
|
||||
// nat_test_server: nat_test_server.iter().map(|v| v.to_string()).collect::<Vec<String>>(),
|
||||
// device_id,
|
||||
// pid: 0,
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
pub fn lock_file() -> io::Result<File> {
|
||||
let path = SWITCH_HOME_PATH.lock().clone().unwrap().join(".lock");
|
||||
Ok(File::create(path)?)
|
||||
let path = get_home().join(".lock");
|
||||
let file = File::create(path)?;
|
||||
file.sync_all()?;
|
||||
Ok(file)
|
||||
}
|
||||
|
||||
pub fn save_config(config: ArgsConfig) -> io::Result<()> {
|
||||
let config_path = SWITCH_HOME_PATH.lock().clone().unwrap().join("config");
|
||||
save_config_(config, config_path)
|
||||
}
|
||||
|
||||
fn save_config_(config: ArgsConfig, config_path: PathBuf) -> io::Result<()> {
|
||||
let mut config_lock = CONFIG.lock();
|
||||
config_lock.take();
|
||||
fn save_runtime_data(config: RuntimeData) -> io::Result<()> {
|
||||
let config_path = get_runtime_data_path();
|
||||
let str = serde_yaml::to_string(&config).unwrap();
|
||||
let mut file = File::create(config_path)?;
|
||||
file.write_all(str.as_bytes())
|
||||
file.write_all(str.as_bytes())?;
|
||||
file.sync_all()
|
||||
}
|
||||
|
||||
pub fn update_pid(pid: u32) -> io::Result<()> {
|
||||
let home_lock = SWITCH_HOME_PATH.lock();
|
||||
if let Some(home) = home_lock.clone() {
|
||||
drop(home_lock);
|
||||
let config_path = home.join("config");
|
||||
if let Some(mut config) = read_config() {
|
||||
config.pid = pid;
|
||||
return save_config_(config, config_path);
|
||||
}
|
||||
}
|
||||
Err(io::Error::new(io::ErrorKind::Other, "not found"))
|
||||
let mut config = read_runtime_data()?;
|
||||
config.pid = pid;
|
||||
return save_runtime_data(config);
|
||||
}
|
||||
|
||||
#[cfg(any(unix))]
|
||||
pub fn read_pid() -> io::Result<u32> {
|
||||
let home = SWITCH_HOME_PATH.lock().clone().unwrap();
|
||||
let config = read_config_(home)?;
|
||||
let config = read_runtime_data()?;
|
||||
Ok(config.pid)
|
||||
}
|
||||
|
||||
pub fn update_command_port(port: u16) -> io::Result<()> {
|
||||
let home_lock = SWITCH_HOME_PATH.lock();
|
||||
if let Some(home) = home_lock.clone() {
|
||||
drop(home_lock);
|
||||
let config_path = home.join("config");
|
||||
if let Some(mut config) = read_config() {
|
||||
config.command_port = Some(port);
|
||||
return save_config_(config, config_path);
|
||||
}
|
||||
}
|
||||
Err(io::Error::new(io::ErrorKind::Other, "not found"))
|
||||
let mut config = read_runtime_data()?;
|
||||
config.command_port = Some(port);
|
||||
return save_runtime_data(config);
|
||||
}
|
||||
|
||||
pub fn read_command_port() -> io::Result<u16> {
|
||||
let home = SWITCH_HOME_PATH.lock().clone().unwrap();
|
||||
let config = read_config_(home)?;
|
||||
let config = read_runtime_data()?;
|
||||
if let Some(p) = config.command_port {
|
||||
Ok(p)
|
||||
} else {
|
||||
@@ -247,37 +403,28 @@ pub fn read_command_port() -> io::Result<u16> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn read_config() -> Option<ArgsConfig> {
|
||||
let mut lock = CONFIG.lock();
|
||||
let c = lock.clone();
|
||||
if c.is_some() {
|
||||
return c;
|
||||
}
|
||||
if let Some(home) = SWITCH_HOME_PATH.lock().clone() {
|
||||
match read_config_(home.to_path_buf()) {
|
||||
Ok(config) => {
|
||||
lock.replace(config.clone());
|
||||
Some(config)
|
||||
}
|
||||
Err(e) => {
|
||||
log::error!("{:?},path:{:?}", e,home);
|
||||
None
|
||||
}
|
||||
}
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_home(home: PathBuf) {
|
||||
pub fn get_home() -> PathBuf {
|
||||
#[cfg(windows)]
|
||||
{
|
||||
if let Some(path) = SWITCH_HOME_PATH.lock().as_ref() {
|
||||
return path.clone();
|
||||
}
|
||||
}
|
||||
let home = dirs::home_dir().unwrap().join(".switch_desktop");
|
||||
if !home.exists() {
|
||||
std::fs::create_dir(&home).unwrap();
|
||||
}
|
||||
SWITCH_HOME_PATH.lock().replace(home);
|
||||
home
|
||||
}
|
||||
|
||||
fn read_config_(home: PathBuf) -> io::Result<ArgsConfig> {
|
||||
let config_path = home.join("config");
|
||||
pub fn get_runtime_data_path() -> PathBuf {
|
||||
let home = get_home();
|
||||
home.join(".data")
|
||||
}
|
||||
|
||||
fn read_runtime_data() -> io::Result<RuntimeData> {
|
||||
let config_path = get_runtime_data_path();
|
||||
let mut file = if config_path.exists() {
|
||||
File::open(config_path)?
|
||||
} else {
|
||||
@@ -285,6 +432,19 @@ fn read_config_(home: PathBuf) -> io::Result<ArgsConfig> {
|
||||
};
|
||||
let mut str = String::new();
|
||||
file.read_to_string(&mut str)?;
|
||||
match serde_yaml::from_str::<RuntimeData>(&str) {
|
||||
Ok(config) => Ok(config),
|
||||
Err(e) => {
|
||||
log::warn!("{:?}", e);
|
||||
Err(io::Error::new(io::ErrorKind::Other, "config error"))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn read_config(config_path: PathBuf) -> io::Result<ArgsConfig> {
|
||||
let mut file = File::open(config_path)?;
|
||||
let mut str = String::new();
|
||||
file.read_to_string(&mut str)?;
|
||||
match serde_yaml::from_str::<ArgsConfig>(&str) {
|
||||
Ok(config) => Ok(config),
|
||||
Err(e) => {
|
||||
@@ -292,4 +452,4 @@ fn read_config_(home: PathBuf) -> io::Result<ArgsConfig> {
|
||||
Err(io::Error::new(io::ErrorKind::Other, "config error"))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+28
-11
@@ -97,7 +97,19 @@ pub struct StartArgs {
|
||||
log: bool,
|
||||
/// 使用tap网卡
|
||||
#[arg(long)]
|
||||
tap: Option<bool>,
|
||||
tap: bool,
|
||||
/// 配置点对网时使用,--in-ip 192.168.10.0/24,10.26.0.3,表示允许接收网段192.168.10.0/24的数据并转发到10.26.0.3
|
||||
/// Use when configuring peer-to-peer networks
|
||||
#[arg(long)]
|
||||
in_ip:Option<Vec<String>>,
|
||||
/// 配置点对网时使用,--out-ip 192.168.10.0/24,192.168.1.10,表示允许目标为192.168.10.0/24的数据从网卡192.168.1.10转发出去
|
||||
/// Use when configuring peer-to-peer networks
|
||||
#[arg(long)]
|
||||
out_ip:Option<Vec<String>>,
|
||||
/// 读取配置文件 --config config_file_path
|
||||
/// Read configuration file
|
||||
#[arg(long)]
|
||||
config:Option<String>,
|
||||
}
|
||||
|
||||
#[cfg(target_os = "windows")]
|
||||
@@ -124,37 +136,42 @@ pub struct ConfigArgs {
|
||||
|
||||
|
||||
#[cfg(windows)]
|
||||
fn main() {
|
||||
#[tokio::main]
|
||||
async fn main() {
|
||||
let args: Vec<_> = std::env::args().collect();
|
||||
if args.len() == 3 && args[1] == windows::SERVICE_FLAG {
|
||||
//以服务的方式启动
|
||||
config::set_home(std::path::PathBuf::from(&args[2]));
|
||||
config::set_win_server_home(std::path::PathBuf::from(&args[2]));
|
||||
windows::service::start();
|
||||
return;
|
||||
} else {
|
||||
let home = dirs::home_dir().unwrap().join(".switch_desktop");
|
||||
config::set_home(home);
|
||||
let args = BaseArgs::parse();
|
||||
if let Commands::Start(start_args) = &args.command {
|
||||
if start_args.log {
|
||||
let _ = log_init();
|
||||
}
|
||||
}
|
||||
windows::main0(args);
|
||||
windows::main0(args).await;
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(any(target_os = "linux", target_os = "macos"))]
|
||||
fn main() {
|
||||
let home = dirs::home_dir().unwrap().join(".switch_desktop");
|
||||
config::set_home(home);
|
||||
#[tokio::main]
|
||||
async fn main() {
|
||||
if sudo::RunningAs::Root != sudo::check() {
|
||||
println!(
|
||||
"{}",
|
||||
style("需要使用root权限执行(Need to execute with root permission)...").red()
|
||||
);
|
||||
sudo::escalate_if_needed().unwrap();
|
||||
}
|
||||
let args = BaseArgs::parse();
|
||||
if let Commands::Start(start_args) = &args.command {
|
||||
if start_args.log {
|
||||
let _ = log_init();
|
||||
}
|
||||
}
|
||||
unix::main0(args);
|
||||
unix::main0(args).await;
|
||||
}
|
||||
|
||||
pub fn console_listen(switch: &Switch) {
|
||||
@@ -196,7 +213,7 @@ pub fn console_listen(switch: &Switch) {
|
||||
if let Err(e) = switch.stop() {
|
||||
log::error!("stop:{:?}", e);
|
||||
}
|
||||
std::thread::sleep(std::time::Duration::from_secs(1));
|
||||
thread::sleep(Duration::from_secs(1));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,104 +9,93 @@ use crate::{BaseArgs, Commands, config};
|
||||
use crate::command::{command, CommandEnum};
|
||||
|
||||
|
||||
pub fn main0(base_args: BaseArgs) {
|
||||
pub async fn main0(base_args: BaseArgs) {
|
||||
match base_args.command {
|
||||
Commands::Start(args) => {
|
||||
let off_command_server = args.off_command_server;
|
||||
match config::default_config(args) {
|
||||
Ok(start_config) => {
|
||||
if sudo::RunningAs::Root != sudo::check() {
|
||||
println!(
|
||||
"{}",
|
||||
style("需要使用root权限执行(Need to execute with root permission)...").red()
|
||||
);
|
||||
sudo::escalate_if_needed().unwrap();
|
||||
let start_config = if let Some(config_path) = &args.config {
|
||||
match config::read_config_file(config_path.into()) {
|
||||
Ok(start_config) => {
|
||||
start_config
|
||||
}
|
||||
|
||||
let config = Config::new(
|
||||
start_config.tap,
|
||||
start_config.token.clone(),
|
||||
start_config.device_id.clone(),
|
||||
start_config.name.clone(),
|
||||
start_config.server,
|
||||
start_config.nat_test_server.clone(),
|
||||
);
|
||||
let args_config = config::ArgsConfig::new(
|
||||
start_config.tap,
|
||||
start_config.token.clone(),
|
||||
start_config.name.clone(),
|
||||
start_config.server,
|
||||
&start_config.nat_test_server,
|
||||
start_config.device_id.clone(),
|
||||
);
|
||||
let lock = match config::lock_file() {
|
||||
Ok(lock) => {
|
||||
lock
|
||||
}
|
||||
Err(e) => {
|
||||
log::error!("{:?}",e);
|
||||
println!("文件锁定失败:{:?}", e);
|
||||
return;
|
||||
}
|
||||
};
|
||||
if lock.try_lock_exclusive().is_err() {
|
||||
println!("{}", style("文件被重复打开").red());
|
||||
Err(e) => {
|
||||
println!("{}", style(&e).red());
|
||||
log::error!("{:?}", e);
|
||||
return;
|
||||
}
|
||||
if let Err(e) = config::save_config(args_config) {
|
||||
log::error!("{:?}",e);
|
||||
lock.unlock().unwrap();
|
||||
}
|
||||
} else {
|
||||
match config::default_config(args) {
|
||||
Ok(start_config) => {
|
||||
start_config
|
||||
}
|
||||
Err(e) => {
|
||||
println!("{}", style(&e).red());
|
||||
log::error!("{:?}", e);
|
||||
return;
|
||||
}
|
||||
let switch = match Switch::start(config) {
|
||||
Ok(switch) => {
|
||||
switch
|
||||
}
|
||||
Err(e) => {
|
||||
log::error!("{:?}", e);
|
||||
println!("启动switch失败:{:?}", e);
|
||||
lock.unlock().unwrap();
|
||||
return;
|
||||
}
|
||||
};
|
||||
let switch = Arc::new(switch);
|
||||
let command_server = crate::command::server::CommandServer::new();
|
||||
if off_command_server {
|
||||
crate::console_listen(&switch);
|
||||
log::info!("前台任务结束");
|
||||
} else {
|
||||
if let Err(e) = config::update_pid(std::process::id()) {
|
||||
log::error!("{:?}", e);
|
||||
}
|
||||
let switch1 = switch.clone();
|
||||
let handle = std::thread::Builder::new().name("cmd-server".into()).spawn(move || {
|
||||
if let Err(e) = command_server.start(switch1) {
|
||||
log::error!("{:?}", e);
|
||||
}
|
||||
}).unwrap();
|
||||
crate::console_listen(&switch);
|
||||
if let Err(e) = handle.join() {
|
||||
log::error!("后台任务异常{:?}",e);
|
||||
} else {
|
||||
log::info!("后台任务结束");
|
||||
}
|
||||
}
|
||||
lock.unlock().unwrap();
|
||||
}
|
||||
};
|
||||
let off_command_server = start_config.off_command_server;
|
||||
let config = Config::new(
|
||||
start_config.tap,
|
||||
start_config.token.clone(),
|
||||
start_config.device_id.clone(),
|
||||
start_config.name.clone(),
|
||||
start_config.server,
|
||||
start_config.nat_test_server.clone(),
|
||||
start_config.in_ips.clone(),
|
||||
start_config.out_ips.clone(),
|
||||
);
|
||||
let lock = match config::lock_file() {
|
||||
Ok(lock) => {
|
||||
lock
|
||||
}
|
||||
Err(e) => {
|
||||
println!("{}", style(&e).red());
|
||||
log::error!("{:?}",e);
|
||||
println!("文件锁定失败:{:?}", e);
|
||||
return;
|
||||
}
|
||||
};
|
||||
if lock.try_lock_exclusive().is_err() {
|
||||
println!("{}", style("文件被重复打开").red());
|
||||
return;
|
||||
}
|
||||
let switch = match Switch::start(config).await {
|
||||
Ok(switch) => {
|
||||
switch
|
||||
}
|
||||
Err(e) => {
|
||||
log::error!("{:?}", e);
|
||||
println!("启动switch失败:{:?}", e);
|
||||
lock.unlock().unwrap();
|
||||
return;
|
||||
}
|
||||
};
|
||||
let switch = Arc::new(switch);
|
||||
let command_server = crate::command::server::CommandServer::new();
|
||||
if off_command_server {
|
||||
crate::console_listen(&switch);
|
||||
log::info!("前台任务结束");
|
||||
} else {
|
||||
if let Err(e) = config::update_pid(std::process::id()) {
|
||||
log::error!("{:?}", e);
|
||||
}
|
||||
let switch1 = switch.clone();
|
||||
let handle = std::thread::Builder::new().name("cmd-server".into()).spawn(move || {
|
||||
if let Err(e) = command_server.start(switch1) {
|
||||
log::error!("{:?}", e);
|
||||
}
|
||||
}).unwrap();
|
||||
crate::console_listen(&switch);
|
||||
if let Err(e) = handle.join() {
|
||||
log::error!("后台任务异常{:?}",e);
|
||||
} else {
|
||||
log::info!("后台任务结束");
|
||||
}
|
||||
}
|
||||
lock.unlock().unwrap();
|
||||
}
|
||||
Commands::Stop => {
|
||||
if sudo::RunningAs::Root != sudo::check() {
|
||||
println!(
|
||||
"{}",
|
||||
style("需要使用root权限执行(Need to execute with root permission)...").red()
|
||||
);
|
||||
sudo::escalate_if_needed().unwrap();
|
||||
}
|
||||
command(CommandEnum::Stop);
|
||||
if let Ok(pid) = config::read_pid() {
|
||||
if pid != 0 {
|
||||
|
||||
@@ -52,7 +52,7 @@ fn not_started() -> bool {
|
||||
return true;
|
||||
}
|
||||
|
||||
pub fn main0(base_args: BaseArgs) {
|
||||
pub async fn main0(base_args: BaseArgs) {
|
||||
match base_args.command {
|
||||
Commands::Start(args) => {
|
||||
if admin_check() {
|
||||
@@ -62,92 +62,98 @@ pub fn main0(base_args: BaseArgs) {
|
||||
// 允许应用通过防火墙
|
||||
let _udp = UdpSocket::bind("0.0.0.0:0").unwrap();
|
||||
}
|
||||
let out_log = args.log;
|
||||
match config::default_config(args) {
|
||||
Ok(start_config) => {
|
||||
if let Err(e) = config::save_config(config::ArgsConfig::new(start_config.tap,
|
||||
start_config.token.clone(),
|
||||
start_config.name.clone(),
|
||||
start_config.server,
|
||||
&start_config.nat_test_server,
|
||||
start_config.device_id.clone(),
|
||||
)) {
|
||||
let start_config = if let Some(config_path) = &args.config {
|
||||
match config::read_config_file(config_path.into()) {
|
||||
Ok(start_config) => {
|
||||
start_config
|
||||
}
|
||||
Err(e) => {
|
||||
println!("{}", style(&e).red());
|
||||
log::error!("{:?}",e);
|
||||
log::error!("{:?}", e);
|
||||
return;
|
||||
}
|
||||
match service_state() {
|
||||
Ok(state) => {
|
||||
if state == ServiceState::Stopped {
|
||||
match start(out_log) {
|
||||
Ok(_) => {
|
||||
//需要检查启动状态
|
||||
thread::sleep(Duration::from_secs(2));
|
||||
println!("{}", style("启动成功(Start successfully)").green())
|
||||
}
|
||||
Err(e) => {
|
||||
log::error!("{:?}", e);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
println!("服务未停止(Service not stopped)");
|
||||
}
|
||||
} else {
|
||||
match config::default_config(args) {
|
||||
Ok(start_config) => {
|
||||
start_config
|
||||
}
|
||||
Err(e) => {
|
||||
println!("{}", style(&e).red());
|
||||
log::error!("{:?}", e);
|
||||
return;
|
||||
}
|
||||
}
|
||||
};
|
||||
match service_state() {
|
||||
Ok(state) => {
|
||||
if state == ServiceState::Stopped {
|
||||
match start() {
|
||||
Ok(_) => {
|
||||
//需要检查启动状态
|
||||
thread::sleep(Duration::from_secs(2));
|
||||
println!("{}", style("启动成功(Start successfully)").green());
|
||||
}
|
||||
Err(e) => {
|
||||
log::error!("{:?}", e);
|
||||
println!("{}:{}", style("启动失败").red(),e);
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
match e {
|
||||
Error::Winapi(ref e) => {
|
||||
if let Some(code) = e.raw_os_error() {
|
||||
if code == 1060 {
|
||||
//指定的服务未安装。
|
||||
println!(
|
||||
"{}",
|
||||
style("服务未安装,在当前进程启动(The service is not installed and started in the current process)").red()
|
||||
);
|
||||
let config = Config::new(
|
||||
start_config.tap,
|
||||
start_config.token,
|
||||
start_config.device_id,
|
||||
start_config.name,
|
||||
start_config.server,
|
||||
start_config.nat_test_server,
|
||||
);
|
||||
let lock = match config::lock_file() {
|
||||
Ok(lock) => {
|
||||
lock
|
||||
}
|
||||
Err(e) => {
|
||||
log::error!("文件锁定失败:{:?}",e);
|
||||
println!("文件锁定失败:{:?}", e);
|
||||
return;
|
||||
}
|
||||
};
|
||||
if lock.try_lock_exclusive().is_err() {
|
||||
println!("{}", style("文件被重复打开").red());
|
||||
return;
|
||||
}
|
||||
match Switch::start(config) {
|
||||
Ok(switch) => {
|
||||
crate::console_listen(&switch);
|
||||
}
|
||||
Err(e) => {
|
||||
log::error!("{:?}", e);
|
||||
println!("启动switch失败:{:?}", e);
|
||||
}
|
||||
}
|
||||
lock.unlock().unwrap();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
println!("{:?}", e);
|
||||
}
|
||||
} else {
|
||||
println!("服务未停止(Service not stopped)");
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
println!("{}", style(&e).red());
|
||||
log::error!("{:?}", e);
|
||||
match e {
|
||||
Error::Winapi(ref e) => {
|
||||
if let Some(code) = e.raw_os_error() {
|
||||
if code == 1060 {
|
||||
//指定的服务未安装。
|
||||
println!(
|
||||
"{}",
|
||||
style("服务未安装,在当前进程启动(The service is not installed and started in the current process)").red()
|
||||
);
|
||||
let config = Config::new(
|
||||
start_config.tap,
|
||||
start_config.token,
|
||||
start_config.device_id,
|
||||
start_config.name,
|
||||
start_config.server,
|
||||
start_config.nat_test_server,
|
||||
start_config.in_ips,
|
||||
start_config.out_ips,
|
||||
);
|
||||
let lock = match config::lock_file() {
|
||||
Ok(lock) => {
|
||||
lock
|
||||
}
|
||||
Err(e) => {
|
||||
log::error!("文件锁定失败:{:?}",e);
|
||||
println!("文件锁定失败:{:?}", e);
|
||||
return;
|
||||
}
|
||||
};
|
||||
if lock.try_lock_exclusive().is_err() {
|
||||
println!("{}", style("文件被重复打开").red());
|
||||
return;
|
||||
}
|
||||
match Switch::start(config).await {
|
||||
Ok(switch) => {
|
||||
crate::console_listen(&switch);
|
||||
}
|
||||
Err(e) => {
|
||||
log::error!("{:?}", e);
|
||||
println!("启动switch失败:{:?}", e);
|
||||
}
|
||||
}
|
||||
lock.unlock().unwrap();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
println!("{:?}", e);
|
||||
}
|
||||
};
|
||||
pause();
|
||||
@@ -165,6 +171,7 @@ pub fn main0(base_args: BaseArgs) {
|
||||
}
|
||||
Err(e) => {
|
||||
log::error!("{:?}", e);
|
||||
println!("停止失败:{}",e);
|
||||
}
|
||||
}
|
||||
pause();
|
||||
@@ -182,6 +189,7 @@ pub fn main0(base_args: BaseArgs) {
|
||||
} else {
|
||||
if let Err(e) = install(path, args.auto) {
|
||||
log::error!("{:?}", e);
|
||||
println!("安装失败:{}",e);
|
||||
} else {
|
||||
println!("{}", style("安装成功(Installation succeeded)").green())
|
||||
}
|
||||
@@ -194,6 +202,7 @@ pub fn main0(base_args: BaseArgs) {
|
||||
}
|
||||
if let Err(e) = uninstall() {
|
||||
log::error!("{:?}", e);
|
||||
println!("卸载失败:{}",e);
|
||||
} else {
|
||||
println!("{}", style("卸载成功(Uninstall succeeded)").green())
|
||||
}
|
||||
@@ -202,6 +211,7 @@ pub fn main0(base_args: BaseArgs) {
|
||||
Commands::Config(args) => {
|
||||
if let Err(e) = change(args.auto) {
|
||||
log::error!("{:?}", e);
|
||||
println!("配置失败:{}",e);
|
||||
} else {
|
||||
println!("{}", style("配置成功(Config succeeded)").green())
|
||||
}
|
||||
@@ -259,7 +269,7 @@ fn install(path: PathBuf, auto: bool) -> Result<(), Error> {
|
||||
let mut launch_arguments = Vec::new();
|
||||
launch_arguments.push(OsString::from(SERVICE_FLAG));
|
||||
launch_arguments.push(OsString::from(
|
||||
dirs::home_dir().unwrap().join(".switch").to_str().unwrap(),
|
||||
config::get_home().to_str().unwrap(),
|
||||
));
|
||||
let start_type = if auto {
|
||||
ServiceStartType::AutoStart
|
||||
@@ -298,7 +308,7 @@ fn change(auto: bool) -> Result<(), Error> {
|
||||
let mut launch_arguments = Vec::new();
|
||||
launch_arguments.push(OsString::from(SERVICE_FLAG));
|
||||
launch_arguments.push(OsString::from(
|
||||
dirs::home_dir().unwrap().join(".switch").to_str().unwrap(),
|
||||
config::get_home().to_str().unwrap(),
|
||||
));
|
||||
let service_info = ServiceInfo {
|
||||
name: OsString::from(SERVICE_NAME),
|
||||
@@ -333,15 +343,12 @@ fn uninstall() -> Result<(), Error> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn start(out_log: bool) -> Result<(), Error> {
|
||||
fn start() -> Result<(), Error> {
|
||||
let manager_access = ServiceManagerAccess::CONNECT;
|
||||
let service_manager = ServiceManager::local_computer(None::<&str>, manager_access)?;
|
||||
let service = service_manager.open_service(SERVICE_NAME, ServiceAccess::START)?;
|
||||
if out_log {
|
||||
service.start(&["log"])
|
||||
} else {
|
||||
service.start(&[""])
|
||||
}
|
||||
let args: Vec<_> = std::env::args().collect();
|
||||
service.start(&args[1..])
|
||||
}
|
||||
|
||||
fn service_state() -> Result<ServiceState, Error> {
|
||||
|
||||
@@ -5,6 +5,7 @@ use std::ffi::OsString;
|
||||
use std::sync::Arc;
|
||||
use std::thread;
|
||||
use std::time::Duration;
|
||||
use clap::Parser;
|
||||
|
||||
use windows_service::{define_windows_service, service_control_handler, service_dispatcher};
|
||||
use windows_service::service::{
|
||||
@@ -14,27 +15,36 @@ use windows_service::service_control_handler::ServiceControlHandlerResult;
|
||||
|
||||
use switch::core::{Config, Switch};
|
||||
|
||||
use crate::{config, StartArgs};
|
||||
use crate::{BaseArgs, Commands, config, StartArgs};
|
||||
use crate::windows::SERVICE_NAME;
|
||||
|
||||
define_windows_service!(ffi_service_main, switch_service_main);
|
||||
pub fn switch_service_main(arguments: Vec<OsString>) {
|
||||
if !arguments.is_empty() {
|
||||
if let Some(str) = arguments[0].to_str() {
|
||||
if str == "log" {
|
||||
let base_args = BaseArgs::parse_from(arguments);
|
||||
match base_args.command {
|
||||
Commands::Start(args) => {
|
||||
if args.log {
|
||||
let _ = config::log_config::log_service_init();
|
||||
}
|
||||
tokio::runtime::Builder::new_multi_thread()
|
||||
.enable_all()
|
||||
.build()
|
||||
.unwrap()
|
||||
.block_on(async {
|
||||
match service_main(args).await {
|
||||
Ok(_) => {}
|
||||
Err(e) => {
|
||||
log::error!("启动服务失败:{:?}",e);
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
thread::spawn(|| match service_main() {
|
||||
Ok(_) => {}
|
||||
Err(e) => {
|
||||
log::error!("{:?}", e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
fn service_main() -> windows_service::Result<()> {
|
||||
async fn service_main(args: StartArgs) -> windows_service::Result<()> {
|
||||
log::info!("service_main:{:?}",args);
|
||||
let parker = crossbeam::sync::Parker::new();
|
||||
let un_parker = parker.unparker().clone();
|
||||
let event_handler = move |control_event| -> ServiceControlHandlerResult {
|
||||
@@ -68,7 +78,7 @@ fn service_main() -> windows_service::Result<()> {
|
||||
wait_hint: Duration::default(),
|
||||
process_id: None,
|
||||
})?;
|
||||
match start_switch() {
|
||||
match start_switch(args).await {
|
||||
Ok(switch) => {
|
||||
parker.park();
|
||||
if let Err(e) = switch.stop() {
|
||||
@@ -90,36 +100,52 @@ fn service_main() -> windows_service::Result<()> {
|
||||
})
|
||||
}
|
||||
|
||||
fn start_switch() -> switch::Result<Arc<Switch>> {
|
||||
match config::default_config(StartArgs::default()) {
|
||||
Ok(start_config) => {
|
||||
let config = Config::new(
|
||||
start_config.tap,
|
||||
start_config.token,
|
||||
start_config.device_id,
|
||||
start_config.name,
|
||||
start_config.server,
|
||||
start_config.nat_test_server,
|
||||
);
|
||||
let switch = Switch::start(config)?;
|
||||
log::info!("switch-service服务启动");
|
||||
let switch = Arc::new(switch);
|
||||
let command_server = crate::command::server::CommandServer::new();
|
||||
let switch1 = switch.clone();
|
||||
thread::spawn(move || {
|
||||
if let Err(e) = config::update_pid(std::process::id()) {
|
||||
log::error!("{:?}", e);
|
||||
}
|
||||
if let Err(e) = command_server.start(switch1) {
|
||||
log::error!("{:?}", e);
|
||||
}
|
||||
});
|
||||
Ok(switch)
|
||||
async fn start_switch(args: StartArgs) -> switch::Result<Arc<Switch>> {
|
||||
let start_config = if let Some(config_path) = &args.config {
|
||||
match config::read_config_file(config_path.into()) {
|
||||
Ok(start_config) => {
|
||||
start_config
|
||||
}
|
||||
Err(e) => {
|
||||
log::error!("{:?}", e);
|
||||
return Err(switch::error::Error::Stop(e));
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
return Err(switch::error::Error::Stop(e));
|
||||
} else {
|
||||
match config::default_config(args) {
|
||||
Ok(start_config) => {
|
||||
start_config
|
||||
}
|
||||
Err(e) => {
|
||||
log::error!("{:?}", e);
|
||||
return Err(switch::error::Error::Stop(e));
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
let config = Config::new(
|
||||
start_config.tap,
|
||||
start_config.token,
|
||||
start_config.device_id,
|
||||
start_config.name,
|
||||
start_config.server,
|
||||
start_config.nat_test_server,
|
||||
start_config.in_ips,
|
||||
start_config.out_ips,
|
||||
);
|
||||
let switch = Switch::start(config).await?;
|
||||
log::info!("switch-service服务启动");
|
||||
let switch = Arc::new(switch);
|
||||
let command_server = crate::command::server::CommandServer::new();
|
||||
let switch1 = switch.clone();
|
||||
thread::spawn(move || {
|
||||
if let Err(e) = config::update_pid(std::process::id()) {
|
||||
log::error!("{:?}", e);
|
||||
}
|
||||
if let Err(e) = command_server.start(switch1) {
|
||||
log::error!("{:?}", e);
|
||||
}
|
||||
});
|
||||
Ok(switch)
|
||||
}
|
||||
|
||||
pub fn start() {
|
||||
|
||||
+2
-3
@@ -28,13 +28,12 @@ chrono = "0.4.23"
|
||||
protobuf = "3.2.0"
|
||||
#local-ip-address = "0.4.9"
|
||||
socket2 ={ version = "0.5.2", features = ["all"] }
|
||||
|
||||
#mio = {version = "0.8.6",features = ["os-poll", "net"]}
|
||||
#tokio = { version = "1.24.1", features = ["full"] }
|
||||
tokio = { version = "1.28.1", features = ["full"] }
|
||||
[target.'cfg(any(unix))'.dependencies]
|
||||
tun = { path = "./rust-tun" }
|
||||
|
||||
[target.'cfg(target_os = "windows")'.dependencies]
|
||||
|
||||
win-tun-tap = {path = "./win-tun-tap"}
|
||||
libloading = "0.7.4"
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ use crate::icmp::{Code, Kind};
|
||||
use crate::ip::ipv4::packet::IpV4Packet;
|
||||
|
||||
pub struct IcmpPacket<B> {
|
||||
buffer: B,
|
||||
pub buffer: B,
|
||||
}
|
||||
|
||||
impl<B: AsRef<[u8]>> IcmpPacket<B> {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#[derive(Eq, PartialEq, Copy, Clone, Debug)]
|
||||
#[derive(Eq, PartialEq,Ord, PartialOrd, Copy, Clone, Debug)]
|
||||
pub enum Protocol {
|
||||
///
|
||||
Hopopt,
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
use std::fmt;
|
||||
use std::net::IpAddr;
|
||||
|
||||
use byteorder::{BigEndian, ReadBytesExt};
|
||||
use std::net::Ipv4Addr;
|
||||
|
||||
use crate::error::*;
|
||||
use crate::tcp::Flags;
|
||||
@@ -48,20 +46,20 @@ use crate::tcp::Flags;
|
||||
Options+Padding:32位整数倍,最多40个字节
|
||||
*/
|
||||
pub struct TcpPacket<B> {
|
||||
source_ip: IpAddr,
|
||||
destination_ip: IpAddr,
|
||||
source_ip: Ipv4Addr,
|
||||
destination_ip: Ipv4Addr,
|
||||
buffer: B,
|
||||
}
|
||||
|
||||
impl<B: AsRef<[u8]>> TcpPacket<B> {
|
||||
pub fn unchecked(source_ip: IpAddr, destination_ip: IpAddr, buffer: B) -> TcpPacket<B> {
|
||||
pub fn unchecked(source_ip: Ipv4Addr, destination_ip: Ipv4Addr, buffer: B) -> TcpPacket<B> {
|
||||
TcpPacket {
|
||||
source_ip,
|
||||
destination_ip,
|
||||
buffer,
|
||||
}
|
||||
}
|
||||
pub fn new(source_ip: IpAddr, destination_ip: IpAddr, buffer: B) -> Result<TcpPacket<B>> {
|
||||
pub fn new(source_ip: Ipv4Addr, destination_ip: Ipv4Addr, buffer: B) -> Result<TcpPacket<B>> {
|
||||
let packet = TcpPacket::unchecked(source_ip, destination_ip, buffer);
|
||||
|
||||
if packet.buffer.as_ref().len() < 20 {
|
||||
@@ -80,6 +78,12 @@ impl<B: AsRef<[u8]> + AsMut<[u8]>> TcpPacket<B> {
|
||||
fn set_checksum(&mut self, value: u16) {
|
||||
self.buffer.as_mut()[16..18].copy_from_slice(&value.to_be_bytes())
|
||||
}
|
||||
pub fn set_source_port(&mut self, value: u16) {
|
||||
self.buffer.as_mut()[0..2].copy_from_slice(&value.to_be_bytes())
|
||||
}
|
||||
pub fn set_destination_port(&mut self, value: u16) {
|
||||
self.buffer.as_mut()[2..4].copy_from_slice(&value.to_be_bytes())
|
||||
}
|
||||
/// 更新校验和
|
||||
pub fn update_checksum(&mut self) {
|
||||
//先将校验和置0
|
||||
@@ -87,31 +91,24 @@ impl<B: AsRef<[u8]> + AsMut<[u8]>> TcpPacket<B> {
|
||||
self.set_checksum(self.cal_checksum())
|
||||
}
|
||||
}
|
||||
|
||||
impl<B: AsRef<[u8]>> TcpPacket<B> {
|
||||
/// 源端口
|
||||
pub fn source_port(&self) -> u16 {
|
||||
(&self.buffer.as_ref()[0..])
|
||||
.read_u16::<BigEndian>()
|
||||
.unwrap()
|
||||
u16::from_be_bytes(self.buffer.as_ref()[0..2].try_into().unwrap())
|
||||
}
|
||||
|
||||
/// 目标端口
|
||||
pub fn destination_port(&self) -> u16 {
|
||||
(&self.buffer.as_ref()[2..])
|
||||
.read_u16::<BigEndian>()
|
||||
.unwrap()
|
||||
u16::from_be_bytes(self.buffer.as_ref()[2..4].try_into().unwrap())
|
||||
}
|
||||
/// 序列号
|
||||
pub fn sequence(&self) -> u32 {
|
||||
(&self.buffer.as_ref()[4..])
|
||||
.read_u32::<BigEndian>()
|
||||
.unwrap()
|
||||
u32::from_be_bytes(self.buffer.as_ref()[4..8].try_into().unwrap())
|
||||
}
|
||||
/// 确认号
|
||||
pub fn acknowledgment(&self) -> u32 {
|
||||
(&self.buffer.as_ref()[8..])
|
||||
.read_u32::<BigEndian>()
|
||||
.unwrap()
|
||||
u32::from_be_bytes(self.buffer.as_ref()[8..12].try_into().unwrap())
|
||||
}
|
||||
/// 数据偏移 4字节为单位
|
||||
pub fn data_offset(&self) -> u8 {
|
||||
@@ -121,14 +118,10 @@ impl<B: AsRef<[u8]>> TcpPacket<B> {
|
||||
Flags(self.buffer.as_ref()[13])
|
||||
}
|
||||
pub fn window(&self) -> u16 {
|
||||
(&self.buffer.as_ref()[14..])
|
||||
.read_u16::<BigEndian>()
|
||||
.unwrap()
|
||||
u16::from_be_bytes(self.buffer.as_ref()[14..16].try_into().unwrap())
|
||||
}
|
||||
pub fn checksum(&self) -> u16 {
|
||||
(&self.buffer.as_ref()[16..])
|
||||
.read_u16::<BigEndian>()
|
||||
.unwrap()
|
||||
u16::from_be_bytes(self.buffer.as_ref()[16..18].try_into().unwrap())
|
||||
}
|
||||
/// 验证校验和,ipv4中为0表示不使用校验和,ipv6校验和不能为0
|
||||
/// TCP/IP协议栈不会自己计算校验和,而是简单地将一个空的校验和字段(零或随机填充)交给网卡硬件。
|
||||
@@ -137,26 +130,16 @@ impl<B: AsRef<[u8]>> TcpPacket<B> {
|
||||
self.checksum() == 0 || self.cal_checksum() == 0
|
||||
}
|
||||
fn cal_checksum(&self) -> u16 {
|
||||
match self.source_ip {
|
||||
IpAddr::V4(src) => {
|
||||
if let IpAddr::V4(dest) = self.destination_ip {
|
||||
return crate::ipv4_cal_checksum(
|
||||
self.buffer.as_ref(),
|
||||
&src,
|
||||
&dest,
|
||||
6,
|
||||
self.buffer.as_ref().len() as u16,
|
||||
);
|
||||
}
|
||||
}
|
||||
IpAddr::V6(_src) => {}
|
||||
}
|
||||
unimplemented!()
|
||||
crate::ipv4_cal_checksum(
|
||||
self.buffer.as_ref(),
|
||||
&self.source_ip,
|
||||
&self.destination_ip,
|
||||
6,
|
||||
self.buffer.as_ref().len() as u16,
|
||||
)
|
||||
}
|
||||
pub fn urgent_pointer(&self) -> u16 {
|
||||
(&self.buffer.as_ref()[18..])
|
||||
.read_u16::<BigEndian>()
|
||||
.unwrap()
|
||||
u16::from_be_bytes(self.buffer.as_ref()[18..20].try_into().unwrap())
|
||||
}
|
||||
pub fn options(&self) -> &[u8] {
|
||||
&self.buffer.as_ref()[20..(self.data_offset() as usize * 4)]
|
||||
|
||||
@@ -1,9 +1,5 @@
|
||||
use std::fmt;
|
||||
use std::io::Cursor;
|
||||
use std::net::IpAddr;
|
||||
|
||||
use byteorder::WriteBytesExt;
|
||||
use byteorder::{BigEndian, ReadBytesExt};
|
||||
use std::net::Ipv4Addr;
|
||||
|
||||
use crate::error::*;
|
||||
|
||||
@@ -53,20 +49,20 @@ RFC 768 https://www.ietf.org/rfc/rfc768.txt
|
||||
*/
|
||||
|
||||
pub struct UdpPacket<B> {
|
||||
source_ip: IpAddr,
|
||||
destination_ip: IpAddr,
|
||||
source_ip: Ipv4Addr,
|
||||
destination_ip: Ipv4Addr,
|
||||
buffer: B,
|
||||
}
|
||||
|
||||
impl<B: AsRef<[u8]>> UdpPacket<B> {
|
||||
pub fn unchecked(source_ip: IpAddr, destination_ip: IpAddr, buffer: B) -> UdpPacket<B> {
|
||||
pub fn unchecked(source_ip: Ipv4Addr, destination_ip: Ipv4Addr, buffer: B) -> UdpPacket<B> {
|
||||
UdpPacket {
|
||||
source_ip,
|
||||
destination_ip,
|
||||
buffer,
|
||||
}
|
||||
}
|
||||
pub fn new(source_ip: IpAddr, destination_ip: IpAddr, buffer: B) -> Result<UdpPacket<B>> {
|
||||
pub fn new(source_ip: Ipv4Addr, destination_ip: Ipv4Addr, buffer: B) -> Result<UdpPacket<B>> {
|
||||
if buffer.as_ref().len() < 8 {
|
||||
Err(Error::SmallBuffer)?
|
||||
}
|
||||
@@ -78,30 +74,22 @@ impl<B: AsRef<[u8]>> UdpPacket<B> {
|
||||
impl<B: AsRef<[u8]>> UdpPacket<B> {
|
||||
/// 源端口
|
||||
pub fn source_port(&self) -> u16 {
|
||||
(&self.buffer.as_ref()[0..])
|
||||
.read_u16::<BigEndian>()
|
||||
.unwrap()
|
||||
u16::from_be_bytes(self.buffer.as_ref()[0..2].try_into().unwrap())
|
||||
}
|
||||
|
||||
/// 目标端口
|
||||
pub fn destination_port(&self) -> u16 {
|
||||
(&self.buffer.as_ref()[2..])
|
||||
.read_u16::<BigEndian>()
|
||||
.unwrap()
|
||||
u16::from_be_bytes(self.buffer.as_ref()[2..4].try_into().unwrap())
|
||||
}
|
||||
|
||||
/// 总字节数
|
||||
pub fn length(&self) -> u16 {
|
||||
(&self.buffer.as_ref()[4..])
|
||||
.read_u16::<BigEndian>()
|
||||
.unwrap()
|
||||
u16::from_be_bytes(self.buffer.as_ref()[4..6].try_into().unwrap())
|
||||
}
|
||||
|
||||
/// Checksum of the packet.
|
||||
pub fn checksum(&self) -> u16 {
|
||||
(&self.buffer.as_ref()[6..])
|
||||
.read_u16::<BigEndian>()
|
||||
.unwrap()
|
||||
u16::from_be_bytes(self.buffer.as_ref()[6..8].try_into().unwrap())
|
||||
}
|
||||
/// 验证校验和,ipv4中为0表示不使用校验和,ipv6校验和不能为0
|
||||
pub fn is_valid(&self) -> bool {
|
||||
@@ -111,21 +99,13 @@ impl<B: AsRef<[u8]>> UdpPacket<B> {
|
||||
&self.buffer.as_ref()[8..]
|
||||
}
|
||||
fn cal_checksum(&self) -> u16 {
|
||||
match self.source_ip {
|
||||
IpAddr::V4(src) => {
|
||||
if let IpAddr::V4(dest) = self.destination_ip {
|
||||
return crate::ipv4_cal_checksum(
|
||||
self.buffer.as_ref(),
|
||||
&src,
|
||||
&dest,
|
||||
17,
|
||||
self.length(),
|
||||
);
|
||||
}
|
||||
}
|
||||
IpAddr::V6(_src) => {}
|
||||
}
|
||||
unimplemented!()
|
||||
crate::ipv4_cal_checksum(
|
||||
self.buffer.as_ref(),
|
||||
&self.source_ip,
|
||||
&self.destination_ip,
|
||||
17,
|
||||
self.length(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -137,29 +117,21 @@ impl<B: AsRef<[u8]> + AsMut<[u8]>> UdpPacket<B> {
|
||||
|
||||
impl<B: AsRef<[u8]> + AsMut<[u8]>> UdpPacket<B> {
|
||||
/// 设置源端口
|
||||
pub fn set_source_port(&mut self, value: u16) -> &mut Self {
|
||||
Cursor::new(&mut self.header_mut()[0..])
|
||||
.write_u16::<BigEndian>(value)
|
||||
.unwrap();
|
||||
self
|
||||
pub fn set_source_port(&mut self, value: u16) {
|
||||
self.buffer.as_mut()[0..2].copy_from_slice(&value.to_be_bytes())
|
||||
}
|
||||
|
||||
/// 设置目的端口
|
||||
pub fn set_destination_port(&mut self, value: u16) -> &mut Self {
|
||||
Cursor::new(&mut self.header_mut()[2..])
|
||||
.write_u16::<BigEndian>(value)
|
||||
.unwrap();
|
||||
self
|
||||
pub fn set_destination_port(&mut self, value: u16) {
|
||||
self.buffer.as_mut()[2..4].copy_from_slice(&value.to_be_bytes())
|
||||
}
|
||||
fn set_checknum(&mut self, value: u16) {
|
||||
Cursor::new(&mut self.header_mut()[6..])
|
||||
.write_u16::<BigEndian>(value)
|
||||
.unwrap();
|
||||
fn set_checksum(&mut self, value: u16) {
|
||||
self.buffer.as_mut()[6..8].copy_from_slice(&value.to_be_bytes())
|
||||
}
|
||||
pub fn update_checknum(&mut self) {
|
||||
pub fn update_checksum(&mut self) {
|
||||
//先写0
|
||||
self.set_checknum(0);
|
||||
self.set_checknum(self.cal_checksum());
|
||||
self.set_checksum(0);
|
||||
self.set_checksum(self.cal_checksum());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+32
-15
@@ -1,15 +1,19 @@
|
||||
use std::io;
|
||||
use std::net::{Ipv4Addr, SocketAddr};
|
||||
use std::sync::Arc;
|
||||
|
||||
use crossbeam::atomic::AtomicCell;
|
||||
use crossbeam_skiplist::SkipMap;
|
||||
use parking_lot::Mutex;
|
||||
|
||||
use p2p_channel::boot::Boot;
|
||||
use p2p_channel::channel::{Channel, Route, RouteKey};
|
||||
use p2p_channel::punch::NatInfo;
|
||||
use crate::handle::{ConnectStatus, CurrentDeviceInfo, heartbeat_handler, PeerDeviceInfo, punch_handler, recv_handler, registration_handler, tap_handler, tun_handler};
|
||||
use crate::nat::NatTest;
|
||||
|
||||
use crate::{tap_device, tun_device};
|
||||
use crate::external_route::ExternalRoute;
|
||||
use crate::handle::{ConnectStatus, CurrentDeviceInfo, CurrentDeviceInfoExt, heartbeat_handler, PeerDeviceInfo, punch_handler, recv_handler, registration_handler, tap_handler, tun_handler};
|
||||
use crate::nat::NatTest;
|
||||
use crate::tap_device::TapWriter;
|
||||
use crate::tun_device::TunWriter;
|
||||
|
||||
@@ -29,8 +33,9 @@ pub struct Switch {
|
||||
}
|
||||
|
||||
impl Switch {
|
||||
pub fn start(config: Config) -> crate::Result<Switch> {
|
||||
pub async fn start(config: Config) -> crate::Result<Switch> {
|
||||
log::info!("config:{:?}",config);
|
||||
|
||||
let (mut channel, punch, idle) = Boot::new::<Ipv4Addr>(80, 15000, 0)?;
|
||||
let response = registration_handler::registration(&mut channel, config.server_address, config.token.clone(), config.device_id.clone(), config.name.clone())?;
|
||||
let register = Arc::new(registration_handler::Register::new(channel.sender()?, config.server_address, config.token.clone(), config.device_id.clone(), config.name.clone()));
|
||||
@@ -45,18 +50,24 @@ impl Switch {
|
||||
let local_port = channel.local_addr()?.port();
|
||||
// NAT检测
|
||||
let nat_test = NatTest::new(config.nat_test_server.clone(), Ipv4Addr::from(response.public_ip), response.public_port as u16, local_ip, local_port);
|
||||
let (current_device, tun_writer, tap_writer) = if config.tap {
|
||||
let in_ips = config.in_ips.iter().map(|(dest, mask, _)| { (Ipv4Addr::from(*dest), Ipv4Addr::from(*mask)) }).collect::<Vec<(Ipv4Addr, Ipv4Addr)>>();
|
||||
|
||||
let out_ips = config.out_ips.iter().map(|(_, _, ip)| *ip).collect::<Vec<Ipv4Addr>>();
|
||||
let out_external_route = ExternalRoute::new(config.out_ips);
|
||||
let in_external_route = ExternalRoute::new(config.in_ips);
|
||||
let current_device = Arc::new(AtomicCell::new(CurrentDeviceInfo::new(virtual_ip, virtual_gateway, virtual_netmask, config.server_address)));
|
||||
let ip_proxy_map = crate::ip_proxy::init_proxy(channel.sender()?,out_ips,current_device.clone()).await?;
|
||||
let ( current_device_ext,tun_writer, tap_writer) = if config.tap {
|
||||
#[cfg(windows)]
|
||||
{
|
||||
//删除switch的tun网卡避免ip冲突,因为非正常退出会保留网卡
|
||||
tun_device::delete_tun();
|
||||
}
|
||||
let (tap_writer, tap_reader, mac) = tap_device::create_tap(virtual_ip, virtual_netmask, virtual_gateway)?;
|
||||
let current_device = Arc::new(AtomicCell::new(CurrentDeviceInfo::new(virtual_ip, virtual_gateway, virtual_netmask,
|
||||
config.server_address, mac)));
|
||||
let current_device_ext = Arc::new(AtomicCell::new(CurrentDeviceInfoExt::new( mac)));
|
||||
//tap数据处理
|
||||
tap_handler::start(channel.sender()?, tap_reader.clone(), tap_writer.clone(), current_device.clone());
|
||||
(current_device, None, Some(tap_writer))
|
||||
tap_handler::start(channel.sender()?, tap_reader.clone(), tap_writer.clone(), current_device.clone(), in_external_route, ip_proxy_map.clone());
|
||||
(current_device_ext, None, Some(tap_writer))
|
||||
} else {
|
||||
#[cfg(windows)]
|
||||
{
|
||||
@@ -64,15 +75,16 @@ impl Switch {
|
||||
tap_device::delete_tap();
|
||||
}
|
||||
// tun通道
|
||||
let (tun_writer, tun_reader) = tun_device::create_tun(virtual_ip, virtual_netmask, virtual_gateway)?;
|
||||
let current_device = Arc::new(AtomicCell::new(CurrentDeviceInfo::new(virtual_ip, virtual_gateway, virtual_netmask, config.server_address, [0, 0, 0, 0, 0, 0])));
|
||||
let (tun_writer, tun_reader) = tun_device::create_tun(virtual_ip, virtual_netmask, virtual_gateway,in_ips)?;
|
||||
let current_device_ext = Arc::new(AtomicCell::new(CurrentDeviceInfoExt::new( [0, 0, 0, 0, 0, 0])));
|
||||
//tun数据接收处理
|
||||
tun_handler::start(channel.sender()?, tun_reader.clone(), tun_writer.clone(), current_device.clone());
|
||||
(current_device, Some(tun_writer), None)
|
||||
tun_handler::start(channel.sender()?, tun_reader.clone(), tun_writer.clone(), current_device.clone(), in_external_route, ip_proxy_map.clone());
|
||||
(current_device_ext,Some(tun_writer), None)
|
||||
};
|
||||
//外部数据接收处理
|
||||
let channel_recv_handler = recv_handler::RecvHandler::new(channel.try_clone()?, current_device.clone(), device_list.clone(), register.clone(),
|
||||
nat_test.clone(), tun_writer.clone(), tap_writer.clone(), connect_status.clone(), peer_nat_info_map.clone());
|
||||
let channel_recv_handler = recv_handler::RecvHandler::new(channel.try_clone()?, current_device.clone(), current_device_ext,device_list.clone(), register.clone(),
|
||||
nat_test.clone(), tun_writer.clone(), tap_writer.clone(),
|
||||
connect_status.clone(), peer_nat_info_map.clone(), ip_proxy_map, out_external_route);
|
||||
recv_handler::start(channel_recv_handler);
|
||||
// 定时心跳
|
||||
heartbeat_handler::start_heartbeat(channel.sender()?, device_list.clone(), current_device.clone());
|
||||
@@ -148,6 +160,8 @@ pub struct Config {
|
||||
pub name: String,
|
||||
pub server_address: SocketAddr,
|
||||
pub nat_test_server: Vec<SocketAddr>,
|
||||
pub in_ips: Vec<(u32, u32, Ipv4Addr)>,
|
||||
pub out_ips: Vec<(u32, u32, Ipv4Addr)>,
|
||||
}
|
||||
|
||||
impl Config {
|
||||
@@ -155,7 +169,8 @@ impl Config {
|
||||
device_id: String,
|
||||
name: String,
|
||||
server_address: SocketAddr,
|
||||
nat_test_server: Vec<SocketAddr>, ) -> Self {
|
||||
nat_test_server: Vec<SocketAddr>,
|
||||
in_ips: Vec<(u32, u32, Ipv4Addr)>, out_ips: Vec<(u32, u32, Ipv4Addr)>, ) -> Self {
|
||||
Self {
|
||||
tap,
|
||||
token,
|
||||
@@ -163,6 +178,8 @@ impl Config {
|
||||
name,
|
||||
server_address,
|
||||
nat_test_server,
|
||||
in_ips,
|
||||
out_ips,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
use std::net::Ipv4Addr;
|
||||
|
||||
// 目标ip,子网掩码,网关
|
||||
|
||||
pub struct ExternalRoute {
|
||||
route_table: Vec<(u32, u32, Ipv4Addr)>,
|
||||
}
|
||||
|
||||
impl ExternalRoute {
|
||||
pub fn new(route_table: Vec<(u32, u32, Ipv4Addr)>) -> Self {
|
||||
Self {
|
||||
route_table
|
||||
}
|
||||
}
|
||||
pub fn route(&self, ip: &Ipv4Addr) -> Option<Ipv4Addr> {
|
||||
let ip = u32::from_be_bytes(ip.octets());
|
||||
for (dest, mask, gateway) in &self.route_table {
|
||||
if *mask & ip == *mask & *dest {
|
||||
return Some(*gateway);
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
}
|
||||
@@ -60,6 +60,19 @@ pub enum ConnectStatus {
|
||||
Connected,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
|
||||
pub struct CurrentDeviceInfoExt {
|
||||
pub mac: [u8; 6],
|
||||
}
|
||||
|
||||
impl CurrentDeviceInfoExt {
|
||||
pub fn new(mac: [u8; 6]) -> Self {
|
||||
Self {
|
||||
mac,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
|
||||
pub struct CurrentDeviceInfo {
|
||||
virtual_ip: Ipv4Addr,
|
||||
@@ -71,7 +84,7 @@ pub struct CurrentDeviceInfo {
|
||||
pub broadcast_address: Ipv4Addr,
|
||||
//链接的服务器地址
|
||||
pub connect_server: SocketAddr,
|
||||
pub mac:[u8;6]
|
||||
|
||||
}
|
||||
|
||||
impl CurrentDeviceInfo {
|
||||
@@ -80,7 +93,6 @@ impl CurrentDeviceInfo {
|
||||
virtual_gateway: Ipv4Addr,
|
||||
virtual_netmask: Ipv4Addr,
|
||||
connect_server: SocketAddr,
|
||||
mac:[u8;6],
|
||||
) -> Self {
|
||||
let broadcast_address = (!u32::from_be_bytes(virtual_netmask.octets()))
|
||||
| u32::from_be_bytes(virtual_gateway.octets());
|
||||
@@ -95,7 +107,6 @@ impl CurrentDeviceInfo {
|
||||
virtual_network,
|
||||
broadcast_address,
|
||||
connect_server,
|
||||
mac
|
||||
}
|
||||
}
|
||||
#[inline]
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use std::{io, thread};
|
||||
use std::net::{IpAddr, Ipv4Addr, SocketAddr};
|
||||
use std::thread;
|
||||
use std::net::{IpAddr, Ipv4Addr, SocketAddr, SocketAddrV4};
|
||||
use std::sync::Arc;
|
||||
|
||||
use chrono::Local;
|
||||
@@ -12,12 +12,15 @@ use p2p_channel::channel::{Channel, Route, RouteKey};
|
||||
use p2p_channel::punch::NatInfo;
|
||||
use packet::ethernet;
|
||||
use packet::icmp::{icmp, Kind};
|
||||
use packet::icmp::icmp::HeaderOther;
|
||||
use packet::ip::ipv4;
|
||||
use packet::ip::ipv4::packet::IpV4Packet;
|
||||
|
||||
use crate::error::Error;
|
||||
use crate::handle::{check_dest, ConnectStatus, CurrentDeviceInfo, PeerDeviceInfo};
|
||||
use crate::external_route::ExternalRoute;
|
||||
use crate::handle::{check_dest, ConnectStatus, CurrentDeviceInfo, CurrentDeviceInfoExt, PeerDeviceInfo};
|
||||
use crate::handle::registration_handler::Register;
|
||||
use crate::ip_proxy::IpProxyMap;
|
||||
use crate::nat;
|
||||
use crate::nat::NatTest;
|
||||
use crate::proto::message::{DeviceList, PunchInfo, PunchNatType, RegistrationResponse};
|
||||
@@ -56,6 +59,7 @@ pub fn start(mut handler: RecvHandler) {
|
||||
pub struct RecvHandler {
|
||||
channel: Channel<Ipv4Addr>,
|
||||
current_device: Arc<AtomicCell<CurrentDeviceInfo>>,
|
||||
current_device_ext: Arc<AtomicCell<CurrentDeviceInfoExt>>,
|
||||
device_list: Arc<Mutex<(u16, Vec<PeerDeviceInfo>)>>,
|
||||
register: Arc<Register>,
|
||||
nat_test: NatTest,
|
||||
@@ -63,11 +67,14 @@ pub struct RecvHandler {
|
||||
tap_writer: Option<TapWriter>,
|
||||
connect_status: Arc<AtomicCell<ConnectStatus>>,
|
||||
peer_nat_info_map: Arc<SkipMap<Ipv4Addr, NatInfo>>,
|
||||
ip_proxy_map: IpProxyMap,
|
||||
out_external_route: ExternalRoute,
|
||||
}
|
||||
|
||||
impl RecvHandler {
|
||||
pub fn new(channel: Channel<Ipv4Addr>,
|
||||
current_device: Arc<AtomicCell<CurrentDeviceInfo>>,
|
||||
current_device_ext: Arc<AtomicCell<CurrentDeviceInfoExt>>,
|
||||
device_list: Arc<Mutex<(u16, Vec<PeerDeviceInfo>)>>,
|
||||
register: Arc<Register>,
|
||||
nat_test: NatTest,
|
||||
@@ -75,10 +82,13 @@ impl RecvHandler {
|
||||
tap_writer: Option<TapWriter>,
|
||||
connect_status: Arc<AtomicCell<ConnectStatus>>,
|
||||
peer_nat_info_map: Arc<SkipMap<Ipv4Addr, NatInfo>>,
|
||||
ip_proxy_map: IpProxyMap,
|
||||
out_external_route: ExternalRoute,
|
||||
) -> Self {
|
||||
Self {
|
||||
channel,
|
||||
current_device,
|
||||
current_device_ext,
|
||||
device_list,
|
||||
register,
|
||||
nat_test,
|
||||
@@ -86,21 +96,23 @@ impl RecvHandler {
|
||||
tap_writer,
|
||||
connect_status,
|
||||
peer_nat_info_map,
|
||||
ip_proxy_map,
|
||||
out_external_route,
|
||||
}
|
||||
}
|
||||
pub fn try_clone(&self) -> io::Result<Self> {
|
||||
Ok(Self {
|
||||
channel: self.channel.try_clone()?,
|
||||
current_device: self.current_device.clone(),
|
||||
device_list: self.device_list.clone(),
|
||||
register: self.register.clone(),
|
||||
nat_test: self.nat_test.clone(),
|
||||
tun_writer: self.tun_writer.clone(),
|
||||
tap_writer: self.tap_writer.clone(),
|
||||
connect_status: self.connect_status.clone(),
|
||||
peer_nat_info_map: self.peer_nat_info_map.clone(),
|
||||
})
|
||||
}
|
||||
// pub fn try_clone(&self) -> io::Result<Self> {
|
||||
// Ok(Self {
|
||||
// channel: self.channel.try_clone()?,
|
||||
// current_device: self.current_device.clone(),
|
||||
// device_list: self.device_list.clone(),
|
||||
// register: self.register.clone(),
|
||||
// nat_test: self.nat_test.clone(),
|
||||
// tun_writer: self.tun_writer.clone(),
|
||||
// tap_writer: self.tap_writer.clone(),
|
||||
// connect_status: self.connect_status.clone(),
|
||||
// peer_nat_info_map: self.peer_nat_info_map.clone(),
|
||||
// })
|
||||
// }
|
||||
}
|
||||
|
||||
impl RecvHandler {
|
||||
@@ -109,7 +121,6 @@ impl RecvHandler {
|
||||
if net_packet.ttl() == 0 {
|
||||
return Ok(());
|
||||
}
|
||||
net_packet.set_ttl(net_packet.ttl() - 1);
|
||||
let source = net_packet.source();
|
||||
let current_device = self.current_device.load();
|
||||
if source == current_device.virtual_ip() {
|
||||
@@ -126,14 +137,15 @@ impl RecvHandler {
|
||||
log::warn!("转发数据,目的地址错误:{:?},当前网络:{:?},route_key:{:?}",destination,current_device.virtual_network,route_key);
|
||||
return Ok(());
|
||||
}
|
||||
net_packet.set_ttl(net_packet.ttl() - 1);
|
||||
let ttl = net_packet.ttl();
|
||||
if ttl > 1 {
|
||||
if ttl > 0 {
|
||||
// 转发
|
||||
if let Some(route) = self.channel.route(&destination) {
|
||||
if route.metric <= net_packet.ttl() {
|
||||
self.channel.send_to_route(net_packet.buffer(), &route.route_key())?;
|
||||
}
|
||||
} else if (ttl > 2 || destination == current_device.virtual_gateway())
|
||||
} else if (ttl > 1 || destination == current_device.virtual_gateway())
|
||||
&& source != current_device.virtual_gateway() {
|
||||
//网关默认要转发一次,生存时间不够的发到网关也会被丢弃
|
||||
self.channel.send_to_addr(net_packet.buffer(), current_device.connect_server)?;
|
||||
@@ -144,36 +156,82 @@ impl RecvHandler {
|
||||
match net_packet.protocol() {
|
||||
Protocol::Ipv4Turn => {
|
||||
let mut ipv4 = IpV4Packet::new(net_packet.payload_mut())?;
|
||||
if ipv4.destination_ip() == destination && ipv4.protocol() == ipv4::protocol::Protocol::Icmp {
|
||||
let mut icmp_packet = icmp::IcmpPacket::new(ipv4.payload_mut())?;
|
||||
if icmp_packet.kind() == Kind::EchoRequest {
|
||||
//开启ping
|
||||
icmp_packet.set_kind(Kind::EchoReply);
|
||||
icmp_packet.update_checksum();
|
||||
ipv4.set_source_ip(destination);
|
||||
ipv4.set_destination_ip(source);
|
||||
ipv4.update_checksum();
|
||||
net_packet.set_source(destination);
|
||||
net_packet.set_destination(source);
|
||||
self.channel.send_to_route(net_packet.buffer(), route_key)?;
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
if ipv4.destination_ip() != destination {
|
||||
//todo 外部数据转发
|
||||
} else {
|
||||
if ipv4.protocol() == ipv4::protocol::Protocol::Icmp {
|
||||
let mut icmp_packet = icmp::IcmpPacket::new(ipv4.payload_mut())?;
|
||||
if icmp_packet.kind() == Kind::EchoRequest {
|
||||
//开启ping
|
||||
icmp_packet.set_kind(Kind::EchoReply);
|
||||
icmp_packet.update_checksum();
|
||||
ipv4.set_source_ip(destination);
|
||||
ipv4.set_destination_ip(source);
|
||||
ipv4.update_checksum();
|
||||
net_packet.set_source(destination);
|
||||
net_packet.set_destination(source);
|
||||
self.channel.send_to_route(net_packet.buffer(), route_key)?;
|
||||
return Ok(());
|
||||
if let Some(gate_way) = self.out_external_route.route(&ipv4.destination_ip()) {
|
||||
match ipv4.protocol() {
|
||||
ipv4::protocol::Protocol::Tcp => {
|
||||
let dest_ip = ipv4.destination_ip();
|
||||
//转发到代理目标地址
|
||||
let mut tcp_packet = packet::tcp::tcp::TcpPacket::new(source, destination, ipv4.payload_mut())?;
|
||||
let source_port = tcp_packet.source_port();
|
||||
let dest_port = tcp_packet.destination_port();
|
||||
tcp_packet.set_destination_port(self.ip_proxy_map.tcp_proxy_port);
|
||||
tcp_packet.update_checksum();
|
||||
ipv4.set_destination_ip(destination);
|
||||
ipv4.update_checksum();
|
||||
self.ip_proxy_map.tcp_proxy_map.insert(SocketAddrV4::new(source, source_port),
|
||||
(SocketAddrV4::new(gate_way, 0), SocketAddrV4::new(dest_ip, dest_port)));
|
||||
}
|
||||
ipv4::protocol::Protocol::Udp => {
|
||||
let dest_ip = ipv4.destination_ip();
|
||||
//转发到代理目标地址
|
||||
let mut udp_packet = packet::udp::udp::UdpPacket::new(source, destination, ipv4.payload_mut())?;
|
||||
let source_port = udp_packet.source_port();
|
||||
let dest_port = udp_packet.destination_port();
|
||||
udp_packet.set_destination_port(self.ip_proxy_map.udp_proxy_port);
|
||||
udp_packet.update_checksum();
|
||||
ipv4.set_destination_ip(destination);
|
||||
ipv4.update_checksum();
|
||||
println!("{:?}",ipv4);
|
||||
self.ip_proxy_map.udp_proxy_map.insert(SocketAddrV4::new(source, source_port),
|
||||
(SocketAddrV4::new(gate_way, 0), SocketAddrV4::new(dest_ip, dest_port)));
|
||||
}
|
||||
ipv4::protocol::Protocol::Icmp => {
|
||||
let dest_ip = ipv4.destination_ip();
|
||||
//转发到代理目标地址
|
||||
let icmp_packet = icmp::IcmpPacket::new(ipv4.payload())?;
|
||||
match icmp_packet.header_other() {
|
||||
HeaderOther::Identifier(id, seq) => {
|
||||
self.ip_proxy_map.icmp_proxy_map.insert((dest_ip, id, seq), source);
|
||||
self.ip_proxy_map.send_icmp(ipv4.payload(), &gate_way, &dest_ip)?;
|
||||
}
|
||||
_ => {
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
}
|
||||
if let Some(tun_writer) = &self.tun_writer {
|
||||
tun_writer.write(net_packet.payload())?;
|
||||
} else {
|
||||
if let Some(tap_writer) = &self.tap_writer {
|
||||
let mut ethernet_packet = ethernet::packet::EthernetPacket::unchecked(vec![0; 14 + ipv4.buffer.len()]);
|
||||
let source = source.octets();
|
||||
ethernet_packet.set_source(&[source[0], source[1], source[2], source[3], 123, 234]);
|
||||
ethernet_packet.set_destination(¤t_device.mac);
|
||||
ethernet_packet.set_protocol(ethernet::protocol::Protocol::Ipv4);
|
||||
ethernet_packet.payload_mut().copy_from_slice(ipv4.buffer);
|
||||
tap_writer.write(ðernet_packet.buffer)?;
|
||||
}
|
||||
}
|
||||
if let Some(tun_writer) = &self.tun_writer {
|
||||
tun_writer.write(net_packet.payload())?;
|
||||
} else {
|
||||
if let Some(tap_writer) = &self.tap_writer {
|
||||
let mut ethernet_packet = ethernet::packet::EthernetPacket::unchecked(vec![0; 14 + ipv4.buffer.len()]);
|
||||
let source = source.octets();
|
||||
ethernet_packet.set_source(&[source[0], source[1], source[2], source[3], 123, 234]);
|
||||
ethernet_packet.set_destination(&self.current_device_ext.load().mac);
|
||||
ethernet_packet.set_protocol(ethernet::protocol::Protocol::Ipv4);
|
||||
ethernet_packet.payload_mut().copy_from_slice(ipv4.buffer);
|
||||
tap_writer.write(ðernet_packet.buffer)?;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -225,7 +283,7 @@ impl RecvHandler {
|
||||
}
|
||||
}
|
||||
let new_current_device = CurrentDeviceInfo::new(virtual_ip, virtual_gateway,
|
||||
virtual_netmask, current_device.connect_server, current_device.mac);
|
||||
virtual_netmask, current_device.connect_server);
|
||||
if let Err(e) = self.current_device.compare_exchange(current_device, new_current_device) {
|
||||
log::warn!("替换失败:{:?}",e);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use std::net::Ipv4Addr;
|
||||
use std::net::{Ipv4Addr, SocketAddrV4};
|
||||
use std::sync::Arc;
|
||||
use std::{io, thread};
|
||||
use crossbeam::atomic::AtomicCell;
|
||||
@@ -10,16 +10,20 @@ use packet::icmp::icmp::IcmpPacket;
|
||||
use packet::icmp::Kind;
|
||||
use packet::ip::ipv4;
|
||||
use packet::ip::ipv4::packet::IpV4Packet;
|
||||
use crate::external_route::ExternalRoute;
|
||||
use crate::handle::{check_dest, CurrentDeviceInfo};
|
||||
use crate::ip_proxy::IpProxyMap;
|
||||
use crate::protocol::{MAX_TTL, NetPacket, Protocol, Version};
|
||||
use crate::tap_device::{TapReader, TapWriter};
|
||||
|
||||
pub fn start(sender: Sender<Ipv4Addr>,
|
||||
tap_reader: TapReader,
|
||||
tap_writer: TapWriter,
|
||||
current_device: Arc<AtomicCell<CurrentDeviceInfo>>, ) {
|
||||
current_device: Arc<AtomicCell<CurrentDeviceInfo>>,
|
||||
ip_route: ExternalRoute,
|
||||
ip_proxy_map: IpProxyMap) {
|
||||
thread::Builder::new().name("tap-handler".into()).spawn(move || {
|
||||
if let Err(e) = start_(sender, tap_reader, tap_writer, current_device) {
|
||||
if let Err(e) = start_(sender, tap_reader, tap_writer, current_device,ip_route,ip_proxy_map) {
|
||||
log::warn!("{:?}",e);
|
||||
}
|
||||
}).unwrap();
|
||||
@@ -28,7 +32,9 @@ pub fn start(sender: Sender<Ipv4Addr>,
|
||||
fn start_(sender: Sender<Ipv4Addr>,
|
||||
tap_reader: TapReader,
|
||||
tap_writer: TapWriter,
|
||||
current_device: Arc<AtomicCell<CurrentDeviceInfo>>, ) -> io::Result<()> {
|
||||
current_device: Arc<AtomicCell<CurrentDeviceInfo>>,
|
||||
ip_route: ExternalRoute,
|
||||
ip_proxy_map: IpProxyMap) -> io::Result<()> {
|
||||
let mut net_packet = NetPacket::new(vec![0u8; 4 + 8 + 1500]).unwrap();
|
||||
net_packet.set_version(Version::V1);
|
||||
net_packet.set_protocol(Protocol::Ipv4Turn);
|
||||
@@ -41,17 +47,17 @@ fn start_(sender: Sender<Ipv4Addr>,
|
||||
continue;
|
||||
}
|
||||
let mut ethernet_packet = EthernetPacket::unchecked(&mut buf[..len]);
|
||||
if let Err(e) = handle(&mut net_packet, ¤t_device, &tap_writer, &mut ethernet_packet, &sender) {
|
||||
if let Err(e) = handle(&mut net_packet, ¤t_device, &tap_writer, &mut ethernet_packet, &sender,&ip_route,&ip_proxy_map) {
|
||||
log::error!("tap handle{:?}",e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn handle(net_packet: &mut NetPacket<Vec<u8>>, current_device: &AtomicCell<CurrentDeviceInfo>, tap_writer: &TapWriter, ethernet_packet: &mut EthernetPacket<&mut [u8]>, sender: &Sender<Ipv4Addr>) -> io::Result<()> {
|
||||
fn handle(net_packet: &mut NetPacket<Vec<u8>>, current_device: &AtomicCell<CurrentDeviceInfo>, tap_writer: &TapWriter, ethernet_packet: &mut EthernetPacket<&mut [u8]>, sender: &Sender<Ipv4Addr>, ip_route: &ExternalRoute, proxy_map: &IpProxyMap) -> crate::Result<()> {
|
||||
let current_device = current_device.load();
|
||||
match ethernet_packet.protocol() {
|
||||
ethernet::protocol::Protocol::Arp => {
|
||||
let mut out_ethernet_packet = ethernet::packet::EthernetPacket::unchecked(ethernet_packet.buffer.to_vec());
|
||||
let mut out_ethernet_packet = EthernetPacket::unchecked(ethernet_packet.buffer.to_vec());
|
||||
let arp_packet = ArpPacket::unchecked(ethernet_packet.payload());
|
||||
let mut out_arp_packet = ArpPacket::unchecked(out_ethernet_packet.payload_mut());
|
||||
let sender_h = arp_packet.sender_hardware_addr();
|
||||
@@ -75,10 +81,55 @@ fn handle(net_packet: &mut NetPacket<Vec<u8>>, current_device: &AtomicCell<Curre
|
||||
// println!("in ethernet_packet {:?}", ethernet_packet);
|
||||
let mut ipv4_packet = IpV4Packet::unchecked(ethernet_packet.payload_mut());
|
||||
let src_ip = ipv4_packet.source_ip();
|
||||
let dest_ip = ipv4_packet.destination_ip();
|
||||
if src_ip != current_device.virtual_ip() || (!check_dest(dest_ip, current_device.virtual_netmask, current_device.virtual_network) && !dest_ip.is_broadcast()) {
|
||||
let mut dest_ip = ipv4_packet.destination_ip();
|
||||
if src_ip != current_device.virtual_ip() {
|
||||
return Ok(());
|
||||
}
|
||||
if !check_dest(dest_ip, current_device.virtual_netmask, current_device.virtual_network) && !dest_ip.is_broadcast() {
|
||||
if let Some(r_dest_ip) = ip_route.route(&dest_ip) {
|
||||
//路由的目标不能是自己
|
||||
if r_dest_ip == src_ip {
|
||||
return Ok(());
|
||||
}
|
||||
dest_ip = r_dest_ip;
|
||||
} else {
|
||||
return Ok(());
|
||||
}
|
||||
}else{
|
||||
match ipv4_packet.protocol() {
|
||||
ipv4::protocol::Protocol::Tcp => {
|
||||
let dest_addr = {
|
||||
let tcp_packet = packet::tcp::tcp::TcpPacket::new(src_ip, dest_ip, ipv4_packet.payload())?;
|
||||
SocketAddrV4::new(dest_ip, tcp_packet.destination_port())
|
||||
};
|
||||
if let Some(entry) = proxy_map.tcp_proxy_map.get(&dest_addr) {
|
||||
let source_addr = entry.value().1;
|
||||
let source_ip = *source_addr.ip();
|
||||
let mut tcp_packet = packet::tcp::tcp::TcpPacket::new(source_ip, dest_ip, ipv4_packet.payload_mut())?;
|
||||
tcp_packet.set_source_port(source_addr.port());
|
||||
tcp_packet.update_checksum();
|
||||
ipv4_packet.set_source_ip(source_ip);
|
||||
ipv4_packet.update_checksum();
|
||||
}
|
||||
}
|
||||
ipv4::protocol::Protocol::Udp => {
|
||||
let dest_addr = {
|
||||
let udp_packet = packet::udp::udp::UdpPacket::new(src_ip, dest_ip, ipv4_packet.payload())?;
|
||||
SocketAddrV4::new(dest_ip, udp_packet.destination_port())
|
||||
};
|
||||
if let Some(entry) = proxy_map.udp_proxy_map.get(&dest_addr) {
|
||||
let source_addr = entry.value().1;
|
||||
let source_ip = *source_addr.ip();
|
||||
let mut udp_packet = packet::udp::udp::UdpPacket::new(src_ip, dest_ip, ipv4_packet.payload_mut())?;
|
||||
udp_packet.set_source_port(source_addr.port());
|
||||
udp_packet.update_checksum();
|
||||
ipv4_packet.set_source_ip(source_ip);
|
||||
ipv4_packet.update_checksum();
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
if src_ip == dest_ip {
|
||||
if ipv4_packet.protocol() == ipv4::protocol::Protocol::Icmp {
|
||||
let mut icmp = IcmpPacket::unchecked(ipv4_packet.payload_mut());
|
||||
@@ -103,8 +154,8 @@ fn handle(net_packet: &mut NetPacket<Vec<u8>>, current_device: &AtomicCell<Curre
|
||||
sender.send_to_addr(&net_packet.buffer()[..(12 + data_len)], current_device.connect_server)?;
|
||||
}
|
||||
}
|
||||
p => {
|
||||
log::warn!("不支持的二层协议:{:?}",p)
|
||||
_ => {
|
||||
// log::warn!("不支持的二层协议:{:?}",p)
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
|
||||
@@ -1,17 +1,19 @@
|
||||
use std::{io, thread};
|
||||
use std::net::Ipv4Addr;
|
||||
use std::net::{Ipv4Addr, SocketAddrV4};
|
||||
use std::sync::Arc;
|
||||
|
||||
use crossbeam::atomic::AtomicCell;
|
||||
|
||||
use p2p_channel::channel::sender::Sender;
|
||||
use packet::icmp::icmp::IcmpPacket;
|
||||
use packet::icmp::Kind;
|
||||
use packet::icmp:: Kind;
|
||||
use packet::icmp::icmp:: IcmpPacket;
|
||||
use packet::ip::ipv4;
|
||||
use packet::ip::ipv4::packet::IpV4Packet;
|
||||
|
||||
use crate::error::*;
|
||||
use crate::external_route::ExternalRoute;
|
||||
use crate::handle::{check_dest, CurrentDeviceInfo};
|
||||
use crate::ip_proxy::IpProxyMap;
|
||||
use crate::protocol::{MAX_TTL, NetPacket, Protocol, Version};
|
||||
use crate::tun_device::{TunReader, TunWriter};
|
||||
|
||||
@@ -33,9 +35,9 @@ fn icmp(tun_writer: &TunWriter, mut ipv4_packet: IpV4Packet<&mut [u8]>) -> Resul
|
||||
|
||||
/// 接收tun数据,并且转发到udp上
|
||||
#[inline]
|
||||
fn handle(sender: &Sender<Ipv4Addr>, data: &mut [u8], tun_writer: &TunWriter, current_device: CurrentDeviceInfo, net_packet: &mut NetPacket<Vec<u8>>) -> Result<()> {
|
||||
fn handle(sender: &Sender<Ipv4Addr>, data: &mut [u8], tun_writer: &TunWriter, current_device: CurrentDeviceInfo, net_packet: &mut NetPacket<[u8; 1512]>, ip_route: &ExternalRoute, proxy_map: &IpProxyMap) -> Result<()> {
|
||||
let data_len = data.len();
|
||||
let ipv4_packet = match IpV4Packet::new(data) {
|
||||
let mut ipv4_packet = match IpV4Packet::new(data) {
|
||||
Ok(ipv4_packet) => ipv4_packet,
|
||||
Err(packet::error::Error::Unimplemented) => {
|
||||
return Ok(());
|
||||
@@ -43,18 +45,65 @@ fn handle(sender: &Sender<Ipv4Addr>, data: &mut [u8], tun_writer: &TunWriter, cu
|
||||
Err(e) => Err(e)?,
|
||||
};
|
||||
let src_ip = ipv4_packet.source_ip();
|
||||
let dest_ip = ipv4_packet.destination_ip();
|
||||
let mut dest_ip = ipv4_packet.destination_ip();
|
||||
// if dest_ip == cur_info.broadcast_address {
|
||||
// // 启动服务后会收到对137端口的广播
|
||||
// // 137端口是在局域网中提供计算机的名字或IP地址查询服务
|
||||
// return Ok(());
|
||||
// }
|
||||
if src_ip != current_device.virtual_ip() || (!check_dest(dest_ip, current_device.virtual_netmask, current_device.virtual_network) && !dest_ip.is_broadcast()) {
|
||||
if src_ip != current_device.virtual_ip() {
|
||||
return Ok(());
|
||||
}
|
||||
if src_ip == dest_ip {
|
||||
return icmp(&tun_writer, ipv4_packet);
|
||||
}
|
||||
if !check_dest(dest_ip, current_device.virtual_netmask, current_device.virtual_network) && !dest_ip.is_broadcast() {
|
||||
// println!("非目标 {:?}",ipv4_packet);
|
||||
if let Some(r_dest_ip) = ip_route.route(&dest_ip) {
|
||||
//路由的目标不能是自己
|
||||
if r_dest_ip == src_ip {
|
||||
return Ok(());
|
||||
}
|
||||
dest_ip = r_dest_ip;
|
||||
} else {
|
||||
return Ok(());
|
||||
}
|
||||
} else {
|
||||
match ipv4_packet.protocol() {
|
||||
ipv4::protocol::Protocol::Tcp => {
|
||||
let dest_addr = {
|
||||
let tcp_packet = packet::tcp::tcp::TcpPacket::new(src_ip, dest_ip, ipv4_packet.payload())?;
|
||||
SocketAddrV4::new(dest_ip, tcp_packet.destination_port())
|
||||
};
|
||||
if let Some(entry) = proxy_map.tcp_proxy_map.get(&dest_addr) {
|
||||
let source_addr = entry.value().1;
|
||||
let source_ip = *source_addr.ip();
|
||||
let mut tcp_packet = packet::tcp::tcp::TcpPacket::new(source_ip, dest_ip, ipv4_packet.payload_mut())?;
|
||||
tcp_packet.set_source_port(source_addr.port());
|
||||
tcp_packet.update_checksum();
|
||||
ipv4_packet.set_source_ip(source_ip);
|
||||
ipv4_packet.update_checksum();
|
||||
}
|
||||
}
|
||||
ipv4::protocol::Protocol::Udp => {
|
||||
let dest_addr = {
|
||||
let udp_packet = packet::udp::udp::UdpPacket::new(src_ip, dest_ip, ipv4_packet.payload())?;
|
||||
SocketAddrV4::new(dest_ip, udp_packet.destination_port())
|
||||
};
|
||||
if let Some(entry) = proxy_map.udp_proxy_map.get(&dest_addr) {
|
||||
let source_addr = entry.value().1;
|
||||
let source_ip = *source_addr.ip();
|
||||
let mut udp_packet = packet::udp::udp::UdpPacket::new(source_ip, dest_ip, ipv4_packet.payload_mut())?;
|
||||
udp_packet.set_source_port(source_addr.port());
|
||||
udp_packet.update_checksum();
|
||||
ipv4_packet.set_source_ip(source_ip);
|
||||
ipv4_packet.update_checksum();
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
net_packet.set_source(src_ip);
|
||||
net_packet.set_destination(dest_ip);
|
||||
net_packet.set_payload(ipv4_packet.buffer);
|
||||
@@ -68,9 +117,11 @@ fn handle(sender: &Sender<Ipv4Addr>, data: &mut [u8], tun_writer: &TunWriter, cu
|
||||
pub fn start(sender: Sender<Ipv4Addr>,
|
||||
tun_reader: TunReader,
|
||||
tun_writer: TunWriter,
|
||||
current_device: Arc<AtomicCell<CurrentDeviceInfo>>) {
|
||||
current_device: Arc<AtomicCell<CurrentDeviceInfo>>,
|
||||
ip_route: ExternalRoute,
|
||||
ip_proxy_map: IpProxyMap) {
|
||||
thread::Builder::new().name("tun-handler".into()).spawn(move || {
|
||||
if let Err(e) = start_(sender, tun_reader, tun_writer, current_device) {
|
||||
if let Err(e) = start_(sender, tun_reader, tun_writer, current_device, ip_route, ip_proxy_map) {
|
||||
log::warn!("{:?}",e);
|
||||
}
|
||||
}).unwrap();
|
||||
@@ -80,15 +131,17 @@ pub fn start(sender: Sender<Ipv4Addr>,
|
||||
fn start_(sender: Sender<Ipv4Addr>,
|
||||
tun_reader: TunReader,
|
||||
tun_writer: TunWriter,
|
||||
current_device: Arc<AtomicCell<CurrentDeviceInfo>>) -> io::Result<()> {
|
||||
let mut net_packet = NetPacket::new(vec![0u8; 4 + 8 + 1500])?;
|
||||
current_device: Arc<AtomicCell<CurrentDeviceInfo>>,
|
||||
ip_route: ExternalRoute,
|
||||
ip_proxy_map: IpProxyMap) -> io::Result<()> {
|
||||
let mut net_packet = NetPacket::new([0u8; 4 + 8 + 1500])?;
|
||||
net_packet.set_version(Version::V1);
|
||||
net_packet.set_protocol(Protocol::Ipv4Turn);
|
||||
net_packet.set_transport_protocol(ipv4::protocol::Protocol::Ipv4.into());
|
||||
net_packet.set_ttl(MAX_TTL);
|
||||
loop {
|
||||
let mut data = tun_reader.next()?;
|
||||
match handle(&sender, data.bytes_mut(), &tun_writer, current_device.load(), &mut net_packet) {
|
||||
match handle(&sender, data.bytes_mut(), &tun_writer, current_device.load(), &mut net_packet, &ip_route, &ip_proxy_map) {
|
||||
Ok(_) => {}
|
||||
Err(e) => {
|
||||
log::warn!("{:?}", e)
|
||||
@@ -101,8 +154,10 @@ fn start_(sender: Sender<Ipv4Addr>,
|
||||
fn start_(sender: Sender<Ipv4Addr>,
|
||||
tun_reader: TunReader,
|
||||
tun_writer: TunWriter,
|
||||
current_device: Arc<AtomicCell<CurrentDeviceInfo>>, ) -> io::Result<()> {
|
||||
let mut net_packet = NetPacket::new(vec![0u8; 4 + 8 + 1500])?;
|
||||
current_device: Arc<AtomicCell<CurrentDeviceInfo>>,
|
||||
ip_route: ExternalRoute,
|
||||
ip_proxy_map: IpProxyMap) -> io::Result<()> {
|
||||
let mut net_packet = NetPacket::new([0u8; 4 + 8 + 1500])?;
|
||||
net_packet.set_version(Version::V1);
|
||||
net_packet.set_protocol(Protocol::Ipv4Turn);
|
||||
net_packet.set_transport_protocol(ipv4::protocol::Protocol::Ipv4.into());
|
||||
@@ -110,7 +165,7 @@ fn start_(sender: Sender<Ipv4Addr>,
|
||||
let mut buf = [0; 4096];
|
||||
loop {
|
||||
let len = tun_reader.read(&mut buf)?;
|
||||
match handle(&sender, &mut buf[..len], &tun_writer, current_device.load(), &mut net_packet) {
|
||||
match handle(&sender, &mut buf[..len], &tun_writer, current_device.load(), &mut net_packet, &ip_route, &ip_proxy_map) {
|
||||
Ok(_) => {}
|
||||
Err(e) => {
|
||||
log::warn!("{:?}", e)
|
||||
|
||||
@@ -0,0 +1,131 @@
|
||||
use std::io;
|
||||
use std::mem::MaybeUninit;
|
||||
use std::net::{IpAddr, Ipv4Addr, SocketAddrV4};
|
||||
use std::sync::Arc;
|
||||
use crossbeam::atomic::AtomicCell;
|
||||
|
||||
use crossbeam_skiplist::SkipMap;
|
||||
use socket2::{Domain, SockAddr, Socket, Type};
|
||||
use p2p_channel::channel::sender::Sender;
|
||||
|
||||
use packet::icmp::icmp;
|
||||
use packet::icmp::icmp::HeaderOther;
|
||||
use packet::ip::ipv4;
|
||||
use crate::handle::CurrentDeviceInfo;
|
||||
use crate::protocol::{MAX_TTL, NetPacket, Protocol, Version};
|
||||
|
||||
pub struct IcmpProxy {
|
||||
icmp_socket: Arc<Socket>,
|
||||
// 对端-> 真实来源
|
||||
icmp_proxy_map: Arc<SkipMap<(Ipv4Addr, u16, u16), Ipv4Addr>>,
|
||||
sender: Sender<Ipv4Addr>,
|
||||
current_device: Arc<AtomicCell<CurrentDeviceInfo>>,
|
||||
}
|
||||
|
||||
impl IcmpProxy {
|
||||
pub fn new(addr: SocketAddrV4, icmp_proxy_map: Arc<SkipMap<(Ipv4Addr, u16, u16), Ipv4Addr>>, sender: Sender<Ipv4Addr>, current_device: Arc<AtomicCell<CurrentDeviceInfo>>) -> io::Result<IcmpProxy> {
|
||||
let icmp_socket = Arc::new(Socket::new(Domain::IPV4, Type::RAW, Some(socket2::Protocol::ICMPV4))?);
|
||||
icmp_socket.bind(&SockAddr::from(addr))?;
|
||||
// // 设置 SIO_RCVALL 参数
|
||||
// #[cfg(windows)]
|
||||
// {
|
||||
// use std::os::windows::io::AsRawSocket;
|
||||
// let raw_fd = icmp_socket.as_raw_socket();
|
||||
// let mut rcvall: winapi::shared::minwindef::DWORD = 1;
|
||||
// let mut bytes_returned: winapi::shared::minwindef::DWORD = 0;
|
||||
// let result = unsafe {
|
||||
// winapi::um::winsock2::WSAIoctl(
|
||||
// raw_fd as _,
|
||||
// winapi::shared::mstcpip::SIO_RCVALL,
|
||||
// &mut rcvall as *mut winapi::shared::minwindef::DWORD as *mut std::ffi::c_void,
|
||||
// std::mem::size_of::<winapi::shared::minwindef::DWORD>() as winapi::shared::minwindef::DWORD,
|
||||
// std::ptr::null_mut(),
|
||||
// 0,
|
||||
// &mut bytes_returned as winapi::shared::minwindef::LPDWORD,
|
||||
// std::ptr::null_mut(),
|
||||
// None,
|
||||
// )
|
||||
// };
|
||||
// if result != 0 {
|
||||
// return Err(io::Error::from_raw_os_error(unsafe { winapi::um::winsock2::WSAGetLastError() }));
|
||||
// }
|
||||
// }
|
||||
Ok(IcmpProxy {
|
||||
icmp_socket,
|
||||
icmp_proxy_map,
|
||||
sender,
|
||||
current_device,
|
||||
})
|
||||
}
|
||||
pub fn icmp_socket(&self) ->Arc<Socket>{
|
||||
self.icmp_socket.clone()
|
||||
}
|
||||
pub fn start(self) {
|
||||
let mut buf = [0 as u8; 1500];
|
||||
let data: &mut [MaybeUninit<u8>] =
|
||||
unsafe { std::mem::transmute(&mut buf[..]) };
|
||||
let mut net_packet = NetPacket::new([0u8; 4 + 8 + 1500]).unwrap();
|
||||
net_packet.set_version(Version::V1);
|
||||
net_packet.set_protocol(Protocol::Ipv4Turn);
|
||||
net_packet.set_transport_protocol(ipv4::protocol::Protocol::Ipv4.into());
|
||||
net_packet.set_ttl(MAX_TTL);
|
||||
loop {
|
||||
match self.recv(data) {
|
||||
Ok((len, peer_ip)) => {
|
||||
match peer_ip {
|
||||
IpAddr::V4(peer_ip) => {
|
||||
match ipv4::packet::IpV4Packet::new(&mut buf[..len]) {
|
||||
Ok(mut ipv4_packet) => {
|
||||
match icmp::IcmpPacket::new(ipv4_packet.payload()) {
|
||||
Ok(icmp_packet) => {
|
||||
match icmp_packet.header_other() {
|
||||
HeaderOther::Identifier(id, seq) => {
|
||||
if let Some(entry) = self.icmp_proxy_map.get(&(peer_ip, id, seq)) {
|
||||
//将数据发送到真实的来源
|
||||
let dest_ip = *entry.value();
|
||||
ipv4_packet.set_destination_ip(dest_ip);
|
||||
ipv4_packet.update_checksum();
|
||||
let virtual_ip = self.current_device.load().virtual_ip();
|
||||
net_packet.set_source(virtual_ip);
|
||||
net_packet.set_destination(dest_ip);
|
||||
let data_len = ipv4_packet.buffer.len();
|
||||
net_packet.set_payload(ipv4_packet.buffer);
|
||||
let _ = self.sender.send_to_id(&net_packet.buffer()[..(12 + data_len)], &dest_ip);
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
Err(_) => {}
|
||||
};
|
||||
}
|
||||
Err(_) => {}
|
||||
}
|
||||
}
|
||||
IpAddr::V6(_) => {}
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
log::warn!("icmp代理异常:{:?}",e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
fn recv(&self, buf: &mut [MaybeUninit<u8>]) -> io::Result<(usize, IpAddr)> {
|
||||
let (size, addr) = self.icmp_socket.recv_from(buf)?;
|
||||
let addr = match addr.as_socket() {
|
||||
None => {
|
||||
IpAddr::V4(Ipv4Addr::UNSPECIFIED)
|
||||
}
|
||||
Some(add) => {
|
||||
add.ip()
|
||||
}
|
||||
};
|
||||
Ok((size, addr))
|
||||
}
|
||||
// fn send_to(&self, buf: &[u8], addr: SocketAddrV4) -> io::Result<usize> {
|
||||
// self.icmp_socket.send_to(buf, &SockAddr::from(addr))
|
||||
// }
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
use std::{io, thread};
|
||||
use std::collections::HashMap;
|
||||
use std::net::{Ipv4Addr, SocketAddrV4};
|
||||
use std::sync::Arc;
|
||||
use crossbeam::atomic::AtomicCell;
|
||||
use crossbeam_skiplist::SkipMap;
|
||||
use socket2::{SockAddr, Socket};
|
||||
use tokio::net::{TcpListener, UdpSocket};
|
||||
use p2p_channel::channel::sender::Sender;
|
||||
use crate::handle::CurrentDeviceInfo;
|
||||
use crate::ip_proxy::icmp_proxy::IcmpProxy;
|
||||
use crate::ip_proxy::tcp_proxy::TcpProxy;
|
||||
use crate::ip_proxy::udp_proxy::UdpProxy;
|
||||
|
||||
pub mod icmp_proxy;
|
||||
pub mod tcp_proxy;
|
||||
pub mod udp_proxy;
|
||||
|
||||
#[derive(Eq, PartialEq, Ord, PartialOrd, Copy, Clone, Debug)]
|
||||
pub enum Protocol {
|
||||
Icmp,
|
||||
Tcp,
|
||||
Udp,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct IpProxyMap {
|
||||
pub(crate) tcp_proxy_port: u16,
|
||||
pub(crate) udp_proxy_port: u16,
|
||||
//真实源地址 -> (绑定地址,目的地址)
|
||||
pub(crate) tcp_proxy_map: Arc<SkipMap<SocketAddrV4, (SocketAddrV4, SocketAddrV4)>>,
|
||||
pub(crate) udp_proxy_map: Arc<SkipMap<SocketAddrV4, (SocketAddrV4, SocketAddrV4)>>,
|
||||
// icmp用Identifier来区分,没有Identifier的一律不转发
|
||||
pub(crate) icmp_proxy_map: Arc<SkipMap<(Ipv4Addr, u16, u16), Ipv4Addr>>,
|
||||
icmp_sockets: HashMap<Ipv4Addr, Arc<Socket>>,
|
||||
}
|
||||
|
||||
impl IpProxyMap {
|
||||
pub fn send_icmp(&self, buf: &[u8], src: &Ipv4Addr, dest: &Ipv4Addr) -> io::Result<usize> {
|
||||
if let Some(socket) = self.icmp_sockets.get(src) {
|
||||
socket.send_to(buf, &SockAddr::from(SocketAddrV4::new(*dest, 0)))
|
||||
} else {
|
||||
Err(io::Error::new(io::ErrorKind::Other, format!("not found src:{},dest:{}", src, dest)))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn init_proxy(sender: Sender<Ipv4Addr>, bind_ips: Vec<Ipv4Addr>, current_device: Arc<AtomicCell<CurrentDeviceInfo>>) -> io::Result<IpProxyMap> {
|
||||
let mut icmp_sockets = HashMap::new();
|
||||
let tcp_proxy_map: Arc<SkipMap<SocketAddrV4, (SocketAddrV4, SocketAddrV4)>> = Arc::new(SkipMap::new());
|
||||
let udp_proxy_map: Arc<SkipMap<SocketAddrV4, (SocketAddrV4, SocketAddrV4)>> = Arc::new(SkipMap::new());
|
||||
let icmp_proxy_map: Arc<SkipMap<(Ipv4Addr, u16, u16), Ipv4Addr>> = Arc::new(SkipMap::new());
|
||||
let tcp_listener = TcpListener::bind("0.0.0.0:0").await?;
|
||||
let udp_socket = UdpSocket::bind("0.0.0.0:0").await?;
|
||||
let tcp_proxy_port = tcp_listener.local_addr()?.port();
|
||||
let udp_proxy_port = udp_socket.local_addr()?.port();
|
||||
|
||||
{
|
||||
let tcp_proxy_map = tcp_proxy_map.clone();
|
||||
tokio::spawn(async {
|
||||
let tcp_proxy = TcpProxy::new(tcp_listener, tcp_proxy_map);
|
||||
tcp_proxy.start().await
|
||||
});
|
||||
}
|
||||
{
|
||||
let udp_proxy_map = udp_proxy_map.clone();
|
||||
tokio::spawn(async {
|
||||
let udp_proxy = UdpProxy::new(udp_socket, udp_proxy_map);
|
||||
udp_proxy.start().await
|
||||
});
|
||||
}
|
||||
for ip in bind_ips {
|
||||
let addr = SocketAddrV4::new(ip, 0);
|
||||
let icmp_proxy_map = icmp_proxy_map.clone();
|
||||
let icmp_proxy = IcmpProxy::new(addr, icmp_proxy_map, sender.try_clone()?, current_device.clone())?;
|
||||
icmp_sockets.insert(ip, icmp_proxy.icmp_socket());
|
||||
thread::spawn(move || {
|
||||
icmp_proxy.start();
|
||||
});
|
||||
}
|
||||
|
||||
Ok(IpProxyMap {
|
||||
tcp_proxy_port,
|
||||
udp_proxy_port,
|
||||
tcp_proxy_map,
|
||||
udp_proxy_map,
|
||||
icmp_proxy_map,
|
||||
icmp_sockets,
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
use std::io;
|
||||
use std::net::{SocketAddr, SocketAddrV4};
|
||||
use std::sync::Arc;
|
||||
use crossbeam_skiplist::SkipMap;
|
||||
use tokio::net::{TcpListener, TcpStream};
|
||||
|
||||
pub struct TcpProxy {
|
||||
tcp_listener: TcpListener,
|
||||
// todo 怎么过期
|
||||
map: Arc<SkipMap<SocketAddrV4, (SocketAddrV4, SocketAddrV4)>>,
|
||||
}
|
||||
|
||||
impl TcpProxy {
|
||||
pub fn new(tcp_listener: TcpListener, map: Arc<SkipMap<SocketAddrV4, (SocketAddrV4, SocketAddrV4)>>) -> Self {
|
||||
Self {
|
||||
tcp_listener,
|
||||
map,
|
||||
}
|
||||
}
|
||||
pub async fn start(self) {
|
||||
let tcp_listener = self.tcp_listener;
|
||||
let map = self.map;
|
||||
loop {
|
||||
match tcp_listener.accept().await {
|
||||
Ok((tcp_stream, sender_addr)) => {
|
||||
match sender_addr {
|
||||
SocketAddr::V4(sender_addr) => {
|
||||
if let Some(entry) = map.get(&sender_addr) {
|
||||
let (src_addr, dest_addr) = *entry.value();
|
||||
let peer_tcp_stream = match TcpStream::connect(dest_addr).await {
|
||||
Ok(peer_tcp_stream) => {peer_tcp_stream}
|
||||
Err(e) => {
|
||||
log::warn!("tcp代理异常:{:?},来源:{},目标:{}",e,src_addr,dest_addr);
|
||||
continue;
|
||||
}
|
||||
};
|
||||
tokio::spawn(async move {
|
||||
match proxy(tcp_stream, peer_tcp_stream).await {
|
||||
Ok(_) => {}
|
||||
Err(e) => {
|
||||
log::warn!("tcp代理异常:{:?},来源:{},目标:{}",e,src_addr,dest_addr);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
SocketAddr::V6(_) => {}
|
||||
}
|
||||
|
||||
}
|
||||
Err(e) => {
|
||||
log::warn!("tcp代理监听:{:?}",e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async fn proxy(mut client: TcpStream, mut server: TcpStream) -> io::Result<()> {
|
||||
let (mut client_reader, mut client_writer) = client.split();
|
||||
let (mut server_reader, mut server_writer) = server.split();
|
||||
|
||||
let client_to_server = tokio::io::copy(&mut client_reader, &mut server_writer);
|
||||
let server_to_client = tokio::io::copy(&mut server_reader, &mut client_writer);
|
||||
|
||||
tokio::try_join!(client_to_server, server_to_client)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
use std::io;
|
||||
use std::net::{SocketAddr, SocketAddrV4};
|
||||
use std::sync::Arc;
|
||||
use std::time::Duration;
|
||||
use crossbeam_skiplist::SkipMap;
|
||||
use tokio::net::UdpSocket;
|
||||
|
||||
/// 一个udp代理,作用是利用系统协议栈,将udp数据报解析出来再转发到目的地址
|
||||
pub struct UdpProxy {
|
||||
udp_socket: Arc<UdpSocket>,
|
||||
// todo 过期处理
|
||||
map: Arc<SkipMap<SocketAddrV4, (SocketAddrV4, SocketAddrV4)>>,
|
||||
}
|
||||
|
||||
impl UdpProxy {
|
||||
pub fn new(udp_socket: UdpSocket, map: Arc<SkipMap<SocketAddrV4, (SocketAddrV4, SocketAddrV4)>>) -> Self {
|
||||
let udp_socket = Arc::new(udp_socket);
|
||||
Self {
|
||||
udp_socket,
|
||||
map,
|
||||
}
|
||||
}
|
||||
pub async fn start(self) {
|
||||
let map = self.map;
|
||||
let udp_socket = self.udp_socket;
|
||||
let mut buf = [0u8; 65536];
|
||||
let inner_map: Arc<SkipMap<SocketAddrV4, Arc<UdpSocket>>> = Arc::new(SkipMap::new());
|
||||
|
||||
loop {
|
||||
match udp_socket.recv_from(&mut buf).await {
|
||||
Ok((len, sender_addr)) => {
|
||||
match sender_addr {
|
||||
SocketAddr::V4(sender_addr) => {
|
||||
match start0(&buf[..len], sender_addr, &inner_map, &map, &udp_socket).await {
|
||||
Ok(_) => {}
|
||||
Err(e) => {
|
||||
log::warn!("udp代理异常:{:?},来源:{}",e,sender_addr);
|
||||
}
|
||||
}
|
||||
}
|
||||
SocketAddr::V6(_) => {}
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
log::warn!("udp代理异常:{:?}",e);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async fn start0(buf: &[u8], sender_addr: SocketAddrV4, inner_map: &Arc<SkipMap<SocketAddrV4, Arc<UdpSocket>>>, map: &Arc<SkipMap<SocketAddrV4, (SocketAddrV4, SocketAddrV4)>>, udp_socket: &Arc<UdpSocket>) -> io::Result<()> {
|
||||
if let Some(entry) = inner_map.get(&sender_addr) {
|
||||
entry.value().send(buf).await?;
|
||||
} else if let Some(entry) = map.get(&sender_addr) {
|
||||
let (src_addr, dest_addr) = *entry.value();
|
||||
let peer_udp_socket = UdpSocket::bind("0.0.0.0:0").await?;
|
||||
peer_udp_socket.connect(dest_addr).await?;
|
||||
peer_udp_socket.send(buf).await?;
|
||||
let peer_udp_socket = Arc::new(peer_udp_socket);
|
||||
let inner_map = inner_map.clone();
|
||||
inner_map.insert(sender_addr, peer_udp_socket.clone());
|
||||
let udp_socket = udp_socket.clone();
|
||||
tokio::spawn(async move {
|
||||
let mut buf = [0u8; 65536];
|
||||
loop {
|
||||
match tokio::time::timeout(Duration::from_secs(300), peer_udp_socket.recv(&mut buf)).await {
|
||||
Ok(rs) => {
|
||||
match rs {
|
||||
Ok(len) => {
|
||||
match udp_socket.send_to(&buf[..len], sender_addr).await {
|
||||
Ok(_) => {}
|
||||
Err(e) => {
|
||||
log::warn!("udp代理异常:{:?},来源:{},目标:{}",e,src_addr,dest_addr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
log::warn!("udp代理异常:{:?},来源:{},目标:{}",e,src_addr,dest_addr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
Err(_) => {
|
||||
//超时关闭
|
||||
log::warn!("udp代理超时关闭,来源:{},目标:{}",src_addr,dest_addr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
inner_map.remove(&sender_addr);
|
||||
});
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
@@ -11,4 +11,6 @@ pub mod proto;
|
||||
pub mod protocol;
|
||||
pub mod tun_device;
|
||||
pub mod tap_device;
|
||||
pub mod ip_proxy;
|
||||
pub mod external_route;
|
||||
pub mod core;
|
||||
|
||||
@@ -1,13 +1,16 @@
|
||||
use std::io;
|
||||
use crate::tun_device::{TunReader, TunWriter};
|
||||
use std::net::Ipv4Addr;
|
||||
use std::sync::Arc;
|
||||
use tun::Device;
|
||||
use parking_lot::Mutex;
|
||||
use std::process::Command;
|
||||
|
||||
pub fn create_tun(
|
||||
address: Ipv4Addr,
|
||||
netmask: Ipv4Addr,
|
||||
gateway: Ipv4Addr,
|
||||
in_ips: Vec<(Ipv4Addr, Ipv4Addr)>,
|
||||
) -> crate::error::Result<(TunWriter, TunReader)> {
|
||||
println!("========TUN网卡配置========");
|
||||
let mut config = tun::Configuration::default();
|
||||
@@ -19,20 +22,36 @@ pub fn create_tun(
|
||||
.mtu(1420)
|
||||
// .queues(2) 用多个队列有兼容性问题
|
||||
.up();
|
||||
//
|
||||
// config.platform(|config| {
|
||||
// config.packet_information(true);
|
||||
// });
|
||||
|
||||
let dev = tun::create(&config).unwrap();
|
||||
let packet_information = dev.has_packet_information();
|
||||
let queue = dev.queue(0).unwrap();
|
||||
let reader = queue.reader();
|
||||
let writer = queue.writer();
|
||||
println!("name:{:?}", dev.name());
|
||||
let name = dev.name();
|
||||
println!("name:{:?}", name);
|
||||
for (address, netmask) in in_ips {
|
||||
add_route(name, address, netmask)?;
|
||||
}
|
||||
println!("========TUN网卡配置========");
|
||||
Ok((
|
||||
TunWriter(writer, packet_information, Arc::new(Mutex::new(dev))),
|
||||
TunReader(reader, packet_information),
|
||||
))
|
||||
}
|
||||
|
||||
fn add_route(name: &str, address: Ipv4Addr, netmask: Ipv4Addr) -> io::Result<()> {
|
||||
let route_add_str: String = format!(
|
||||
"ip route add {:?}/{:?} dev {}",
|
||||
address, netmask, name
|
||||
);
|
||||
let route_add_out = Command::new("sh")
|
||||
.arg("-c")
|
||||
.arg(route_add_str)
|
||||
.output()
|
||||
.expect("sh exec error!");
|
||||
if !route_add_out.status.success() {
|
||||
return Err(io::Error::new(io::ErrorKind::Other, format!("添加路由失败: {:?}", route_add_out)));
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ pub fn create_tun(
|
||||
address: Ipv4Addr,
|
||||
netmask: Ipv4Addr,
|
||||
gateway: Ipv4Addr,
|
||||
in_ips: Vec<(Ipv4Addr, Ipv4Addr)>,
|
||||
) -> crate::error::Result<(TunWriter, TunReader)> {
|
||||
println!("========TUN网卡配置========");
|
||||
let mut config = tun::Configuration::default();
|
||||
@@ -23,13 +24,17 @@ pub fn create_tun(
|
||||
.up();
|
||||
|
||||
let dev = tun::create(&config).unwrap();
|
||||
config_ip(dev.name(), address, netmask, gateway)?;
|
||||
|
||||
let name = dev.name();
|
||||
config_ip(name, address, netmask, gateway)?;
|
||||
add_route(name, address, netmask)?;
|
||||
for (address, netmask) in in_ips {
|
||||
add_route(name, address, netmask)?;
|
||||
}
|
||||
let packet_information = dev.has_packet_information();
|
||||
let queue = dev.queue(0).unwrap();
|
||||
let reader = queue.reader();
|
||||
let writer = queue.writer();
|
||||
println!("name:{:?}", dev.name());
|
||||
println!("name:{:?}", name);
|
||||
println!("========TUN网卡配置========");
|
||||
Ok((
|
||||
TunWriter(writer, packet_information, Arc::new(Mutex::new(dev))),
|
||||
@@ -37,12 +42,24 @@ pub fn create_tun(
|
||||
))
|
||||
}
|
||||
|
||||
fn add_route(name: &str, address: Ipv4Addr, netmask: Ipv4Addr) -> io::Result<()> {
|
||||
let route_add_str: String = format!(
|
||||
"sudo route -n add -net {:?}/{:?} -interface {}",
|
||||
address, netmask, name
|
||||
);
|
||||
let route_add_out = Command::new("sh")
|
||||
.arg("-c")
|
||||
.arg(route_add_str)
|
||||
.output()
|
||||
.expect("sh exec error!");
|
||||
if !route_add_out.status.success() {
|
||||
return Err(io::Error::new(io::ErrorKind::Other, format!("添加路由失败: {:?}", route_add_out)));
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn config_ip(name: &str, address: Ipv4Addr, netmask: Ipv4Addr, gateway: Ipv4Addr) -> io::Result<()> {
|
||||
let up_eth_str: String = format!("ifconfig {} {:?} {:?} up ", name, address, gateway);
|
||||
let route_add_str: String = format!(
|
||||
"sudo route -n add -net {:?} -netmask {:?} {:?}",
|
||||
address, netmask, gateway
|
||||
);
|
||||
let up_eth_out = Command::new("sh")
|
||||
.arg("-c")
|
||||
.arg(up_eth_str)
|
||||
@@ -51,13 +68,5 @@ pub(crate) fn config_ip(name: &str, address: Ipv4Addr, netmask: Ipv4Addr, gatewa
|
||||
if !up_eth_out.status.success() {
|
||||
return Err(io::Error::new(io::ErrorKind::Other, format!("设置网络地址失败: {:?}", up_eth_out)));
|
||||
}
|
||||
let if_config_out = Command::new("sh")
|
||||
.arg("-c")
|
||||
.arg(route_add_str)
|
||||
.output()
|
||||
.expect("sh exec error!");
|
||||
if !if_config_out.status.success() {
|
||||
return Err(io::Error::new(io::ErrorKind::Other, format!("添加路由失败: {:?}", if_config_out)));
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
use std::io;
|
||||
use std::{io, thread};
|
||||
use std::net::Ipv4Addr;
|
||||
use std::sync::Arc;
|
||||
use std::time::Duration;
|
||||
|
||||
use libloading::Library;
|
||||
use parking_lot::Mutex;
|
||||
@@ -67,6 +68,7 @@ pub fn create_tun(
|
||||
address: Ipv4Addr,
|
||||
netmask: Ipv4Addr,
|
||||
gateway: Ipv4Addr,
|
||||
in_ips:Vec<(Ipv4Addr,Ipv4Addr)>
|
||||
) -> io::Result<(TunWriter, TunReader)> {
|
||||
unsafe {
|
||||
println!("========TUN网卡配置========");
|
||||
@@ -74,6 +76,7 @@ pub fn create_tun(
|
||||
Ok(lib) => match TunDevice::open(lib, TUN_INTERFACE_NAME) {
|
||||
Ok(tun_device) => {
|
||||
let _ = tun_device.delete();
|
||||
thread::sleep(Duration::from_millis(5));
|
||||
}
|
||||
Err(_) => {}
|
||||
},
|
||||
@@ -91,11 +94,21 @@ pub fn create_tun(
|
||||
TUN_INTERFACE_NAME,
|
||||
) {
|
||||
Ok(tun_device) => tun_device,
|
||||
Err(e) => {
|
||||
return Err(io::Error::new(
|
||||
io::ErrorKind::Other,
|
||||
format!("{:?}", e),
|
||||
));
|
||||
Err(_) => {
|
||||
thread::sleep(Duration::from_millis(200));
|
||||
match TunDevice::create(
|
||||
Library::new("wintun.dll").unwrap(),
|
||||
TUN_POOL_NAME,
|
||||
TUN_INTERFACE_NAME,
|
||||
) {
|
||||
Ok(tun_device) => tun_device,
|
||||
Err(e) => {
|
||||
return Err(io::Error::new(
|
||||
io::ErrorKind::Other,
|
||||
format!("{:?}", e),
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
println!("name:{:?}", tun_device.get_name()?);
|
||||
@@ -103,6 +116,9 @@ pub fn create_tun(
|
||||
log::error!("创建tun成功 {:?}",tun_device.get_name()?);
|
||||
tun_device.set_ip(address, netmask)?;
|
||||
tun_device.set_mtu(1420)?;
|
||||
for (address, netmask) in in_ips {
|
||||
tun_device.add_route(address, netmask, gateway)?;
|
||||
}
|
||||
tun_device.add_route(address, netmask, gateway)?;
|
||||
let device = Arc::new(tun_device);
|
||||
println!("========TUN网卡配置========");
|
||||
|
||||
Reference in New Issue
Block a user