A minimal ngrok
implementation in Rust, for educational purpose.
This work is largely based on rathole, especially the very first commit.
This is by no mean an idiomatic or correct Rust implementation. I am mastering
Rust and fairly new to writing networking code with tokio
.
There are two components in ngok
:
src/server.rs
: the server consists of two part, the control server and the proxy server.- The control server take in request from the clients, assign domain name and setup proxy server for each clients.
- The proxy server will receive requests through the provided domain name and proxy it to the client. running locally in the user machine.
src/client.rs
: the client receive the requests from the internet through the server, and further proxy it to the web server running locally by the user.
So in order to see this code in action, you'll have to run 3 service:
The server
binary expect the domains
to be provided. These are the domains that
users from the internet will send requests to. Since we are running locally, we could
mock those domains and have it work locally by manually editing our hosts file at
/etc/hosts
. Hence, this would only work in your local machine
# /etc/hosts
127.0.0.1 a.domain.com
127.0.0.1 b.domain.com
127.0.0.1 c.domain.com
Then, we can pass these to the server
and run it:
RUST_LOG=info cargo run --bin server -- --domains a.domain.com --domains b.domain.com --domains c.domain.com
By default, the server start at port 3001.
Apr 30 09:58:49.694 INFO server: Listening on TCP: 0.0.0.0:3001
You could customize it by passing it into --port
.
The client, on the other hand, only required the --domain-name
to be passed in, which is the
domain/IP for your ngok
server above:
# Since we are running our server locally, we can just pass in 127.0.0.1
cargo run --bin client -- --domain-name 127.0.0.1
Similarly, by default, it assumed the ngok
server is start at port 3001 and can be customize
by passing the value at --port
. You shall see the following output once it start successfully:
tunnel up!
Host: c.domain.com
On the ngok
server side, you will see the following logs:
Apr 30 09:59:55.722 INFO server: Accepting new client...
Apr 30 09:59:55.723 INFO server: Accepting new client...
Apr 30 09:59:55.723 INFO server: Listening to 0.0.0.0:3004
Apr 30 10:02:08.773 INFO server: Accept incoming from visitor_rx
This mean that the ngok
server has spin up another server at port 3004 to proxy the requests for the above client
.
The last piece of it is a working webserver running locally at port 4000. (Yes, it is currently hardcoded at port 4000...).
Once you have the above servers running, you can now curl
the provided domain on the client
output and see your requests going through the proxy:
# The reason we are hitting port 3004, is because the `ngok` server
# spin up the proxy server at port 3004.
curl http://c.domain.com:3004
You'll now see the ngok
client show some information about
the request we just send:
GET / 7.973482ms 200 OK
That's all. Hope you enjoy it. Once again, these only works locally.
If you wish to see it work deploy somewhere to the cloud, let me know. If it gain enough traction, it's definitely a future work I would like to work on.