From 6b70eb63ffcd46859cfce8ec7d063c3f3b1421f5 Mon Sep 17 00:00:00 2001 From: gumi Date: Thu, 10 Jan 2019 17:22:09 -0500 Subject: limit login requests to 1 per ip per X seconds --- src/login/login.cpp | 33 ++++++++++++++++++++++++++++++++- tools/config.py | 2 ++ 2 files changed, 34 insertions(+), 1 deletion(-) diff --git a/src/login/login.cpp b/src/login/login.cpp index 49c2438..c8a44c2 100644 --- a/src/login/login.cpp +++ b/src/login/login.cpp @@ -139,7 +139,6 @@ struct mmo_account SEX sex; }; - //------------------------------ // Writing function of logs file //------------------------------ @@ -165,6 +164,14 @@ void delete_login(Session *sess) (void)sess; } +std::vector recent_ips; + +static +void conn_limit_empty(TimerData *, tick_t) +{ + recent_ips.clear(); +} + static void delete_fromchar(Session *sess) { @@ -2413,6 +2420,22 @@ void parse_login(Session *s) break; } + if (login_conf.conn_limit_enable && !login_lan_conf.lan_subnet.covers(ip)) + { + if (std::find(recent_ips.begin(), recent_ips.end(), ip) != recent_ips.end()) + { + LOGIN_LOG_AND_ECHO("Connection refused: Login request flood detected. (REJECTED IP: %s)\n"_fmt, ip); + Packet_Fixed<0x0081> fixed_81; + fixed_81.error_code = 2; // already logged in (for lack of better error message) + send_fpacket<0x0081, 3>(s, fixed_81); + break; + } + else + { + recent_ips.push_back(ip); + } + } + result = mmo_auth(&account, s); if (result == 1) { @@ -3088,6 +3111,14 @@ int do_init(Slice argv) ).detach(); } + if (login::login_conf.conn_limit_enable) + { + Timer(gettick() + 1_s, + login::conn_limit_empty, + login::login_conf.conn_limit_interval + ).detach(); + } + // add timer to check GM accounts file modification std::chrono::seconds j = login::login_conf.gm_account_filename_check_timer; if (j == interval_t::zero()) diff --git a/tools/config.py b/tools/config.py index 0892973..f029777 100755 --- a/tools/config.py +++ b/tools/config.py @@ -523,6 +523,8 @@ def build_config(): login_conf.opt('main_server', ServerName, '{}') login_conf.opt('userid', AccountName, '{}') login_conf.opt('passwd', AccountPass, '{}') + login_conf.opt('conn_limit_enable', bool, 'true') + login_conf.opt('conn_limit_interval', seconds, '5_s') admin_conf.opt('login_ip', IP4Address, 'IP4_LOCALHOST') -- cgit v1.2.3-60-g2f50