Skip to content

Commit

Permalink
refactor(Core/IpCache): refactoring ip cache (WarheadCore#153)
Browse files Browse the repository at this point in the history
* Rename to IpCache
* Added guard ban for malformed packet flood
* Added configure option for each type of ban
* Now manager initialized at start up
  • Loading branch information
Winfidonarleyan committed Nov 7, 2022
1 parent 24699e1 commit e731670
Show file tree
Hide file tree
Showing 11 changed files with 499 additions and 300 deletions.
9 changes: 7 additions & 2 deletions src/server/apps/authserver/Main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
#include "SharedDefines.h"
#include "SignalHandlerMgr.h"
#include "Util.h"
#include "IpCache.h"
#include <boost/program_options.hpp>
#include <boost/version.hpp>
#include <filesystem>
Expand Down Expand Up @@ -126,13 +127,16 @@ int main(int argc, char** argv)
if (!StartDB())
return 1;

std::shared_ptr<void> dbHandle(nullptr, [](void*) { StopDB(); });

// Load ip cache
sIPCacheMgr->Initialize(Warhead::ApplicationType::AuthServer);

sSecretMgr->Initialize();

// Load IP Location Database
sIPLocation->Load();

std::shared_ptr<void> dbHandle(nullptr, [](void*) { StopDB(); });

// Get the list of realms for the server
sRealmList->Initialize(sConfigMgr->GetOption<int32>("RealmsStateUpdateDelay", 20));

Expand Down Expand Up @@ -201,6 +205,7 @@ bool StartDB()
return false;

LOG_INFO("server.authserver", "Started auth database connection pool.");
LOG_INFO("server.authserver", "");
return true;
}

Expand Down
28 changes: 12 additions & 16 deletions src/server/apps/authserver/Server/AuthSession.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@
#include "CryptoGenerics.h"
#include "DatabaseEnv.h"
#include "Errors.h"
#include "IpCache.h"
#include "IPLocation.h"
#include "IpInfoCache.h"
#include "Log.h"
#include "RealmList.h"
#include "SecretMgr.h"
Expand Down Expand Up @@ -174,22 +174,24 @@ void AuthSession::Start()
std::string ipAddress = GetRemoteIpAddress().to_string();
LOG_TRACE("session", "Accepted connection from {}", ipAddress);

if (sIPInfoCacheMgr->CanCheckIpFromDB(ipAddress))
sIPCacheMgr->CheckIp(ipAddress);

if (sIPCacheMgr->CanCheckIpFromDB(ipAddress))
{
AuthDatabasePreparedStatement stmt = AuthDatabase.GetPreparedStatement(LOGIN_SEL_IP_INFO);
stmt->SetArguments(ipAddress);
_queryProcessor.AddCallback(AuthDatabase.AsyncQuery(stmt).WithPreparedCallback(std::bind(&AuthSession::CheckIpCallback, this, std::placeholders::_1)));
return;
}

if (sIPInfoCacheMgr->IsIPBanned(ipAddress))
if (sIPCacheMgr->IsBanned(ipAddress))
{
ByteBuffer pkt;
pkt << uint8(AUTH_LOGON_CHALLENGE);
pkt << uint8(0x00);
pkt << uint8(WOW_FAIL_BANNED);
SendPacket(pkt);
LOG_DEBUG("session", "[AuthSession::Start] Banned ip '{}:{}' tries to login!", GetRemoteIpAddress().to_string(), GetRemotePort());
LOG_DEBUG("ipcache", "[AuthSession::Start] Banned ip '{}:{}' tries to login!", GetRemoteIpAddress().to_string(), GetRemotePort());
return;
}

Expand All @@ -211,9 +213,6 @@ void AuthSession::CheckIpCallback(PreparedQueryResult result)

if (!result)
{
// Update cache
sIPInfoCacheMgr->UpdateIPInfo(ipAddress);

AsyncRead();
return;
}
Expand All @@ -222,22 +221,19 @@ void AuthSession::CheckIpCallback(PreparedQueryResult result)
{
if (row[0].Get<uint64>())
{
// Update cache
sIPInfoCacheMgr->UpdateIPInfo(ipAddress, true);
// Set ban in cache
sIPCacheMgr->SetBannedForIP(ipAddress, Warhead::CheckIpType::LoginFlood);

ByteBuffer pkt;
pkt << uint8(AUTH_LOGON_CHALLENGE);
pkt << uint8(0x00);
pkt << uint8(WOW_FAIL_BANNED);
SendPacket(pkt);
LOG_DEBUG("session", "[AuthSession::CheckIpCallback] Banned ip '{}:{}' tries to login!", GetRemoteIpAddress().to_string(), GetRemotePort());
LOG_INFO("session", "[AuthSession::CheckIpCallback] Banned ip '{}:{}' tries to login!", GetRemoteIpAddress().to_string(), GetRemotePort());
return;
}
}

// Update cache
sIPInfoCacheMgr->UpdateIPInfo(ipAddress);

AsyncRead();
}

