Compare commits

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