ipban/src/ipban.cpp
2024-01-05 00:23:33 +01:00

145 lines
3.8 KiB
C++

#include "../lib/ipban.hpp"
marcelb::ipban::ipban(const uint& _duration, const uint& _fail_interval, const uint& _fail_limit, const string& _db_file) {
ban_duration = _duration*60;
fail_interval = _fail_interval*60;
fail_limit = _fail_limit;
db_file = _db_file;
load_db();
unban_bot = async(launch::async, [&]() {
while (run_unban_bot) {
sleep_if(BOT_LOOP_TIME, run_unban_bot);
for (uint i=0; i<banned.size(); i++) {
if (difftime(time(NULL), banned[i]._time) >= ban_duration) {
unban(banned.begin() + i);
}
}
for (auto _failed = failed.begin(); _failed != failed.end(); ) {
if (difftime(time(NULL), _failed->second.first_fail) >= fail_interval && _failed != failed.end()) {
f_io.lock();
_failed = failed.erase(_failed);
f_io.unlock();
} else {
++_failed;
}
}
}
return;
});
}
marcelb::ipban::~ipban() {
run_unban_bot = false;
unban_bot.get();
/**
* ako aplikaciju sruši napadač - želimo da ostane banovan - unbanovat će se po isteku intervala
*/
// for (uint i=0; i<banned.size(); i++) {
// unban(banned.begin() + i);
// }
}
void marcelb::ipban::load_db() {
string line;
ifstream mydb (db_file);
if (mydb.is_open()) {
while (getline(mydb, line) ) {
struct _ban saved_ban;
saved_ban.ip = line.substr(0, line.find('-'));
saved_ban._time = stol(line.substr(line.find('-')+1));
banned.push_back(saved_ban);
}
mydb.close();
}
}
bool marcelb::ipban::update_db() {
bool success = false;
ofstream mydb (db_file);
if (mydb.is_open()) {
for (int i=0; i<banned.size(); i++) {
mydb << banned[i].ip << "-" << banned[i]._time << "\n";
}
success = true;
mydb.close();
}
else {
success = false;
}
return success;
}
bool marcelb::ipban::ban(const string& ip) {
bool status = ufw_ban(ip);
io.lock();
banned.push_back({ip, time(NULL)});
status = status && update_db();
io.unlock();
return status;
}
bool marcelb::ipban::unban(vector<_ban>::iterator ban_itr) {
bool status = ufw_unban(ban_itr->ip);
io.lock();
banned.erase(ban_itr);
status = status && update_db();
io.unlock();
return status;
}
bool marcelb::ipban::ufw_ban(const string& ip) {
string ufw_cmd = "sudo ufw deny from " + ip + " to any";
try {
string execute_res = exec(ufw_cmd);
if (execute_res == "Rule added\n") {
return true;
}
} catch (const string except) {
cout << except << endl;
}
return false;
}
bool marcelb::ipban::ufw_unban(const string& ip) {
string ufw_cmd = "sudo ufw delete deny from " + ip + " to any";
try {
string execute_res = exec(ufw_cmd);
if (execute_res == "Rule deleted\n") {
return true;
}
} catch (const string except) {
cout << except << endl;
}
return false;
}
void marcelb::ipban::fail(const string& ip) {
lock_guard<mutex> _io(f_io);
if (failed[ip].n_fails == 0) {
failed[ip].n_fails = 1;
failed[ip].first_fail = time(NULL);
} else if (++failed[ip].n_fails >= fail_limit) {
ban(ip);
failed.erase(ip);
}
}
bool marcelb::ipban::unfail(const string& ip) {
lock_guard<mutex> _io(f_io);
return failed.erase(ip);;
}
static void marcelb::sleep_if(const uint& _time, const bool& _condition) {
time_t start_time = time(NULL);
do {
sleep(BOT_SLEEP_LOOP_TIME);
} while (difftime(time(NULL), start_time) < _time && _condition);
}