feat: add proxy node probe command and docs

This commit is contained in:
tianrking committed 2026-03-20 13:54:33 +08:00
1 parent 33dd48d4b4
commit e70e6c3b4c
3 files changed
+87 -1

No files matched your search

+3
View File
@@ -40,6 +40,7 @@ Recommendation:
- Discovery/validation:
- `--list-groups`
- `--check`
- `--probe` (quick per-node reachability/latency check)
- DNS:
- `proxy_dns`
- compatibility aliases: `proxy_dns_old`, `proxy_dns_daemon`
@@ -88,6 +89,8 @@ Validate config and groups:
```bash
proxychains4 -f ./proxychains.conf --list-groups
proxychains4 -f ./proxychains.conf --group jp --check
proxychains4 -f ./proxychains.conf --group jp --probe
proxychains4 -f ./proxychains.conf --probe --probe-timeout-ms 1200
```
## Example Config
+3
View File
@@ -40,6 +40,7 @@
- 配置发现/校验:
- `--list-groups`
- `--check`
- `--probe`(快速探测每个节点连通性与时延)
- DNS:
- `proxy_dns`
- 兼容别名:`proxy_dns_old`、`proxy_dns_daemon`
@@ -88,6 +89,8 @@ proxychains4.exe curl https://ifconfig.me
```bash
proxychains4 -f ./proxychains.conf --list-groups
proxychains4 -f ./proxychains.conf --group jp --check
proxychains4 -f ./proxychains.conf --group jp --probe
proxychains4 -f ./proxychains.conf --probe --probe-timeout-ms 1200
```
## 示例配置
+81 -1
View File
@@ -7,8 +7,10 @@
//! - Windows: Uses DLL injection
use std::env;
use std::net::{SocketAddr, SocketAddrV4, TcpStream};
use std::path::PathBuf;
use std::process;
use std::time::{Duration, Instant};
use clap::Parser;
use tracing::{debug, error, info, Level};
@@ -47,9 +49,17 @@ struct Args {
#[arg(long)]
check: bool,
/// Probe configured proxy nodes and print per-node reachability
#[arg(long)]
probe: bool,
/// Probe timeout in milliseconds (default: config tcp_connect_time_out)
#[arg(long, value_name = "MS")]
probe_timeout_ms: Option<u64>,
/// The command to run
#[arg(
required_unless_present_any = ["list_groups", "check"],
required_unless_present_any = ["list_groups", "check", "probe"],
trailing_var_arg = true
)]
command: Vec<String>,
@@ -121,6 +131,11 @@ fn main() {
process::exit(0);
}
if args.probe {
let failed = run_probe(&config, &args);
process::exit(if failed == 0 { 0 } else { 2 });
}
// Execute the command with platform-specific injection
match execute_command(&args, &config) {
Ok(status) => {
@@ -190,6 +205,62 @@ fn print_check_summary(config: &Config, args: &Args) {
}
}
fn run_probe(config: &Config, args: &Args) -> usize {
let timeout = args
.probe_timeout_ms
.map(Duration::from_millis)
.unwrap_or(config.tcp_connect_timeout);
let mut failed = 0usize;
println!("Proxy probe:");
println!(" timeout_ms={}", timeout.as_millis());
println!(
" group={}",
args.group.as_deref().unwrap_or("default/all")
);
for (idx, proxy) in config.proxies.iter().enumerate() {
let target_v4 = SocketAddrV4::new(proxy.ip, proxy.port);
let target = SocketAddr::V4(target_v4);
let start = Instant::now();
match TcpStream::connect_timeout(&target, timeout) {
Ok(stream) => {
let elapsed = start.elapsed().as_millis();
let _ = stream.shutdown(std::net::Shutdown::Both);
println!(
" [{}] OK {:<6} {}:{} {} ms",
idx + 1,
proxy.proxy_type,
proxy.ip,
proxy.port,
elapsed
);
}
Err(e) => {
failed += 1;
let elapsed = start.elapsed().as_millis();
println!(
" [{}] FAIL {:<6} {}:{} {} ms ({})",
idx + 1,
proxy.proxy_type,
proxy.ip,
proxy.port,
elapsed,
e
);
}
}
}
println!(
"Probe summary: total={}, ok={}, fail={}",
config.proxies.len(),
config.proxies.len().saturating_sub(failed),
failed
);
failed
}
/// Set proxychains-specific environment variables
fn set_proxychains_env(config: &Config, args: &Args) {
if args.quiet {
@@ -425,4 +496,13 @@ mod tests {
assert!(args.list_groups);
assert!(args.command.is_empty());
}
#[test]
fn test_args_probe_without_command() {
let args = Args::try_parse_from(["proxychains4", "--probe"]);
assert!(args.is_ok());
let args = args.unwrap();
assert!(args.probe);
assert!(args.command.is_empty());
}
}