⚡ Created by Kencypher ⚡

Cypher OpenVPN
Load Balancer

Free to use · Not open source · Python · UDP · Multi-Region

Python 3.8+ AsyncIO OpenVPN UDP Proxy No Dependencies Free Forever

It's ALIVE — and It Routes Traffic

They said it could not be done — that a free load balancer for OpenVPN was a madman's dream, a patchwork of impossible ideas stitched together on a stormy night. But I, Kencypher, descended into the laboratory, surrounded by flickering terminals and the smell of burning electrons, and I BUILT IT. From the raw sinew of Python's asyncio, the cold bones of UDP sockets, and the beating heart of a round-robin algorithm — I assembled life where there was none. It breathes. It distributes. It load balances.

— Kencypher, somewhere between sane and enlightened

Cypher OpenVPN Load Balancer is a fully async, zero-dependency Python load balancer built specifically for OpenVPN UDP traffic. It sits between your VPN clients and your pool of OpenVPN servers, intelligently distributing connections across multiple servers and multiple geographic regions — entirely for free.

No expensive hardware appliances. No paid SaaS. No bloated daemons. Just Python, a text file of servers, and the will to run it.

What the Creature Can Do

🌍

Multi-Region Routing

Define server pools per region (USA, UK, Singapore, Germany…). Each region gets its own listening port. Clients connect to the nearest region port — traffic stays local.

⚖️

Round-Robin Distribution

New connections are distributed evenly across all healthy servers in a region. No server gets overwhelmed while others idle. Configurable per-server client cap.

💓

Live Health Checks

Every server is pinged on a configurable interval. Unhealthy servers are immediately taken out of rotation. They are automatically reinstated when they recover.

👁️

Real-Time Client Tracking

Only currently connected clients are counted. Disconnected or timed-out clients vanish from the registry instantly — no stale data, ever.

⏱️

Idle Timeout Cleanup

Flows that go silent for longer than the configurable idle window are automatically released, freeing server capacity without manual intervention.

🖥️

Interactive CLI

A clean menu lets you start/stop the service, inspect clients by region, watch live connection counts, and check server health — all from the terminal.

🔧

Zero Dependencies

100% Python standard library. No pip installs. No virtual environments required. If Python 3.8+ is installed, this runs.

📄

Plain-Text Server Config

Add or remove servers by editing a single server_list.txt. No YAML hell, no JSON nightmares, no reload daemons — just save and restart.

The Anatomy of the Monster

The load balancer operates as a UDP proxy. It opens one listening port per region and maintains a persistent UDP socket to every upstream OpenVPN server. Client packets arrive, get assigned to a server via round-robin, and are forwarded. Return packets from the server are matched back to the originating client using an in-memory flow table.

VPN Client A ──┐
VPN Client B ──┤    UDP :1194     ┌─── REGION: USA ─────────────────────────────────┐
VPN Client C ──┼──────────────────────────► ClientProtocol (listener)          │
               │                                        │  assign_server() [round-robin]   │
               │                                        ▼                                  │
               │                              LoadBalancer + FlowTable                   │
               │                                        │                                  │
               │                         ┌─────────────┬┴─────────────┐            │
               │                         ▼             ▼             ▼            │
               │               ServerProto[0]  ServerProto[1]  ServerProto[2]        │
               │                   │               │               │            │
               │                   ▼               ▼               ▼            │
               │            usa-node-1      usa-node-2      usa-node-3         │
               └──────────────────────────────────────────────────────────────────────┘

VPN Client D ──┐
VPN Client E ──┼──────────────────────────► REGION: UK  (port :1195)
               │                              → uk-node-1, uk-node-2, uk-node-3

                                   ···  and so on per region  ···
    

The Flow Table

UDP is stateless, so the load balancer maintains its own flow table: a dictionary keyed by (client_ip, client_port, server_ip, server_port) that records the last packet timestamp. When the upstream server replies, the balancer looks up the flow, finds the original client, and sends the response back. This is the core of bidirectional UDP proxying.

Session Stickiness

Once a client is assigned to a server, that assignment is pinned in the ClientRegistry for the lifetime of the connection. OpenVPN sessions are long-lived — bouncing between servers mid-session would destroy the tunnel. Stickiness ensures continuity.

Health Checks

Every HEALTHCHECK_INTERVAL seconds, an async ICMP ping is sent to each server. If a server goes dark, it is marked unhealthy and excluded from new assignments. Existing flows to that server are preserved until they idle out — no forced disconnects.

The Parts of the Body

