port forward (#736)

* support tcp port forward
* support udp port forward
* command line option for port forward
This commit is contained in:
Sijie.Sun
2025-04-01 09:59:53 +08:00
committed by GitHub
parent 8dc8c7d9e2
commit c142db301a
19 changed files with 955 additions and 143 deletions
+86 -17
View File
@@ -7,7 +7,10 @@ use std::{
use anyhow::Context;
use serde::{Deserialize, Serialize};
use crate::{proto::common::CompressionAlgoPb, tunnel::generate_digest_from_str};
use crate::{
proto::common::{CompressionAlgoPb, PortForwardConfigPb, SocketType},
tunnel::generate_digest_from_str,
};
pub type Flags = crate::proto::common::FlagsInConfig;
@@ -97,6 +100,9 @@ pub trait ConfigLoader: Send + Sync {
fn get_socks5_portal(&self) -> Option<url::Url>;
fn set_socks5_portal(&self, addr: Option<url::Url>);
fn get_port_forwards(&self) -> Vec<PortForwardConfig>;
fn set_port_forwards(&self, forwards: Vec<PortForwardConfig>);
fn dump(&self) -> String;
}
@@ -180,6 +186,41 @@ pub struct VpnPortalConfig {
pub wireguard_listen: SocketAddr,
}
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq)]
pub struct PortForwardConfig {
pub bind_addr: SocketAddr,
pub dst_addr: SocketAddr,
pub proto: String,
}
impl From<PortForwardConfigPb> for PortForwardConfig {
fn from(config: PortForwardConfigPb) -> Self {
PortForwardConfig {
bind_addr: config.bind_addr.unwrap_or_default().into(),
dst_addr: config.dst_addr.unwrap_or_default().into(),
proto: match SocketType::try_from(config.socket_type) {
Ok(SocketType::Tcp) => "tcp".to_string(),
Ok(SocketType::Udp) => "udp".to_string(),
_ => "tcp".to_string(),
},
}
}
}
impl Into<PortForwardConfigPb> for PortForwardConfig {
fn into(self) -> PortForwardConfigPb {
PortForwardConfigPb {
bind_addr: Some(self.bind_addr.into()),
dst_addr: Some(self.dst_addr.into()),
socket_type: match self.proto.to_lowercase().as_str() {
"tcp" => SocketType::Tcp as i32,
"udp" => SocketType::Udp as i32,
_ => SocketType::Tcp as i32,
},
}
}
}
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq)]
struct Config {
netns: Option<String>,
@@ -207,6 +248,8 @@ struct Config {
socks5_proxy: Option<url::Url>,
port_forward: Option<Vec<PortForwardConfig>>,
flags: Option<serde_json::Map<String, serde_json::Value>>,
#[serde(skip)]
@@ -534,6 +577,35 @@ impl ConfigLoader for TomlConfigLoader {
self.config.lock().unwrap().exit_nodes = Some(nodes);
}
fn get_routes(&self) -> Option<Vec<cidr::Ipv4Cidr>> {
self.config.lock().unwrap().routes.clone()
}
fn set_routes(&self, routes: Option<Vec<cidr::Ipv4Cidr>>) {
self.config.lock().unwrap().routes = routes;
}
fn get_socks5_portal(&self) -> Option<url::Url> {
self.config.lock().unwrap().socks5_proxy.clone()
}
fn set_socks5_portal(&self, addr: Option<url::Url>) {
self.config.lock().unwrap().socks5_proxy = addr;
}
fn get_port_forwards(&self) -> Vec<PortForwardConfig> {
self.config
.lock()
.unwrap()
.port_forward
.clone()
.unwrap_or_default()
}
fn set_port_forwards(&self, forwards: Vec<PortForwardConfig>) {
self.config.lock().unwrap().port_forward = Some(forwards);
}
fn dump(&self) -> String {
let default_flags_json = serde_json::to_string(&gen_default_flags()).unwrap();
let default_flags_hashmap =
@@ -558,22 +630,6 @@ impl ConfigLoader for TomlConfigLoader {
config.flags = Some(flag_map);
toml::to_string_pretty(&config).unwrap()
}
fn get_routes(&self) -> Option<Vec<cidr::Ipv4Cidr>> {
self.config.lock().unwrap().routes.clone()
}
fn set_routes(&self, routes: Option<Vec<cidr::Ipv4Cidr>>) {
self.config.lock().unwrap().routes = routes;
}
fn get_socks5_portal(&self) -> Option<url::Url> {
self.config.lock().unwrap().socks5_proxy.clone()
}
fn set_socks5_portal(&self, addr: Option<url::Url>) {
self.config.lock().unwrap().socks5_proxy = addr;
}
}
#[cfg(test)]
@@ -614,6 +670,11 @@ dir = "/tmp/easytier"
[console_logger]
level = "warn"
[[port_forward]]
bind_addr = "0.0.0.0:11011"
dst_addr = "192.168.94.33:11011"
proto = "tcp"
"#;
let ret = TomlConfigLoader::new_from_str(config_str);
if let Err(e) = &ret {
@@ -634,6 +695,14 @@ level = "warn"
.collect::<Vec<String>>()
);
assert_eq!(
vec![PortForwardConfig {
bind_addr: "0.0.0.0:11011".parse().unwrap(),
dst_addr: "192.168.94.33:11011".parse().unwrap(),
proto: "tcp".to_string(),
}],
ret.get_port_forwards()
);
println!("{}", ret.dump());
}
}