Big picture Link to heading
This was a few months long project at the end of 2020. Given a ~30-50 Minecraft player both Java (original) and Bedrock (rewritten cross-platform optimized) Edition. The rigs available is a Contabo VPS 6 cores, 16GB ram,400 GB SSD
and a AMD A8 desktop PC 8GB ram 250GB SSD
. Above all this we used an S3 Glacier as backup storage. To let all players to play together we need an extra bit, a plugin called Geyzer,which is a translation layer between java edition server and bedrock edition clients. There are some restriction with this plugin as the clients have different protocols, which means that a general java plugin would look broken on the bedrock client. It is known that Java servers are resource hungry beasts, which means we need to keep it in mind that there will be services higher and lower priorities. Needs to be noted ,that this game has many hack/cheat which never been fixed ,because it’s a non-competitive sandbox creative game( I will elaborate later) Which is why this whole operation needs to be data resilient
. So that anytime some skiddy destroys the world or do something nasty ,we need a backup solution just like duplicati
to be back on track in no-time.
BASE Link to heading
For a base I used an Ubuntu 20.04 LTS server on both machine, and installed docker-ce , openssh-server, ufw, fail2ban, wireguard. Created a directory for the infrastructure. minecraft
directory where i store everything related to server and next to it a duplicati
for a scheduled backup solution.
SERVICES Link to heading
The production server was the Contabo VPS
and the AMD A8 Desktop
was the dev/test branch mostly for “builders”. As the minecraft servers behind the reverse proxy I will called them ąlt-server
from this point onward.
Service | Specific version | Extra information |
---|---|---|
Minecraft Java server | PaperMc | Plugins: ExploitFixer, |
Minecraft reverse proxy server | Velocity | Plugins: Geyzer, Viaversion, Viabackward Luckperms, Skinsrestorer |
SQL server | Postgresql | |
VPN | Wireguard | |
Backup | Duplicati |
Layout:
- Securing
ssh
with moving port to a really high port and activatefail2ban
on it. With these 2 changes we got rid of 99% of the botnets. - Setting up 2 Wireguard connection for different purpose. One for Privileged gamer/builder, one for Minecraft servers later to join behind the proxy called
Velocity
and give read-only access toPostgresql
databases for the used auth and permission plugin - Testing out Minecraft server side plugins to work with both Clients without bugs. And build out Lobby and auth server (Most time consuming of all)
- Make auth and lobby worlds read-only so even someone try to destroy it would take a server restart to reload it.
- Setup
duplicati
to make backup daily of thesurvival, postgresql
into S3 Glacier and of coursetest server Creative
, so that we have multiple snapshots. - Privileged player could only connect trough our own VPN
- Security plugin called EpicGuard would block players from connecting from TOR and other VPN/PROXY
Plugins TL;DR :
-
Operational/Security plugins:
-
Geyzer: Translation layer between the java server and the bedrock clients
-
Viaversion/Viabackward: Allows different versions of java client to connect to the server. This is important as we have different server versions behind the reverse proxy called Velocity
-
EpicGuard: Security plugin with Geographical , Anti-bot, Proxy/VPN(proxycheck.io) checks. Blocks most of the skiddys
-
Luckperms: permission plugin, however needs to be noted that this plugin has many features, but it was coded in a really unsecure way and there are logic holes in the plugins. Nevertheless we need this plugin, because this is still one of the best on the market as of yet.
-
ExploitFixer: As the name suggest, this one fixing the basic, low hanging fruit exploits and on detection it would kick the player out of the game. We noticed that when its used together with Viaversion/Geyzer it could cause some false positive results and would kick bedrock player, however this was rare and caused only minor annoyance for the players.
-
AuthMe: This plugin only used on the Authentication alt-server. Where the Velocity(reverse proxy) directs the players first. If you player fails the authentication the game will kick them out and they have to reconnect. This plugin has some bugs, which allows attacker to bypass this plugin,however these are less known attacks and only experienced attackers using these
0-day
-ish bugs.
-
-
Extra feature/moderation plugins:
-
Skinsrestorer: This plugin allow us that even if run the alt-servers in offline auth mode that players would still have their skins on their characters.
-
WorldBorder: This is necessary plugin for read-only alt-servers (auth, lobby), where players has a restricted area to use. Other case is used for optimizing large maps and pre-generate landscape in a given area.
-
VentureChat: A really powerfull chat moderation and style plugin, with many usefull features. Working well together with Luckperms
-
Docker-compose example:
version: "2.4"
services:
postgres:
image: postgres
container_name: postgres
environment:
- PUID=1000
- PGID=1000
- POSTGRES_USER=root #placeholder only
- POSTGRES_PASSWORD=changeme #placeholder only
- POSTGRES_DB=root #placeholder only
ports:
- 127.0.0.1:5432:5432 #For admins
- 10.1.0.1:5432:5432 #VPN
volumes:
- /docker/geyzer/postgres:/var/lib/postgresql/data/
- ./docker_postgres_init.sql:/docker-entrypoint-initdb.d/docker_postgres_init.sql #To create databases for multiple plugins
- /docker/backup/postgres:/backup
restart: unless-stopped
velocity:
image: openjdk:14-slim
container_name: velocity
stdin_open: true
tty: true
environment:
- PUID=1000
- PGID=1000
volumes:
- /docker/mine/velocity:/data
working_dir: /data
command: java -Xms512M -Xmx512M -jar velocity.jar
ports:
- 0.0.0.0:25565:25577 # java protocol
- 0.0.0.0:19132:19132/udp # bedrock protocol
cap_add:
- NET_RAW # Show real client IP of the service
restart: unless-stopped
auth:
mage: openjdk:14-slim
container_name: auth
stdin_open: true
tty: true
environment:
- PUID=1000
- PGID=1000
volumes:
- /docker/mine/auth:/data
working_dir: /data
command: java -Xms512M -Xmx512M -jar papermc.jar
restart: unless-stopped
lobby:
image: openjdk:11-slim #older server needed java-11
container_name: lobby
stdin_open: true
tty: true
environment:
- PUID=1000
- PGID=1000
volumes:
- /docker/mine/lobby:/data
working_dir: /data
command: java -Xms512M -Xmx2048M -jar papermc.jar
restart: unless-stopped
survival:
image: openjdk:14-slim
container_name: survival
stdin_open: true
tty: true
environment:
- PUID=1000
- PGID=1000
volumes:
- /docker/mine/survival:/data
working_dir: /data
command: java -Xms512M -Xmx3048M -jar papermc.jar
restart: unless-stopped
Attack Link to heading
As I mentioned before even with us using multiple Security plugin and Security Policy, that way we can get rid of the easier attack vectors. For example proxy bypass impossible in this setup as minecraft servers have no internet access at all. One of our Security Policy was that privileged gamers could only connect trough VPN and any account trying to connect otherwise would be blocked and after a few try locked. Even after all this we had one attacker whom used a bit more sophisticated attack. The player create a book with a specific payload in it, if a privileged player would read the book in-game the command would run. This way our “hacker” gained admin access inside the game and used a “hacker” client to destroy the world map. After this incident happened took us 15 mins to lock-out the attacker and restore to previous backup. To mitigate this attack we just had to disable book writing feature for normal users in the permission plugin. In 3 months this was the only successful attack.
Summary Link to heading
This was a good opportunity to learn about more the dockers and reinforce a server with actual users. However the project died out as interests in Minecraft frequently goes a few months mostly end of the year and it dies out. There could be so much tiny detail with plugins and configuration that I could go into ,but that would take much time and it wouldn’t be up to date. Regarding security the biggest improvement would have been the online authentication with Microsoft ,but that would break the geyzer as authenticated bedrock players would be unauthenticated from the java server points of view. This project probably going to reborn later with possibly in an improved form, however interesting that this project was a bit more secure and reproducible solution than majority of the private offline servers out there. One interesting thing that for a short time i was playing with the idea to take a SOC like approach and monitor the incoming packet to detect cheaters, but after investigating I found that it would be so much effort. To make it work I would need a Proxy plugin which would log all the packet and store it inside elasticsearch and then i would need to create baseline for normal behaviour and one with a cheating/hacking tool to see some hacks in action. However this plan failed as all of this would take too much effort and I was on my own.