@@ -5,6 +5,8 @@ use tun::AbstractDevice;
55use crate :: codec:: frame:: { HandshakeReplyFrame , PeerDetail } ;
66use crate :: utils:: sys_route:: SysRoute ;
77use std:: collections:: HashSet ;
8+ #[ allow( unused_imports) ]
9+ use crate :: utils:: sys_route:: { ip_to_network, mask_to_prefix_length} ;
810
911const DEFAULT_MTU : u16 = 1430 ;
1012
@@ -41,7 +43,7 @@ impl Device {
4143 }
4244 }
4345
44- pub async fn run ( & mut self , ready : oneshot:: Sender < Option < i32 > > ) -> crate :: Result < ( ) > {
46+ pub async fn run ( & mut self , ready : oneshot:: Sender < Option < i32 > > , name : oneshot :: Sender < Option < String > > ) -> crate :: Result < ( ) > {
4547 let mut config = tun:: Configuration :: default ( ) ;
4648 config
4749 . address ( self . ip . clone ( ) )
@@ -69,6 +71,16 @@ impl Device {
6971 #[ cfg( not( target_os = "windows" ) ) ]
7072 let tun_index: Option < i32 > = None ;
7173
74+ // Get interface name (Linux only, for MASQUERADE)
75+ #[ cfg( target_os = "linux" ) ]
76+ {
77+ let interface_name = dev. tun_name ( ) . ok ( ) ;
78+ let _ = name. send ( interface_name) ;
79+ }
80+
81+ #[ cfg( not( target_os = "linux" ) ) ]
82+ let _ = name. send ( None ) ;
83+
7284 let _ = ready. send ( tun_index) ;
7385 let mut buf = vec ! [ 0 ; 2048 ] ;
7486 loop {
@@ -102,7 +114,10 @@ impl Device {
102114pub struct DeviceHandler {
103115 peer_details : Vec < PeerDetail > ,
104116 private_ip : String ,
117+ mask : String ,
118+ local_ciders : Vec < String > ,
105119 tun_index : Option < i32 > ,
120+ interface_name : Option < String > ,
106121 inbound_rx : Option < mpsc:: Receiver < Vec < u8 > > > ,
107122 outbound_tx : Option < mpsc:: Sender < Vec < u8 > > > ,
108123 pub rx_bytes : usize ,
@@ -114,28 +129,34 @@ impl DeviceHandler {
114129 Self {
115130 peer_details : vec ! [ ] ,
116131 private_ip : String :: new ( ) ,
132+ mask : String :: new ( ) ,
133+ local_ciders : vec ! [ ] ,
117134 tun_index : None ,
135+ interface_name : None ,
118136 inbound_rx : None ,
119137 outbound_tx : None ,
120138 rx_bytes : 0 ,
121139 tx_bytes : 0 ,
122140 }
123141 }
124142
125- pub async fn run ( & mut self , cfg : & HandshakeReplyFrame ) -> crate :: Result < Option < i32 > > {
143+ pub async fn run ( & mut self , cfg : & HandshakeReplyFrame , enable_masq : bool ) -> crate :: Result < Option < i32 > > {
126144 let ( inbound_tx, inbound_rx) = mpsc:: channel ( 1000 ) ;
127145 let ( outbound_tx, outbound_rx) = mpsc:: channel ( 1000 ) ;
128146 self . inbound_rx = Some ( inbound_rx) ;
129147 self . outbound_tx = Some ( outbound_tx) ;
130148 self . private_ip = cfg. private_ip . clone ( ) ;
149+ self . mask = cfg. mask . clone ( ) ;
150+ self . local_ciders = cfg. ciders . clone ( ) ;
131151
132152 let mut dev = Device :: new ( cfg. private_ip . clone ( ) ,
133153 cfg. mask . clone ( ) ,
134154 DEFAULT_MTU ,
135155 inbound_tx, outbound_rx) ;
136156 let ( ready_tx, ready_rx) = oneshot:: channel ( ) ;
157+ let ( name_tx, name_rx) = oneshot:: channel ( ) ;
137158 tokio:: spawn ( async move {
138- let res = dev. run ( ready_tx) . await ;
159+ let res = dev. run ( ready_tx, name_tx ) . await ;
139160 match res {
140161 Ok ( _) => ( ) ,
141162 Err ( e) => tracing:: error!( "device handler fail: {:?}" , e) ,
@@ -144,6 +165,21 @@ impl DeviceHandler {
144165
145166 let tun_index = ready_rx. await . unwrap_or ( None ) ;
146167 self . tun_index = tun_index;
168+
169+ if let Ok ( Some ( name) ) = name_rx. await {
170+ self . interface_name = Some ( name) ;
171+ }
172+
173+
174+ if enable_masq {
175+ if let Err ( e) = self . enable_masquerade ( ) {
176+ tracing:: error!( "Failed to enable MASQUERADE: {:?}" , e) ;
177+ }
178+ if let Err ( e) = self . enable_snat ( ) {
179+ tracing:: warn!( "Failed to enable SNAT: {:?}" , e) ;
180+ }
181+ }
182+
147183 Ok ( tun_index)
148184 }
149185
@@ -227,9 +263,58 @@ impl DeviceHandler {
227263
228264 // Update stored routes
229265 self . peer_details = new_routes;
230-
266+
231267 tracing:: info!( "Route reload complete" ) ;
232268 }
269+
270+ /// Enable MASQUERADE (NAT) for VPN interface (Linux only)
271+ /// Uses source network address instead of interface name for better reliability
272+ pub fn enable_masquerade ( & mut self ) -> crate :: Result < ( ) > {
273+ let cidr = self . ip_mask_to_cidr ( & self . private_ip , & self . mask ) ?;
274+
275+ let sys_route = SysRoute :: new ( ) ;
276+ sys_route. enable_masquerade_by_source ( & cidr) ?;
277+ Ok ( ( ) )
278+ }
279+
280+ /// Disable MASQUERADE (NAT) for VPN interface (Linux only)
281+ pub fn disable_masquerade ( & mut self ) -> crate :: Result < ( ) > {
282+ let cidr = self . ip_mask_to_cidr ( & self . private_ip , & self . mask ) ?;
283+
284+ let sys_route = SysRoute :: new ( ) ;
285+ sys_route. disable_masquerade_by_source ( & cidr) ?;
286+ Ok ( ( ) )
287+ }
288+
289+ /// Convert IP address and subnet mask to CIDR notation
290+ fn ip_mask_to_cidr ( & self , ip : & str , mask : & str ) -> crate :: Result < String > {
291+ // Parse subnet mask to prefix length
292+ let prefix_len = mask_to_prefix_length ( mask) ?;
293+ let network = ip_to_network ( ip, mask) ?;
294+ Ok ( format ! ( "{}/{}" , network, prefix_len) )
295+ }
296+
297+ /// Enable SNAT for local network segments to use virtual IP (Linux only)
298+ /// This makes packets from local ciders appear as coming from virtual IP
299+ pub fn enable_snat ( & mut self ) -> crate :: Result < ( ) > {
300+ let sys_route = SysRoute :: new ( ) ;
301+
302+ for cidr in & self . local_ciders {
303+ sys_route. enable_snat_for_local_network ( cidr, "" , & self . private_ip ) ?;
304+ tracing:: info!( "Enabled SNAT for local network {} -> {}" , cidr, self . private_ip) ;
305+ }
306+ Ok ( ( ) )
307+ }
308+
309+ /// Disable SNAT for local network segments (Linux only)
310+ pub fn disable_snat ( & mut self ) -> crate :: Result < ( ) > {
311+ let sys_route = SysRoute :: new ( ) ;
312+
313+ for cidr in & self . local_ciders {
314+ sys_route. disable_snat_for_local_network ( cidr, "" , & self . private_ip ) ?;
315+ }
316+ Ok ( ( ) )
317+ }
233318}
234319
235320impl Default for DeviceHandler {
0 commit comments