added connection key and recorded event to LoginLog
This commit is contained in:
1 parent
095db7e796
commit
86ae261c60
4 files changed
+148
-6
No files matched your search
+21
-6
@@ -5,6 +5,8 @@ import eu.mhsl.craftattack.spawn.core.Main;
|
||||
import eu.mhsl.craftattack.spawn.core.api.server.HttpServer;
|
||||
import eu.mhsl.craftattack.spawn.core.appliance.Appliance;
|
||||
import eu.mhsl.craftattack.spawn.core.database.Database;
|
||||
import eu.mhsl.craftattack.spawn.core.event.LoginAttemptRecordedEvent;
|
||||
import eu.mhsl.craftattack.spawn.core.util.network.Networks;
|
||||
import eu.mhsl.craftattack.spawn.core.util.server.Floodgate;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer;
|
||||
@@ -16,6 +18,8 @@ import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.net.InetAddress;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.Statement;
|
||||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
import java.time.LocalDateTime;
|
||||
@@ -30,6 +34,7 @@ import java.util.concurrent.ConcurrentHashMap;
|
||||
/**
|
||||
* Records every login attempt (allowed or not) with its IP address in the table login_attempts
|
||||
* (schema: resources/migrations/loginLog). Basis for detecting ban evasion.
|
||||
* After each insert a LoginAttemptRecordedEvent is fired on the database thread.
|
||||
* The website reports signups and logins of its users via POST /api/loginlog/website.
|
||||
* Never blocks or delays a login: writes run on the database thread, failures are only logged.
|
||||
*/
|
||||
@@ -101,19 +106,29 @@ public class LoginLog extends Appliance {
|
||||
}
|
||||
|
||||
private void write(LoginAttempt attempt) {
|
||||
String sql = "INSERT INTO login_attempts (at, uuid, name, ip, bedrock, stage, result, reason) VALUES (?, ?, ?, ?, ?, ?, ?, ?)";
|
||||
String network = Networks.networkOf(attempt.ip());
|
||||
String sql = "INSERT INTO login_attempts (at, uuid, name, ip, network, bedrock, stage, result, reason) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)";
|
||||
this.database.execute("recording login attempt of " + attempt.name(), connection -> {
|
||||
try(PreparedStatement statement = connection.prepareStatement(sql)) {
|
||||
long id;
|
||||
try(PreparedStatement statement = connection.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS)) {
|
||||
statement.setObject(1, LocalDateTime.ofInstant(attempt.at(), ZoneOffset.UTC));
|
||||
statement.setString(2, attempt.uuid().toString());
|
||||
statement.setString(3, attempt.name());
|
||||
statement.setString(4, attempt.ip());
|
||||
statement.setBoolean(5, attempt.bedrock());
|
||||
statement.setString(6, attempt.stage());
|
||||
statement.setString(7, attempt.result());
|
||||
statement.setString(8, attempt.reason());
|
||||
statement.setString(5, network);
|
||||
statement.setBoolean(6, attempt.bedrock());
|
||||
statement.setString(7, attempt.stage());
|
||||
statement.setString(8, attempt.result());
|
||||
statement.setString(9, attempt.reason());
|
||||
statement.executeUpdate();
|
||||
try(ResultSet keys = statement.getGeneratedKeys()) {
|
||||
if(!keys.next()) return;
|
||||
id = keys.getLong(1);
|
||||
}
|
||||
}
|
||||
Bukkit.getPluginManager().callEvent(new LoginAttemptRecordedEvent(new LoginAttemptRecordedEvent.RecordedAttempt(
|
||||
id, attempt.at(), attempt.uuid(), attempt.name(), attempt.ip(), network, attempt.stage(), attempt.result()
|
||||
)));
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
-- Connection key per attempt: the IPv4 address or the IPv6 /64 prefix. Groups accounts by internet connection.
|
||||
ALTER TABLE login_attempts
|
||||
ADD COLUMN network VARCHAR(45) NULL COMMENT 'IPv4 address or IPv6 /64 prefix, NULL if unknown' AFTER ip,
|
||||
ADD KEY idx_network_at (network, at);
|
||||
|
||||
UPDATE login_attempts SET network = ip WHERE ip REGEXP '^[0-9]{1,3}([.][0-9]{1,3}){3}$';
|
||||
Reference in new issue
Block a user