tokio-sando

This is a simple proxy server implementation based on tokio.

The proxy is a server sandwiched (sando in Japanese) between the client and the client's destination. It will ask for the data from the destination on behalf of its client. In another word, the proxy essentially acts as a VPN. Please see how it works to know more.

How to Run

Open two terminals. One for the server, one for the client.

  1. Add 127.0.0.1 proxy.tokio.sando in your /etc/hosts
  2. On server-side, run ./server.
  3. On client side, run ./client.

Advance Setting

You can set the pattern for the destination's URL, in regex expression. For example, you can run the following commands:

On server side:

sh cargo run -- 127.0.0.1:7878 --pkcs12 domain.p12 --password "^G#=QVbVhh7Bt8t9L" --destination-pattern "([a-z]).(mozilla|rust-lang).org"

On client side:

```sh

Work

curl -vp --proxy "https://proxy.tokio.sando:7878" --proxy-cacert domain.crt "https://www.rust-lang.org/"

Work

curl -vp --proxy "https://proxy.tokio.sando:7878" --proxy-cacert domain.crt "https://www.mozilla.org/en-US/"

Won't work. Doesn't match "([a-z]).(mozilla|rust-lang).org" pattern

curl -vp --proxy "https://proxy.tokio.sando:7878" --proxy-cacert domain.crt "https://en.wikipedia.org/" ```

Generate a Certificate

This repo has a built-in certificate. If the certificate is expired or you wish to generate your own certificate, run the commands below:

  1. Generate a Self-Signed Certificate

    sh openssl req \ -newkey rsa:2048 -nodes -keyout domain.key \ -x509 -days 365 -out domain.crt

  2. Pack the certificate and the private key into a PKCS12 file

    sh openssl pkcs12 \ -inkey domain.key \ -in domain.crt \ -export -out domain.p12

  3. Now the server.sh and client.sh should work with your own certificate

Here is a server-client example.

How It Works

txt client proxy destination | | | * <--- 1 ---> * | | | | * ---- 2 ---> * ---- 3 ---> * | | | * <--- 5 ---- * <--- 4 ---- * | | | * ----------> * ----------> * relay data: client -> destination | | | * <---------- * <---------- * relay data: destination -> client | | |

  1. TCP and TLS handshake between client and proxy (HTTPS now)
  2. client sends a HTTP CONNECT request to proxy
  3. proxy establishs a TCP channel to the client's destination
  4. Once the above TCP channel is built
  5. notify client the HTTP tunnel is established
  6. Now proxy can relay data between client and destination via the tunnel

Use case

One use case for the proxy is the privacy-preserving service. Once the proxy builds the tunnel, the client can talk to the destination anonymously if the data relay via the tunnel is in HTTPS. The destination knows the client's request, but it has no idea of who the client is. The proxy knows both who the client and the destination are, but it has no idea of what they are talking about.

A demo here is the giphy search. Open two terminals. One for the server, one for the client.

  1. Add 127.0.0.1 proxy.tokio.sando in your /etc/hosts if 127.0.0.1 proxy.tokio.sando is not there yet
  2. On server-side, run ./server, or the following command if the server is for giphy service only

    sh cargo run -- 127.0.0.1:7878 \ --pkcs12 domain.p12 \ # or your own PKCS12 file --password "^G#=QVbVhh7Bt8t9L" \ # or your new password if using your own PKCS12 file --destination-pattern "api.giphy.com" # Server only accept HTTP CONNECT to "api.giphy.com"

  3. On client side, run ./giphy_search.sh to search the gif anonymously.

Please ensure the HTTP CONNECT request, which asks to relay data between the client and the destination, is in HTTPS protocol. Otherwise, the proxy will know the contents transferred between the client and the destination if tunnel communication is in HTTP since HTTP transfers data in plain text.

TODO