Skip to content

Commit

Permalink
support udp tunneling with some breaking changes
Browse files Browse the repository at this point in the history
BREAKING CHANGES:
* rstund
  1. The --upstreams option is replaced with --tcp-upstream
     and --udp-upstream, these are default TCP and UDP upstreams for
     TunnelOut mode tunneling, only one single default upstream for
     each protocol.
  2. the short `-w` option for `--max_idle_timeout_ms` is now `i`
  3. the short `-t` option is used for `--tcp-upstream` now
  4. the short `-u` option is used for `--udp-upstream` now
* rstunc
  1. The --addr-mapping option is replaced with --tcp-mapping and
     --udp-mapping
  2. `-t` for `--threads` is now `-w` for `--workers`.
  3. `-r` for `--server-addr` is now `-a`

And a lot of refactor in this commit.
  • Loading branch information
neevek committed Oct 13, 2024
1 parent 2c94f07 commit cebb50a
Show file tree
Hide file tree
Showing 17 changed files with 1,558 additions and 679 deletions.
54 changes: 53 additions & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 4 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "rstun"
version = "0.5.2"
version = "0.6.0"
edition = "2021"

[lib]
Expand Down Expand Up @@ -32,6 +32,9 @@ byte-pool = { git = "https://github.com/neevek/byte-pool" }
x509-parser = "0.16"
lazy_static = "1.5"
rustls-pemfile = "2.1"
bytes = "1"
backon = "1.2"
dashmap = "6"

[dev-dependencies]
jni = "0.19"
Expand Down
120 changes: 74 additions & 46 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,35 +1,61 @@
rstun
=====

A secure UDP tunnel written in Rust.
A TCP/UDP tunnel over QUIC written in Rust.

