Add: socks5 support. It may have problems with DoT, will see.

This commit is contained in:
DaZuo0122
2026-01-16 23:59:02 +08:00
parent edd1779920
commit 7746511fc4
12 changed files with 489 additions and 50 deletions

View File

@@ -226,6 +226,10 @@ struct ProbeTcpingArgs {
#[arg(long, default_value_t = 800)]
timeout_ms: u64,
#[arg(long)]
socks5: Option<String>,
#[arg(long)]
prefer_ipv4: bool,
#[arg(long)]
no_geoip: bool,
}
@@ -256,6 +260,8 @@ struct DnsQueryArgs {
tls_name: Option<String>,
#[arg(long)]
socks5: Option<String>,
#[arg(long)]
prefer_ipv4: bool,
#[arg(long, default_value_t = 2000)]
timeout_ms: u64,
}
@@ -271,6 +277,8 @@ struct DnsDetectArgs {
tls_name: Option<String>,
#[arg(long)]
socks5: Option<String>,
#[arg(long)]
prefer_ipv4: bool,
#[arg(long, default_value_t = 3)]
repeat: u32,
#[arg(long, default_value_t = 2000)]
@@ -328,6 +336,8 @@ struct HttpRequestArgs {
http2_only: bool,
#[arg(long)]
geoip: bool,
#[arg(long)]
socks5: Option<String>,
}
#[derive(Parser, Debug, Clone)]
@@ -341,6 +351,10 @@ struct TlsArgs {
timeout_ms: u64,
#[arg(long)]
insecure: bool,
#[arg(long)]
socks5: Option<String>,
#[arg(long)]
prefer_ipv4: bool,
}
#[derive(Parser, Debug, Clone)]
@@ -988,14 +1002,31 @@ async fn handle_probe_tcping(cli: &Cli, args: ProbeTcpingArgs) -> i32 {
}
};
match wtfnet_probe::tcp_ping(&host, port, args.count, args.timeout_ms).await {
match wtfnet_probe::tcp_ping(
&host,
port,
args.count,
args.timeout_ms,
args.socks5.as_deref(),
args.prefer_ipv4,
)
.await
{
Ok(mut report) => {
if !args.no_geoip {
enrich_tcp_geoip(&mut report);
}
if cli.json {
let meta = Meta::new("wtfnet", env!("CARGO_PKG_VERSION"), false);
let command = CommandInfo::new("probe tcping", vec![args.target]);
let mut command_args = vec![args.target];
if let Some(proxy) = args.socks5 {
command_args.push("--socks5".to_string());
command_args.push(proxy);
}
if args.prefer_ipv4 {
command_args.push("--prefer-ipv4".to_string());
}
let command = CommandInfo::new("probe tcping", command_args);
let envelope = CommandEnvelope::new(meta, command, report);
emit_json(cli, &envelope)
} else {
@@ -1280,7 +1311,12 @@ async fn handle_dns_query(cli: &Cli, args: DnsQueryArgs) -> i32 {
}
};
let server = match args.server.as_deref() {
Some(value) => match parse_dns_server_target(value, transport, args.tls_name.as_deref()) {
Some(value) => match parse_dns_server_target(
value,
transport,
args.tls_name.as_deref(),
args.prefer_ipv4,
) {
Ok(addr) => Some(addr),
Err(err) => {
eprintln!("{err}");
@@ -1360,7 +1396,14 @@ async fn handle_dns_detect(cli: &Cli, args: DnsDetectArgs) -> i32 {
let parsed = raw
.split(',')
.filter(|value| !value.trim().is_empty())
.map(|value| parse_dns_server_target(value.trim(), transport, args.tls_name.as_deref()))
.map(|value| {
parse_dns_server_target(
value.trim(),
transport,
args.tls_name.as_deref(),
args.prefer_ipv4,
)
})
.collect::<Result<Vec<_>, _>>();
match parsed {
Ok(values) => values,
@@ -1617,6 +1660,7 @@ fn parse_dns_server_target(
value: &str,
transport: wtfnet_dns::DnsTransport,
tls_name: Option<&str>,
prefer_ipv4: bool,
) -> Result<wtfnet_dns::DnsServerTarget, String> {
let default_port = match transport {
wtfnet_dns::DnsTransport::Udp | wtfnet_dns::DnsTransport::Tcp => 53,
@@ -1638,10 +1682,8 @@ fn parse_dns_server_target(
}
let (host, port) = split_host_port_with_default(value, default_port)?;
let addr = format!("{host}:{port}")
.to_socket_addrs()
let addr = resolve_host_port(&host, port, prefer_ipv4)
.map_err(|_| format!("invalid server address: {value}"))?
.next()
.ok_or_else(|| format!("unable to resolve server: {value}"))?;
let name = tls_name
@@ -1687,6 +1729,28 @@ fn split_host_port_with_default(value: &str, default_port: u16) -> Result<(Strin
Ok((value.to_string(), default_port))
}
fn resolve_host_port(
host: &str,
port: u16,
prefer_ipv4: bool,
) -> Result<Option<std::net::SocketAddr>, std::io::Error> {
let mut iter = (host, port).to_socket_addrs()?;
if prefer_ipv4 {
let mut fallback = None;
for addr in iter.by_ref() {
if addr.is_ipv4() {
return Ok(Some(addr));
}
if fallback.is_none() {
fallback = Some(addr);
}
}
Ok(fallback)
} else {
Ok(iter.next())
}
}
async fn handle_http_request(
cli: &Cli,
args: HttpRequestArgs,
@@ -1701,6 +1765,7 @@ async fn handle_http_request(
show_body: args.show_body,
http1_only: args.http1_only,
http2_only: args.http2_only,
proxy: args.socks5.clone(),
};
match wtfnet_http::request(&args.url, opts).await {
@@ -1850,6 +1915,8 @@ fn build_tls_options(args: &TlsArgs) -> wtfnet_tls::TlsOptions {
alpn: parse_alpn(args.alpn.as_deref()),
timeout_ms: args.timeout_ms,
insecure: args.insecure,
socks5: args.socks5.clone(),
prefer_ipv4: args.prefer_ipv4,
}
}