SOCKS5: If host is domain use proxy for DNS.
This commit is contained in:
@@ -8,6 +8,8 @@ use std::time::Duration;
|
|||||||
use rustls::ClientSession;
|
use rustls::ClientSession;
|
||||||
#[cfg(feature = "tls")]
|
#[cfg(feature = "tls")]
|
||||||
use rustls::StreamOwned;
|
use rustls::StreamOwned;
|
||||||
|
#[cfg(feature = "socks-proxy")]
|
||||||
|
use socks::{TargetAddr, ToTargetAddr};
|
||||||
|
|
||||||
use crate::proxy::Proto;
|
use crate::proxy::Proto;
|
||||||
use crate::proxy::Proxy;
|
use crate::proxy::Proxy;
|
||||||
@@ -199,7 +201,7 @@ pub(crate) fn connect_host(unit: &Unit, hostname: &str, port: u16) -> Result<Tcp
|
|||||||
unit.proxy.to_owned().unwrap(),
|
unit.proxy.to_owned().unwrap(),
|
||||||
unit.timeout_connect,
|
unit.timeout_connect,
|
||||||
sock_addr,
|
sock_addr,
|
||||||
hostname.to_string(),
|
hostname,
|
||||||
port,
|
port,
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
@@ -255,25 +257,51 @@ pub(crate) fn connect_host(unit: &Unit, hostname: &str, port: u16) -> Result<Tcp
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "socks-proxy")]
|
#[cfg(feature = "socks-proxy")]
|
||||||
fn connect_socks5(
|
fn socks5_local_nslookup(hostname: &str, port: u16) -> Result<TargetAddr, std::io::Error> {
|
||||||
proxy: Proxy,
|
let addrs: Vec<SocketAddr> = format!("{}:{}", hostname, port)
|
||||||
timeout_connect: u64,
|
|
||||||
proxy_addr: SocketAddr,
|
|
||||||
hostname: String,
|
|
||||||
port: u16,
|
|
||||||
) -> Result<TcpStream, std::io::Error> {
|
|
||||||
let host_addrs: Vec<SocketAddr> = format!("{}:{}", hostname, port)
|
|
||||||
.to_socket_addrs()
|
.to_socket_addrs()
|
||||||
.map_err(|e| std::io::Error::new(ErrorKind::NotFound, format!("DNS failure: {}.", e)))?
|
.map_err(|e| std::io::Error::new(ErrorKind::NotFound, format!("DNS failure: {}.", e)))?
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
if host_addrs.is_empty() {
|
if addrs.is_empty() {
|
||||||
return Err(std::io::Error::new(
|
return Err(std::io::Error::new(
|
||||||
ErrorKind::NotFound,
|
ErrorKind::NotFound,
|
||||||
format!("DNS lookup failed for {}:{}.", hostname, port),
|
"DNS failure: no socket addrs found.",
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
match addrs[0].to_target_addr() {
|
||||||
|
Ok(addr) => Ok(addr),
|
||||||
|
Err(err) => {
|
||||||
|
return Err(std::io::Error::new(
|
||||||
|
ErrorKind::NotFound,
|
||||||
|
format!("DNS failure: {}.", err),
|
||||||
|
))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "socks-proxy")]
|
||||||
|
fn connect_socks5(
|
||||||
|
proxy: Proxy,
|
||||||
|
timeout_connect: u64,
|
||||||
|
proxy_addr: SocketAddr,
|
||||||
|
host: &str,
|
||||||
|
port: u16,
|
||||||
|
) -> Result<TcpStream, std::io::Error> {
|
||||||
|
use socks::TargetAddr::Domain;
|
||||||
|
use std::net::{Ipv4Addr, Ipv6Addr};
|
||||||
|
use std::str::FromStr;
|
||||||
|
|
||||||
|
let host_addr = if Ipv4Addr::from_str(host).is_ok() || Ipv6Addr::from_str(host).is_ok() {
|
||||||
|
match socks5_local_nslookup(host, port) {
|
||||||
|
Ok(addr) => addr,
|
||||||
|
Err(err) => return Err(err),
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Domain(String::from(host), port)
|
||||||
|
};
|
||||||
|
|
||||||
// Since Socks5Stream doesn't support set_read_timeout, a suboptimal one is implemented via
|
// Since Socks5Stream doesn't support set_read_timeout, a suboptimal one is implemented via
|
||||||
// thread::spawn.
|
// thread::spawn.
|
||||||
// # Happy Path
|
// # Happy Path
|
||||||
@@ -294,11 +322,10 @@ fn connect_socks5(
|
|||||||
let master_signal = Arc::new((Mutex::new(false), Condvar::new()));
|
let master_signal = Arc::new((Mutex::new(false), Condvar::new()));
|
||||||
let slave_signal = master_signal.clone();
|
let slave_signal = master_signal.clone();
|
||||||
let (tx, rx) = channel();
|
let (tx, rx) = channel();
|
||||||
let host_addr = host_addrs[0];
|
|
||||||
thread::spawn(move || {
|
thread::spawn(move || {
|
||||||
let (lock, cvar) = &*slave_signal;
|
let (lock, cvar) = &*slave_signal;
|
||||||
if tx // try to get a socks5 stream and send it to the parent thread's rx
|
if tx // try to get a socks5 stream and send it to the parent thread's rx
|
||||||
.send(get_socks5_stream(&proxy, &proxy_addr, &host_addr))
|
.send(get_socks5_stream(&proxy, &proxy_addr, host_addr))
|
||||||
.is_ok()
|
.is_ok()
|
||||||
{
|
{
|
||||||
// if sending the stream has succeeded we need to notify the parent thread
|
// if sending the stream has succeeded we need to notify the parent thread
|
||||||
@@ -324,12 +351,12 @@ fn connect_socks5(
|
|||||||
ErrorKind::TimedOut,
|
ErrorKind::TimedOut,
|
||||||
format!(
|
format!(
|
||||||
"SOCKS5 proxy: {}:{} timed out connecting after {}ms.",
|
"SOCKS5 proxy: {}:{} timed out connecting after {}ms.",
|
||||||
hostname, port, timeout_connect
|
host, port, timeout_connect
|
||||||
),
|
),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
get_socks5_stream(&proxy, &proxy_addr, &host_addrs[0])?
|
get_socks5_stream(&proxy, &proxy_addr, host_addr)?
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(stream)
|
Ok(stream)
|
||||||
@@ -339,20 +366,20 @@ fn connect_socks5(
|
|||||||
fn get_socks5_stream(
|
fn get_socks5_stream(
|
||||||
proxy: &Proxy,
|
proxy: &Proxy,
|
||||||
proxy_addr: &SocketAddr,
|
proxy_addr: &SocketAddr,
|
||||||
host_addr: &SocketAddr,
|
host_addr: TargetAddr,
|
||||||
) -> Result<TcpStream, std::io::Error> {
|
) -> Result<TcpStream, std::io::Error> {
|
||||||
use socks::{Socks5Stream, ToTargetAddr};
|
use socks::Socks5Stream;
|
||||||
if proxy.use_authorization() {
|
if proxy.use_authorization() {
|
||||||
let stream = Socks5Stream::connect_with_password(
|
let stream = Socks5Stream::connect_with_password(
|
||||||
proxy_addr,
|
proxy_addr,
|
||||||
host_addr.to_target_addr()?,
|
host_addr,
|
||||||
&proxy.user.as_ref().unwrap(),
|
&proxy.user.as_ref().unwrap(),
|
||||||
&proxy.password.as_ref().unwrap(),
|
&proxy.password.as_ref().unwrap(),
|
||||||
)?
|
)?
|
||||||
.into_inner();
|
.into_inner();
|
||||||
Ok(stream)
|
Ok(stream)
|
||||||
} else {
|
} else {
|
||||||
match Socks5Stream::connect(proxy_addr, host_addr.to_target_addr()?) {
|
match Socks5Stream::connect(proxy_addr, host_addr) {
|
||||||
Ok(socks_stream) => Ok(socks_stream.into_inner()),
|
Ok(socks_stream) => Ok(socks_stream.into_inner()),
|
||||||
Err(err) => Err(err),
|
Err(err) => Err(err),
|
||||||
}
|
}
|
||||||
@@ -364,7 +391,7 @@ fn connect_socks5(
|
|||||||
_proxy: Proxy,
|
_proxy: Proxy,
|
||||||
_timeout_connect: u64,
|
_timeout_connect: u64,
|
||||||
_proxy_addr: SocketAddr,
|
_proxy_addr: SocketAddr,
|
||||||
_hostname: String,
|
_hostname: &str,
|
||||||
_port: u16,
|
_port: u16,
|
||||||
) -> Result<TcpStream, std::io::Error> {
|
) -> Result<TcpStream, std::io::Error> {
|
||||||
Err(std::io::Error::new(
|
Err(std::io::Error::new(
|
||||||
|
|||||||
Reference in New Issue
Block a user