Skip to content
Muslu Yüksektepe

CemirFastRustProxy

A high-performance asynchronous reverse proxy built on Tokio and Hyper.

CemirFastRustProxy is an asynchronous reverse proxy I wrote in Rust. A reverse proxy is the layer that receives requests from the internet, forwards them to the application servers behind it and sends the responses back. The project is built on Tokio and Hyper and brings TLS termination, load balancing, health checks, rate limiting and static file serving together in one program.

Purpose

With this project I wanted to build a reverse proxy where every domain is managed through its own small configuration file and where configuration changes do not require a restart.

Another goal was to make traffic move automatically to healthy servers when one of the backend services fails, and to stop sending requests to the failed server. For that reason the project puts a lot of weight on resilience mechanisms such as load balancing, health checks and a circuit breaker.

How it works

When the program starts, it reads the main configuration file, cemir.fast. This file holds general settings such as the listening addresses, the number of worker threads, the log level and client timeouts. Each domain is defined in a separate file with the .cem extension. These files are written in TOML and contain the virtual host details, backend servers, routing rules, health check settings, CSRF settings and custom error pages.

Requests arriving on port 80 are redirected to HTTPS automatically. On port 443, TLS is terminated with rustls, and thanks to SNI several domains can use different certificates on the same IP address. SNI is a TLS extension in which the client states which domain it wants to reach during the handshake.

Depending on the route that matches its path and method, an incoming request is either served as a static file from a local directory or forwarded to a group of backend servers. The backend is chosen with round-robin (in turn), least-connections (fewest active connections) or a latency-aware algorithm. The latency-aware algorithm tracks each server's response time with an exponentially weighted moving average and picks the fastest one.

The configuration files are watched with the notify library. When a file changes, the new configuration is read and swapped in without locks using arc-swap. Settings are updated without stopping the program or dropping open connections.

Key features

  • Every domain is configured independently with its own .cem file.
  • If certificate and log paths are not given, default paths based on the domain name are used automatically.
  • Active health checks probe each backend at set intervals, while passive checks update a server's state based on the outcome of real requests.
  • A circuit breaker cuts traffic to a server that keeps failing for a while, then tests whether it has recovered.
  • Retries with exponential backoff can be limited to idempotent requests, meaning requests that cause no side effects when repeated.
  • Rate limiting is applied per IP with a token bucket algorithm.
  • POST, PUT and DELETE requests from origins outside the allowed list must carry a CSRF header.
  • Responses can be compressed with gzip, zstd, brotli or deflate.
  • Custom HTML error pages can be defined for status codes such as 404, 500 and 502.
  • All traffic is written to central access and error logs, and optionally to separate log files per domain.

Technical stack

The project is written in the Rust 2024 edition. I use Tokio as the asynchronous runtime, Hyper and tower for the HTTP layer and tower-http for compression and timeouts. TLS is handled by rustls and tokio-rustls. Configuration is read with serde and toml. Concurrent data structures come from parking_lot, dashmap and crossbeam, and logging is done with tracing.

On the network side, socket2 applies settings such as SO_REUSEPORT, TCP_NODELAY and keep-alive to the listening sockets. jemalloc is used as the memory allocator. Release builds use the highest optimisation level, LTO and symbol stripping. Installing, starting and stopping are managed with a Makefile, and the program can run as a systemd service.

Use cases

  • Serving several domains over HTTPS from a single server.
  • Acting as a load balancer in front of several application servers.
  • Reducing downtime with a circuit breaker and health checks where backend services fail from time to time.
  • Setups where static sites and APIs need to be served from different paths under the same domain.
  • An example to study for anyone who wants to learn network programming and reverse proxy design in Rust.

Status

The current version number of the project is 2026.5.3. The repository also includes configuration examples, error pages and a systemd service file.

Category
Networking, servers & infrastructure
Year
2026

Technologies

  • Rust
  • Tokio
  • Hyper
  • Networking
  • Open Source

Links

  • GitHub https://github.com/muslu/cemirfastrustproxy

Back to all projects