Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c8d0f3850f | ||
|
|
b846f54d79 | ||
|
|
bb7b1d23af | ||
|
|
9e700b3094 | ||
|
|
38f28e313c | ||
|
|
63f03fb11f | ||
|
|
cf7854906f | ||
|
|
78ae5f3036 | ||
|
|
c412a256b8 | ||
|
|
94def558fc | ||
|
|
25e9c523d3 | ||
|
|
a009d06000 | ||
|
|
675e0c52ff | ||
|
|
dc4219753a | ||
|
|
c003b9acbb | ||
|
|
f4869ebd1d | ||
|
|
de4f42537d | ||
|
|
b9ebe80ef3 | ||
|
|
ea5ba750d4 | ||
|
|
b594afce16 |
+42
-25
@@ -2,7 +2,8 @@ name: Rust
|
|||||||
|
|
||||||
on:
|
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
|
||||||
@@ -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
|
||||||
- 支持安卓
|
- 支持安卓
|
||||||
|
|||||||
@@ -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"
|
||||||
|
|||||||
@@ -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
@@ -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
@@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
@@ -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> {
|
||||||
|
|||||||
@@ -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
@@ -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"
|
||||||
|
|
||||||
|
|||||||
@@ -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,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,
|
||||||
|
|||||||
@@ -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)]
|
||||||
|
|||||||
@@ -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
@@ -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,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
use std::net::Ipv4Addr;
|
||||||
|
|
||||||
|
// 目标ip,子网掩码,网关
|
||||||
|
|
||||||
|
pub struct ExternalRoute {
|
||||||
|
route_table: Vec<(u32, u32, Ipv4Addr)>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ExternalRoute {
|
||||||
|
pub fn new(route_table: Vec<(u32, u32, Ipv4Addr)>) -> Self {
|
||||||
|
Self {
|
||||||
|
route_table
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn route(&self, ip: &Ipv4Addr) -> Option<Ipv4Addr> {
|
||||||
|
let ip = u32::from_be_bytes(ip.octets());
|
||||||
|
for (dest, mask, gateway) in &self.route_table {
|
||||||
|
if *mask & ip == *mask & *dest {
|
||||||
|
return Some(*gateway);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -60,6 +60,19 @@ pub enum ConnectStatus {
|
|||||||
Connected,
|
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]
|
||||||
|
|||||||
@@ -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(¤t_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(ðernet_packet.buffer)?;
|
ethernet_packet.payload_mut().copy_from_slice(ipv4.buffer);
|
||||||
}
|
tap_writer.write(ðernet_packet.buffer)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -225,7 +283,7 @@ impl RecvHandler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
let new_current_device = CurrentDeviceInfo::new(virtual_ip, virtual_gateway,
|
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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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, ¤t_device, &tap_writer, &mut ethernet_packet, &sender) {
|
if let Err(e) = handle(&mut net_packet, ¤t_device, &tap_writer, &mut ethernet_packet, &sender,&ip_route,&ip_proxy_map) {
|
||||||
log::error!("tap handle{:?}",e);
|
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(())
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -0,0 +1,131 @@
|
|||||||
|
use std::io;
|
||||||
|
use std::mem::MaybeUninit;
|
||||||
|
use std::net::{IpAddr, Ipv4Addr, SocketAddrV4};
|
||||||
|
use std::sync::Arc;
|
||||||
|
use crossbeam::atomic::AtomicCell;
|
||||||
|
|
||||||
|
use crossbeam_skiplist::SkipMap;
|
||||||
|
use socket2::{Domain, SockAddr, Socket, Type};
|
||||||
|
use p2p_channel::channel::sender::Sender;
|
||||||
|
|
||||||
|
use packet::icmp::icmp;
|
||||||
|
use packet::icmp::icmp::HeaderOther;
|
||||||
|
use packet::ip::ipv4;
|
||||||
|
use crate::handle::CurrentDeviceInfo;
|
||||||
|
use crate::protocol::{MAX_TTL, NetPacket, Protocol, Version};
|
||||||
|
|
||||||
|
pub struct IcmpProxy {
|
||||||
|
icmp_socket: Arc<Socket>,
|
||||||
|
// 对端-> 真实来源
|
||||||
|
icmp_proxy_map: Arc<SkipMap<(Ipv4Addr, u16, u16), Ipv4Addr>>,
|
||||||
|
sender: Sender<Ipv4Addr>,
|
||||||
|
current_device: Arc<AtomicCell<CurrentDeviceInfo>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl IcmpProxy {
|
||||||
|
pub fn new(addr: SocketAddrV4, icmp_proxy_map: Arc<SkipMap<(Ipv4Addr, u16, u16), Ipv4Addr>>, sender: Sender<Ipv4Addr>, current_device: Arc<AtomicCell<CurrentDeviceInfo>>) -> io::Result<IcmpProxy> {
|
||||||
|
let icmp_socket = Arc::new(Socket::new(Domain::IPV4, Type::RAW, Some(socket2::Protocol::ICMPV4))?);
|
||||||
|
icmp_socket.bind(&SockAddr::from(addr))?;
|
||||||
|
// // 设置 SIO_RCVALL 参数
|
||||||
|
// #[cfg(windows)]
|
||||||
|
// {
|
||||||
|
// use std::os::windows::io::AsRawSocket;
|
||||||
|
// let raw_fd = icmp_socket.as_raw_socket();
|
||||||
|
// let mut rcvall: winapi::shared::minwindef::DWORD = 1;
|
||||||
|
// let mut bytes_returned: winapi::shared::minwindef::DWORD = 0;
|
||||||
|
// let result = unsafe {
|
||||||
|
// winapi::um::winsock2::WSAIoctl(
|
||||||
|
// raw_fd as _,
|
||||||
|
// winapi::shared::mstcpip::SIO_RCVALL,
|
||||||
|
// &mut rcvall as *mut winapi::shared::minwindef::DWORD as *mut std::ffi::c_void,
|
||||||
|
// std::mem::size_of::<winapi::shared::minwindef::DWORD>() as winapi::shared::minwindef::DWORD,
|
||||||
|
// std::ptr::null_mut(),
|
||||||
|
// 0,
|
||||||
|
// &mut bytes_returned as winapi::shared::minwindef::LPDWORD,
|
||||||
|
// std::ptr::null_mut(),
|
||||||
|
// None,
|
||||||
|
// )
|
||||||
|
// };
|
||||||
|
// if result != 0 {
|
||||||
|
// return Err(io::Error::from_raw_os_error(unsafe { winapi::um::winsock2::WSAGetLastError() }));
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
Ok(IcmpProxy {
|
||||||
|
icmp_socket,
|
||||||
|
icmp_proxy_map,
|
||||||
|
sender,
|
||||||
|
current_device,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
pub fn icmp_socket(&self) ->Arc<Socket>{
|
||||||
|
self.icmp_socket.clone()
|
||||||
|
}
|
||||||
|
pub fn start(self) {
|
||||||
|
let mut buf = [0 as u8; 1500];
|
||||||
|
let data: &mut [MaybeUninit<u8>] =
|
||||||
|
unsafe { std::mem::transmute(&mut buf[..]) };
|
||||||
|
let mut net_packet = NetPacket::new([0u8; 4 + 8 + 1500]).unwrap();
|
||||||
|
net_packet.set_version(Version::V1);
|
||||||
|
net_packet.set_protocol(Protocol::Ipv4Turn);
|
||||||
|
net_packet.set_transport_protocol(ipv4::protocol::Protocol::Ipv4.into());
|
||||||
|
net_packet.set_ttl(MAX_TTL);
|
||||||
|
loop {
|
||||||
|
match self.recv(data) {
|
||||||
|
Ok((len, peer_ip)) => {
|
||||||
|
match peer_ip {
|
||||||
|
IpAddr::V4(peer_ip) => {
|
||||||
|
match ipv4::packet::IpV4Packet::new(&mut buf[..len]) {
|
||||||
|
Ok(mut ipv4_packet) => {
|
||||||
|
match icmp::IcmpPacket::new(ipv4_packet.payload()) {
|
||||||
|
Ok(icmp_packet) => {
|
||||||
|
match icmp_packet.header_other() {
|
||||||
|
HeaderOther::Identifier(id, seq) => {
|
||||||
|
if let Some(entry) = self.icmp_proxy_map.get(&(peer_ip, id, seq)) {
|
||||||
|
//将数据发送到真实的来源
|
||||||
|
let dest_ip = *entry.value();
|
||||||
|
ipv4_packet.set_destination_ip(dest_ip);
|
||||||
|
ipv4_packet.update_checksum();
|
||||||
|
let virtual_ip = self.current_device.load().virtual_ip();
|
||||||
|
net_packet.set_source(virtual_ip);
|
||||||
|
net_packet.set_destination(dest_ip);
|
||||||
|
let data_len = ipv4_packet.buffer.len();
|
||||||
|
net_packet.set_payload(ipv4_packet.buffer);
|
||||||
|
let _ = self.sender.send_to_id(&net_packet.buffer()[..(12 + data_len)], &dest_ip);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(_) => {}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
Err(_) => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
IpAddr::V6(_) => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
log::warn!("icmp代理异常:{:?}",e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fn recv(&self, buf: &mut [MaybeUninit<u8>]) -> io::Result<(usize, IpAddr)> {
|
||||||
|
let (size, addr) = self.icmp_socket.recv_from(buf)?;
|
||||||
|
let addr = match addr.as_socket() {
|
||||||
|
None => {
|
||||||
|
IpAddr::V4(Ipv4Addr::UNSPECIFIED)
|
||||||
|
}
|
||||||
|
Some(add) => {
|
||||||
|
add.ip()
|
||||||
|
}
|
||||||
|
};
|
||||||
|
Ok((size, addr))
|
||||||
|
}
|
||||||
|
// fn send_to(&self, buf: &[u8], addr: SocketAddrV4) -> io::Result<usize> {
|
||||||
|
// self.icmp_socket.send_to(buf, &SockAddr::from(addr))
|
||||||
|
// }
|
||||||
|
}
|
||||||
@@ -0,0 +1,90 @@
|
|||||||
|
use std::{io, thread};
|
||||||
|
use std::collections::HashMap;
|
||||||
|
use std::net::{Ipv4Addr, SocketAddrV4};
|
||||||
|
use std::sync::Arc;
|
||||||
|
use crossbeam::atomic::AtomicCell;
|
||||||
|
use crossbeam_skiplist::SkipMap;
|
||||||
|
use socket2::{SockAddr, Socket};
|
||||||
|
use tokio::net::{TcpListener, UdpSocket};
|
||||||
|
use p2p_channel::channel::sender::Sender;
|
||||||
|
use crate::handle::CurrentDeviceInfo;
|
||||||
|
use crate::ip_proxy::icmp_proxy::IcmpProxy;
|
||||||
|
use crate::ip_proxy::tcp_proxy::TcpProxy;
|
||||||
|
use crate::ip_proxy::udp_proxy::UdpProxy;
|
||||||
|
|
||||||
|
pub mod icmp_proxy;
|
||||||
|
pub mod tcp_proxy;
|
||||||
|
pub mod udp_proxy;
|
||||||
|
|
||||||
|
#[derive(Eq, PartialEq, Ord, PartialOrd, Copy, Clone, Debug)]
|
||||||
|
pub enum Protocol {
|
||||||
|
Icmp,
|
||||||
|
Tcp,
|
||||||
|
Udp,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct IpProxyMap {
|
||||||
|
pub(crate) tcp_proxy_port: u16,
|
||||||
|
pub(crate) udp_proxy_port: u16,
|
||||||
|
//真实源地址 -> (绑定地址,目的地址)
|
||||||
|
pub(crate) tcp_proxy_map: Arc<SkipMap<SocketAddrV4, (SocketAddrV4, SocketAddrV4)>>,
|
||||||
|
pub(crate) udp_proxy_map: Arc<SkipMap<SocketAddrV4, (SocketAddrV4, SocketAddrV4)>>,
|
||||||
|
// icmp用Identifier来区分,没有Identifier的一律不转发
|
||||||
|
pub(crate) icmp_proxy_map: Arc<SkipMap<(Ipv4Addr, u16, u16), Ipv4Addr>>,
|
||||||
|
icmp_sockets: HashMap<Ipv4Addr, Arc<Socket>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl IpProxyMap {
|
||||||
|
pub fn send_icmp(&self, buf: &[u8], src: &Ipv4Addr, dest: &Ipv4Addr) -> io::Result<usize> {
|
||||||
|
if let Some(socket) = self.icmp_sockets.get(src) {
|
||||||
|
socket.send_to(buf, &SockAddr::from(SocketAddrV4::new(*dest, 0)))
|
||||||
|
} else {
|
||||||
|
Err(io::Error::new(io::ErrorKind::Other, format!("not found src:{},dest:{}", src, dest)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn init_proxy(sender: Sender<Ipv4Addr>, bind_ips: Vec<Ipv4Addr>, current_device: Arc<AtomicCell<CurrentDeviceInfo>>) -> io::Result<IpProxyMap> {
|
||||||
|
let mut icmp_sockets = HashMap::new();
|
||||||
|
let tcp_proxy_map: Arc<SkipMap<SocketAddrV4, (SocketAddrV4, SocketAddrV4)>> = Arc::new(SkipMap::new());
|
||||||
|
let udp_proxy_map: Arc<SkipMap<SocketAddrV4, (SocketAddrV4, SocketAddrV4)>> = Arc::new(SkipMap::new());
|
||||||
|
let icmp_proxy_map: Arc<SkipMap<(Ipv4Addr, u16, u16), Ipv4Addr>> = Arc::new(SkipMap::new());
|
||||||
|
let tcp_listener = TcpListener::bind("0.0.0.0:0").await?;
|
||||||
|
let udp_socket = UdpSocket::bind("0.0.0.0:0").await?;
|
||||||
|
let tcp_proxy_port = tcp_listener.local_addr()?.port();
|
||||||
|
let udp_proxy_port = udp_socket.local_addr()?.port();
|
||||||
|
|
||||||
|
{
|
||||||
|
let tcp_proxy_map = tcp_proxy_map.clone();
|
||||||
|
tokio::spawn(async {
|
||||||
|
let tcp_proxy = TcpProxy::new(tcp_listener, tcp_proxy_map);
|
||||||
|
tcp_proxy.start().await
|
||||||
|
});
|
||||||
|
}
|
||||||
|
{
|
||||||
|
let udp_proxy_map = udp_proxy_map.clone();
|
||||||
|
tokio::spawn(async {
|
||||||
|
let udp_proxy = UdpProxy::new(udp_socket, udp_proxy_map);
|
||||||
|
udp_proxy.start().await
|
||||||
|
});
|
||||||
|
}
|
||||||
|
for ip in bind_ips {
|
||||||
|
let addr = SocketAddrV4::new(ip, 0);
|
||||||
|
let icmp_proxy_map = icmp_proxy_map.clone();
|
||||||
|
let icmp_proxy = IcmpProxy::new(addr, icmp_proxy_map, sender.try_clone()?, current_device.clone())?;
|
||||||
|
icmp_sockets.insert(ip, icmp_proxy.icmp_socket());
|
||||||
|
thread::spawn(move || {
|
||||||
|
icmp_proxy.start();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(IpProxyMap {
|
||||||
|
tcp_proxy_port,
|
||||||
|
udp_proxy_port,
|
||||||
|
tcp_proxy_map,
|
||||||
|
udp_proxy_map,
|
||||||
|
icmp_proxy_map,
|
||||||
|
icmp_sockets,
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -0,0 +1,70 @@
|
|||||||
|
use std::io;
|
||||||
|
use std::net::{SocketAddr, SocketAddrV4};
|
||||||
|
use std::sync::Arc;
|
||||||
|
use crossbeam_skiplist::SkipMap;
|
||||||
|
use tokio::net::{TcpListener, TcpStream};
|
||||||
|
|
||||||
|
pub struct TcpProxy {
|
||||||
|
tcp_listener: TcpListener,
|
||||||
|
// todo 怎么过期
|
||||||
|
map: Arc<SkipMap<SocketAddrV4, (SocketAddrV4, SocketAddrV4)>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TcpProxy {
|
||||||
|
pub fn new(tcp_listener: TcpListener, map: Arc<SkipMap<SocketAddrV4, (SocketAddrV4, SocketAddrV4)>>) -> Self {
|
||||||
|
Self {
|
||||||
|
tcp_listener,
|
||||||
|
map,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub async fn start(self) {
|
||||||
|
let tcp_listener = self.tcp_listener;
|
||||||
|
let map = self.map;
|
||||||
|
loop {
|
||||||
|
match tcp_listener.accept().await {
|
||||||
|
Ok((tcp_stream, sender_addr)) => {
|
||||||
|
match sender_addr {
|
||||||
|
SocketAddr::V4(sender_addr) => {
|
||||||
|
if let Some(entry) = map.get(&sender_addr) {
|
||||||
|
let (src_addr, dest_addr) = *entry.value();
|
||||||
|
let peer_tcp_stream = match TcpStream::connect(dest_addr).await {
|
||||||
|
Ok(peer_tcp_stream) => {peer_tcp_stream}
|
||||||
|
Err(e) => {
|
||||||
|
log::warn!("tcp代理异常:{:?},来源:{},目标:{}",e,src_addr,dest_addr);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
tokio::spawn(async move {
|
||||||
|
match proxy(tcp_stream, peer_tcp_stream).await {
|
||||||
|
Ok(_) => {}
|
||||||
|
Err(e) => {
|
||||||
|
log::warn!("tcp代理异常:{:?},来源:{},目标:{}",e,src_addr,dest_addr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SocketAddr::V6(_) => {}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
log::warn!("tcp代理监听:{:?}",e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn proxy(mut client: TcpStream, mut server: TcpStream) -> io::Result<()> {
|
||||||
|
let (mut client_reader, mut client_writer) = client.split();
|
||||||
|
let (mut server_reader, mut server_writer) = server.split();
|
||||||
|
|
||||||
|
let client_to_server = tokio::io::copy(&mut client_reader, &mut server_writer);
|
||||||
|
let server_to_client = tokio::io::copy(&mut server_reader, &mut client_writer);
|
||||||
|
|
||||||
|
tokio::try_join!(client_to_server, server_to_client)?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
@@ -0,0 +1,96 @@
|
|||||||
|
use std::io;
|
||||||
|
use std::net::{SocketAddr, SocketAddrV4};
|
||||||
|
use std::sync::Arc;
|
||||||
|
use std::time::Duration;
|
||||||
|
use crossbeam_skiplist::SkipMap;
|
||||||
|
use tokio::net::UdpSocket;
|
||||||
|
|
||||||
|
/// 一个udp代理,作用是利用系统协议栈,将udp数据报解析出来再转发到目的地址
|
||||||
|
pub struct UdpProxy {
|
||||||
|
udp_socket: Arc<UdpSocket>,
|
||||||
|
// todo 过期处理
|
||||||
|
map: Arc<SkipMap<SocketAddrV4, (SocketAddrV4, SocketAddrV4)>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl UdpProxy {
|
||||||
|
pub fn new(udp_socket: UdpSocket, map: Arc<SkipMap<SocketAddrV4, (SocketAddrV4, SocketAddrV4)>>) -> Self {
|
||||||
|
let udp_socket = Arc::new(udp_socket);
|
||||||
|
Self {
|
||||||
|
udp_socket,
|
||||||
|
map,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub async fn start(self) {
|
||||||
|
let map = self.map;
|
||||||
|
let udp_socket = self.udp_socket;
|
||||||
|
let mut buf = [0u8; 65536];
|
||||||
|
let inner_map: Arc<SkipMap<SocketAddrV4, Arc<UdpSocket>>> = Arc::new(SkipMap::new());
|
||||||
|
|
||||||
|
loop {
|
||||||
|
match udp_socket.recv_from(&mut buf).await {
|
||||||
|
Ok((len, sender_addr)) => {
|
||||||
|
match sender_addr {
|
||||||
|
SocketAddr::V4(sender_addr) => {
|
||||||
|
match start0(&buf[..len], sender_addr, &inner_map, &map, &udp_socket).await {
|
||||||
|
Ok(_) => {}
|
||||||
|
Err(e) => {
|
||||||
|
log::warn!("udp代理异常:{:?},来源:{}",e,sender_addr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SocketAddr::V6(_) => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
log::warn!("udp代理异常:{:?}",e);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn start0(buf: &[u8], sender_addr: SocketAddrV4, inner_map: &Arc<SkipMap<SocketAddrV4, Arc<UdpSocket>>>, map: &Arc<SkipMap<SocketAddrV4, (SocketAddrV4, SocketAddrV4)>>, udp_socket: &Arc<UdpSocket>) -> io::Result<()> {
|
||||||
|
if let Some(entry) = inner_map.get(&sender_addr) {
|
||||||
|
entry.value().send(buf).await?;
|
||||||
|
} else if let Some(entry) = map.get(&sender_addr) {
|
||||||
|
let (src_addr, dest_addr) = *entry.value();
|
||||||
|
let peer_udp_socket = UdpSocket::bind("0.0.0.0:0").await?;
|
||||||
|
peer_udp_socket.connect(dest_addr).await?;
|
||||||
|
peer_udp_socket.send(buf).await?;
|
||||||
|
let peer_udp_socket = Arc::new(peer_udp_socket);
|
||||||
|
let inner_map = inner_map.clone();
|
||||||
|
inner_map.insert(sender_addr, peer_udp_socket.clone());
|
||||||
|
let udp_socket = udp_socket.clone();
|
||||||
|
tokio::spawn(async move {
|
||||||
|
let mut buf = [0u8; 65536];
|
||||||
|
loop {
|
||||||
|
match tokio::time::timeout(Duration::from_secs(300), peer_udp_socket.recv(&mut buf)).await {
|
||||||
|
Ok(rs) => {
|
||||||
|
match rs {
|
||||||
|
Ok(len) => {
|
||||||
|
match udp_socket.send_to(&buf[..len], sender_addr).await {
|
||||||
|
Ok(_) => {}
|
||||||
|
Err(e) => {
|
||||||
|
log::warn!("udp代理异常:{:?},来源:{},目标:{}",e,src_addr,dest_addr);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
log::warn!("udp代理异常:{:?},来源:{},目标:{}",e,src_addr,dest_addr);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(_) => {
|
||||||
|
//超时关闭
|
||||||
|
log::warn!("udp代理超时关闭,来源:{},目标:{}",src_addr,dest_addr);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
inner_map.remove(&sender_addr);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
@@ -11,4 +11,6 @@ pub mod proto;
|
|||||||
pub mod protocol;
|
pub mod 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;
|
||||||
|
|||||||
@@ -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(())
|
||||||
|
}
|
||||||
|
|||||||
@@ -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(())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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网卡配置========");
|
||||||
|
|||||||
Reference in New Issue
Block a user