@@ -10,6 +10,7 @@ use std::{
10
10
} ,
11
11
} ;
12
12
13
+ use cfg_if:: cfg_if;
13
14
use futures:: future:: { self , Either } ;
14
15
use log:: { debug, error, info, trace} ;
15
16
use tokio:: net:: { TcpListener , TcpStream } ;
@@ -23,78 +24,79 @@ use crate::{
23
24
} ,
24
25
} ;
25
26
26
- #[ cfg( not( target_os = "linux" ) ) ]
27
- pub fn get_original_destination_addr ( _: & mut TcpStream ) -> io:: Result < SocketAddr > {
28
- unimplemented ! ( "Transparent Proxy (redir) doesn't work on this platform" ) ;
29
- }
30
-
31
- #[ cfg( target_os = "linux" ) ]
32
- pub fn get_original_destination_addr ( s : & mut TcpStream ) -> io:: Result < SocketAddr > {
33
- use std:: {
34
- io:: Error ,
35
- mem,
36
- net:: { SocketAddrV4 , SocketAddrV6 } ,
37
- os:: unix:: io:: AsRawFd ,
38
- } ;
39
-
40
- let fd = s. as_raw_fd ( ) ;
41
-
42
- unsafe {
43
- let mut target_addr: libc:: sockaddr_storage = mem:: zeroed ( ) ;
44
- let mut target_addr_len = mem:: size_of_val ( & target_addr) as libc:: socklen_t ;
45
-
46
- // Check if it is IPv6 address
47
- let ret = libc:: getsockopt (
48
- fd,
49
- libc:: SOL_IPV6 ,
50
- libc:: SO_ORIGINAL_DST , // FIXME: Should use IP6T_SO_ORIGINAL_DST
51
- & mut target_addr as * mut _ as * mut _ ,
52
- & mut target_addr_len,
53
- ) ;
54
-
55
- if ret != 0 {
56
- let err = Error :: last_os_error ( ) ;
57
- match err. raw_os_error ( ) {
58
- Some ( libc:: ENOPROTOOPT ) | Some ( libc:: EOPNOTSUPP ) => {
59
- // The option is unknown at the level indicated.
60
- //
61
- // - The current system doesn't support IPv6 netfilter
62
- // - This is not an IPv6 connection
63
- //
64
- // Continue with IPv4
27
+ cfg_if ! {
28
+ if #[ cfg( any( target_os = "linux" , target_os = "android" ) ) ] {
29
+ fn get_original_destination_addr( s: & mut TcpStream ) -> io:: Result <SocketAddr > {
30
+ use std:: {
31
+ io:: Error ,
32
+ mem,
33
+ net:: { SocketAddrV4 , SocketAddrV6 } ,
34
+ os:: unix:: io:: AsRawFd ,
35
+ } ;
36
+ let fd = s. as_raw_fd( ) ;
37
+ unsafe {
38
+ let mut target_addr: libc:: sockaddr_storage = mem:: zeroed( ) ;
39
+ let mut target_addr_len = mem:: size_of_val( & target_addr) as libc:: socklen_t;
40
+ // Check if it is IPv6 address
41
+ let ret = libc:: getsockopt(
42
+ fd,
43
+ libc:: SOL_IPV6 ,
44
+ libc:: SO_ORIGINAL_DST , // FIXME: Should use IP6T_SO_ORIGINAL_DST
45
+ & mut target_addr as * mut _ as * mut _,
46
+ & mut target_addr_len,
47
+ ) ;
48
+ if ret != 0 {
49
+ let err = Error :: last_os_error( ) ;
50
+ match err. raw_os_error( ) {
51
+ Some ( libc:: ENOPROTOOPT ) | Some ( libc:: EOPNOTSUPP ) => {
52
+ // The option is unknown at the level indicated.
53
+ //
54
+ // - The current system doesn't support IPv6 netfilter
55
+ // - This is not an IPv6 connection
56
+ //
57
+ // Continue with IPv4
58
+ }
59
+ _ => {
60
+ return Err ( err) ;
61
+ }
62
+ }
63
+ let ret = libc:: getsockopt(
64
+ fd,
65
+ libc:: SOL_IP ,
66
+ libc:: SO_ORIGINAL_DST ,
67
+ & mut target_addr as * mut _ as * mut _,
68
+ & mut target_addr_len,
69
+ ) ;
70
+ if ret != 0 {
71
+ return Err ( Error :: last_os_error( ) ) ;
72
+ }
65
73
}
66
- _ => {
67
- return Err ( err) ;
74
+ // Convert sockaddr_storage to SocketAddr
75
+ match target_addr. ss_family as libc:: c_int {
76
+ libc:: AF_INET => {
77
+ let addr: SocketAddrV4 = mem:: transmute_copy( & target_addr) ;
78
+ Ok ( SocketAddr :: V4 ( addr) )
79
+ }
80
+ libc:: AF_INET6 => {
81
+ let addr: SocketAddrV6 = mem:: transmute_copy( & target_addr) ;
82
+ Ok ( SocketAddr :: V6 ( addr) )
83
+ }
84
+ _ => {
85
+ let err = Error :: new( ErrorKind :: InvalidData , "family must be either AF_INET or AF_INET6" ) ;
86
+ return Err ( err) ;
87
+ }
68
88
}
69
89
}
70
-
71
- let ret = libc:: getsockopt (
72
- fd,
73
- libc:: SOL_IP ,
74
- libc:: SO_ORIGINAL_DST ,
75
- & mut target_addr as * mut _ as * mut _ ,
76
- & mut target_addr_len,
77
- ) ;
78
-
79
- if ret != 0 {
80
- return Err ( Error :: last_os_error ( ) ) ;
81
- }
82
90
}
83
-
84
- // Convert sockaddr_storage to SocketAddr
85
- match target_addr. ss_family as libc:: c_int {
86
- libc:: AF_INET => {
87
- let addr: SocketAddrV4 = mem:: transmute_copy ( & target_addr) ;
88
- Ok ( SocketAddr :: V4 ( addr) )
89
- }
90
- libc:: AF_INET6 => {
91
- let addr: SocketAddrV6 = mem:: transmute_copy ( & target_addr) ;
92
- Ok ( SocketAddr :: V6 ( addr) )
93
- }
94
- _ => {
95
- let err = Error :: new ( ErrorKind :: InvalidData , "family must be either AF_INET or AF_INET6" ) ;
96
- return Err ( err) ;
97
- }
91
+ } else if #[ cfg( any( target_os = "macos" , target_os = "freebsd" , target_os = "openbsd" ) ) ] {
92
+ fn get_original_destination_addr( s: & mut TcpStream ) -> io:: Result <SocketAddr > {
93
+ // On FreeBSD, Mac OS X, OpenBSD, ... use fwd action in IPFW or PF
94
+ // Retrieve original destination address with getsockname()
95
+ s. local_addr( )
96
+ }
97
+ } else {
98
+ fn get_original_destination_addr( _: & mut TcpStream ) -> io:: Result <SocketAddr > {
99
+ unimplemented!( "Transparent Proxy (redir) doesn't work on this platform" ) ;
98
100
}
99
101
}
100
102
}
@@ -239,10 +241,6 @@ impl PingServer for ServerScore {
239
241
}
240
242
241
243
pub async fn run ( context : SharedContext ) -> io:: Result < ( ) > {
242
- if cfg ! ( not( target_os = "linux" ) ) {
243
- unimplemented ! ( "Transparent Proxy (redir) doesn't work on this platform" ) ;
244
- }
245
-
246
244
assert ! (
247
245
context. config( ) . mode. enable_tcp( ) ,
248
246
"You must enable TCP relay for transparent proxy"
0 commit comments