From a8c5c0b910b6d17498a116d1eaaf40b72efeaf34 Mon Sep 17 00:00:00 2001 From: neevek Date: Sun, 7 Jul 2024 11:25:52 +0800 Subject: [PATCH] fix the way of specifying upstreams (now comma separated) --- Cargo.lock | 2 +- Cargo.toml | 2 +- README.md | 138 +++++++++++++++++++--------------------------- src/bin/rstund.rs | 24 ++++---- 4 files changed, 72 insertions(+), 94 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index fa7c123..1e9f68d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1049,7 +1049,7 @@ dependencies = [ [[package]] name = "rstun" -version = "0.4.17" +version = "0.4.18" dependencies = [ "android_logger", "anyhow", diff --git a/Cargo.toml b/Cargo.toml index 3701e20..8443d61 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rstun" -version = "0.4.17" +version = "0.4.18" edition = "2021" [lib] diff --git a/README.md b/README.md index a28ba54..c640575 100644 --- a/README.md +++ b/README.md @@ -28,7 +28,7 @@ rstund \ --key path/to/key.der ``` - `addr` specifies the ip:port that the server is listening on. - - `upstreams` specifies a TCP port which traffic from the client through the tunnel will be relayed to on the server, this is applicable for `OUT` mode tunnels only, multiple space-separated upstreams can be set. Note this argument is optional, if it is not specified, all open ports of the server are exposed to the clients through the tunnel. So make sure to specify upstreams if exposing all open ports of the server is not desired. + - `upstreams` specifies a TCP port which traffic from the client through the tunnel will be relayed to on the server, this is applicable for `OUT` mode tunnels only, multiple comma-separated upstreams can be set. Note this argument is optional, if it is not specified, all open ports of the server are exposed to the clients through the tunnel. So make sure to specify upstreams if exposing all open ports of the server is not desired. - `password`, password of the server, the client `rstunc` is required to send this password to successfully build a tunnel with the server. - `cert` and `key` are certificate and private key for the domain of the server, self-signed certificate is allowed, but you will have to connect to the server using IP address and the certificate will also be required by `rstunc` for verification in this case (see below). Anyway, getting a certificate for your domain from a trusted CA and connecting to the server using domain name is always recommended. Note `cert` and `key` are optional, if they are not specified, the domain `localhost` is assumed and a self-signed certificate is generated on the fly, but this is for TEST only, Man-In-The-Middle attack can occur with such setting, so make sure **it is only used for TEST**! @@ -68,92 +68,66 @@ rstunc -m OUT -r 127.0.0.1:9000 -p 1234 -a 0.0.0.0:9900^8800 * Complete options for `rstund` ``` -USAGE: - rstund [OPTIONS] --password - -OPTIONS: - -a, --addr - Address ([ip:]port pair) to listen on, a random port will be chosen and binding to all - network interfaces (0.0.0.0) if empty [default: ] - - -u, --upstreams - Exposed upstreams as the receiving end of the tunnel, e.g. -d [ip:]port, The entire - local network is exposed through the tunnel if empty - - -p, --password - Password of the tunnel server - - -c, --cert - Path to the certificate file, if empty, a self-signed certificate with the - domain "localhost" will be used [default: ] - - -k, --key - Path to the key file, can be empty if no cert is provided [default: ] - - -t, --threads - Threads to run async tasks [default: 0] - - -w, --max-idle-timeout-ms - Max idle timeout for the connection [default: 40000] - - -l, --loglevel - [default: I] [possible values: T, D, I, W, E] - - -h, --help - Print help information - - -V, --version - Print version information +Usage: rstund [OPTIONS] --password + +Options: + -a, --addr + Address ([ip:]port pair) to listen on, a random port will be chosen and binding to all network interfaces (0.0.0.0) if empty [default: ] + -u, --upstreams + Exposed upstreams (comma separated) as the receiving end of the tunnel, e.g. -u [ip:]port, The entire local network is exposed through the tunnel if empty + -p, --password + Password of the tunnel server + -c, --cert + Path to the certificate file, if empty, a self-signed certificate with the domain "localhost" will be used [default: ] + -k, --key + Path to the key file, can be empty if no cert is provided [default: ] + -t, --threads + Threads to run async tasks [default: 0] + -w, --max-idle-timeout-ms + Max idle timeout for the connection [default: 40000] + -l, --loglevel + [default: I] [possible values: T, D, I, W, E] + -h, --help + Print help + -V, --version + Print version ``` * Complete options for `rstunc` ``` -USAGE: - rstunc [OPTIONS] --mode --server-addr --password --addr-mapping - -OPTIONS: - -m, --mode - Create a tunnel running in IN or OUT mode [possible values: IN, OUT] - - -r, --server-addr - Address ([:port] pair) of rstund, default port is 3515 - - -p, --password - Password to connect with rstund - - -a, --addr-mapping - LOCAL and REMOTE mapping in [ip:]port^[ip:]port format, e.g. 8080^0.0.0.0:9090 - `ANY^8000` for not explicitly specifying a port for the local access server (the client) - `8000^ANY` for not explicitly specifying a port to bind with the remote server, the - server decides that port, so it depends on that the server is started with explicitly - setting the `--upstreams` option. `ANY^ANY` both the cases of the settings above - - -c, --cert - Path to the certificate file, only needed for self signed certificate - [default: ] - - -e, --cipher - Preferred cipher suite [default: chacha20-poly1305] [possible values: chacha20-poly1305, - aes-256-gcm, aes-128-gcm] - - -t, --threads - Threads to run async tasks [default: 0] - - -w, --wait-before-retry-ms - Wait time before trying [default: 5000] - - -i, --max-idle-timeout-ms - Max idle timeout for the connection [default: 30000] - - -l, --loglevel - Log level [default: I] [possible values: T, D, I, W, E] - - -h, --help - Print help information - - -V, --version - Print version information +Usage: rstunc [OPTIONS] --mode --server-addr --password --addr-mapping + +Options: + -m, --mode + Create a tunnel running in IN or OUT mode [possible values: IN, OUT] + -r, --server-addr + Address ([:port] pair) of rstund, default port is 3515 + -p, --password + Password to connect with rstund + -a, --addr-mapping + LOCAL and REMOTE mapping in [ip:]port^[ip:]port format, + e.g. 8080^0.0.0.0:9090 `ANY^8000` for not explicitly specifying a port + for the local access server (the client) `8000^ANY` for not explicitly + specifying a port to bind with the remote server, the server decides that + port, so it depends on that the server is started with explicitly setting + the `--upstreams` option. `ANY^ANY` both the cases of the settings above + -c, --cert + Path to the certificate file, only needed for self signed certificate [default: ] + -e, --cipher + Preferred cipher suite [default: chacha20-poly1305] [possible values: chacha20-poly1305, aes-256-gcm, aes-128-gcm] + -t, --threads + Threads to run async tasks [default: 0] + -w, --wait-before-retry-ms + Wait time before trying [default: 5000] + -i, --max-idle-timeout-ms + Max idle timeout for the connection [default: 30000] + -l, --loglevel + Log level [default: I] [possible values: T, D, I, W, E] + -h, --help + Print help + -V, --version + Print version ``` License diff --git a/src/bin/rstund.rs b/src/bin/rstund.rs index 166ddf2..1a199ef 100644 --- a/src/bin/rstund.rs +++ b/src/bin/rstund.rs @@ -47,19 +47,22 @@ async fn run(mut args: RstundArgs) -> Result<()> { let mut upstreams = Vec::::new(); - for d in &mut args.upstreams { - if d.starts_with("0.0.0.0:") { - *d = d.replace("0.0.0.0:", "127.0.0.1:"); + for mut u in &mut args.upstreams.split(',').map(|u| u.to_string()) { + if u.starts_with("0.0.0.0:") { + u = u.replace("0.0.0.0:", "127.0.0.1:"); } - if !d.contains(':') { - *d = format!("127.0.0.1:{d}"); + if !u.contains(':') { + u = format!("127.0.0.1:{u}"); } - if let Ok(addr) = d.parse() { - upstreams.push(addr); + if let Ok(addr) = u.parse() { + if !upstreams.contains(&addr) { + info!("upstream: {addr}"); + upstreams.push(addr); + } } else { - log_and_bail!("invalid upstreams address: {d}"); + log_and_bail!("invalid upstreams address: {u}"); } } @@ -85,10 +88,11 @@ struct RstundArgs { #[arg(short = 'a', long, default_value_t = String::from(""))] addr: String, - /// Exposed upstreams as the receiving end of the tunnel, e.g. -d [ip:]port, + /// Exposed upstreams (comma separated) as the receiving end of the tunnel, + /// e.g. -u "[ip:]port,[ip:]port,[ip:]port", /// The entire local network is exposed through the tunnel if empty #[arg(short = 'u', long, required = false)] - upstreams: Vec, + upstreams: String, /// Password of the tunnel server #[arg(short = 'p', long, required = true)]