2
2
#[ macro_use]
3
3
extern crate log;
4
4
5
+ use std:: net:: { IpAddr , Ipv4Addr , Ipv6Addr , SocketAddr } ;
6
+
5
7
use fast_socks5:: { client:: Socks5Datagram , Result } ;
6
8
use structopt:: StructOpt ;
7
9
use tokio:: {
@@ -28,7 +30,7 @@ use tokio::{
28
30
struct Opt {
29
31
/// Socks5 server address + port, e.g. `127.0.0.1:1080`
30
32
#[ structopt( short, long) ]
31
- pub socks_server : String ,
33
+ pub socks_server : SocketAddr ,
32
34
33
35
/// Target (DNS) server address, e.g. `8.8.8.8`
34
36
#[ structopt( short = "a" , long) ]
@@ -60,18 +62,25 @@ async fn spawn_socks_client() -> Result<()> {
60
62
61
63
// Creating a SOCKS stream to the target address through the socks server
62
64
let backing_socket = TcpStream :: connect ( opt. socks_server ) . await ?;
65
+ // At least on some platforms it is important to use the same protocol as the server
66
+ // XXX: assumes the returned UDP proxy will have the same protocol as the socks_server
67
+ let client_bind_addr = if opt. socks_server . is_ipv4 ( ) {
68
+ SocketAddr :: new ( IpAddr :: V4 ( Ipv4Addr :: UNSPECIFIED ) , 0 )
69
+ } else {
70
+ SocketAddr :: new ( IpAddr :: V6 ( Ipv6Addr :: UNSPECIFIED ) , 0 )
71
+ } ;
63
72
let mut socks = match opt. username {
64
73
Some ( username) => {
65
74
Socks5Datagram :: bind_with_password (
66
75
backing_socket,
67
- "[::]:0" ,
76
+ client_bind_addr ,
68
77
& username,
69
78
& opt. password . expect ( "Please fill the password" ) ,
70
79
)
71
80
. await ?
72
81
}
73
82
74
- _ => Socks5Datagram :: bind ( backing_socket, "[::]:0" ) . await ?,
83
+ _ => Socks5Datagram :: bind ( backing_socket, client_bind_addr ) . await ?,
75
84
} ;
76
85
77
86
// Once socket creation is completed, can start to communicate with the server
0 commit comments