OpenVPN Load Balancer
A zero-dependency Python load balancer that spreads OpenVPN clients across servers and regions.
What OpenVPN Load Balancer is
A UDP proxy that sits between OpenVPN clients and a pool of OpenVPN servers and spreads the connections across them, region by region. Each region gets its own port, new clients go round-robin to healthy servers, a session stays on the server it started on, and dead servers drop out of rotation until they recover. Pure Python standard library on asyncio: nothing to install, and one text file of servers.
OpenVPN Load Balancer features
What it actually does.
Multi-region
A pool per region, such as USA, UK or Singapore, each on its own listening port starting at 1194.
Round robin with a cap
New connections are spread evenly across healthy servers, up to a per-server limit of 100 by default.
Health checks
Every server is pinged every 15 seconds. A dead one is taken out of rotation and put back when it answers again.
Sticky sessions
A client stays on the server it was given for the life of the tunnel, because moving an OpenVPN session mid-stream would break it.
Idle cleanup
Flows that stay silent for five minutes are released, and only clients that are really connected are counted.
Interactive or headless
A menu to start and stop the service, watch clients per region and check server health, or --headless for systemd.
How to use OpenVPN Load Balancer
From a fresh install to the thing working.
1 Describe your servers
- Clone the repository onto the machine that will be the load balancer.
- Edit server_list.txt: one server per line, as name, region, IP, port and, optionally, protocol. UDP is the default.
2 Run it
- python3 main.py opens the menu: start the service, check clients by region, see the service status, or stop it.
- python3 main.py --headless runs without the menu, for servers and systemd. Add --log-level DEBUG for detail.
- Root is only needed to bind ports below 1024.
3 Point the clients at it
- In each client’s .ovpn file, set remote to the load balancer’s address and its region’s port, with proto udp.
- Region ports are given out alphabetically: the first region gets 1194, the next 1195, and so on. Adding a region shifts them.
4 Tune it
- MAX_CLIENTS_PER_SERVER, IDLE_TIMEOUT_SECONDS, HEALTHCHECK_INTERVAL and HEALTHCHECK_TIMEOUT sit at the top of openvpn.py.
- Edit, save and restart to apply them.
Built with
Licence
Made by Kencypher. Not open source.
OpenVPN Load Balancer was written by Kencypher. The source is not published and is not licensed for reuse. You have permission to run it — that is the whole of it.
You may
- Run it on as many of your own machines as you like
- Use it for anything, including commercial work
- Pass an unmodified copy to a friend, free
You may not, without asking
- Sell it or charge for access
- Re-upload or mirror it anywhere
- Rebrand it or publish it as your own
- Decompile it or lift its assets
This is enforced. Re-uploading it, repackaging it, stripping the author's name off it or passing it off as your own is copyright infringement — protected without registration under the Berne Convention — and is pursued with DMCA takedowns to the host, CDN, app store and search engine, platform reports for impersonation, and legal proceedings where the infringement is commercial, repeated, or involves falsely claiming authorship.
Asking first is free, and the answer is usually yes — kencypher56@gmail.com. The only official source is this store; a copy from anywhere else is not one Kencypher published.
Good to know
- UDP is stateless, so it keeps its own flow table, keyed by client and server address and port, and uses it to send each reply back to the right client.
- A server that fails a health check keeps its existing flows until they idle out. It just gets no new ones, so nobody is forcibly disconnected.
- The load balancer must be able to send and receive UDP on the region ports, so open them in its firewall.
- Servers are listed in one text file, a line each: name, region, address, port and protocol. Adding a server is a line; removing one is deleting a line.
- A server is offered to a new client only when it is both healthy and under its client cap, so a recovering server is not handed the whole queue the moment it answers again.
- Flows are expired on a timer rather than on disconnect, because UDP has no disconnect: a client that stops talking is released once it has been quiet long enough.
- The full write-up, with the architecture diagram and every setting, is on the project’s documentation page.