Expand All @@ -257,8 +253,8 @@ void AuthSession::ReadHandler()
// Ban this ip for malformed packet
{
auto ipAddress{ GetRemoteIpAddress().to_string() };
LOG_WARN("session", "IP: {}. Try send malformed packet!", ipAddress);
sIPInfoCacheMgr->AddBanForIP(ipAddress, 5min, "Auth: Malformed packet");
LOG_WARN("session", "IP: {} sent malformed packet!", ipAddress);
sIPCacheMgr->CheckIp(ipAddress, Warhead::CheckIpType::Malformed);
}

CloseSocket();
Expand Down Expand Up @@ -614,7 +610,7 @@ bool AuthSession::HandleLogonProof()
if (++_accountInfo.FailedLogins >= MaxWrongPassCount)
{
uint32 WrongPassBanTime = sConfigMgr->GetOption<int32>("WrongPass.BanTime", 600);
bool WrongPassBanType = sConfigMgr->GetOption<bool>("WrongPass.BanType", false);
bool WrongPassBanType = sConfigMgr->GetOption<bool>("WrongPass.CheckIpType", false);

if (WrongPassBanType)
{
Expand Down
40 changes: 19 additions & 21 deletions src/server/apps/authserver/authserver.conf.dist
Original file line number Diff line number Diff line change
Expand Up @@ -114,12 +114,12 @@ WrongPass.MaxCount = 0
WrongPass.BanTime = 600

#
# WrongPass.BanType
# WrongPass.CheckIpType
# Description: Ban type for invalid login attempts.
# Default: 0 - (Ban IP)
# 1 - (Ban Account)

WrongPass.BanType = 0
WrongPass.CheckIpType = 0

#
# WrongPass.Logging
Expand Down Expand Up @@ -240,6 +240,14 @@ MaxPingTime = 30

###################################################################################################
# IP CACHE SETTINGS
#
# IPCache.Enable
# Description: Enable ip cache
# Default: 1
#

IPCache.Enable = 1

#
# IPCache.Check.Delay
# Description: Delay in seconds for check ip from db and update cache
Expand All @@ -250,37 +258,27 @@ IPCache.Check.Delay = 60

#
# IPCache.Check.MaxCount
# Description: Max check count in period IPCache.Check.Delay
# Default: 10
#

IPCache.Check.MaxCount = 10

#
# IPCache.Ban.Enable
# Description: Enable ban for login flood
# Default: 1
# Description: Max check count for add ban (LoginFlood Malformed DDOS)
# Default: "10 3 50"
#

IPCache.Ban.Enable = 1
IPCache.Check.MaxCount = "10 3 50"

#
# IPCache.Ban.Enable
# Description: Ban duration in seconds
# Default: 300 (5 min)
# Description: Enable ban (LoginFlood Malformed DDOS)
# Default: "1 1 1"
#

IPCache.Ban.Duration = 300
IPCache.Ban.Enable = "1 1 1"

#
# IPCache.Ban.Enable
# Description: DDOS ban duration in seconds (need WarheadDDOSGuard app for this ban)
# Default: 604800 (7 days)
# 2592000 (30 days)
# 0 (permanent)
# Description: Ban duration in seconds (LoginFlood Malformed DDOS)
# Default: "300 300 604800"
#

IPCache.DDOSBan.Duration = 604800
IPCache.Ban.Duration = "300 300 604800"
###################################################################################################

###################################################################################################
Expand Down
4 changes: 4 additions & 0 deletions src/server/apps/worldserver/Main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@
#include "WorldSocket.h"
#include "WorldSocketMgr.h"
#include "DiscordChannel.h"
#include "IpCache.h"
#include <boost/program_options.hpp>
#include <filesystem>
#include <iostream>
Expand Down Expand Up @@ -268,6 +269,9 @@ int main(int argc, char** argv)

std::shared_ptr<void> dbHandle(nullptr, [](void*) { StopDB(); });

// Load ip cache
sIPCacheMgr->Initialize(Warhead::ApplicationType::WorldServer);

// set server offline (not connectable)
AuthDatabase.DirectExecute("UPDATE realmlist SET flag = (flag & ~{}) | {} WHERE id = '{}'", REALM_FLAG_OFFLINE, REALM_FLAG_VERSION_MISMATCH, realm.Id.Realm);

Expand Down
36 changes: 17 additions & 19 deletions src/server/apps/worldserver/worldserver.conf.dist
Original file line number Diff line number Diff line change
Expand Up @@ -4187,6 +4187,14 @@ ExternalMail.Enable = 1

###################################################################################################
# IP CACHE SETTINGS
#
# IPCache.Enable
# Description: Enable ip cache
# Default: 1
#

IPCache.Enable = 1

#
# IPCache.Check.Delay
# Description: Delay in seconds for check ip from db and update cache
Expand All @@ -4197,37 +4205,27 @@ IPCache.Check.Delay = 60

#
# IPCache.Check.MaxCount
# Description: Max check count in period IPCache.Check.Delay
# Default: 10
#

IPCache.Check.MaxCount = 10

#
# IPCache.Ban.Enable
# Description: Enable ban for login flood
# Default: 1
# Description: Max check count for add ban (LoginFlood Malformed DDOS)
# Default: "10 3 50"
#

IPCache.Ban.Enable = 1
IPCache.Check.MaxCount = "10 3 50"

#
# IPCache.Ban.Enable
# Description: Ban duration in seconds
# Default: 300 (5 min)
# Description: Enable ban (LoginFlood Malformed DDOS)
# Default: "1 1 1"
#

IPCache.Ban.Duration = 300
IPCache.Ban.Enable = "1 1 1"

#
# IPCache.Ban.Enable
# Description: DDOS ban duration in seconds (need WarheadDDOSGuard app for this ban)
# Default: 604800 (7 days)
# 2592000 (30 days)
# 0 (permanent)
# Description: Ban duration in seconds (LoginFlood Malformed DDOS)
# Default: "300 300 604800"
#

IPCache.DDOSBan.Duration = 604800
IPCache.Ban.Duration = "300 300 604800"
###################################################################################################

########################################
Expand Down
2 changes: 1 addition & 1 deletion src/server/game/Server/WorldSession.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1235,7 +1235,7 @@ void WorldSession::SendAddonsInfo()
data.append(itr->NameMD5, sizeof(itr->NameMD5));
data.append(itr->VersionMD5, sizeof(itr->VersionMD5));
data << uint32(itr->Timestamp);
data << uint32(1); // IsBanned
data << uint32(1); // IsDefaultBanned
}

SendPacket(&data);
Expand Down
23 changes: 9 additions & 14 deletions src/server/game/Server/WorldSocket.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
#include "GameConfig.h"
#include "GameTime.h"
#include "IPLocation.h"
#include "IpInfoCache.h"
#include "IpCache.h"
#include "Opcodes.h"
#include "PacketLog.h"
#include "Realm.h"
Expand All @@ -52,18 +52,20 @@ void WorldSocket::Start()
{
std::string ipAddress = GetRemoteIpAddress().to_string();

if (sIPInfoCacheMgr->CanCheckIpFromDB(ipAddress))
sIPCacheMgr->CheckIp(ipAddress);

if (sIPCacheMgr->CanCheckIpFromDB(ipAddress))
{
AuthDatabasePreparedStatement stmt = AuthDatabase.GetPreparedStatement(LOGIN_SEL_IP_INFO);
stmt->SetArguments(ipAddress);
_queryProcessor.AddCallback(AuthDatabase.AsyncQuery(stmt).WithPreparedCallback(std::bind(&WorldSocket::CheckIpCallback, this, std::placeholders::_1)));
return;
}

if (sIPInfoCacheMgr->IsIPBanned(ipAddress))
if (sIPCacheMgr->IsBanned(ipAddress))
{
SendAuthResponseError(AUTH_REJECT);
LOG_ERROR("network", "WorldSocket::Start: Sent Auth Response (IP {} banned).", ipAddress);
LOG_ERROR("network", "WorldSocket::Start: Client try login with ban ignore authserver. IP: {}", ipAddress);
DelayedCloseSocket();
return;
}
Expand All @@ -79,9 +81,6 @@ void WorldSocket::CheckIpCallback(PreparedQueryResult result)
// Not found ban info for this ip
if (!result)
{
// Update cache
sIPInfoCacheMgr->UpdateIPInfo(ipAddress);

AsyncRead();
HandleSendAuthSession();
return;
Expand All @@ -91,8 +90,8 @@ void WorldSocket::CheckIpCallback(PreparedQueryResult result)
{
if (row[0].Get<uint64>())
{
// Update cache
sIPInfoCacheMgr->UpdateIPInfo(ipAddress, true);
// Set ban in cache
sIPCacheMgr->SetBannedForIP(ipAddress, Warhead::CheckIpType::LoginFlood);

SendAuthResponseError(AUTH_REJECT);
LOG_ERROR("network", "WorldSocket::CheckIpCallback: Sent Auth Response (IP {} banned).", GetRemoteIpAddress().to_string());
Expand All @@ -101,9 +100,6 @@ void WorldSocket::CheckIpCallback(PreparedQueryResult result)
}
}

// Update cache
sIPInfoCacheMgr->UpdateIPInfo(ipAddress);

AsyncRead();
HandleSendAuthSession();
}
Expand Down Expand Up @@ -251,8 +247,7 @@ bool WorldSocket::ReadHeaderHandler()
LOG_ERROR("network", "WorldSocket::ReadHeaderHandler(): client {} sent malformed packet (size: {}, cmd: {})",
ipAddress, header->size, header->cmd);

sBan->BanIP(ipAddress, "5min", "World: Malformed packet", "System");
sIPInfoCacheMgr->UpdateIPInfo(ipAddress, true);
sIPCacheMgr->CheckIp(ipAddress, Warhead::CheckIpType::Malformed);
return false;
}

Expand Down
Loading

0 comments on commit e731670

Please sign in to comment.