From f3c5a5400b8678deeb9003a1f2b616146aa40638 Mon Sep 17 00:00:00 2001 From: hanwei Date: Tue, 19 Mar 2024 10:55:20 +0800 Subject: [PATCH] feature: support fwmark in server side to split outbound tunnel --- crates/shadowsocks-service/src/config.rs | 25 ++++++++++++++++++- .../shadowsocks-service/src/manager/server.rs | 2 ++ crates/shadowsocks-service/src/server/mod.rs | 5 ++++ 3 files changed, 31 insertions(+), 1 deletion(-) diff --git a/crates/shadowsocks-service/src/config.rs b/crates/shadowsocks-service/src/config.rs index c02c2f0cb0bb..faf85c17befe 100644 --- a/crates/shadowsocks-service/src/config.rs +++ b/crates/shadowsocks-service/src/config.rs @@ -365,6 +365,10 @@ struct SSServerExtConfig { #[serde(skip_serializing_if = "Option::is_none")] acl: Option, + + #[serde(skip_serializing_if = "Option::is_none")] + #[cfg(any(target_os = "linux", target_os = "android"))] + outbound_fwmark: Option, } /// Server config type @@ -1119,12 +1123,20 @@ pub struct ServerInstanceConfig { pub config: ServerConfig, /// Server's private ACL, set to `None` will use the global `AccessControl` pub acl: Option, + /// Server's outbound fwmark to support split tunnel + #[cfg(any(target_os = "linux", target_os = "android"))] + pub outbound_fwmark: Option, } impl ServerInstanceConfig { /// Create with `ServerConfig` pub fn with_server_config(config: ServerConfig) -> ServerInstanceConfig { - ServerInstanceConfig { config, acl: None } + ServerInstanceConfig { + config, + acl: None, + #[cfg(any(target_os = "linux", target_os = "android"))] + outbound_fwmark: None, + } } } @@ -1762,6 +1774,8 @@ impl Config { let server_instance = ServerInstanceConfig { config: nsvr, acl: None, + #[cfg(any(target_os = "linux", target_os = "android"))] + outbound_fwmark: config.outbound_fwmark, }; nconfig.server.push(server_instance); @@ -1928,6 +1942,8 @@ impl Config { let mut server_instance = ServerInstanceConfig { config: nsvr, acl: None, + #[cfg(any(target_os = "linux", target_os = "android"))] + outbound_fwmark: config.outbound_fwmark, }; if let Some(acl_path) = svr.acl { @@ -1945,6 +1961,11 @@ impl Config { server_instance.acl = Some(acl); } + #[cfg(any(target_os = "linux", target_os = "android"))] + if let Some(outbound_fwmark) = svr.outbound_fwmark { + server_instance.outbound_fwmark = Some(outbound_fwmark); + } + nconfig.server.push(server_instance); } } @@ -2699,6 +2720,8 @@ impl fmt::Display for Config { .acl .as_ref() .and_then(|a| a.file_path().to_str().map(ToOwned::to_owned)), + #[cfg(any(target_os = "linux", target_os = "android"))] + outbound_fwmark: inst.outbound_fwmark.clone(), }); } diff --git a/crates/shadowsocks-service/src/manager/server.rs b/crates/shadowsocks-service/src/manager/server.rs index 6b16035db02e..acce92e9df63 100644 --- a/crates/shadowsocks-service/src/manager/server.rs +++ b/crates/shadowsocks-service/src/manager/server.rs @@ -408,6 +408,8 @@ impl Manager { let server_instance = ServerInstanceConfig { config: svr_cfg.clone(), acl: None, // Set with --acl command line argument + #[cfg(any(target_os = "linux", target_os = "android"))] + outbound_fwmark: None, }; let mut config = Config::new(ConfigType::Server); diff --git a/crates/shadowsocks-service/src/server/mod.rs b/crates/shadowsocks-service/src/server/mod.rs index 9910b5b26292..34f26c718e88 100644 --- a/crates/shadowsocks-service/src/server/mod.rs +++ b/crates/shadowsocks-service/src/server/mod.rs @@ -111,6 +111,11 @@ pub async fn run(config: Config) -> io::Result<()> { server_builder.set_dns_resolver(r.clone()); } + #[cfg(any(target_os = "linux", target_os = "android"))] + if let Some(fwmark) = inst.outbound_fwmark { + connect_opts.fwmark = Some(fwmark); + } + server_builder.set_connect_opts(connect_opts.clone()); server_builder.set_accept_opts(accept_opts.clone());