# fail2ban for Minecraft servers

> Ban bots that keep trying to join a whitelisted Minecraft server: a tested fail2ban filter for latest.log (vanilla and Paper), the jail, Docker and limits.
>
> Source: https://fail2ban.dev/guides/minecraft/ · Updated 2026-10-26 · Checked against fail2ban 1.1.1
> fail2ban.dev is an independent guide, not the official fail2ban project.

fail2ban can protect a Java Edition Minecraft server, but only against one thing: clients that keep trying to join and get rejected during login. The usual case is a server scanner or griefer bot trying to join a **whitelisted** server. fail2ban 1.1.1 ships no Minecraft filter. You create one that matches the `lost connection: You are not white-listed on this server!` line in `logs/latest.log`, then add a jail that bans TCP port 25565. It doesn't stop DDoS floods, and it can't see attacks that never reach the log.

## What Minecraft logs, and what it doesn't

Minecraft writes everything to `logs/latest.log` in the server directory (the file is rotated to a dated `.log.gz` on every restart). Most player events name the player but not the address. A ban needs the address, so only a few lines are usable:

```log
[18:36:12] [Server thread/INFO]: Disconnecting Steve (/203.0.113.42:51234): You are not white-listed on this server!
[18:36:12] [Server thread/INFO]: Steve (/203.0.113.42:51234) lost connection: You are not white-listed on this server!
[18:36:20] [Server thread/INFO]: Notch (/198.51.100.7:40122) lost connection: Failed to verify username!
[18:36:31] [Server thread/INFO]: Steve[/192.0.2.99:41000] logged in with entity id 123 at (0.5, 64.0, 0.5)
[18:36:40] [Server thread/INFO]: Steve lost connection: Disconnected
```
- **`lost connection: Failed to verify username!`** is an online-mode server rejecting a client whose session Mojang couldn't confirm: a cracked client, a bot or a bad session token. A genuine player can hit it too, for example when the same account is signed in on two launchers.
- **`Disconnecting …`** often appears just before the `lost connection` line for the same rejection. Match only one of the two, or every rejection counts twice.
- Lines after login (`logged in`, `lost connection: Disconnected`, chat, commands) don't need banning. Once a player is in, moderation is a job for `/ban`.

The address is written as `/IP:port`, with brackets around IPv6. Older server versions print a `com.mojang.authlib.GameProfile@…[id=…,name=…]` object where newer ones print the name. Paper and Spigot use a shorter prefix (`[18:36:12 INFO]: …`) but the same messages. Recent versions also have a `log-ips` setting in `server.properties`. It must stay `true` (the default), or the address is withheld and no filter can work.

> **Check your own log first**
Versions, forks and plugins change these lines. Before you enable the jail, run `grep -E "white-listed|Failed to verify" logs/latest.log` and paste a few results into the [regex tester](/tools/regex-tester/) with the filter below.

## Step 1: create the filter

```ini
[Definition]
# Login-phase rejections only: these are the lines that carry the client address.
failregex = ^[^\]]*\](?: \[[^\]]+\])?: (?:\S+ )?\(/\[?<ADDR>\]?:\d+\) lost connection: (?:You are not white-listed on this server!|Failed to verify username!)\s*$
ignoreregex =
# latest.log only has the time of day; fail2ban assumes today's date.
datepattern = ^\[%%H:%%M:%%S
```

Test it against your log before going live:

```bash
```

## Step 2: add the jail

```ini
[minecraft]
enabled  = true
filter   = minecraft
logpath  = /opt/minecraft/logs/latest.log
backend  = auto
port     = 25565
protocol = tcp
maxretry = 3
findtime = 10m
bantime  = 1d
```
- `backend = auto` matters on Ubuntu 24.04. Its package sets `backend = systemd` for all jails, and that setting ignores `logpath`.
- If you changed `server-port`, change `port` to match. To block the address from everything on the host, including SSH and the query port, use `banaction = %(banaction_allports)s` in place of `port` and `protocol`.
- Add your own home IP and your friends' static addresses to [`ignoreip`](/config/whitelist/) if they ever join from a machine that isn't whitelisted yet.

Reload and check:

```bash
sudo fail2ban-client status minecraft
```

With the popular `itzg/minecraft-server` image, the server directory is the `/data` volume, so the log is at `<your volume>/logs/latest.log` on the host. Point `logpath` there. The ban must also land in the chain Docker uses for published ports, or it won't affect the container. For iptables actions, add `chain = DOCKER-USER` to the jail. The full explanation and the nftables variant are in [fail2ban with Docker](/guides/docker/).

## Behind Velocity, BungeeCord or a hosting panel

With a proxy in front, the backend servers see the proxy's address unless forwarding is set up, and the whitelist check may happen on the proxy instead. Run fail2ban on the machine that has the public port. Point the jail at the log that shows the real client address, and check that log's lines in the [regex tester](/tools/regex-tester/) first. Put the proxy's own address in `ignoreip`. Banning it would kick every player. On shared game hosting with no root access you can't run fail2ban at all. Use the host's firewall or DDoS settings instead.

## What fail2ban can't do for a Minecraft server

- **DDoS and connection floods.** A flood that never completes a login writes nothing useful to `latest.log`, and a large one saturates the link before any log line exists. That needs your provider's DDoS protection or a proxy-level rate limit.
- **Bedrock Edition.** Bedrock Dedicated Server's connection messages give the player name and XUID, not the IP address, so there is nothing for a filter to match.
- **Offline-mode servers.** Login plugins such as AuthMe handle passwords there, and their failed-login messages often don't include the address. Use the plugin's own lockout settings, and only switch to fail2ban if its log line carries the IP.
- **RCON.** Keep `enable-rcon=false`, or bind it to localhost and block port 25575 in your firewall. It shouldn't be reachable from the internet at all.

The most useful fail2ban jail on a game server is often the plain [SSH jail](/guides/ssh/): the host's SSH port is attacked far more than the game port.

## FAQ

### Does fail2ban have a Minecraft filter?

No. fail2ban 1.1.1 ships 96 filters and none of them is for Minecraft. You need a custom filter, such as the one on this page, that matches the `lost connection: You are not white-listed on this server!` line in `logs/latest.log` and captures the address after `(/`.

### Can fail2ban stop bots joining my Minecraft server?

It can stop bots that repeatedly try to join a whitelisted server, because each rejected attempt is logged with the client's address. With `maxretry = 3`, a bot gets three tries before it is blocked at the firewall for the ban time. It doesn't help on a public server without a whitelist, where bots can simply join.

### Can fail2ban stop a Minecraft DDoS attack?

No. A DDoS fills your connection or the server's network stack before Minecraft writes a log line, and it comes from too many addresses to ban one by one. Use DDoS protection from your host or a protected proxy. fail2ban only helps against a handful of addresses that keep failing to log in.

### Where is the Minecraft server log file?

In the `logs` folder of the server directory: `logs/latest.log` holds the current session, and older sessions are compressed to dated `.log.gz` files. In the `itzg/minecraft-server` Docker image the server directory is `/data`, so the log is `/data/logs/latest.log` inside the container.
