Compare commits

..

No commits in common. "dev" and "v0.1" have entirely different histories.
dev ... v0.1

9 changed files with 56 additions and 246 deletions

3
.gitignore vendored
View File

@ -1,3 +1,2 @@
example
exec
test/*.o
exec

6
.vscode/tasks.json vendored
View File

@ -7,11 +7,9 @@
"args": [
"-fdiagnostics-color=always",
"-g",
"${fileDirname}/test.cpp",
"${fileDirname}/../src/*.cpp",
"${fileDirname}/../../exec/src/*.cpp",
"${file}",
"-o",
"${fileDirname}/test.o"
"${fileDirname}/${fileBasenameNoExtension}"
],
"options": {
"cwd": "${fileDirname}"

View File

@ -1,57 +1,3 @@
# ipban
# Library for the fail-ban function
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.
A library for managing IP address bans on UFW systems

View File

@ -3,17 +3,15 @@
#include <iostream>
#include <vector>
#include <map>
#include <string>
#include <future>
#include <mutex>
#include <fstream>
#include <algorithm>
#include <time.h>
#include <unistd.h>
#include "../../exec/lib/exec.hpp"
#include "../exec/lib/exec.hpp"
using namespace std;
@ -23,8 +21,8 @@ namespace marcelb {
#define BOT_SLEEP_LOOP_TIME 1 // 1 second
/**
* Banned object
* IP address and ban time
* Banovani objekt
* IP adresa i vrijeme banovanja
*/
struct _ban {
string ip;
@ -32,112 +30,68 @@ struct _ban {
};
/**
* Auxiliary structure - to track the number of errors
*/
struct _fail {
time_t first_fail;
uint n_fails = 0;
};
/**
* Library to ban IP addresses through the UFW firewall for a certain period of time
* Automatically removes ban after timeout
* It has its own DB mechanism for protection against irreversible ban
* Biblioteka za ban IP adrese kroz UFW vatrozid na određeno vrijeme
* Automatski uklanja zabranu po isteku vremena
* Posjeduje vlastiti DB mehanizam za zaštitu od nepovratnog ban-a
*/
class ipban {
mutex io, f_io, wl_io;
mutex io;
time_t ban_duration;
uint fail_interval;
uint fail_limit;
string db_file;
vector<_ban> banned;
map<string, struct _fail> failed;
vector<string> white_list;
future<void> unban_bot;
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();
/**
* The method updates database states with memory states
* Metoda ažurira stanja baze sa stanjima iz memorije
*/
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);
/**
* The method checks if the forwarding ip address is currently banned
*/
bool is_banned(const string& ip);
/**
* Method calls exec and adds rules to UFW firewall
* Metoda poziva exec i dodaje pravila u UFW vatrozid
*/
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);
/**
* 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:
/**
* Constructor, receives the default value of the duration of the ban in minutes,
* address error tracking time, number of allowed errors
* and the database file path
* Konstruktor, prima zadanu vrijednost trajanja ban-a u minutama
* 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 string& db_file = "ipban.db"); // u minutama?
/**
* The method that bans the forwarded IP address, adds it to the banned vector, updates the database
* Returns the status of the operation
* Metoda koja banuje proslijeđenu IP adresu, dodaje je u vector banned, ažurira bazu
* Vraća status operacije
*/
bool ban(const string& ip);
/**
* Incrementally increase the number of errors for the forwarded address
* if the number of allowed errors in the interval is exceeded - the address is banned
*/
bool fail(const string& ip);
/**
* Removes errors for forwarded address
*/
bool unfail(const string& ip);
/**
* Adds the forwarded address to the white list
*/
void add_white_list(const string& ip);
/**
* Adds forwarded addresses to the white list
*/
void add_white_list(const vector<string>& ips);
/**
* Destructor
* Destruktor, uklanja sve zabrane.
*/
~ipban();
};
/**
* Sleep function, which sleeps until timeout or logic condition condition
* Receives time in seconds, and logical condition
* Funkcija za mirovanje tijeka, koj miruje do isteka vremena ili logičkog stanja uvijeta
* Prima vrijeme u sekundama, i logički uvijet
*/
static void sleep_if(const uint& _time, const bool& _condition);

View File

@ -1,9 +1,7 @@
#include "../lib/ipban.hpp"
marcelb::ipban::ipban(const uint& _duration, const uint& _fail_interval, const uint& _fail_limit, const string& _db_file) {
marcelb::ipban::ipban(const uint& _duration, const string& _db_file) {
ban_duration = _duration*60;
fail_interval = _fail_interval*60;
fail_limit = _fail_limit;
db_file = _db_file;
load_db();
@ -15,15 +13,6 @@ marcelb::ipban::ipban(const uint& _duration, const uint& _fail_interval, const u
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;
});
@ -32,6 +21,14 @@ marcelb::ipban::ipban(const uint& _duration, const uint& _fail_interval, const u
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() {
@ -65,52 +62,28 @@ bool marcelb::ipban::update_db() {
}
bool marcelb::ipban::ban(const string& ip) {
bool status = !is_in_white_list(ip);
if (!status) {
return status;
}
if (is_banned(ip)) {
return status;
}
status = ufw_ban(ip);
if (status) {
io.lock();
banned.push_back({ip, time(NULL)});
status = update_db();
io.unlock();
}
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);
if (status) {
io.lock();
banned.erase(ban_itr);
status = update_db();
io.unlock();
}
io.lock();
banned.erase(ban_itr);
status = status && update_db();
io.unlock();
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) {
string ufw_cmd = "sudo ufw insert 1 deny from " + ip + " to any";
string ufw_cmd = "sudo ufw deny from " + ip + " to any";
try {
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;
}
} catch (const string except) {
@ -133,49 +106,6 @@ bool marcelb::ipban::ufw_unban(const string& ip) {
return false;
}
bool marcelb::ipban::fail(const string& ip) {
lock_guard<mutex> _io(f_io);
bool status = !is_in_white_list(ip);
if (status) {
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);
}
}
return status;
}
bool marcelb::ipban::unfail(const string& ip) {
lock_guard<mutex> _io(f_io);
return failed.erase(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) {
time_t start_time = time(NULL);
do {

View File

@ -1 +1 @@
g++ test.cpp ../src/*.cpp ../../exec/src/*.cpp -o test
g++ test.cpp ../src/*.cpp ../exec/src/*.cpp -o test

View File

@ -0,0 +1 @@
90.163.88.49-1702323353

BIN
test/test

Binary file not shown.

View File

@ -23,33 +23,15 @@ int main() {
ipban myban(1);
// myban.ban("192.168.2.74");
// sleep(300);
// uint i=0;
uint i=0;
// while (i<10) {
// string ip = generateRandomIP();
// cout << "Ban " << ip << endl;
// myban.ban(ip);
// sleep(30);
// i++;
// }
// myban.add_white_list("192.168.2.74");
cout << myban.ban("192.168.2.74") << endl;
sleep(5);
cout << myban.ban("192.168.2.74") << endl;
sleep(200);
// myban.fail("192.168.2.74");
// sleep(5);
// // myban.unfail("192.168.2.74");
// sleep(2);
// myban.fail("192.168.2.74");
// sleep(5);
// myban.fail("192.168.2.74");
sleep(100);
while (i<10) {
string ip = generateRandomIP();
cout << "Ban " << ip << endl;
myban.ban(ip);
sleep(30);
i++;
}
return 0;
}