Network: Auto-kick clients after too many failed rcon/settings attempts

This commit is contained in:
Jonathan G Rennison
2023-06-14 21:58:35 +01:00
parent 120f0e8a81
commit b18d3c9603
4 changed files with 31 additions and 2 deletions

View File

@@ -1039,9 +1039,12 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::Receive_CLIENT_SETTINGS_PASSWO
DEBUG(net, 0, "[settings-ctrl] wrong password from client-id %d", this->client_id);
NetworkServerSendRcon(this->client_id, CC_ERROR, "Access Denied");
this->settings_authed = false;
NetworkRecvStatus status = this->HandleAuthFailure(this->settings_auth_failures);
if (status != NETWORK_RECV_STATUS_OKAY) return status;
} else {
DEBUG(net, 0, "[settings-ctrl] client-id %d", this->client_id);
this->settings_authed = true;
this->settings_auth_failures = 0;
}
return this->SendSettingsAccessUpdate(this->settings_authed);
@@ -1592,7 +1595,7 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::Receive_CLIENT_RCON(Packet *p)
if (_settings_client.network.rcon_password.empty()) {
NetworkServerSendRcon(this->client_id, CC_ERROR, "Access Denied");
return NETWORK_RECV_STATUS_OKAY;
return this->HandleAuthFailure(this->rcon_auth_failures);
}
std::vector<byte> password = p->Recv_buffer();
@@ -1601,7 +1604,7 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::Receive_CLIENT_RCON(Packet *p)
if (password != this->rcon_password_hash_cache.GetHash(_settings_client.network.rcon_password, this->rcon_hash_bits)) {
DEBUG(net, 0, "[rcon] wrong password from client-id %d", this->client_id);
NetworkServerSendRcon(this->client_id, CC_ERROR, "Access Denied");
return NETWORK_RECV_STATUS_OKAY;
return this->HandleAuthFailure(this->rcon_auth_failures);
}
DEBUG(net, 3, "[rcon] Client-id %d executed: %s", this->client_id, command.c_str());
@@ -1609,6 +1612,7 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::Receive_CLIENT_RCON(Packet *p)
_redirect_console_to_client = this->client_id;
IConsoleCmdExec(command.c_str());
_redirect_console_to_client = INVALID_CLIENT_ID;
this->rcon_auth_failures = 0;
return NETWORK_RECV_STATUS_OKAY;
}
@@ -1638,6 +1642,17 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::Receive_CLIENT_MOVE(Packet *p)
return NETWORK_RECV_STATUS_OKAY;
}
NetworkRecvStatus ServerNetworkGameSocketHandler::HandleAuthFailure(uint &failure_count)
{
failure_count++;
if (_settings_client.network.max_auth_failures != 0 && failure_count >= _settings_client.network.max_auth_failures) {
DEBUG(net, 0, "Kicked client-id #%d due to too many failed authentication attempts", this->client_id);
return this->SendError(NETWORK_ERROR_KICKED);
} else {
return NETWORK_RECV_STATUS_OKAY;
}
}
const char *ServerNetworkGameSocketHandler::GetClientStatusName(ClientStatus status)
{
static const char* _client_status_names[] {

View File

@@ -100,6 +100,9 @@ public:
uint desync_frame_seed = 0;
uint desync_frame_state_checksum = 0;
uint rcon_auth_failures = 0;
uint settings_auth_failures = 0;
ServerNetworkGameSocketHandler(SOCKET s);
~ServerNetworkGameSocketHandler();
@@ -131,6 +134,8 @@ public:
NetworkRecvStatus SendConfigUpdate();
NetworkRecvStatus SendSettingsAccessUpdate(bool ok);
NetworkRecvStatus HandleAuthFailure(uint &failure_count);
std::string GetDebugInfo() const override;
static void Send();

View File

@@ -383,6 +383,7 @@ struct NetworkSettings {
std::string network_id; ///< network ID for servers
std::string company_password_storage_token; ///< company password storage token
std::string company_password_storage_secret; ///< company password storage secret
uint8 max_auth_failures; ///< maximum auth failures before client is kicked
bool autoclean_companies; ///< automatically remove companies that are not in use
uint8 autoclean_unprotected; ///< remove passwordless companies after this many months
uint8 autoclean_protected; ///< remove the password from passworded companies after this many months

View File

@@ -256,3 +256,11 @@ var = network.reload_cfg
flags = SF_NOT_IN_SAVE | SF_NO_NETWORK_SYNC | SF_NETWORK_ONLY
def = false
cat = SC_EXPERT
[SDTC_VAR]
var = network.max_auth_failures
type = SLE_UINT8
flags = SF_NOT_IN_SAVE | SF_NO_NETWORK_SYNC | SF_NETWORK_ONLY
def = 10
min = 0
max = 255