A super-simple and minimally configurable HTTP reverse proxy for local development with support for HTTP/1.1, HTTP/2, TLS/SSL and web sockets.
This is a work in progress. It's not stable, it's not secure, and performance isn't great.
At this time, I wouldn't recommend using this for anything more than playing around. If you're looking for something production-ready, there are plenty of good alternatives out there.
- Support for clients using HTTP/1.1
- Support for clients using HTTP/2
- Support for TLS/SSL (HTTPS)
- Adds client
ip:port
tox-forwarded-for
header - Removes hop-by-hop headers (as defined in RFC2616) by default
- Support for connection pooling
- Support for web sockets
- Optionally don't remove hop-by-hop headers?
- Support for on-the-fly creation of SSL certificates
$ joubini --help
A super-simple and minimally configurable HTTP reverse proxy for local development with support for HTTP/1.1, HTTP/2, TLS/SSL and web sockets.
Usage: joubini [OPTIONS]
Options:
-H, --host <host> Hostname or IP [default: 127.0.0.1]
-P, --port <local_port> Local port for reverse proxy server to listen on [default: 80]
-p, --proxy <proxy_config> Configuration for proxy in format '<:local_port?></local_path?><:remote_port!></remote_path?>'
-C, --config <config_file> Path to configuration file
-T, --tls Serve over TLS
--pem <PEM> Path to SSL certificate as `.pem` or `.crt`. Required if `--tls` flag is enabled.
--key <KEY> Path to SSL certificate key as `.key`. Required if `--tls` flag is enabled.
-h, --help Print help
-V, --version Print version
Ordering of proxy configurations matters.
โ This will not work as (probably) intended:
joubini --proxy=myapp/api:3001/api --proxy=myapp:3000/ui
โ
This will work as (probably) intended:
joubini --proxy=myapp:3000/ui --proxy=myapp/api:3001/api
If a config file is provided then no other provided CLI arguments will be parsed.
Proxies defined in the config file follow the same pattern as via CLI, i.e.
</local_path?><:remote_port!></remote_path?>
# joubini.yml
port: 7878
host: localhost
tls: true
pem: /tmp/localhost.crt
key: /tmp/localhost.key
proxies:
- :3000 # http://127.0.0.1 -> http://127.0.0.1:3000
- api:3001/api # http://127.0.0.1/api -> http://127.0.0.1:3001/api
- admin:3002/dashboard # http://127.0.0.1/admin -> http://127.0.0.1:3002/dashboard
- db:5432 # http://127.0.0.1/db -> http://127.0.0.1:5432
Some common use cases are shown below. Combinations of these and other more complex use cases can be achieved, so see the more detailed documentation.
http://127.0.0.1/*
๐ ฎ http://127.0.0.1:3000/*
joubini -p ":3000"
http://127.0.0.1/api/*
๐ ฎ http://127.0.0.1:3001/*
joubini -p "api:3001"
http://127.0.0.1/admin/*
๐ ฎ http://127.0.0.1:3002/admin/*
joubini -p "admin:3002/admin"
joubini -p ":3000" -p "api:3001" -p "admin:3002/admin"
joubini \
--tls \
--pem "path/to/cert.pem" \
--key "path/to/key.key" \
--host localhost \
--port ":3000"
Note: see section below on generating an SSL certificate for localhost
using the included shell script.
- Install the Rust toolchain (instructions)
git clone https://github.com/nixpig/joubini.git
cd joubini
cargo build --release
mv ./target/release/joubini ~/.local/bin/
- Create a new CA and generate certificates using the included script:
bash -c scripts/ca.sh
- Specify the
/tmp/localhost.crt
and/tmp/localhost.key
when configuringjoubini
- Trust certificate:
cp /tmp/localhost.crt /etc/ca-certificates/trust-source/anchors/ && update-ca-trust extract
- In Chrome, add the
/tmp/myCA.pem
underchrome://settings/certificates
-> Authorities
I just wanted an interesting little project to work on in Rust which involves some basic networking stuff and that would actually be useful.
Any suggestions, feel free to open an issue.
In order to bind to port 80 (or any port below 1024), you'll need to grant access to the binary to do so.
Replace $PATH_TO_PROJECT
in command below with the absolute path to the project.
sudo setcap CAP_NET_BIND_SERVICE=+eip $PATH_TO_PROJECT/target/debug/joubini