rproxy 0.2.0

Platform independent asynchronous UDP/TCP proxy
Documentation

rproxy

A blazing fast, cross-platform, transparent TCP & UDP proxy written in Rust. No bloat, no config headaches — just simple port forwarding that works out of the box.

Now ships with rproxy-edit, a built-in terminal UI for managing your proxy configurations visually instead of hand-editing JSON.

Installation

cargo install rproxy

This installs both rproxy (the proxy) and rproxy-edit (the config editor).

Quick Start

Single Proxy

Forward local port 8080 to a remote service:

rproxy -b 0.0.0.0:8080 -r 10.0.0.5:3000 -p TCP

Forward UDP traffic (e.g. DNS, VPN tunnels):

rproxy -b 0.0.0.0:1194 -r vpn-server.example.com:1194 -p UDP

Multiple Proxies with a Config File

Run many proxies at once from a single JSON config:

rproxy -c proxies.json

Where proxies.json looks like:

[
    {
        "bind": "0.0.0.0:8080",
        "remote": "10.0.0.5:3000",
        "protocol": "TCP"
    },
    {
        "bind": "0.0.0.0:1194",
        "remote": "vpn-server.example.com:1194",
        "protocol": "UDP"
    }
]

Edit Configs with the TUI

Tired of editing raw JSON? Open any config in the built-in terminal editor:

rproxy-edit proxies.json
┌─────────────────────────────────────────────────┐
│  rproxy config editor — proxies.json            │
├────┬──────────────────┬──────────────────┬───────┤
│  # │ Bind             │ Remote           │ Proto │
├────┼──────────────────┼──────────────────┼───────┤
│> 1 │ 0.0.0.0:8080     │ 10.0.0.5:3000    │  TCP  │
│  2 │ 0.0.0.0:1194     │ vpn-server.ex... │  UDP  │
├────┴──────────────────┴──────────────────┴───────┤
│ [NORMAL] j/k:nav  i:edit  a:add  d:del  ?:help  │
└─────────────────────────────────────────────────┘

Keybindings (Helix/Vim-style):

Key Action
j / k Navigate up/down
i / Enter Edit selected entry
a Add new proxy entry
d Delete selected entry
Tab / Shift+Tab Cycle fields in edit mode
Space Toggle protocol (TCP/UDP)
:w Save
:q Quit
:wq Save and quit
? Show help

CLI Reference

rproxy — A platform neutral asynchronous UDP/TCP proxy

Options:
  -r, --remote <host>:<port>    Remote endpoint to forward traffic to
  -b, --bind <ip>:<port>        Local address to listen on
  -p, --protocol TCP|UDP        Protocol (UDP by default)
  -c, --config <file.json>      JSON config for multiple proxies
  -d, --debug                   Enable debug logging
  -l, --logger_settings <file>  Logger config file (YAML)

Use Cases

Expose a Local Development Service

Forward traffic from a public-facing port to a service running on localhost:

rproxy -b 0.0.0.0:443 -r 127.0.0.1:3000 -p TCP

OpenVPN / WireGuard Relay

Relay VPN tunnel traffic through an intermediary server. rproxy handles UDP natively with per-client session tracking:

rproxy -b 0.0.0.0:1194 -r vpn-backend.internal:1194 -p UDP

Multi-Service Gateway

Run a single rproxy instance as a lightweight gateway that fans out to multiple backend services:

[
    { "bind": "0.0.0.0:80",   "remote": "web-server:8080",      "protocol": "TCP" },
    { "bind": "0.0.0.0:443",  "remote": "web-server:8443",      "protocol": "TCP" },
    { "bind": "0.0.0.0:5432", "remote": "db.internal:5432",     "protocol": "TCP" },
    { "bind": "0.0.0.0:53",   "remote": "dns.internal:53",      "protocol": "UDP" }
]
rproxy -c gateway.json

SSH Jump Host Alternative

Forward SSH access to machines behind a firewall without configuring SSH ProxyJump:

rproxy -b 0.0.0.0:2222 -r 192.168.1.100:22 -p TCP

Then connect with: ssh -p 2222 user@proxy-host

Game Server Relay

Relay UDP game traffic to reduce latency or provide a stable entry point:

rproxy -b 0.0.0.0:27015 -r game-server.region.example.com:27015 -p UDP

Managing Configs Across Environments

Use rproxy-edit to maintain separate configs for different environments:

rproxy-edit configs/production.json   # edit production proxies
rproxy-edit configs/staging.json      # edit staging proxies
rproxy -c configs/production.json     # run production

The editor validates addresses and protocols before saving, so you catch mistakes before they hit production.

Configuration Format

Each config file is a JSON array of proxy entries:

Field Type Description
bind string Local ip:port to listen on
remote string Remote host:port to forward to (supports hostnames with auto DNS refresh)
protocol string "TCP" or "UDP"

rproxy automatically re-resolves DNS hostnames every 30 seconds, so you can point at dynamic endpoints without restarts.

Dynamic DNS Resolution

Most proxies resolve a hostname to an IP once at startup and hold onto it forever. If the IP behind that hostname changes, traffic breaks and you have to restart the proxy. rproxy takes a different approach: it re-resolves DNS every 30 seconds and seamlessly switches to the new IP with zero downtime.

This matters more than you might think:

Cloud Instances with Elastic IPs

Cloud providers frequently reassign public IPs when instances are stopped, restarted, or auto-scaled. Your VPN relay points at vpn.example.com, and after a routine maintenance window the underlying IP changes from 52.14.88.10 to 52.14.91.33. A traditional proxy keeps sending packets to the old IP — connections time out and users call you at 3 AM. rproxy picks up the new IP on the next 30-second cycle automatically.

{ "bind": "0.0.0.0:1194", "remote": "vpn.example.com:1194", "protocol": "UDP" }

Kubernetes Services and Rolling Deployments

In Kubernetes, a Service or Ingress hostname can resolve to different pod IPs after a rolling deployment. If you're proxying traffic into the cluster through an external rproxy, the backend IP may shift every time a deployment rolls out. Dynamic resolution means deployments never cause proxy downtime.

{ "bind": "0.0.0.0:8080", "remote": "my-app.k8s.internal:8080", "protocol": "TCP" }

DNS-Based Failover and Load Balancing

Services like Route 53, Cloudflare DNS, or Consul use DNS records for health-based failover — when a primary server goes down, the DNS record updates to point at a standby. rproxy follows the DNS change within 30 seconds, so failover works end-to-end without manual intervention.

{ "bind": "0.0.0.0:5432", "remote": "db-primary.service.consul:5432", "protocol": "TCP" }

Dynamic Home / Edge Networks

If you're running rproxy on a home server or edge device, the remote endpoint might be behind a dynamic DNS provider (e.g. myhouse.duckdns.org). The ISP rotates your IP periodically. rproxy handles this transparently — no cron jobs, no restart scripts.

rproxy -b 0.0.0.0:2222 -r myhouse.duckdns.org:22 -p TCP

What Happens Under the Hood

Every 30 seconds, rproxy re-resolves the hostname for each proxy. When a new IP is detected, it logs the change and routes all new connections to the updated address — existing connections continue on the old IP until they naturally close. No connections are dropped, no traffic is interrupted.

License

MIT