rstun builds on [Quinn](https://github.com/quinn-rs/quinn), which is an implementation of the IETF [QUIC](https://quicwg.org/) transport protocol.
rstun is a high-performance TCP/UDP tunneling solution. It leverages the [Quinn](https://github.com/quinn-rs/quinn) library for [QUIC](https://quicwg.org/) transport, ensuring efficient, low-latency communication, secured by QUIC’s integrated TLS layer.

rstun consists of two binaries, `rstunc` for client and `rstund` for server. `rstund` accepts connections from `rstunc`.
Key Features
------------

`rstunc` connects to the server to build a secure tunnel to allow data to be exchanged between two ends, it initiates the connection in one of two modes:
* TCP and UDP tunneling over a single QUIC connection.
* Encryption provided by QUIC’s inherent TLS integration.
* Bidirectional traffic support over a single tunnel, with two operating modes:
* `IN` mode: Exposes local ports through the server, allowing external access via the tunnel.
* `OUT` mode: Secures outgoing traffic from a local network to the internet via the server.

* The `IN` mode for exposing a local port to the internet through the server.
* The `OUT` mode for securing data going out from local to the internet through the server.

All traffic going through the tunnel is secured by the builtin TLS layer of the QUIC protocol, when the negotiation of the connection completes and a tunnel is built, QUIC streams can be initiated from both ends, for the `OUT` mode, streams are initiated from the client, and for the `IN` mode, it is just the opposite.
Components
----------

rstun consists of two main binaries:

* rstunc (client): Establishes and manages tunnels to the server.
* rstund (server): Accepts incoming connections and forwards traffic according to the configured routing rules.

Once the QUIC handshake completes, bidirectional streams are available, facilitating high-throughput data exchange.


Usage
-----

* Inbound Tunneling (IN Mode)

In IN mode, rstunc allows you to expose a local service (e.g., a web server or application) to the public internet securely through the QUIC tunnel. This mode is useful for scenarios where a service is running locally behind a NAT or firewall but needs to be accessible from outside.

* Outbound Tunneling (OUT Mode)

In OUT mode, rstunc securely tunnels local outbound traffic through rstund, which forwards it to the destination. This is typically used to secure traffic between a local network and the internet, similar to a traditional VPN but using QUIC for improved performance and security.


Example
=======

* Start the server

```
rstund \
--addr 0.0.0.0:6060 \
--upstreams 8800 \
--tcp-upstream 8800 \
--udp-upstream 8.8.8.8:53 \
--password 123456 \
--cert path/to/cert.der \
--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 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.
- `--addr` specifies the ip:port that the server is listening on.
- `--tcp-upstream` is the default TCP upstream for `OUT` mode tunneling if the client doesn't specify one. Traffic from the client through the tunnel will be forwarded to this upstream.
- `--udp-upstream` is the default UDP upstream for `OUT` mode tunneling if the client doesn't specify one. Traffic from the client through the tunnel will be forwarded to this upstream.
- `--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**!

* Start the client
Expand All @@ -42,14 +68,11 @@ rstunc
--cert path/to/cert.der \
--addr-mapping 0.0.0.0:9900^8800
```
- `mode` here is `OUT`, for securing traffic from local to the server through the tunnel.
- `server-addr`, domain name or IP address of the server.
- `password`, same as that for the server.
- `cert`, see explanation above for `rstund`. Note this is also optional if connecting to the server with a domain name, or the server `rstund` runs with an auto-generated self-signed certificate (see the TEST example below).
- `addr-mapping` is an address mapping between two `ip:port` pairs separated by the `^` character, the format is `[ip:]port^[ip:]port`, in the example above, a local port `9900` is mapped to the remote port `8800` of the `1.2.3.4` server that runs `rstund`. i.e. all traffic from the local port `9900` will be forwarded to the remote port `8800` through the tunnel. `addr-mapping` also supports the following 3 combinations:
- `ANY^8000` for not explicitly specifying a port for the local access server (the client), the bound port will be printed to the terminal as following `[TunnelOut] access server bound to: 0.0.0.0:60001`, in which `60001` is a random port.
- `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.
- `--mode`, `OUT` for securing data from local to the server through the tunnel.
- `--server-addr`, domain name or IP address of the server.
- `--password`, same as that for the server.
- `--cert`, see explanation above for `rstund`. Note this is also optional if connecting to the server with a domain name, or the server `rstund` runs with an auto-generated self-signed certificate (see the TEST example below).
- `--addr-mapping` is an address mapping between two `ip:port` pairs separated by the `^` character, the format is `[ip:]port^[ip:]port`, in the example above, a local port `9900` is mapped to the remote port `8800` of the `1.2.3.4` server that runs `rstund`. i.e. all traffic from the local port `9900` will be forwarded to the remote port `8800` through the tunnel. `--addr-mapping` also supports using `ANY` as the second part of the mapping for `OUT` mode tunneling, in which case, the server default will be used. For example `9900^ANY`.

* Simple TEST example

Expand All @@ -60,31 +83,34 @@ The following commands run a server, then a client that connects to the server i
# Remote: run the server with auto-generated self-signed certificate
rstund -a 9000 -p 1234
# Local: connect to the server (127.0.0.1:9000) and bind the local port 9900 to remote port 8800
rstunc -m OUT -r 127.0.0.1:9000 -p 1234 -a 0.0.0.0:9900^8800
# Local: connect to the server (127.0.0.1:9000) and bind both the TCP and UDP port 9900 to remote TCP and UDP port 8800
rstunc -m OUT -a 127.0.0.1:9000 -p 1234 -t 0.0.0.0:9900^8800 -u 0.0.0.0:9900^8800
```

* Complete options for `rstund`
Options for `rstund` and `rstunc`
---

```
Usage: rstund [OPTIONS] --password <PASSWORD>
Usage: rstund [OPTIONS] --addr <ADDR> --password <PASSWORD>
Options:
-a, --addr <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 <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
Address ([ip:]port pair) to listen on [default: ]
-t, --tcp-upstream <TCP_UPSTREAM>
The default TCP upstream for TunnelOut connections, format: [ip:]port [default: ]
-u, --udp-upstream <UDP_UPSTREAM>
The default UDP upstream for TunnelOut connections, format: [ip:]port [default: ]
-p, --password <PASSWORD>
Password of the tunnel server
-c, --cert <CERT>
Path to the certificate file, if empty, a self-signed certificate with the domain "localhost" will be used [default: ]
Path to the certificate file, if empty, a self-signed certificate
with the domain "localhost" will be used [default: ]
-k, --key <KEY>
Path to the key file, can be empty if no cert is provided [default: ]
-t, --threads <THREADS>
-w, --workers <WORKERS>
Threads to run async tasks [default: 0]
-w, --max-idle-timeout-ms <MAX_IDLE_TIMEOUT_MS>
Max idle timeout for the connection [default: 40000]
-i, --max-idle-timeout-ms <MAX_IDLE_TIMEOUT_MS>
Max idle timeout milliseconds for the connection [default: 40000]
-l, --loglevel <LOGLEVEL>
[default: I] [possible values: T, D, I, W, E]
-h, --help
Expand All @@ -93,35 +119,37 @@ Options:
Print version
```

* Complete options for `rstunc`

```
Usage: rstunc [OPTIONS] --mode <MODE> --server-addr <SERVER_ADDR> --password <PASSWORD> --addr-mapping <ADDR_MAPPING>
Usage: rstunc [OPTIONS] --mode <MODE> --server-addr <SERVER_ADDR> --password <PASSWORD>
Options:
-m, --mode <MODE>
Create a tunnel running in IN or OUT mode [possible values: IN, OUT]
-r, --server-addr <SERVER_ADDR>
-a, --server-addr <SERVER_ADDR>
Address (<domain:ip>[:port] pair) of rstund, default port is 3515
-p, --password <PASSWORD>
Password to connect with rstund
-a, --addr-mapping <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
-t, --tcp-mapping <TCP_MAPPING>
LOCAL and REMOTE mapping in [ip:]port^[ip:]port format, e.g. 8080^0.0.0.0:9090
`8000^ANY` for not explicitly specifying the upstream on the server, the server
decides that port, so it depends on that the server is started with
explicitly setting the `--tcp-upstream` option. [default: ]
-u, --udp-mapping <UDP_MAPPING>
LOCAL and REMOTE mapping in [ip:]port^[ip:]port format, e.g. 8080^0.0.0.0:9090
`8000^ANY` for not explicitly specifying the upstream on the server, the server
decides that port, so it depends on that the server is started with
explicitly setting the `--udp-upstream` option. [default: ]
-c, --cert <CERT>
Path to the certificate file, only needed for self signed certificate [default: ]
-e, --cipher <CIPHER>
Preferred cipher suite [default: chacha20-poly1305] [possible values: chacha20-poly1305, aes-256-gcm, aes-128-gcm]
-t, --threads <THREADS>
Threads to run async tasks [default: 0]
-w, --wait-before-retry-ms <WAIT_BEFORE_RETRY_MS>
Wait time before trying [default: 5000]
-w, --workers <WORKERS>
Workers to run async tasks [default: 0]
-r, --wait-before-retry-ms <WAIT_BEFORE_RETRY_MS>
Wait time in milliseconds before trying [default: 5000]
-i, --max-idle-timeout-ms <MAX_IDLE_TIMEOUT_MS>
Max idle timeout for the connection [default: 30000]
Max idle timeout in milliseconds for the connection [default: 30000]
-l, --loglevel <LOGLEVEL>
Log level [default: I] [possible values: T, D, I, W, E]
-h, --help
Expand Down
Loading

0 comments on commit cebb50a

Please sign in to comment.