-
-
Notifications
You must be signed in to change notification settings - Fork 1.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Added filter for minecraft server #2852
base: master
Are you sure you want to change the base?
Conversation
The timestamps of the logs are in this format : "[21:20:18]" (no date or year), so I'm not sure what value would "time" in failJSON have. |
The time simulating by test suite for NOW is |
config/filter.d/minecraft.conf
Outdated
|
||
[Definition] | ||
|
||
failregex = \[\/<HOST>\: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is most vulnerable regex ever, I seen in the filter.
It would match [/192.0.2.1:12345] successfully logged in
as well as [/192.0.2.2:12345] access denied
.
Please correct this (provide more precise, anchored regex).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is no "access denied" really. There is a whitelist feature provided by the server, but it's rarely used (but I might as well add it in the future). The purpose of this filter is to block a DOS attack in which players with random names join the server if the server is in offline mode, where an online-based layer of authentication is not used (an attack I've seen). So the key here are the findtime and maxretry options that can rule out spamming bots. I should probably clarify this in a comment in the filter.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
logged in
and lost connection: Disconnected
surely don't represent any attack vector
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here's what a bot attack looks like on my own server:
[03:32:54] [Server thread/INFO]: com.mojang.authlib.GameProfile@508346c3[id=<null>,name=cuute,properties={},legacy=false] (/20.4.48.76:50306) lost connection: Disconnected
[03:36:28] [Server thread/INFO]: com.mojang.authlib.GameProfile@4392677b[id=<null>,name=cuute,properties={},legacy=false] (/20.4.48.76:54278) lost connection: Disconnected
[03:39:37] [Server thread/INFO]: com.mojang.authlib.GameProfile@59032ddf[id=<null>,name=cuute,properties={},legacy=false] (/20.4.48.76:59320) lost connection: Disconnected
[03:40:53] [Server thread/INFO]: com.mojang.authlib.GameProfile@3c65e0e1[id=<null>,name=cuute,properties={},legacy=false] (/20.4.48.76:55888) lost connection: Disconnected
[03:46:07] [Server thread/INFO]: com.mojang.authlib.GameProfile@672c7a59[id=<null>,name=cuute,properties={},legacy=false] (/20.4.48.76:46164) lost connection: Disconnected
[03:56:35] [Server thread/INFO]: com.mojang.authlib.GameProfile@3feaeec1[id=<null>,name=cuute,properties={},legacy=false] (/20.4.48.76:47884) lost connection: Disconnected
[04:00:12] [Server thread/INFO]: com.mojang.authlib.GameProfile@124d287d[id=<null>,name=cuute,properties={},legacy=false] (/20.4.48.76:47432) lost connection: Disconnected
[04:02:28] [Server thread/INFO]: com.mojang.authlib.GameProfile@4c7d9ef5[id=<null>,name=cuute,properties={},legacy=false] (/20.4.48.76:38110) lost connection: Disconnected
[04:06:09] [Server thread/INFO]: com.mojang.authlib.GameProfile@72fd24a0[id=<null>,name=cuute,properties={},legacy=false] (/20.4.48.76:47528) lost connection: Disconnected
[04:09:48] [Server thread/INFO]: com.mojang.authlib.GameProfile@62e80648[id=<null>,name=cuute,properties={},legacy=false] (/20.4.48.76:59492) lost connection: Disconnected
[04:13:36] [Server thread/INFO]: com.mojang.authlib.GameProfile@5981520a[id=<null>,name=cuute,properties={},legacy=false] (/20.4.48.76:35350) lost connection: Disconnected
[04:17:27] [Server thread/INFO]: com.mojang.authlib.GameProfile@351d996e[id=<null>,name=cuute,properties={},legacy=false] (/20.4.48.76:49122) lost connection: Disconnected
[04:21:19] [Server thread/INFO]: com.mojang.authlib.GameProfile@62be7d0d[id=<null>,name=cuute,properties={},legacy=false] (/20.4.48.76:50928) lost connection: Disconnected
[04:25:02] [Server thread/INFO]: com.mojang.authlib.GameProfile@e1ada86[id=<null>,name=cuute,properties={},legacy=false] (/20.4.48.76:59308) lost connection: Disconnected
[04:28:42] [Server thread/INFO]: com.mojang.authlib.GameProfile@46d2bd38[id=<null>,name=cuute,properties={},legacy=false] (/20.4.48.76:44334) lost connection: Disconnected
[04:32:41] [Server thread/INFO]: com.mojang.authlib.GameProfile@4cf80fb3[id=<null>,name=cuute,properties={},legacy=false] (/20.4.48.76:58452) lost connection: Disconnected
[04:36:37] [Server thread/INFO]: com.mojang.authlib.GameProfile@34b3d11a[id=<null>,name=cuute,properties={},legacy=false] (/20.4.48.76:58510) lost connection: Disconnected
[04:40:34] [Server thread/INFO]: com.mojang.authlib.GameProfile@29a1059[id=<null>,name=cuute,properties={},legacy=false] (/20.4.48.76:37508) lost connection: Disconnected
[04:44:27] [Server thread/INFO]: com.mojang.authlib.GameProfile@240239f7[id=<null>,name=cuute,properties={},legacy=false] (/20.4.48.76:56702) lost connection: Disconnected
[04:48:26] [Server thread/INFO]: com.mojang.authlib.GameProfile@4d26720b[id=<null>,name=cuute,properties={},legacy=false] (/20.4.48.76:55874) lost connection: Disconnected
[04:52:23] [Server thread/INFO]: com.mojang.authlib.GameProfile@6e4a5cf3[id=<null>,name=cuute,properties={},legacy=false] (/20.4.48.76:34900) lost connection: Disconnected
[04:56:20] [Server thread/INFO]: com.mojang.authlib.GameProfile@1457bf54[id=<null>,name=cuute,properties={},legacy=false] (/20.4.48.76:32780) lost connection: Disconnected
[05:00:11] [Server thread/INFO]: com.mojang.authlib.GameProfile@213952cc[id=<null>,name=cuute,properties={},legacy=false] (/20.4.48.76:37350) lost connection: Disconnected
[05:04:07] [Server thread/INFO]: com.mojang.authlib.GameProfile@342c9e32[id=<null>,name=cuute,properties={},legacy=false] (/20.4.48.76:40264) lost connection: Disconnected
[05:08:00] [Server thread/INFO]: com.mojang.authlib.GameProfile@4c6b588a[id=<null>,name=cuute,properties={},legacy=false] (/20.4.48.76:42654) lost connection: Disconnected
[05:11:57] [Server thread/INFO]: com.mojang.authlib.GameProfile@40ec9934[id=<null>,name=cuute,properties={},legacy=false] (/20.4.48.76:42936) lost connection: Disconnected
[05:16:17] [Server thread/INFO]: com.mojang.authlib.GameProfile@19967be1[id=<null>,name=cuute,properties={},legacy=false] (/20.4.48.76:54126) lost connection: Disconnected
[05:20:11] [Server thread/INFO]: com.mojang.authlib.GameProfile@151407c8[id=<null>,name=cuute,properties={},legacy=false] (/20.4.48.76:44118) lost connection: Disconnected
[05:24:03] [Server thread/INFO]: com.mojang.authlib.GameProfile@1b7635c7[id=<null>,name=cuute,properties={},legacy=false] (/20.4.48.76:60018) lost connection: Disconnected
[05:28:02] [Server thread/INFO]: com.mojang.authlib.GameProfile@5fcdd47a[id=<null>,name=cuute,properties={},legacy=false] (/20.4.48.76:60892) lost connection: Disconnected
[05:31:57] [Server thread/INFO]: com.mojang.authlib.GameProfile@6c78fdce[id=<null>,name=cuute,properties={},legacy=false] (/20.4.48.76:60474) lost connection: Disconnected
It's a whitelisted server using online mode (meaning player identities are verified by Mojang). As a result the attackers are only generating a disconnected message without ever generating the messages:
[14:36:24] [Server thread/INFO]: <player name>[/<IP>:<port>] logged in with entity id 73 at (-611.530629608662, 65.0, -266.9221458299592)
[14:36:24] [Server thread/INFO]: <player name> joined the game
Regular disconnect messages come in a couple of forms:
[14:43:01] [Server thread/INFO]: <player name> lost connection: Disconnected
[14:43:01] [Server thread/INFO]: <player name> left the game
[19:54:35] [Server thread/INFO]: <player name>lost connection: Timed out
[19:54:35] [Server thread/INFO]: <player name> left the game
This last disconnect, noted here below, came seconds before the legitimate player decided to log in, suggesting this is some kind of scan by the legitimate client to gather server status information on the list of servers configured by the player. This information contains server connection quality as well as the list of players currently online.
The top line of this one makes it difficult to just take the contents of this specific line to make a filter, given the fact that it's an exact match for the log result when a bot scans your server.
[11:21:19] [Server thread/INFO]: com.mojang.authlib.GameProfile@27ce9407[id=<null>,name=<player name>,properties={},legacy=false] (/<ip>:<port>) lost connection: Disconnected
[11:21:29] [User Authenticator #2/INFO]: UUID of player <player name> is <player uuid>
[11:21:29] [Server thread/INFO]: <player name>[/<ip>:<port>] logged in with entity id 294 at (-45.820534318481705, 68.0, 60.00821373182576)
[11:21:29] [Server thread/INFO]: <player name> joined the game
The main purpose of the attack seems to be people scanning for player online information to find griefing targets, or to find servers with sensitive player names (such as youtubers) so they can attack those servers.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What's the difference between a bot's lost connection: Disconnected
message in the logs and a legitimate player's? If they're the same, or have any crossover, fail2ban can't protect against that afaik.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@trainzkid whilst it is possible for a legitimate user to generate the messages containing the com.mojang.authlib.GameProfile
bits, they usually have a much simpler disconnect message. So it's really the frequency of the authlib line that stands out.
If you look at my attack log, at the 4 AM mark, you see that an abnormal connection disconnect happens like 16 times within that hour alone. If that were a normal player trying to put some extra load on my server by trying to load and unload the world around them that often I'd also have no issue with fail2ban showing them the door for a couple of hours/days.
As for when normal players create that message? I've seen it happen once, maybe twice a week. Could be a network issue when that happens though, and if that's the case you don't really wanna block them for having a bad ISP.
With all that said, I agree that Mojang could be providing better log messages for this kind of issue.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see what you mean, however, I think the main intent of fail2ban is to "ban" on bad authentication type errors, and the suggested filter above is just way too vague/broad that it's just as likely to affect legitimate players as it is bots.
That being said, the beauty of open source software and the freedom of config files means anyone who disagrees with my statement is more than welcome to copy the above filter and go to town on their local Minecrafters with extreme prejudice.
I also agree that Mojang could definitely improve their error messages a bit better so it's more obvious when a legitimate bot/baddie attempts to access your server. Unfortunately, I'm not confident that Mojang will make any sort of improvements in the near future. All we can do is adapt with what we're given.
On another note, adding a filter for the whitelist error doesn't sound like a bad idea to me. I think that probably has more candidacy than the subtle "disconnected" error, personally.
fail2ban/tests/files/logs/minecraft
Outdated
@@ -0,0 +1,2 @@ | |||
# failJSON: { "time": "2005-08-13T21:30:40", "match": true, "host": "123.45.67.89" } | |||
[21:30:40] [Server thread/INFO]: Player[/123.45.67.89:12345] logged in with entity id 551 at (825.302579326729, 65.0, -886.9107800126116) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm... now I confused still more - does Player logged in
not mean a successful login.
I don't really see it is an authentication failure or even something critical or evil (in sense of fail2ban).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So you decided to remove it from the test, but the issue remain - the message will be matched with the filter, so still don't think such regex is good idea.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For Geyser (de-DE) these Message should also be handled:
[epollEventLoopGroup-3-2/INFO]: [Geyser-Spigot] /123.127.235.6:1051 versuchte zu verbinden
Codecov Report
@@ Coverage Diff @@
## master #2852 +/- ##
=======================================
Coverage 95.91% 95.91%
=======================================
Files 79 79
Lines 15978 15978
Branches 2615 2615
=======================================
Hits 15326 15326
Misses 344 344
Partials 308 308 Continue to review full report at Codecov.
|
Codecov Report
@@ Coverage Diff @@
## master #2852 +/- ##
=======================================
Coverage 95.91% 95.91%
=======================================
Files 79 79
Lines 15978 15978
Branches 2615 2615
=======================================
Hits 15326 15326
Misses 344 344
Partials 308 308 Continue to review full report at Codecov.
|
1 similar comment
Codecov Report
@@ Coverage Diff @@
## master #2852 +/- ##
=======================================
Coverage 95.91% 95.91%
=======================================
Files 79 79
Lines 15978 15978
Branches 2615 2615
=======================================
Hits 15326 15326
Misses 344 344
Partials 308 308 Continue to review full report at Codecov.
|
-Added support for blocking non-whitelisted players -Added support for blocking "cracked" players -Changed jail.conf recommendations
fe8a9d2
to
9d77fb2
Compare
Any news about this pull request? |
I don't think it is justified to merge this PR, because it still looks "vulnerable" at the moment. If the log-file containing the message like this:
I would use something like this instead: [minecraft]
port = ...
logpath = ...
filter =
failregex = ^[^:]*: Disconnecting \S+ \(/<ADDR>:\d+\): You are not white-listed on this server!
enabled = true |
This is still a non-working solution, but it builds on @sebres suggestion: failregex = \[(?P<time>\d+:\d+:\d+)\].*\(\/(?P<host>\d+.\d+.\d+.\d+):\d+\) lost connection.*$ The host and time capture attempt to comply with some fail2ban specifications, but Minecraft Servers output the timestamp in a format that seems incompatible with the fail2ban time regex. Which I think is what @MinePro120 and @sebres were discussing earlier. I'm looking for a way to modify how the Minecraft server reports the date and time in the logs. Still, all I've found so far are guides for tweaking log4j; from my understanding, that logger was deprecated for vulnerabilities. |
Why then do you provide such non-working "solution" here?
You don't need... One can simply specify datepattern for the jail or filter. datepattern = ^\[%%H:%%M:%%S\]\s+ By the way - usage of catch-all's is ugly and |
Hey, thanks for the reply.
Because this is a collaborative platform, and instead of being snarky, I'll contribute my limited knowledge so that others may improve upon it.
The date patterns the logs provide resolve from seconds up to the hour, so there is no day, month, or year information. Thanks for that link to the documentation; I see that by specifying datepattern as NONE we could bypass that limitation. I don't know what the fial2ban best practices are. Would you recommend keeping the datepattern matching the time from seconds up to the hour or setting it to NONE? Regarding the use of catch-alls not sure how to avoid using it since the log entries are quite heterogeneous. It might not be the best solution, but if it works, it provides something for others with the skills to improve upon it. I was testing it against the regex 101 Python option, and
Just followed what the DOCs I had available said. Hope this helps anyone trying to improve on this solution, it would be really cool to have something like this working (even if it's just remedially) to get rid of the robot-spam on the server. |
This isn't quite the same as the use case mentioned in the aforementioned PR, but I've found using a systemd service for logging means fail2ban can utilize systemd-journal's timestamps, and a regex that matches the whitelist errors works. That's not exactly the bot problem this discussion has been about, but it's better than nothing. Here's my
where I'm also aware there aren't any anchors, I've had some trouble with them in the past for whatever reason. |
Well it depends on log-format (and log-target, e. g. systemd journal or log-file), here is fully-anchored example for log-line from this PR: failregex = ^[^:]*: Disconnecting [^\(]*\(/<ADDR>:\d+\): You are not white-listed on this server! ( Alternatively it can be only anchored from the end, with few conditions:
failregex = \(/<ADDR>:\d+\): You are not white-listed on this server!\s*$ |
I think the issues I ran into were related to extraneous timestamps at the beginning of a log entry, despite using systemd-journal. Basically, the timestamp mentioned earlier in this thread is still present in the journal entry, so when I tried to anchor at the beginning, I'm guessing my regex was having trouble with that initial timestamp when it had already successfully parsed the journal's timestamp. I don't know if fail2ban tries to parse timestamps again after successfully getting the timestamp from the journal or if I need to add something to the regex to make it ignore that initial section in square brackets with the timestamp. I can't tell if that's what your regex does, it doesn't look like it does. The other issue I may have been facing was when I heard anchoring, I thought it meant on both sides (both beginning and end). Is it preferred to only anchor from one or the other and not both? I think in this specific case for |
It is true, either if one needs to be precise as possible, or if there are some catch-alls similar REs used inside, before the captured data in left anchored RE, or after captured data in right anchored RE (quasi to restrict corner cases for injection attempts via foreign data).
It depends, but generally spoken - no, it is not preferred. For instance an RE
And if something of that shall not cause a failure (e. g. 3rd message), it can be pretty simple done with negative lookahead: It is hardly possible to give an unique answer for general usecase.
"I don't think" is not equal "I know", what is mostly expected for a stock filter. |
Before submitting your PR, please review the following checklist:
against certain release version, choose
0.9
,0.10
or0.11
branch,for dev-edition use
master
branchfailregex
for filterX
with sample log lineswithin
fail2ban/tests/files/logs/X
file