Shield
Protects the proxy from Minecraft-specific attacks such as connection, ping and login floods, built into the cloud.
An open Minecraft port is an easy target. Bot waves, ping floods and malformed packets can bring a Velocity proxy to its knees long before the game servers behind it even notice, and every player on the network is kicked with it. Most networks answer this with an external protection service or a hand-built HAProxy setup in front of the proxy, with its own configuration, its own dashboard and one more thing that can break.
MuteCloud ships that protection built in. The shield sits in front of every proxy on its node, takes the connections, checks them in seven layers and hands only clean ones on to Velocity. Server list requests are answered from its own cache, so a ping flood never reaches the proxy at all.
One switch. shield on, then restart the proxy with groups <Proxy> rollout. MuteCloud moves
Velocity to an internal port, switches it to the PROXY protocol and takes over the public one.
Real player IPs. Velocity and every plugin behind it keep seeing the real address of each player, so IP bans, alt checks and statistics keep working. This is where many self-built setups fail.
Part of the cloud, not bolted on. Rejections, blocks and attacks show up in shield, in the
dashboard, as metrics and as alerts through your webhook. Limits can be changed while it runs.
Honest about its limits. The shield stops the attacks that are aimed at Minecraft itself, which is what small and medium networks mostly face. A pure bandwidth flood that fills the line to your machine never reaches it; against that only filtering at your provider helps.
How it works
The shield is built into MuteCloud and sits in front of every proxy on its own node. It accepts the players' connections, checks them and hands only clean ones on to Velocity. It answers server list requests itself, so a ping flood never reaches the proxy in the first place.
addon enable shield and addon disable shield do the same as shield on and shield off;
addon lists it as a built-in addon next to the others.
What it protects against
The shield works in layers, from the raw connection up to the player name.
| Layer | What is checked |
|---|---|
| Connection | at most per_ip_connections open connections per address, new ones only at per_ip_rate per second with a burst of per_ip_burst, at most global_connections in total |
| First packet | if it does not arrive within first_packet_ms, the connection is closed, which keeps half-open connections short |
| Handshake | length fields, packet id, address length and next state must be valid, otherwise the connection is closed immediately |
| Server list | at most status_per_second pings per address, the answer comes from the cache |
| Login | at most logins_per_minute per address, the name must match username_pattern |
| Score | every violation costs points, from score_threshold on the address is blocked for block_minutes minutes |
| Block list | single addresses and ranges, with or without expiry, survives restarts |
The score drops by score_decay every minute. A successful login subtracts 20, so regular
players do not slide into a block. Malformed packets cost 30, a first packet that arrives too
late 15, every exceeded limit 10, a ping over the limit 1, and an attempt despite a block 50.
Opening a connection and closing it again without sending a single byte, such as a
reachability check, costs nothing.
After the login the shield passes the bytes through unchanged. Encryption between player and Velocity is not affected; the shield only sees the handshake and the name.
What it does not protect against
The shield runs on the same machine as the proxy. A flood that simply fills the line, that is volumetric attacks with UDP, SYN or reflection in the gigabit range, never even reaches the shield. Only filtering in front of the machine helps against that, at the server's hosting provider or with a service that protects Minecraft traffic. The shield complements such a setup, it does not replace it.
Nor does it detect bots that log in like real players, with a valid name and within the allowed rate. For that there are plugins on the proxy that check in game.
Switching it on
This writes enabled = true under [shield] in network.toml and places a marker
mutecloud-shield.toml in the template of every proxy group. That changes the template, and
the proxy picks up the shield on its next start. By default proxies wait for approval, exactly
as with any other change to their template:
Until then the running proxies keep accepting players directly as before, and shield shows
"on, waiting for the proxies to restart". Switching it off takes the same way back.
When a proxy with the marker starts, the following happens:
- The shield binds the public address, by default the proxy's port on all addresses.
- Velocity gets a free port between 40000 and 40999 on
127.0.0.1and is no longer reachable from outside. - With
proxy_protocol = truethe cloud setshaproxy-protocol = trueunder[advanced]in the proxy'svelocity.toml. The shield sends a PROXY protocol version 2 header ahead of every connection, so Velocity and every plugin see the player's real address.
If the public address is already taken, the proxy starts without the shield as before, and the
log says why. Without the marker, velocity.toml stays as the template defines it.
Settings
The limits apply immediately, without a restart. Only enabled, listen and
proxy_protocol need one, because they change what Velocity listens on.
| Key | Meaning |
|---|---|
listen | empty means 0.0.0.0 on the proxy's port, a bare IP keeps the port, IP:port sets both |
proxy_protocol | pass real player addresses on to Velocity, should stay on |
global_connections | counts all open connections, including players already playing, raise it for large networks |
status_cache_seconds | how often the shield fetches the server list from the proxy |
alert_rejects_per_minute | from this many rejections in one minute shield-attack is sent, 0 turns it off |
allow | addresses and ranges that are never blocked and never limited |
allow is empty by default. If many players share one address, for example at a LAN event,
that address belongs here, otherwise the per-address limits apply. The same goes for your own
services that log in or ping often.
The shield fetches the server list from the proxy separately for every game version that is currently asking, for at most sixteen versions at once. Until a new version has been fetched for the first time, the client gets the generic answer with its own protocol version, just as Velocity would do. If the proxy is not reachable, the cache stays empty and the request goes through.
Blocks
Without minutes a block is permanent. shield list shows every block with remaining time and
origin; automatic blocks appear there as automatisch with their score. Existing connections
keep running after a block, only new ones are rejected. The list is stored in
shield/blocklist.json in the cloud's directory and saved every minute and on shutdown.
Watching it
shield shows which proxies the shield is in front of, how many connections are open, what
was rejected and why, and the most conspicuous addresses with their score. The dashboard shows
the same in the Network section, where addresses can also be blocked directly.
Two events are sent through the alerts, each at most once within
quiet minutes:
| Event | When |
|---|---|
shield-attack | more rejections in one minute than alert_rejects_per_minute |
shield-block | the shield has blocked addresses automatically, with count and last address |
/metrics exposes mutecloud_shield_connections_accepted_total,
mutecloud_shield_connections_rejected_total with the reason as reason,
mutecloud_shield_connections_active, mutecloud_shield_front_connections per proxy,
mutecloud_shield_blocked, mutecloud_shield_auto_blocks_total,
mutecloud_shield_status_total with from set to cache or proxy,
mutecloud_shield_logins_total and mutecloud_shield_bytes_total.
In a cluster
Every node protects only the proxies running on it and keeps its own block list. The marker in
the template comes from the leader along with the templates, so shield on and shield off
switch the whole cluster. Each node reads the limits from its own network.toml, and shield
shows the state of the node it runs on.
Outlook
Dedicated edge nodes are planned: a node on another machine that runs no servers, only the shield. It accepts the players and passes them over the private network to the least loaded healthy proxy in the cluster. That keeps the address of the game machine hidden, and its proxies only accept connections from the edge nodes.