rama (ラマ)

rama is a proxy framework using Tokio written purely in Rust, it's services all the way down.

The name is Japanese for rama, the mascot and spiritual inspiration of this proxy framework.

rama is in early development and not ready for production use yet. Use this framework at your own risk and your own responsibility.

Look into rama's README for more information.

Issue backlog

Tracking of active issues/features that require urgent attention:

Goals

With rama you can should be able to write any typical tls/http proxy, without having to write all the boilerplate code first, but by keeping all the power that comes with having a source-code driven proxy.

The following technologies are used under the hood of rama, and are for the most part exposed to the user:

All these technologies are built-in to rama and drive many of its provided services. Llama is also bundled with some custom middleware layers as well that can be used in combination with these services. Important to know is that:

As such you should easily be able to implement your own Service for any layer you wish, while at the same time retaining the ability to seamlessly piggy-back on rama for most of your proxy logic.

Services

With Tower everything is a service. A service takes in a request and outputs either an error or a response. What the actual types for these request-response pairs are, is up to you and depend mostly on the layer it is used. In tower it is typical that a service wraps another service, as such all your services and middleware will stack on top of each other, like a... tower.

Socks5 Proxy Example

A socks5 proxy could be implemented as follows:

tcp::Server ⤷ socks5::Server ⭢ /target/

A typical rama proxy will start with tcp::Server. This gives you an accepted TcpStream.

Given "Accept" is a kernel function this is the lowest level you can go painlessly. Should you want to be able to act upon incoming tcp clients prior to accepting, you'll need to implement it yourself on kernel level, and make your own Rust service to make use of that kernel module.

eBPF could help you achieve this, which can be done using https://github.com/foniod/redbpf. Note though that this comes with a lot of effort on your side while at the same time not giving a lot in return.