Skip to content

Latest commit

 

History

2 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

mcproxy

Minecraft reverse proxy. Reads the handshake, routes on the client-supplied hostname, balances across a pool of backends, then splices the raw TCP stream. Standard library only.

Build

go build -o bin/mcproxy ./cmd/proxy
go test ./...

Run

./bin/mcproxy -config config.json
./bin/mcproxy -config config.json -check   # validate and exit

Model

listeners  ->  routes (matched by hostname)  ->  backends (balanced)

A listener is one TCP bind. A route attaches to one or more listeners and claims a set of hostnames. A route has one or more backends, so the same hostname can spread across several servers and ports.

"listen": ":25565" is shorthand for a single listener named default; "backend": "host:port" is shorthand for a single-entry backends.

Routing

Matching order within a listener: exact host, then longest *.suffix, then the * catch-all. A host may be claimed by only one route per listener, so the same hostname can point at different backends on different ports. An unmatched hostname gets an in-protocol disconnect (login) or an MOTD (server-list ping) instead of a dead socket.

Balancing and health

balance per route:

value behaviour
round_robin default, honours weight
least_conn fewest active sessions wins
first strict order — pure failover

Health is passive, nginx-style: max_fails consecutive dial failures eject a backend for fail_timeout; the first success afterwards clears the streak. A client is dialled against up to max_attempts backends before giving up — safe, because nothing has been sent downstream yet. backup: true peers are used only once every primary is ejected; if literally everything is ejected the proxy still tries rather than black-holing the player.

Adding a server

Append a backend to a route, or a whole route:

{ "name": "skyblock", "listeners": ["public"], "hosts": ["sky.example.com"],
  "backends": [{"addr": "10.0.0.13:25565"}, {"addr": "10.0.0.13:25566"}] }

Within reload_interval the file mtime is noticed, re-parsed and validated; a bad config is rejected and the running routing table is kept. Live sessions are never interrupted by a reload. Backend health and counters reset on reload. listeners, admin_listen and max_conns need a restart.

Admin

admin_listen serves /healthz, /stats and /routes in plaintext, with per-backend up/down, active sessions and byte counters. No auth — bind it to localhost.

Notes

  • proxy_protocol prepends a PROXY v1 header so the backend sees the real IP. The backend must be configured to expect it.
  • Only the handshake and login-start packets are parsed; everything after is copied verbatim, so encryption and compression are untouched.
  • max_conns is process-wide, shared by all listeners. "# mcproxy-go"

About

A high-performance, zero-allocation TCP proxy server for Minecraft written in pure Go.

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Contributors

Languages