Monopiped

Monopiped is a pastiche of Colin Percival's spiped.

Motivation

The idea of Monopiped started when working on sobfs which was in turn inspired by this write up by George Murdocca on how IDS middleboxes can be defeated using rot-13 encryption. These are all ideas for testing and improving the security of IDS middleboxes.

After writing sobfs I learned about spiped which was a better solution than sobfs/rot-13 for defeating IDS middleboxes.

Originally Monopiped was intended to modify spiped and replace crypto primitives by those available in Monocypher (e.g. X25519 instead of finite field Diffie-Hellman, ChaCha20Poly1305 instead of AES-CTR+HMAC, etc.).

However since inception there was no progress on this front.

The idea pivoted from being a modification of spiped to instead a reinterpretation in Rust, primarily as a technical exercise for the author to learn Rust and dabble in cryptography and sockets.

Build

Install Rust and run cargo build -r. (You want -r for release version which is at least an order of magnitude faster than debug build.)

Operation

There are two "modes" that monopiped can be run as:

Tunneling over TCP

The usual way to run monopiped is by tunneling a TCP application like ssh encrypted over TCP.

This is a depiction of how a client and server would run:

┌────────────────────────────────────────────────────┐ ┌──────────────────────────────────────────────────┐ │ client │ │ server │ │ │ │ │ │ ┌────────────────────────┐ ┌───────────┐ │ (encrypted over tcp) │ ┌───────────┐ ┌────────────────────────┐ │ │ │ application (e.g. ssh) │◀──────▶│ monopiped │◀───┼───────────────────────────────────┼──▶│ monopiped │◀─────▶│ target (e.g. sshd) │ │ │ └────────────────────────┘ └───────────┘ │ │ └───────────┘ └────────────────────────┘ │ │ │ │ │ └────────────────────────────────────────────────────┘ └──────────────────────────────────────────────────┘

As an example of tunneling SSH, you would:

Then on the client you can connect to the SSH server by running: ssh -p3000 127.0.0.1.

Tunneling over Websockets

monopiped also supports tunneling TCP application encrypted over WebSockets.

This is a depiction of how a client and server would run:

┌────────────────────────────────────────────────────┐ ┌────────────────────────────────────────────────────────────────────────────────────────┐ │ client │ │ server │ │ │ [encrypted over │ │ │ ┌────────────────────────┐ ┌───────────┐ │ WebSockets via HTTP(S)] │ ┌────────────────────────────┐ ┌───────────┐ ┌────────────────────────┐ │ │ │ application (e.g. ssh) │◀──────▶│ monopiped │◀───┼───────────────────────────────────┼──▶│nginx/caddy/websocket proxy │◀─────▶│ monopiped │◀──────▶│ target (e.g. sshd) │ │ │ └────────────────────────┘ └───────────┘ │ │ └────────────────────────────┘ └───────────┘ └────────────────────────┘ │ │ │ │ │ └────────────────────────────────────────────────────┘ └────────────────────────────────────────────────────────────────────────────────────────┘

What's different to TCP is the inclusion of a webserver that will front the monopiped on the server side.

As an example of tunneling SSH, you would:

Then on the client you can connect to the SSH server by running: ssh -p3000 127.0.0.1.

Here is a sample Caddyfile to use with the Caddy v2 webserver to setup a route to a websocket backend, where the backend will be monopiped listening in websocket mode on port 3000:

server.example.com:80 server.example.com:443 { root * /var/www/html file_server reverse_proxy /ssh 127.0.0.1:3000 }

The above Caddyfile listens on both HTTP and HTTPS. Since the transport is end-to-end encrypted between client and server over WebSockets or TCP, it is perfectly fine to use HTTP and still maintain confidentiality and integrity. Packet captures of traffic over HTTP would just show WebSocket binary payloads and little else.

Aspirations

~Currently the program implements a one thread per connection model. To minimise resources and improve scalability (as if it's needed) maybe the model will be switched to asynchronous network I/O using Tokio.~

~It would also be nice to support proxying over WebSockets.~