This provides a toolkit for securely making connections between two computers anywhere in the world.
The service is made up of 3 components:
- Router: a cloud service that routes traffic between a host and a client.
- Host: a program that wants to allow clients to connect remotely.
- Client: a program that wants to connect to a host.
A connection to the router uses a websocket over https. So the connection between the host and router and the connection between the client and router are secured by TLS. It is recommended that the tunnelled connection (between client and host) also use another layer of security (e.g. TLS) to ensure that the router cannot observe or tamper with the communications between host and client.
The host and client need to supply a cryptographically signed token to prove that they are permitted to
- connect to this router
- offer a portal with a specific unique ID (host)
- connect to a portal with a specific unique ID (client)
The router validates the token. A sample program for generating tokens is provided, but it's assumed that the production tokens are generated by another service that's not included here. The portal id must be unique to the host, but has no inherent meaning: it's just an identifier used to help the router connect a client to the expected host. The client token will only open a connection to the host possessing the token for the same portal id.
The router is designed to run on CloudFlare workers, using hibernatable websockets so that an idle connection doesn't consume any resources. This requires a paid CloudFlare account. A demo server is provided for local experimentation, but the demo server can't do websocket hibernation so every open socket consumes server resources.
These steps require Wrangler, npm, worker-build 0.1.2 and wasm-pack.
Set the jwt token secret:
$ cd cf/
$ echo 'jwt_secret=<secret-value>' >.dev.varsRun the router:
$ cd cf/
$ npx wrangler devCreate a token for the echo host:
$ cargo run --example make-token -- --role host --portal-id 1234 --secret <secret-value> --days 1 <name-of-host>With that host token in the environment, run the echo host:
$ RUST_LOG=debug cargo run --example echo-host -- --server ws://localhost:8787Create a token for the echo client:
$ cargo run --example make-token -- --role client --portal-id 1234 --secret <secret-value> --days 1 <name-of-client>With that client token in the environment, run the echo client:
$ RUST_LOG=debug cargo run --example echo-client -- --server ws://localhost:8787Create a host and client token as above. Then run the host and client as follows:
Run a host that offers to tunnel connections to myserver port 80:
RUST_LOG=debug cargo run --example tcp-forward -- --server ws://localhost:8787 --service my_tcp_service --reconnect host --target-host <myserver> --target-port 80Run a client that opens a local port 8000 and proxies data through the tunnel.
RUST_LOG=debug cargo run --example tcp-forward -- --server ws://localhost:8787 --service my_tcp_service --reconnect client --port 8000If you need to reset the portal secret:
$ npx wrangler secret put jwt_secretDeploy the router:
$ cd cf/
$ npx wrangler deployThe host and client programs will work the same way, except you will need to specify the real URL, e.g. wss://portal-router.your-account.workers.dev.
Code in crates/ is (C) 2024 Matic Robots, Inc. and is distributed under the Apache-2.0 license.