shadowsocks_service/local/redir/
server.rs

1//! Shadowsocks Transparent Proxy Local Server
2
3use std::{io, sync::Arc, time::Duration};
4
5use futures::{FutureExt, future};
6use shadowsocks::{ServerAddr, config::Mode};
7
8use crate::{
9    config::RedirType,
10    local::{context::ServiceContext, loadbalancing::PingBalancer},
11};
12
13use super::{tcprelay::RedirTcpServer, udprelay::RedirUdpServer};
14
15/// Transparent Proxy builder
16pub struct RedirBuilder {
17    context: Arc<ServiceContext>,
18    mode: Mode,
19    udp_expiry_duration: Option<Duration>,
20    udp_capacity: Option<usize>,
21    tcp_redir: RedirType,
22    udp_redir: RedirType,
23    client_addr: ServerAddr,
24    udp_bind_addr: Option<ServerAddr>,
25    balancer: PingBalancer,
26}
27
28impl RedirBuilder {
29    /// Create a new transparent proxy server with default configuration
30    pub fn new(client_addr: ServerAddr, balancer: PingBalancer) -> Self {
31        let context = ServiceContext::new();
32        Self::with_context(Arc::new(context), client_addr, balancer)
33    }
34
35    /// Create a new transparent proxy server with context
36    pub fn with_context(context: Arc<ServiceContext>, client_addr: ServerAddr, balancer: PingBalancer) -> Self {
37        Self {
38            context,
39            mode: Mode::TcpOnly,
40            udp_expiry_duration: None,
41            udp_capacity: None,
42            tcp_redir: RedirType::tcp_default(),
43            udp_redir: RedirType::udp_default(),
44            client_addr,
45            udp_bind_addr: None,
46            balancer,
47        }
48    }
49
50    /// Set UDP association's expiry duration
51    pub fn set_udp_expiry_duration(&mut self, d: Duration) {
52        self.udp_expiry_duration = Some(d);
53    }
54
55    /// Set total UDP association to be kept simultaneously in server
56    pub fn set_udp_capacity(&mut self, c: usize) {
57        self.udp_capacity = Some(c);
58    }
59
60    /// Set server mode
61    pub fn set_mode(&mut self, mode: Mode) {
62        self.mode = mode;
63    }
64
65    /// Set transparent proxy type of TCP relay, which is platform dependent
66    pub fn set_tcp_redir(&mut self, ty: RedirType) {
67        self.tcp_redir = ty;
68    }
69
70    /// Set transparent proxy type of UDP relay, which is platform dependent
71    pub fn set_udp_redir(&mut self, ty: RedirType) {
72        self.udp_redir = ty;
73    }
74
75    /// Set UDP bind address
76    pub fn set_udp_bind_addr(&mut self, addr: ServerAddr) {
77        self.udp_bind_addr = Some(addr);
78    }
79
80    pub async fn build(self) -> io::Result<Redir> {
81        let mut tcp_server = None;
82        if self.mode.enable_tcp() {
83            let server = RedirTcpServer::new(
84                self.context.clone(),
85                &self.client_addr,
86                self.balancer.clone(),
87                self.tcp_redir,
88            )
89            .await?;
90            tcp_server = Some(server);
91        }
92
93        let mut udp_server = None;
94        if self.mode.enable_udp() {
95            let udp_addr = self.udp_bind_addr.as_ref().unwrap_or(&self.client_addr);
96
97            let server = RedirUdpServer::new(
98                self.context,
99                self.udp_redir,
100                udp_addr,
101                self.udp_expiry_duration,
102                self.udp_capacity,
103                self.balancer,
104            )
105            .await?;
106            udp_server = Some(server);
107        }
108
109        Ok(Redir { tcp_server, udp_server })
110    }
111}
112
113/// Transparent Proxy
114pub struct Redir {
115    tcp_server: Option<RedirTcpServer>,
116    udp_server: Option<RedirUdpServer>,
117}
118
119impl Redir {
120    /// TCP server instance
121    pub fn tcp_server(&self) -> Option<&RedirTcpServer> {
122        self.tcp_server.as_ref()
123    }
124
125    /// UDP server instance
126    pub fn udp_server(&self) -> Option<&RedirUdpServer> {
127        self.udp_server.as_ref()
128    }
129
130    /// Start serving
131    pub async fn run(self) -> io::Result<()> {
132        let mut vfut = Vec::new();
133
134        if let Some(tcp_server) = self.tcp_server {
135            vfut.push(tcp_server.run().boxed());
136        }
137
138        if let Some(udp_server) = self.udp_server {
139            vfut.push(udp_server.run().boxed());
140        }
141
142        let (res, ..) = future::select_all(vfut).await;
143        res
144    }
145}