A toy/educational project to allow access to internal TCP network services without opening NAT ports or using a VPN. Similar to Cloudflare Access or frp but absolutely not production ready.
TLS support is provided by rustls when the crypto
section of the config files
is filled out. Certificates must be in PEM format, while the key files must
be RSA keys in OpenSSL's tradional format. Conversion can be achieved with
the following command openssl rsa -in key -out key.traditional -traditional
.
cargo build
cargo clippy --no-deps
cargo test
# run these from the manifest directory or provide a path to configuration files
# e.g.: `-- -c path/to/cfg.toml`
cargo run --bin sts
cargo run --bin stc
# pre-shared key that should match between Client/Server. Max of 512 bytes
# Hint: generate this with LC_ALL=C tr -dc 'A-Za-z0-9!"#$%&'\''()*+,-./:;<=>?@[\]^_`{|}~' </dev/urandom | head -c 512; echo
psk = "abcd"
# the FQDN/IP of the Server
addr = "127.0.0.1"
# the port of the Server
port = 12345
[crypto]
ca = "ca.pem"
# Each tunnel looks like this. Copy and paste more blocks to have more tunnels
[[tunnels]]
# The port to open on the Server. Must be unique for each Server
remote_port = 6000
# optional param to specify the hostname/ip of the Internal service
# local_hostname = "127.0.0.1" # defaults to 127.0.0.1
# When a connection to the Server on remote_port is opened, data will be
# redirected to this port on the client
local_port = 8000
# pre-shared key that should match between Client/Server. Max of 512 bytes
psk = "abcd"
# the port the Sever should listen on
port = 12345
[crypto]
key = "key.pem"
cert = "cert.pem"
The above configuration files will
- Have the Server listen for clients on 12345
- Have the Client connect to a server at 127.0.0.1:12345 with TLS
- Have the Server open a listener on port 6000, which redirects all TCP traffic to the socket 127.0.0.1:8000 on the Client
- Server : a publicly facing server (always 1 from the perpsective of a client)
- Client: a server in a private network, such as behind a VPN or (CG)NAT.
- Internal: an internal service that will be proxied by simply-tunnel
- External: an external requestor that is trying to access Internal through simple-tunnel
- A Server is started
- One or more Clients connects to the Server (socket is marked keepalive) and
pushes
crate::config::Tunnel
s to the Server. - The Server listens on each of the provided
remote_port
s
- An External connects to
remote_port
- Server reads and data and ships it over the network to the correct Client
- Client takes the data and opens a connection to the correct Internal.
- Data is shuffled:
- by the Client between the Internal and the Server
- by the Server between the External and the Client
- When either an External or Internal kills the connection, the Client/Server does the same
- Make sure we're not leaking handlers
- Less sloppy error handling
- More testing
- Optimize network packets/buffers
- Limit active number of connections
- Profile and monitor memory consumption