Running a server

Network

On this page

The network link joins several rustmc servers into one network, with no proxy in front of them. Once servers are linked, their plugins can send each other messages, see who is online on every server, and send a player from one server to another. The link carries nothing by itself: what a network does (cross-server chat, a server selector, staff alerts) is up to the plugins you run.

Every server connects to every other server it names, and accepts a connection from each of them. So every server on the network lists every other one.

Turning it on

The network is off by default. Give each server a name, a listen address, the shared secret and its peers in rustmc.yml:

# rustmc.yml on the server named "survival"
network:
  enabled: true
  name: survival
  listen: 127.0.0.1:25700
  secret: "a long random string, the same on every server"
  peers:
    rusty:
      address: 127.0.0.1:25701
      join: rusty.example.net:25567
# rustmc.yml on the server named "rusty"
network:
  enabled: true
  name: rusty
  listen: 127.0.0.1:25701
  secret: "a long random string, the same on every server"
  peers:
    survival:
      address: 127.0.0.1:25700
      join: survival.example.net

The names under peers must be the other servers' own network.name, spelt the same way, and each server must list the others. A server only accepts a connection from a name it lists as a peer, and when it connects out it checks that the server answering has the name it expected.

For a player to be sent to a server, that server needs accepts-transfers=true in its server.properties. Without it, its door turns away anyone sent to it.

With network.enabled on, the server will not start unless the settings are valid: a usable name, a listen address that parses and can be bound, a secret of at least 32 characters, and every peer with a usable name and address. The console says which setting is wrong.

Settings

The default file holds these keys:

KeyDefaultMeaning
network.enabledfalseTurns the link on
network.name""This server's name on the network. 1 to 32 letters, digits, - and _. Every server needs its own
network.listen127.0.0.1:25700The ip:port this server listens on for its peers. It must be an IP address, not a host name
network.secret""The secret every server on the network shares. At least 32 characters

These are not in the default file, because there are none until you add them:

KeyDefaultMeaning
network.peers.<peer>.address""Where that peer listens (its network.listen), as host:port. This server connects to it there
network.peers.<peer>.join""The public address players are sent to, host:port or a host on its own for port 25565. Empty means nobody can be sent there
network.channels.<plugin>""Extra channel namespaces that plugin may use, comma-separated (moderation, chat), or * for every namespace

<peer> is the other server's network name and <plugin> is a plugin's name, each in letters, digits, - and _. Always give address its port: one written without a port is taken as 25565, which is the game port, not the link.

How it behaves

  • Connecting. At startup the server opens its listener and starts connecting to each peer. A peer that is down is retried, waiting 1 second at first and doubling up to 30 seconds between tries. The console says when a link comes up, when it is lost and why, and says once that a peer cannot be reached yet rather than on every try.
  • Proving the secret. Before anything else is sent, both ends prove they hold the same secret. The secret itself never crosses the wire, a recorded handshake cannot be replayed, and a connection from a name that is not a peer is closed straight away. A handshake has 5 seconds to finish.
  • Staying up. A quiet link is pinged every 10 seconds, and a connection silent for 30 seconds is dropped and made again.
  • Off the game's tick. The link runs on a thread of its own. A peer that is down, slow or gone does not slow the game.
  • Up and down. A peer counts as up when this server's own connection to it is up. Plugins can ask which peers are up.

Messages between plugins

Plugins publish messages on named channels and subscribe to the channels they want to hear.

  • A channel belongs to a plugin. A channel is written <namespace>:<name>, such as chat:global. A plugin may use its own name as the namespace and nothing else, unless network.channels.<plugin> grants it more. For example, chat: "moderation" lets the chat plugin also use moderation:... channels, and chat: "*" lets it use any.
  • Delivery is best effort. A message goes to every peer whose link is up at that moment. If the link drops before it is written, that peer never gets it, and nothing is sent again.
  • Arriving messages wait for the tick. A message is handed to its subscribers on the game tick after it arrives, up to 256 a tick. A message that no plugin on this server subscribes to is thrown away when it arrives.

The calls plugins use, and what each one answers, are listed in the server network host calls. Messages arrive as the network_message event, and can be changed or handled on the way in at the network_message hook point.

Who is online where

Each server tells its peers who is online on it, and its max-players. It sends this when a link comes up, and after that about once a second whenever it has changed. When a peer's link is down, nobody is listed for it.

  • Vanished players are listed with a flag saying they are hidden, so a plugin can show them to staff. They are not counted in a server's online count.
  • Fake players are listed as players, but are not counted in any server's online count. Every server can tell a fake from a real player by its uuid.
  • max-players is each server's own setting, as it last said it. It shows as 0 until a peer has said.

So a server selector can show "3/20" for each server the way the server list would.

Sending a player to another server

A plugin sends a player to a peer with the game's own transfer packet, to that peer's join address. The player's client disconnects and logs in to the other server, which treats it as a new login with its own checks: its whitelist, its bans, its online mode. Nothing the player carries moves with them: each server keeps its own player data.

The sending server does not check whether the peer is up, because a player can often reach a server that this server cannot.

Limits

  • 1 MiB a frame. A message's payload may be at most 1 MiB less 1,024 bytes. A peer that sends a larger frame has its connection closed.
  • 200 messages a second from each peer, in bursts of up to 400. Past that, the rest are dropped, and the console says so at most once a minute.
  • 8 MiB waiting to go to each peer. If a peer stops reading, what does not fit is dropped.
  • 16 MiB waiting for this server's plugins. If plugins cannot keep up, newer messages are dropped, and the console says so at most once a minute.
  • 16 connections part-way through a handshake at once. More are turned away, so a flood of connections cannot tie the link up.
  • A peer may list at most 10,000 players.
  • Bedrock players cannot be sent. The transfer packet is not translated for Bedrock clients, so sending a Bedrock player to another server does nothing for them.
  • Servers must run the same link version. A server speaking a different version of the link is turned away at the handshake.

Security and privacy

  • The link is authenticated but not encrypted. Anyone who can watch the traffic between two servers can read every message and every player list. Keep network.listen on loopback (127.0.0.1) when the servers share a machine. When they are on different machines, use a private network or a tunnel between them, and firewall the port so only your servers can reach it. If network.listen is not a loopback or private address, the console warns at startup.
  • The secret is the network. Any server holding it can join the network under a peer's name, speak on every plugin's channels, and tell the others who is online. Generate a long random secret, put the same value in every server's rustmc.yml, and keep that file private. The secret is never written to the log. If it leaks, change it on every server.
  • Player lists are shared. Every server on the network learns the name and uuid of everyone online on every other server, including vanished players. Plugins are expected not to show hidden players to anyone but staff, but the server cannot enforce what a plugin does with the list.
  • Refused connections are logged sparingly. A connection that fails the handshake is noted in the console, with its address, at most once a minute, so someone scanning the port cannot fill the log.

See also the Network section of rustmc.yml.

From docs/network.md in the RustMC repository at bbd81209ad.