Add IPv6 ban table
This commit is contained in:
parent
0217eaf173
commit
04dd5a8bfb
@ -159,9 +159,12 @@ The current server configuration xml looks like this:
|
|||||||
<!-- Specified in millisecond for maximum time waiting in sqlite3_busy_handler. You may need a higher value if your database is shared by many servers or having a slow hard disk. -->
|
<!-- Specified in millisecond for maximum time waiting in sqlite3_busy_handler. You may need a higher value if your database is shared by many servers or having a slow hard disk. -->
|
||||||
<database-timeout value="1000" />
|
<database-timeout value="1000" />
|
||||||
|
|
||||||
<!-- Ip ban list table name, you need to create the table first, see NETWORKING.md for details, empty to disable. This table can be shared for all servers if you use the same name. STK can auto kick active peer from ban list (update per minute) which allows live kicking peer by inserting record to database. -->
|
<!-- IPv4 ban list table name, you need to create the table first, see NETWORKING.md for details, empty to disable. This table can be shared for all servers if you use the same name. STK can auto kick active peer from ban list (update per minute) whichallows live kicking peer by inserting record to database. -->
|
||||||
<ip-ban-table value="ip_ban" />
|
<ip-ban-table value="ip_ban" />
|
||||||
|
|
||||||
|
<!-- IPv6 ban list table name, you need to create the table first, see NETWORKING.md for details, empty to disable. This table can be shared for all servers if you use the same name. STK can auto kick active peer from ban list (update per minute) whichallows live kicking peer by inserting record to database. -->
|
||||||
|
<ipv6-ban-table value="ipv6_ban" />
|
||||||
|
|
||||||
<!-- Online ID ban list table name, you need to create the table first, see NETWORKING.md for details, empty to disable. This table can be shared for all servers if you use the same name. STK can auto kick active peer from ban list (update per minute) which allows live kicking peer by inserting record to database. -->
|
<!-- Online ID ban list table name, you need to create the table first, see NETWORKING.md for details, empty to disable. This table can be shared for all servers if you use the same name. STK can auto kick active peer from ban list (update per minute) which allows live kicking peer by inserting record to database. -->
|
||||||
<online-id-ban-table value="online_id_ban" />
|
<online-id-ban-table value="online_id_ban" />
|
||||||
|
|
||||||
@ -223,7 +226,7 @@ You have the best gaming experience when choosing server having all players less
|
|||||||
|
|
||||||
Currently STK uses sqlite (if building with sqlite3 on) for server management with the following functions at the moment:
|
Currently STK uses sqlite (if building with sqlite3 on) for server management with the following functions at the moment:
|
||||||
1. Server statistics
|
1. Server statistics
|
||||||
2. IPv4 / online ID ban list
|
2. IP / online ID ban list
|
||||||
3. Player reports
|
3. Player reports
|
||||||
4. IPv4 geolocation
|
4. IPv4 geolocation
|
||||||
|
|
||||||
@ -286,6 +289,17 @@ CREATE TABLE ip_ban
|
|||||||
last_trigger TIMESTAMP NULL DEFAULT NULL -- Latest time this banning entry was triggered
|
last_trigger TIMESTAMP NULL DEFAULT NULL -- Latest time this banning entry was triggered
|
||||||
);
|
);
|
||||||
|
|
||||||
|
CREATE TABLE ipv6_ban
|
||||||
|
(
|
||||||
|
ipv6_cidr TEXT NOT NULL UNIQUE, -- IPv6 CIDR range for banning (for example 2001::/64), use /128 for a specific ip
|
||||||
|
starting_time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, -- Starting time of this banning entry to be effective
|
||||||
|
expired_days REAL NULL DEFAULT NULL, -- Days for this banning to be expired, use NULL for a permanent ban
|
||||||
|
reason TEXT NOT NULL DEFAULT '', -- Banned reason shown in user stk menu, can be empty
|
||||||
|
description TEXT NOT NULL DEFAULT '', -- Private description for server admin
|
||||||
|
trigger_count INTEGER UNSIGNED NOT NULL DEFAULT 0, -- Number of banning triggered by this ban entry
|
||||||
|
last_trigger TIMESTAMP NULL DEFAULT NULL -- Latest time this banning entry was triggered
|
||||||
|
);
|
||||||
|
|
||||||
CREATE TABLE online_id_ban
|
CREATE TABLE online_id_ban
|
||||||
(
|
(
|
||||||
online_id INTEGER UNSIGNED NOT NULL UNIQUE, -- Online id from STK addons database for banning
|
online_id INTEGER UNSIGNED NOT NULL UNIQUE, -- Online id from STK addons database for banning
|
||||||
|
@ -218,6 +218,7 @@ void ServerLobby::initDatabase()
|
|||||||
m_last_poll_db_time = StkTime::getMonoTimeMs();
|
m_last_poll_db_time = StkTime::getMonoTimeMs();
|
||||||
m_db = NULL;
|
m_db = NULL;
|
||||||
m_ip_ban_table_exists = false;
|
m_ip_ban_table_exists = false;
|
||||||
|
m_ipv6_ban_table_exists = false;
|
||||||
m_online_id_ban_table_exists = false;
|
m_online_id_ban_table_exists = false;
|
||||||
m_ip_geolocation_table_exists = false;
|
m_ip_geolocation_table_exists = false;
|
||||||
if (!ServerConfig::m_sql_management)
|
if (!ServerConfig::m_sql_management)
|
||||||
@ -248,6 +249,7 @@ void ServerLobby::initDatabase()
|
|||||||
sqlite3_create_function(m_db, "insideIPv6CIDR", 2, SQLITE_UTF8, NULL,
|
sqlite3_create_function(m_db, "insideIPv6CIDR", 2, SQLITE_UTF8, NULL,
|
||||||
&insideIPv6CIDRSQL, NULL, NULL);
|
&insideIPv6CIDRSQL, NULL, NULL);
|
||||||
checkTableExists(ServerConfig::m_ip_ban_table, m_ip_ban_table_exists);
|
checkTableExists(ServerConfig::m_ip_ban_table, m_ip_ban_table_exists);
|
||||||
|
checkTableExists(ServerConfig::m_ipv6_ban_table, m_ipv6_ban_table_exists);
|
||||||
checkTableExists(ServerConfig::m_online_id_ban_table,
|
checkTableExists(ServerConfig::m_online_id_ban_table,
|
||||||
m_online_id_ban_table_exists);
|
m_online_id_ban_table_exists);
|
||||||
checkTableExists(ServerConfig::m_player_reports_table,
|
checkTableExists(ServerConfig::m_player_reports_table,
|
||||||
@ -830,6 +832,40 @@ void ServerLobby::pollDatabase()
|
|||||||
}, &peers, NULL);
|
}, &peers, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (m_ipv6_ban_table_exists)
|
||||||
|
{
|
||||||
|
std::string query =
|
||||||
|
"SELECT ipv6_cidr, reason, description FROM ";
|
||||||
|
query += ServerConfig::m_ipv6_ban_table;
|
||||||
|
query += " WHERE datetime('now') > datetime(starting_time) AND "
|
||||||
|
"(expired_days is NULL OR datetime"
|
||||||
|
"(starting_time, '+'||expired_days||' days') > datetime('now'));";
|
||||||
|
auto peers = STKHost::get()->getPeers();
|
||||||
|
sqlite3_exec(m_db, query.c_str(),
|
||||||
|
[](void* ptr, int count, char** data, char** columns)
|
||||||
|
{
|
||||||
|
std::vector<std::shared_ptr<STKPeer> >* peers_ptr =
|
||||||
|
(std::vector<std::shared_ptr<STKPeer> >*)ptr;
|
||||||
|
for (std::shared_ptr<STKPeer>& p : *peers_ptr)
|
||||||
|
{
|
||||||
|
// IPv6 ban list atm
|
||||||
|
if (p->isAIPeer() || p->getIPV6Address().empty())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
char* ipv6_cidr = data[0];
|
||||||
|
if (insideIPv6CIDR(ipv6_cidr,
|
||||||
|
p->getIPV6Address().c_str()) == 1)
|
||||||
|
{
|
||||||
|
Log::info("ServerLobby",
|
||||||
|
"Kick %s, reason: %s, description: %s",
|
||||||
|
p->getIPV6Address().c_str(), data[1], data[2]);
|
||||||
|
p->kick();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}, &peers, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
if (m_online_id_ban_table_exists)
|
if (m_online_id_ban_table_exists)
|
||||||
{
|
{
|
||||||
std::string query = "SELECT online_id, reason, description FROM ";
|
std::string query = "SELECT online_id, reason, description FROM ";
|
||||||
@ -3008,6 +3044,10 @@ void ServerLobby::connectionRequested(Event* event)
|
|||||||
if (peer->isDisconnected())
|
if (peer->isDisconnected())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
testBannedForIPv6(peer.get());
|
||||||
|
if (peer->isDisconnected())
|
||||||
|
return;
|
||||||
|
|
||||||
if (online_id != 0)
|
if (online_id != 0)
|
||||||
testBannedForOnlineId(peer.get(), online_id);
|
testBannedForOnlineId(peer.get(), online_id);
|
||||||
// Will be disconnected if banned by online id
|
// Will be disconnected if banned by online id
|
||||||
@ -4117,7 +4157,7 @@ void ServerLobby::testBannedForIP(STKPeer* peer) const
|
|||||||
if (!m_db || !m_ip_ban_table_exists)
|
if (!m_db || !m_ip_ban_table_exists)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// We only test for IPv4 atm
|
// Test for IPv4
|
||||||
if (!peer->getIPV6Address().empty())
|
if (!peer->getIPV6Address().empty())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -4177,6 +4217,84 @@ void ServerLobby::testBannedForIP(STKPeer* peer) const
|
|||||||
#endif
|
#endif
|
||||||
} // testBannedForIP
|
} // testBannedForIP
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
void ServerLobby::testBannedForIPv6(STKPeer* peer) const
|
||||||
|
{
|
||||||
|
#ifdef ENABLE_SQLITE3
|
||||||
|
if (!m_db || !m_ipv6_ban_table_exists)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Test for IPv6
|
||||||
|
if (peer->getIPV6Address().empty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
int row_id = -1;
|
||||||
|
std::string ipv6_cidr;
|
||||||
|
std::string query = StringUtils::insertValues(
|
||||||
|
"SELECT rowid, ipv6_cidr, reason, description FROM %s "
|
||||||
|
"WHERE insideIPv6CIDR(ipv6_cidr, ?) = 1 "
|
||||||
|
"AND datetime('now') > datetime(starting_time) AND "
|
||||||
|
"(expired_days is NULL OR datetime"
|
||||||
|
"(starting_time, '+'||expired_days||' days') > datetime('now')) "
|
||||||
|
"LIMIT 1;",
|
||||||
|
ServerConfig::m_ipv6_ban_table.c_str());
|
||||||
|
|
||||||
|
sqlite3_stmt* stmt = NULL;
|
||||||
|
int ret = sqlite3_prepare_v2(m_db, query.c_str(), -1, &stmt, 0);
|
||||||
|
if (ret == SQLITE_OK)
|
||||||
|
{
|
||||||
|
if (sqlite3_bind_text(stmt, 1, peer->getIPV6Address().c_str(),
|
||||||
|
-1, SQLITE_TRANSIENT) != SQLITE_OK)
|
||||||
|
{
|
||||||
|
Log::error("ServerLobby", "Error binding ipv6 addr for query: %s",
|
||||||
|
sqlite3_errmsg(m_db));
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = sqlite3_step(stmt);
|
||||||
|
if (ret == SQLITE_ROW)
|
||||||
|
{
|
||||||
|
row_id = sqlite3_column_int(stmt, 0);
|
||||||
|
ipv6_cidr = (char*)sqlite3_column_text(stmt, 1);
|
||||||
|
const char* reason = (char*)sqlite3_column_text(stmt, 2);
|
||||||
|
const char* desc = (char*)sqlite3_column_text(stmt, 3);
|
||||||
|
Log::info("ServerLobby", "%s banned by IP: %s "
|
||||||
|
"(rowid: %d, description: %s).",
|
||||||
|
peer->getRealAddress().c_str(), reason, row_id, desc);
|
||||||
|
kickPlayerWithReason(peer, reason);
|
||||||
|
}
|
||||||
|
ret = sqlite3_finalize(stmt);
|
||||||
|
if (ret != SQLITE_OK)
|
||||||
|
{
|
||||||
|
Log::error("ServerLobby",
|
||||||
|
"Error finalize database for query %s: %s",
|
||||||
|
query.c_str(), sqlite3_errmsg(m_db));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Log::error("ServerLobby", "Error preparing database for query %s: %s",
|
||||||
|
query.c_str(), sqlite3_errmsg(m_db));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (row_id != -1)
|
||||||
|
{
|
||||||
|
query = StringUtils::insertValues(
|
||||||
|
"UPDATE %s SET trigger_count = trigger_count + 1, "
|
||||||
|
"last_trigger = datetime('now') "
|
||||||
|
"WHERE ipv6_cidr = ?;", ServerConfig::m_ipv6_ban_table.c_str());
|
||||||
|
easySQLQuery(query, [ipv6_cidr](sqlite3_stmt* stmt)
|
||||||
|
{
|
||||||
|
if (sqlite3_bind_text(stmt, 1, ipv6_cidr.c_str(),
|
||||||
|
-1, SQLITE_TRANSIENT) != SQLITE_OK)
|
||||||
|
{
|
||||||
|
Log::error("easySQLQuery", "Failed to bind %s.",
|
||||||
|
ipv6_cidr.c_str());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
} // testBannedForIPv6
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
void ServerLobby::testBannedForOnlineId(STKPeer* peer,
|
void ServerLobby::testBannedForOnlineId(STKPeer* peer,
|
||||||
uint32_t online_id) const
|
uint32_t online_id) const
|
||||||
|
@ -80,6 +80,8 @@ private:
|
|||||||
|
|
||||||
bool m_ip_ban_table_exists;
|
bool m_ip_ban_table_exists;
|
||||||
|
|
||||||
|
bool m_ipv6_ban_table_exists;
|
||||||
|
|
||||||
bool m_online_id_ban_table_exists;
|
bool m_online_id_ban_table_exists;
|
||||||
|
|
||||||
bool m_ip_geolocation_table_exists;
|
bool m_ip_geolocation_table_exists;
|
||||||
@ -325,6 +327,7 @@ private:
|
|||||||
void clientSelectingAssetsWantsToBackLobby(Event* event);
|
void clientSelectingAssetsWantsToBackLobby(Event* event);
|
||||||
void kickPlayerWithReason(STKPeer* peer, const char* reason) const;
|
void kickPlayerWithReason(STKPeer* peer, const char* reason) const;
|
||||||
void testBannedForIP(STKPeer* peer) const;
|
void testBannedForIP(STKPeer* peer) const;
|
||||||
|
void testBannedForIPv6(STKPeer* peer) const;
|
||||||
void testBannedForOnlineId(STKPeer* peer, uint32_t online_id) const;
|
void testBannedForOnlineId(STKPeer* peer, uint32_t online_id) const;
|
||||||
void writeDisconnectInfoTable(STKPeer* peer);
|
void writeDisconnectInfoTable(STKPeer* peer);
|
||||||
void writePlayerReport(Event* event);
|
void writePlayerReport(Event* event);
|
||||||
|
@ -351,7 +351,16 @@ namespace ServerConfig
|
|||||||
SERVER_CFG_PREFIX StringServerConfigParam m_ip_ban_table
|
SERVER_CFG_PREFIX StringServerConfigParam m_ip_ban_table
|
||||||
SERVER_CFG_DEFAULT(StringServerConfigParam("ip_ban",
|
SERVER_CFG_DEFAULT(StringServerConfigParam("ip_ban",
|
||||||
"ip-ban-table",
|
"ip-ban-table",
|
||||||
"Ip ban list table name, you need to create the table first, see "
|
"IPv4 ban list table name, you need to create the table first, see "
|
||||||
|
"NETWORKING.md for details, empty to disable. "
|
||||||
|
"This table can be shared for all servers if you use the same name. "
|
||||||
|
"STK can auto kick active peer from ban list (update per minute) which"
|
||||||
|
"allows live kicking peer by inserting record to database."));
|
||||||
|
|
||||||
|
SERVER_CFG_PREFIX StringServerConfigParam m_ipv6_ban_table
|
||||||
|
SERVER_CFG_DEFAULT(StringServerConfigParam("ipv6_ban",
|
||||||
|
"ipv6-ban-table",
|
||||||
|
"IPv6 ban list table name, you need to create the table first, see "
|
||||||
"NETWORKING.md for details, empty to disable. "
|
"NETWORKING.md for details, empty to disable. "
|
||||||
"This table can be shared for all servers if you use the same name. "
|
"This table can be shared for all servers if you use the same name. "
|
||||||
"STK can auto kick active peer from ban list (update per minute) which"
|
"STK can auto kick active peer from ban list (update per minute) which"
|
||||||
|
Loading…
Reference in New Issue
Block a user