Skip to content

Commit

Permalink
feat(proxy): Add socks4a proxy protocol support (#416)
Browse files Browse the repository at this point in the history
  • Loading branch information
0x676e67 authored Feb 9, 2025
1 parent 01f1387 commit 1f98b6e
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 15 deletions.
11 changes: 3 additions & 8 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -82,10 +82,7 @@ url = "2.5"
bytes = "1.0"
serde = { version = "1.0", features = ["derive"] }
serde_urlencoded = "0.7.1"
tower = { version = "0.5.2", default-features = false, features = [
"timeout",
"util",
] }
tower = { version = "0.5.2", default-features = false, features = ["timeout","util"] }
tower-service = "0.3"
futures-util = { version = "0.3.0", default-features = false }
sync_wrapper = { version = "1.0", features = ["futures"] }
Expand All @@ -104,6 +101,8 @@ encoding_rs = { version = "0.8", optional = true }
http-body = "1"
http-body-util = "0.1"
hyper2 = { version = "1.5.0", features = ["http1", "http2", "client"] }
socket2 = { version = "0.5", features = ["all"] }
lru = { version = "0.13", default-features = false }
log = "0.4"
mime = "0.3.17"
percent-encoding = "2.3"
Expand All @@ -112,10 +111,6 @@ pin-project-lite = "0.2.0"
ipnet = "2.11.0"
arc-swap = "1.7.0"

## util
socket2 = { version = "0.5", features = ["all"] }
lru = { version = "0.13", default-features = false }

## boring-tls
boring2 = { version = "4.15.2", features = ["pq-experimental", "cert-compression"] }
tokio-boring2 = { version = "4.15.2", features = ["pq-experimental"] }
Expand Down
9 changes: 7 additions & 2 deletions src/connect.rs
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,12 @@ impl ConnectorService {
#[cfg(feature = "socks")]
async fn connect_socks(&self, mut dst: Dst, proxy: ProxyScheme) -> Result<Conn, BoxError> {
let dns = match proxy {
ProxyScheme::Socks4 { .. } => socks::DnsResolve::Local,
ProxyScheme::Socks4 {
remote_dns: false, ..
} => socks::DnsResolve::Local,
ProxyScheme::Socks4 {
remote_dns: true, ..
} => socks::DnsResolve::Proxy,
ProxyScheme::Socks5 {
remote_dns: false, ..
} => socks::DnsResolve::Local,
Expand Down Expand Up @@ -777,7 +782,7 @@ mod socks {
}

match proxy {
ProxyScheme::Socks4 { addr } => {
ProxyScheme::Socks4 { addr, .. } => {
let stream = Socks4Stream::connect(addr, (host.as_str(), port))
.await
.map_err(|e| format!("socks connect error: {e}"))?;
Expand Down
31 changes: 26 additions & 5 deletions src/proxy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ pub enum ProxyScheme {
host: http::uri::Authority,
},
#[cfg(feature = "socks")]
Socks4 { addr: SocketAddr },
Socks4 { addr: SocketAddr, remote_dns: bool },
#[cfg(feature = "socks")]
Socks5 {
addr: SocketAddr,
Expand Down Expand Up @@ -586,7 +586,25 @@ impl ProxyScheme {
/// Current SOCKS4 support is provided via blocking IO.
#[cfg(feature = "socks")]
fn socks4(addr: SocketAddr) -> crate::Result<Self> {
Ok(ProxyScheme::Socks4 { addr })
Ok(ProxyScheme::Socks4 {
addr,
remote_dns: false,
})
}

/// Proxy traffic via the specified socket address over SOCKS4A
///
/// This differs from SOCKS4 in that DNS resolution is also performed via the proxy.
///
/// # Note
///
/// Current SOCKS4 support is provided via blocking IO.
#[cfg(feature = "socks")]
fn socks4a(addr: SocketAddr) -> crate::Result<Self> {
Ok(ProxyScheme::Socks4 {
addr,
remote_dns: true,
})
}

/// Proxy traffic via the specified socket address over SOCKS5
Expand Down Expand Up @@ -702,7 +720,7 @@ impl ProxyScheme {
let to_addr = || {
let addrs = url
.socket_addrs(|| match url.scheme() {
"socks4" | "socks5" | "socks5h" => Some(1080),
"socks4" | "socks4a" | "socks5" | "socks5h" => Some(1080),
_ => None,
})
.map_err(crate::error::builder)?;
Expand All @@ -718,6 +736,8 @@ impl ProxyScheme {
#[cfg(feature = "socks")]
"socks4" => Self::socks4(to_addr()?)?,
#[cfg(feature = "socks")]
"socks4a" => Self::socks4a(to_addr()?)?,
#[cfg(feature = "socks")]
"socks5" => Self::socks5(to_addr()?)?,
#[cfg(feature = "socks")]
"socks5h" => Self::socks5h(to_addr()?)?,
Expand All @@ -740,8 +760,9 @@ impl fmt::Debug for ProxyScheme {
ProxyScheme::Http { auth: _auth, host } => write!(f, "http://{}", host),
ProxyScheme::Https { auth: _auth, host } => write!(f, "https://{}", host),
#[cfg(feature = "socks")]
ProxyScheme::Socks4 { addr } => {
write!(f, "socks4://{addr}")
ProxyScheme::Socks4 { addr, remote_dns } => {
let h = if *remote_dns { "a" } else { "" };
write!(f, "socks4{}://{}", h, addr)
}
#[cfg(feature = "socks")]
ProxyScheme::Socks5 {
Expand Down

0 comments on commit 1f98b6e

Please sign in to comment.