Erebus: A Rootless User-Space VPN Proxy

Erebus enables rootless VPN connectivity in restricted environments

Erebus is a user-space VPN proxy that allows users to establish VPN connections without requiring root privileges or modifying the host's networking stack. By implementing the OpenVPN protocol and a TCP/IP stack entirely within a single process, Erebus bypasses the need for kernel tun/tap interfaces and routing table modifications, making it ideal for environments where sudo access is unavailable, such as CI runners, sandboxes, and unprivileged containers.

Architecture: Moving the VPN stack to user space

Erebus replaces the traditional kernel-based routing and TCP handling with its own internal logic. The only system privilege required by the tool is the ability to open a standard network socket.

The data flow

When a request is made, the data follows this path:

  1. Local HTTP Client: A client application points to the local Erebus proxy.
  2. HTTP Proxy: Erebus accepts and relays the request.
  3. User-Space TCP/IP Stack: The process builds and parses IPv4, TCP, and ICMP packets by hand.
  4. Encryption: Packets are encrypted using the OpenVPN static-key (wire format v1) protocol, applying HMAC and packet IDs.
  5. Transport: The encrypted data is sent as a UDP datagram or TCP frame to the OpenVPN server.

Key Features and Capabilities

Rootless Operation

Erebus requires no sudo permissions, no setup scripts, and does not touch the host's interfaces, routes, or DNS settings. It can be started and stopped as a standard user process.

Opt-in Traffic Routing

Connectivity is explicit rather than system-wide. Users must point specific applications to the local proxy to route traffic over the VPN.

  • Outbound: A local HTTP/1.x proxy forwards requests to resources on the VPN.
  • Inbound: Port forwards expose local services to VPN peers bidirectionally.

Protocol Support

  • OpenVPN: Supports static-key mode (pre-shared key) over UDP or TCP. It supports CBC ciphers (AES, ARIA, Camellia) and various HMAC digests.
  • IPsec: Includes an IKEv2 control plane and an ESP data plane that interoperate with strongSwan. Because rootless processes cannot send raw ESP, all traffic is UDP-encapsulated (NAT-T) using pre-shared keys.

Usage and Installation

Erebus is written in Common Lisp (SBCL) and is distributed as a Debian package for Debian/Ubuntu derivatives.

Quick Start Configuration

A minimal configuration for an outbound UDP proxy is defined in an INI file:

[erebus]
client-ip = 10.8.0.2

[openvpn-server]
proto  = udp
 host   = vpn.example.com
port   = 1194
secret = /etc/erebus/static.key
cipher = AES-256-CBC
auth   = SHA256

[proxy-out]
address = 127.0.0.1
port    = 11023

To use the proxy, users can route traffic via the command line: http_proxy=http://127.0.0.1:11023 curl http://10.8.0.1/

Performance and Limitations

Erebus is an early-stage experimental project that prioritizes correctness and clarity over performance.

Use Case Suitability

Ideal For Not Ideal For
Internal HTTP services in unprivileged containers System-wide VPN routing
CI jobs needing private endpoints Bulk data transfer
Sandboxed or multi-tenant hosts TLS-mode OpenVPN (certificates)
Exposing a single local port to a VPN peer HTTPS CONNECT tunneling or SOCKS

Performance Trade-offs

Because the implementation sends data one piece at a time and waits for confirmation before sending the next, large downloads are significantly slower than a standard proxy. This design choice ensures code simplicity and interoperability.

Sources