cypher-openvpn-loadbalancer/
    ├── main.py # Entry point — CLI or headless mode
    ├── cli.py # Interactive menu (start / check / stop)
    ├── interactive.py # Terminal display: live tables, region detail
    ├── loadbalancing.py # Orchestrator: boots regions, health loops
    ├── logic.py # LoadBalancer: round-robin, flow table, idle
    ├── connecting.py # Async UDP protocols: Client + Server
    ├── openvpn.py # Config parser, health checks, constants
    ├── clients.py # ClientRegistry: live connection tracking
    ├── count.py # ServerCounter: per-server stats display
    ├── server_list.txt # Your server definitions (edit this)
    └── requirements.txt # stdlib only — nothing to install
File Role Key Components
main.py Entry point Starts CLI or headless service; handles --headless and --log-level flags
cli.py CLI menu 5-option interactive menu; runs the service in a background thread
interactive.py Display layer Live client tables, region detail views, auto-refresh watch mode
loadbalancing.py Orchestrator LoadBalancingService: sets up regions, runs health check loops
logic.py Balancing logic LoadBalancer: round-robin, flow table, idle timeout, health flags
connecting.py Network layer ClientProtocol, ServerProtocol, create_region_services()
openvpn.py Config & constants Parses server_list.txt, assigns region ports, ICMP health checks
clients.py Client registry Thread-safe store of live clients only — no disconnected entries
count.py Stats display ServerCounter: per-server and per-region client counts
server_list.txt Configuration Plain text: name,region,ip,port,protocol — one server per line

Bringing It to Life

Region port assignment is automatic and alphabetical. The first region alphabetically gets port 1194, the second gets 1195, and so on. Add a region and restart — ports shift accordingly.

The Control Panel

cypher-lb — terminal
______ _ __ ___ __
/ ____/_ ______ / /_ ___ _____ / | / / |/ /
/ / / / / / __ \/ __ \/ _ \/ ___/ / /| |/ /| /
/ /___/ /_/ / /_/ / / / / __/ / / ___ / // |
\____/\__, / .___/_/ /_/\___/_/ /_/ |_/_//_/|_|
/____/_/ OpenVPN Load Balancer

┌─────────────────────────────────────┐
│ CYPHER OpenVPN Load Balancer │
├─────────────────────────────────────┤
│ Service: RUNNING │
├─────────────────────────────────────┤
│ 1. Start load balancing service │
│ 2. Check clients (by region) │
│ 3. Service status │
│ 4. Stop the service │
│ 5. Exit │
└─────────────────────────────────────┘

Enter option [1-5]: 2

══════════════════════════════════════════════════════════════
CYPHER VPN — LIVE CLIENT COUNT [2025-01-15 03:42:11]
Total Connected Clients: 47
══════════════════════════════════════════════════════════════

[USA] — 19 client(s) connected
Server IP:Port Clients
──────────────────────────────────────
203.0.113.10:1194 7
203.0.113.11:1194 6
203.0.113.12:1194 6

[UK] — 15 client(s) connected
198.51.100.5:1194 8
198.51.100.6:1194 7

[SINGAPORE] — 13 client(s) connected
192.0.2.20:1194 7
192.0.2.21:1194 6

Tuning the Creature

All core tunables live at the top of openvpn.py. Edit and restart to apply.

# openvpn.py — core tunables

MAX_CLIENTS_PER_SERVER = 100   # Hard cap per upstream server
IDLE_TIMEOUT_SECONDS   = 300   # 5 min silence = client released
HEALTHCHECK_INTERVAL   = 15    # Ping servers every 15 seconds
HEALTHCHECK_TIMEOUT    = 3     # Ping timeout in seconds

server_list.txt Format

# name , region , ip , port , protocol(optional)

my-server,USA,10.0.0.1,1194,udp

# Omit protocol → defaults to udp
my-server-2,USA,10.0.0.2,1194

# Multiple regions → multiple listening ports assigned automatically
Firewall note: The load balancer must be able to send and receive UDP packets on the region listening ports (1194, 1195, … by default) AND reach each upstream server on its configured port. Ensure your firewall rules allow this traffic in both directions.

Why Free?

Every other load balancer wants your credit card. HAProxy is powerful but not built for VPN UDP flows. AWS NLB costs money. Dedicated appliances cost more money. I built this because the community deserves a free, understandable tool that does exactly one job and does it well. No telemetry. No license keys. No "enterprise tier." Just code. Forever.

— Kencypher

🆓

Free to use

Run it anywhere, including commercially, at no cost. It is not open source: the code is readable here, but not licensed for reuse or redistribution. See LICENSE.txt.

🔍

Transparent

~600 lines of plain Python. Read every line. Understand everything. No black boxes.

🛠️

Tunable

The client cap, idle timeout and health-check timing are constants at the top of openvpn.py. Change them and restart.

What You Need