Compare commits
No commits in common. "dev" and "v0.3" have entirely different histories.
2
.vscode/tasks.json
vendored
2
.vscode/tasks.json
vendored
@ -9,7 +9,7 @@
|
|||||||
"-g",
|
"-g",
|
||||||
"${fileDirname}/test.cpp",
|
"${fileDirname}/test.cpp",
|
||||||
"${fileDirname}/../src/*.cpp",
|
"${fileDirname}/../src/*.cpp",
|
||||||
"${fileDirname}/../../exec/src/*.cpp",
|
"${fileDirname}/../exec/src/*.cpp",
|
||||||
"-o",
|
"-o",
|
||||||
"${fileDirname}/test.o"
|
"${fileDirname}/test.o"
|
||||||
],
|
],
|
||||||
|
58
README.md
58
README.md
@ -1,57 +1,3 @@
|
|||||||
|
# ipban
|
||||||
|
|
||||||
# Library for the fail-ban function
|
A library for managing IP address bans on UFW systems
|
||||||
|
|
||||||
IPBan is a C++ library for banning IP addresses in case of consecutive errors.
|
|
||||||
|
|
||||||
## Features
|
|
||||||
|
|
||||||
- Object oriented
|
|
||||||
- Thread safe
|
|
||||||
- Internal database of banned addresses as a protection mechanism against irreversible ban
|
|
||||||
- Automatic unbanning
|
|
||||||
- Manual fail and unfail methods
|
|
||||||
- White list of IP addresses
|
|
||||||
- It is adjustable: database file location, tracking time for errors, number of attempts before ban, ban duration.
|
|
||||||
## Installation
|
|
||||||
|
|
||||||
This library also requires my exec library to work, download the latest release:
|
|
||||||
|
|
||||||
https://git.bitelex.co/marcelb/exec or https://github.com/bandicm/exec
|
|
||||||
|
|
||||||
Then download the latest backend of these libraries and unzip to the same location. You can turn it on with:
|
|
||||||
|
|
||||||
```
|
|
||||||
#include "cppurl/lib/cppurl.hpp"
|
|
||||||
using namespace marcelb;
|
|
||||||
```
|
|
||||||
|
|
||||||
## Usage
|
|
||||||
|
|
||||||
```c++
|
|
||||||
//init
|
|
||||||
ipban myban(30); // 30 minutes
|
|
||||||
// add white list string or vector<string>
|
|
||||||
myban.add_white_list("10.0.8.1");
|
|
||||||
// ban now ip
|
|
||||||
myban.ban("10.0.8.2");
|
|
||||||
// fail ip
|
|
||||||
myban.fail("10.0.8.3");
|
|
||||||
// unfail ip
|
|
||||||
myban.unfail("10.0.8.3");
|
|
||||||
|
|
||||||
```
|
|
||||||
## License
|
|
||||||
|
|
||||||
[APACHE 2.0](http://www.apache.org/licenses/LICENSE-2.0/)
|
|
||||||
|
|
||||||
|
|
||||||
## Support & Feedback
|
|
||||||
|
|
||||||
For support and any feedback, contact the address: marcelb96@yahoo.com.
|
|
||||||
|
|
||||||
## Contributing
|
|
||||||
|
|
||||||
Contributions are always welcome!
|
|
||||||
|
|
||||||
Feel free to fork and start working with or without a later pull request. Or contact for suggest and request an option.
|
|
||||||
|
|
@ -8,7 +8,6 @@
|
|||||||
#include <future>
|
#include <future>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <algorithm>
|
|
||||||
|
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
@ -23,8 +22,8 @@ namespace marcelb {
|
|||||||
#define BOT_SLEEP_LOOP_TIME 1 // 1 second
|
#define BOT_SLEEP_LOOP_TIME 1 // 1 second
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Banned object
|
* Banovani objekt
|
||||||
* IP address and ban time
|
* IP adresa i vrijeme banovanja
|
||||||
*/
|
*/
|
||||||
struct _ban {
|
struct _ban {
|
||||||
string ip;
|
string ip;
|
||||||
@ -32,7 +31,7 @@ struct _ban {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Auxiliary structure - to track the number of errors
|
* Pomoćna struktura - za praćenje broja pogrešaka
|
||||||
*/
|
*/
|
||||||
struct _fail {
|
struct _fail {
|
||||||
time_t first_fail;
|
time_t first_fail;
|
||||||
@ -40,104 +39,85 @@ struct _fail {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Library to ban IP addresses through the UFW firewall for a certain period of time
|
* Biblioteka za ban IP adrese kroz UFW vatrozid na određeno vrijeme
|
||||||
* Automatically removes ban after timeout
|
* Automatski uklanja zabranu po isteku vremena
|
||||||
* It has its own DB mechanism for protection against irreversible ban
|
* Posjeduje vlastiti DB mehanizam za zaštitu od nepovratnog ban-a
|
||||||
*/
|
*/
|
||||||
class ipban {
|
class ipban {
|
||||||
mutex io, f_io, wl_io;
|
mutex io, f_io;
|
||||||
time_t ban_duration;
|
time_t ban_duration;
|
||||||
uint fail_interval;
|
uint fail_interval;
|
||||||
uint fail_limit;
|
uint fail_limit;
|
||||||
string db_file;
|
string db_file;
|
||||||
vector<_ban> banned;
|
vector<_ban> banned;
|
||||||
map<string, struct _fail> failed;
|
map<string, struct _fail> failed;
|
||||||
vector<string> white_list;
|
|
||||||
future<void> unban_bot;
|
future<void> unban_bot;
|
||||||
bool run_unban_bot = true;
|
bool run_unban_bot = true;
|
||||||
|
// interface možda bude trebao za ban
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The method loads banned IP addresses from the database
|
* Metoda učitava banovane IP adrese iz baze
|
||||||
*/
|
*/
|
||||||
void load_db();
|
void load_db();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The method updates database states with memory states
|
* Metoda ažurira stanja baze sa stanjima iz memorije
|
||||||
*/
|
*/
|
||||||
bool update_db();
|
bool update_db();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The method removes the ban for the passed iterator of the banned vector and updates the base
|
* Metoda uklanja ban za proslijeđeni iterator vektora banned i ažurira bazu
|
||||||
*/
|
*/
|
||||||
bool unban(vector<_ban>::iterator ban_itr);
|
bool unban(vector<_ban>::iterator ban_itr);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The method checks if the forwarding ip address is currently banned
|
* Metoda poziva exec i dodaje pravila u UFW vatrozid
|
||||||
*/
|
|
||||||
bool is_banned(const string& ip);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Method calls exec and adds rules to UFW firewall
|
|
||||||
*/
|
*/
|
||||||
bool ufw_ban(const string& ip);
|
bool ufw_ban(const string& ip);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The method calls exec and removes the rule in the UFW firewall
|
* Metoda poziva exec i uklanja pravilo u UFW vatrozidu
|
||||||
*/
|
*/
|
||||||
bool ufw_unban(const string& ip);
|
bool ufw_unban(const string& ip);
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks whether the forwarded address is in the white list
|
|
||||||
* If it returns true, if not false
|
|
||||||
*/
|
|
||||||
bool is_in_white_list(const string& ip);
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor, receives the default value of the duration of the ban in minutes,
|
* Konstruktor, prima zadanu vrijednost trajanja ban-a u minutama,
|
||||||
* address error tracking time, number of allowed errors
|
* vrijeme praćenja pogreške adrese, broj dozvoljenih pogreški
|
||||||
* and the database file path
|
* i putanju datoteke baze podataka
|
||||||
*/
|
*/
|
||||||
ipban(const uint& _duration, const uint& _fail_interval = 30, const uint& _fail_limit = 3, const string& db_file = "ipban.db"); // u minutama?
|
ipban(const uint& _duration, const uint& _fail_interval = 30, const uint& _fail_limit = 3, const string& db_file = "ipban.db"); // u minutama?
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The method that bans the forwarded IP address, adds it to the banned vector, updates the database
|
* Metoda koja banuje proslijeđenu IP adresu, dodaje je u vector banned, ažurira bazu
|
||||||
* Returns the status of the operation
|
* Vraća status operacije
|
||||||
*/
|
*/
|
||||||
bool ban(const string& ip);
|
bool ban(const string& ip);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Incrementally increase the number of errors for the forwarded address
|
* Inkrementalno povećaj broj grešaka za prosljeđenu adresu
|
||||||
* if the number of allowed errors in the interval is exceeded - the address is banned
|
* ako se prekorači broj dozvoljenih grešaka u intervalu - adresa se banuje
|
||||||
*/
|
*/
|
||||||
bool fail(const string& ip);
|
|
||||||
|
void fail(const string& ip);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Removes errors for forwarded address
|
* Uklanja greške za prosljeđenu adresu
|
||||||
*/
|
*/
|
||||||
|
|
||||||
bool unfail(const string& ip);
|
bool unfail(const string& ip);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds the forwarded address to the white list
|
* Destruktor, uklanja sve zabrane.
|
||||||
*/
|
|
||||||
void add_white_list(const string& ip);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds forwarded addresses to the white list
|
|
||||||
*/
|
|
||||||
void add_white_list(const vector<string>& ips);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Destructor
|
|
||||||
*/
|
*/
|
||||||
~ipban();
|
~ipban();
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sleep function, which sleeps until timeout or logic condition condition
|
* Funkcija za mirovanje tijeka, koj miruje do isteka vremena ili logičkog stanja uvijeta
|
||||||
* Receives time in seconds, and logical condition
|
* Prima vrijeme u sekundama, i logički uvijet
|
||||||
*/
|
*/
|
||||||
static void sleep_if(const uint& _time, const bool& _condition);
|
static void sleep_if(const uint& _time, const bool& _condition);
|
||||||
|
|
||||||
|
@ -32,6 +32,14 @@ marcelb::ipban::ipban(const uint& _duration, const uint& _fail_interval, const u
|
|||||||
marcelb::ipban::~ipban() {
|
marcelb::ipban::~ipban() {
|
||||||
run_unban_bot = false;
|
run_unban_bot = false;
|
||||||
unban_bot.get();
|
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() {
|
void marcelb::ipban::load_db() {
|
||||||
@ -65,52 +73,28 @@ bool marcelb::ipban::update_db() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool marcelb::ipban::ban(const string& ip) {
|
bool marcelb::ipban::ban(const string& ip) {
|
||||||
bool status = !is_in_white_list(ip);
|
bool status = ufw_ban(ip);
|
||||||
if (!status) {
|
io.lock();
|
||||||
return status;
|
banned.push_back({ip, time(NULL)});
|
||||||
}
|
status = status && update_db();
|
||||||
if (is_banned(ip)) {
|
io.unlock();
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
status = ufw_ban(ip);
|
|
||||||
|
|
||||||
if (status) {
|
|
||||||
io.lock();
|
|
||||||
banned.push_back({ip, time(NULL)});
|
|
||||||
status = update_db();
|
|
||||||
io.unlock();
|
|
||||||
}
|
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool marcelb::ipban::unban(vector<_ban>::iterator ban_itr) {
|
bool marcelb::ipban::unban(vector<_ban>::iterator ban_itr) {
|
||||||
bool status = ufw_unban(ban_itr->ip);
|
bool status = ufw_unban(ban_itr->ip);
|
||||||
if (status) {
|
io.lock();
|
||||||
io.lock();
|
banned.erase(ban_itr);
|
||||||
banned.erase(ban_itr);
|
status = status && update_db();
|
||||||
status = update_db();
|
io.unlock();
|
||||||
io.unlock();
|
|
||||||
}
|
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool marcelb::ipban::is_banned(const string& ip) {
|
|
||||||
auto it = std::find_if(banned.begin(), banned.end(), [&](const struct _ban& an_ban){
|
|
||||||
return an_ban.ip == ip;
|
|
||||||
});
|
|
||||||
if (it == banned.end()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool marcelb::ipban::ufw_ban(const string& ip) {
|
bool marcelb::ipban::ufw_ban(const string& ip) {
|
||||||
string ufw_cmd = "sudo ufw insert 1 deny from " + ip + " to any";
|
string ufw_cmd = "sudo ufw deny from " + ip + " to any";
|
||||||
try {
|
try {
|
||||||
string execute_res = exec(ufw_cmd);
|
string execute_res = exec(ufw_cmd);
|
||||||
if (execute_res == "Rule added\n" || execute_res == "Rule inserted\n") {
|
if (execute_res == "Rule added\n") {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
} catch (const string except) {
|
} catch (const string except) {
|
||||||
@ -134,19 +118,15 @@ bool marcelb::ipban::ufw_unban(const string& ip) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool marcelb::ipban::fail(const string& ip) {
|
void marcelb::ipban::fail(const string& ip) {
|
||||||
lock_guard<mutex> _io(f_io);
|
lock_guard<mutex> _io(f_io);
|
||||||
bool status = !is_in_white_list(ip);
|
if (failed[ip].n_fails == 0) {
|
||||||
if (status) {
|
failed[ip].n_fails = 1;
|
||||||
if (failed[ip].n_fails == 0) {
|
failed[ip].first_fail = time(NULL);
|
||||||
failed[ip].n_fails = 1;
|
} else if (++failed[ip].n_fails >= fail_limit) {
|
||||||
failed[ip].first_fail = time(NULL);
|
ban(ip);
|
||||||
} else if (++failed[ip].n_fails >= fail_limit) {
|
failed.erase(ip);
|
||||||
ban(ip);
|
|
||||||
failed.erase(ip);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return status;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -156,26 +136,6 @@ bool marcelb::ipban::unfail(const string& ip) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void marcelb::ipban::add_white_list(const string& ip) {
|
|
||||||
lock_guard<mutex> _io(wl_io);
|
|
||||||
if (find(white_list.begin(), white_list.end(), ip) == white_list.end()) {
|
|
||||||
white_list.push_back(ip);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void marcelb::ipban::add_white_list(const vector<string>& ips) {
|
|
||||||
for (auto ip : ips) {
|
|
||||||
add_white_list(ip);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool marcelb::ipban::is_in_white_list(const string& ip) {
|
|
||||||
return find(white_list.begin(), white_list.end(), ip) != white_list.end();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void marcelb::sleep_if(const uint& _time, const bool& _condition) {
|
static void marcelb::sleep_if(const uint& _time, const bool& _condition) {
|
||||||
time_t start_time = time(NULL);
|
time_t start_time = time(NULL);
|
||||||
do {
|
do {
|
||||||
|
@ -33,23 +33,22 @@ int main() {
|
|||||||
// i++;
|
// i++;
|
||||||
// }
|
// }
|
||||||
|
|
||||||
// myban.add_white_list("192.168.2.74");
|
|
||||||
|
|
||||||
|
myban.fail("192.168.2.74");
|
||||||
cout << myban.ban("192.168.2.74") << endl;
|
sleep(2);
|
||||||
sleep(5);
|
myban.fail("192.168.2.74");
|
||||||
cout << myban.ban("192.168.2.74") << endl;
|
|
||||||
sleep(200);
|
sleep(200);
|
||||||
// myban.fail("192.168.2.74");
|
// myban.fail("192.168.2.74");
|
||||||
// sleep(5);
|
// sleep(120);
|
||||||
|
|
||||||
// // myban.unfail("192.168.2.74");
|
// myban.unfail("192.168.2.74");
|
||||||
// sleep(2);
|
// sleep(2);
|
||||||
// myban.fail("192.168.2.74");
|
// myban.fail("192.168.2.74");
|
||||||
// sleep(5);
|
// sleep(120);
|
||||||
// myban.fail("192.168.2.74");
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
sleep(100);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
Loading…
x
Reference in New Issue
Block a user