Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
UNAME_S := $(shell uname -s)
CXX = g++-4.8
CXX = g++

PROGS = ddosdetector
CLEANFILES = $(PROGS) *.o

LDFLAGS = -lboost_system -lboost_thread -llog4cpp -lboost_program_options -lcurl
LDFLAGS = -lboost_system -lboost_thread -llog4cpp -lboost_program_options -lcurl -lpthread
CPPFLAGS = -std=c++11 -Wall #-O2
CPPFLAGS += -I ./sys -I ./proto

Expand Down Expand Up @@ -66,6 +66,8 @@ test: clean-test build-test run-test
check:
@./test/cppcheck/cppcheck -q -j12 --platform=unix64 -itest --std=c++11 --enable=all --inconclusive --suppressions-list=./test/cppcheck_suppress.cfg ./

build: all

build-test: $(TESTS_BIN)
@echo "====> Run tests <===="

Expand Down
23 changes: 12 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# DDoS attack detector #
Ddosdetector System - a flexible tool for analyzing network traffic and automation of the process of protection against DDoS attacks. The system is based on the framework, [Luigi Rizzo](https://github.com/luigirizzo/netmap) [netmap](https://habrahabr.ru/post/183832/) and is designed to work with a large volume of traffic (10GB / sec and more) without loss of performance.

The system is written in C++ (Standard 11) using *STL* and *Boost (1.55)*. Writing and assembling was done on *Ubuntu 12.04.5 LTS* and compiler *g++4.8*. For static analysis and research style blunders used *cppcheck* version 1.73.
The system is written in C++ (Standard 11) using *STL* and *Boost (1.58)*. Writing and assembling was done on *Ubuntu 16.04 LTS* and compiler *g++-5*. For static analysis and research style blunders used *cppcheck* version 1.73.

InfluxDB can be used for monitoring and collection of statistics.
![Grafana](docs/images/grafana.png)
Expand Down Expand Up @@ -68,6 +68,7 @@ then the system should appear interface with netmap:
### Installing ddosdetector ###
Build ddosdetector from source:
```bash
sudo apt-get install g++ libboost-all-dev libcurl4-gnutls-dev liblog4cpp5-dev
git clone https://velizarx@bitbucket.org/velizarx/ddosdetector.git
cd ./ddosdetector
make
Expand All @@ -86,12 +87,12 @@ depends: mdio,netmap,dca
Run ddosdetector (in example interface eth4):
```bash
cd <path_to_ddosdetector_directory>
./ddosdetector -i eth4 -r ~/ddosdetector.rules -p /tmp/ddosd.sock -l ~/ddosdetector.log
./ddosdetector -i eth4 -r ~/ddosdetector.rules -s /tmp/ddosd.sock -l ~/ddosdetector.log
```
Where:
* *-i eth4 (**parameter is required**)* - *eth4* interface system that gets mirrored traffic;
* *-r ~/ddosdetector.rules* - файл откуда будут загружены правила (этот параметр необязателен, по-умолчанию поиск файла производится по пути */etc/ddosdetector.rules*);
* *-p /tmp/ddosd.sock* - how to run the management server (in this case, the UNIX socket, the file */tmp/ddosd.sock*), may also be the path to the file or port number (then run TCP server to 127.0.0.1 and port specified) parameter is optional. By default, TCP server runs on port 9090;
* *-r ~/ddosdetector.rules* - файл откуда будут загружены правила (этот параметр необязателен, по-умолчанию поиск файла производится по пути */etc/ddosdetector/rules.conf*);
* *-s /tmp/ddosd.sock* - how to run the management server (in this case, the UNIX socket, the file */tmp/ddosd.sock*), may also be the path to the file or ip:port (then run TCP server to ip and port specified) parameter is optional. By default, TCP server runs on 127.0.0.1:9090;
* *-l ~/ddosdetector.log* - the path to the log file, the default output in the stdout

then you can connect to the system:
Expand All @@ -102,16 +103,16 @@ socat - UNIX-CONNECT:/tmp/ddosd.sock
## Control ##
### Configuration files ###
When you start the system tries to read the two configuration files:
* /etc/ddosdetector.conf - general system settings
* /etc/ddosdetector.rules - saved rules
* /etc/ddosdetector/conf.ini - general system settings
* /etc/ddosdetector/rules.conf - saved rules

File */etc/ddosdetector.conf* can contain the following settings (the value of the name):
File */etc/ddosdetector/conf.ini* can contain the following settings (the value of the name):
```ini
[Main]
Interface = eth0
Rules = /etc/ddosdetector.rules
Rules = /etc/ddosdetector/rules.conf
Log = /var/log/ddosdetector.log
Port = 9090
Listen = 127.0.0.1:9090

[IndluxDB]
Enable = yes
Expand All @@ -134,7 +135,7 @@ To manage the system you want to connect to a running daemon. Depending on the s
```bash
telnet 127.1 9090
```
where 9090 - this is the default start port or the specified port option
where 127.1 and 9090 - this is the default start ip:port or specified ip:port options

#### UNIX socket server ####
```bash
Expand Down Expand Up @@ -275,7 +276,7 @@ ICMP rules (num, rule, counter):
1: -d 92.53.96.141/32 --pps-th 100p --type =0 --code =0 : 0.00p/s (0.00b/s), 0 packets, 0 bytes
```
#### Reload rules from file ####
At startup, the system checks the configuration file previously saved rules (by default */etc/ddosdetector.rules*). If the reference system is already running, you can restart the rules from the file manually. Restart the rules of the file is performed either from the command control console **reload rules** any SIGHUP signal sent to the demon. For example rules file has the contents:
At startup, the system checks the configuration file previously saved rules (by default */etc/ddosdetector/rules.conf*). If the reference system is already running, you can restart the rules from the file manually. Restart the rules of the file is performed either from the command control console **reload rules** any SIGHUP signal sent to the demon. For example rules file has the contents:
```bash
$ cat ~/ddosdetector.rules
TCP -d 92.53.96.141/32 --pps-th 100p --seq =0 --pps-th-period 60 --action log:/tmp/test.log --next
Expand Down
59 changes: 40 additions & 19 deletions controld.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -122,9 +122,9 @@ void ControlSession<T>::parse()
do_write(collect_->get_rules());
return;
}
if(t_cmd[0] == "reload" && t_cmd[1] == "rules") // show rules
if(t_cmd[0] == "reload" && t_cmd[1] == "rules") // reload rules from file
{
raise(1);
raise(SIGHUP);
return;
}
// TODO: сделать monitor rules команду, с обновлением раз в секунду
Expand Down Expand Up @@ -267,39 +267,60 @@ void ControlSession<T>::parse()
}


ControlServer::ControlServer(io_service& io_service, const std::string& port,
ControlServer::ControlServer(io_service& io_service, const std::string& listen,
std::shared_ptr<RulesCollection> collect)
: is_unix_socket_(true), port_(port), collect_(collect)
: is_unix_socket_(true), listen_(listen), collect_(collect)
{
short num_port = 0;
try
{
num_port = boost::lexical_cast<short>(port_);
if (listen_.find(":") != std::string::npos) {
is_unix_socket_ = false;
}
catch(boost::bad_lexical_cast &) {}
if(is_unix_socket_)
{
local::stream_protocol::endpoint ep(port_);
unix_acceptor_ = std::make_shared<local::stream_protocol::stream_protocol::acceptor>(io_service, ep);
unix_socket_ = std::make_shared<local::stream_protocol::stream_protocol::socket>(io_service);
logger.info("Start controld unix socket server on " + port_);
try{
local::stream_protocol::endpoint ep(listen_);
unix_acceptor_ = std::make_shared<local::stream_protocol::stream_protocol::acceptor>(io_service, ep);
unix_socket_ = std::make_shared<local::stream_protocol::stream_protocol::socket>(io_service);
logger.info("Start controld unix socket server on " + listen_);
}
catch(std::exception& e)
{
throw ControldException(e.what());
}
do_unix_accept();
}
else
{
ip::tcp::tcp::endpoint ep(ip::tcp::tcp::v4(), num_port);
tcp_acceptor_ = std::make_shared<ip::tcp::tcp::acceptor>(io_service, ep);
tcp_socket_ = std::make_shared<ip::tcp::tcp::socket>(io_service);
logger.info("Start controld tcp server on " + to_string(num_port));
std::vector<std::string> ip_port = tokenize(listen_, ":");
short num_port = 0;
try{
if (ip_port.size() != 2)
{
throw ControldException("Bad ip or port parametr. Use <ip>:<port>.");
}
try
{
num_port = boost::lexical_cast<short>(ip_port[1]);
}
catch(boost::bad_lexical_cast &) {
throw ControldException("Bad port number.");
}
ip::tcp::tcp::endpoint ep(ip::address::from_string(ip_port[0]), num_port);
tcp_acceptor_ = std::make_shared<ip::tcp::tcp::acceptor>(io_service, ep);
tcp_socket_ = std::make_shared<ip::tcp::tcp::socket>(io_service);
logger.info("Start controld tcp server on " + listen_);
}
catch(std::exception& e)
{
throw ControldException(e.what());
}
do_tcp_accept();
}
}
ControlServer::~ControlServer()
{
if(is_unix_socket_ && is_file_exist(port_))
if(is_unix_socket_ && is_file_exist(listen_))
{
remove(port_.c_str());
remove(listen_.c_str());
}
}
void ControlServer::do_tcp_accept()
Expand Down
2 changes: 1 addition & 1 deletion controld.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ class ControlServer
// флаг unix сервера
bool is_unix_socket_;
// порт запуска
std::string port_;
std::string listen_;
// acceptors
std::shared_ptr<boost::asio::ip::tcp::tcp::acceptor> tcp_acceptor_;
std::shared_ptr<boost::asio::local::stream_protocol::acceptor> unix_acceptor_;
Expand Down
25 changes: 15 additions & 10 deletions ddosdetector.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -96,13 +96,18 @@ void monitor(std::shared_ptr<RulesCollection> collect,
Thread sends the data to the database InfluxDB, each period
*/
void start_control(boost::asio::io_service& io_service,
std::string port, std::shared_ptr<RulesCollection> collect)
std::string controld_serv, std::shared_ptr<RulesCollection> collect)
{
try
{
ControlServer serv(io_service, port, collect);
ControlServer serv(io_service, controld_serv, collect);
io_service.run();
}
catch (ControldException& e)
{
std::cout << "Error: " << e.what() << std::endl;
raise(SIGTERM);
}
catch (std::exception& e)
{
logger << log4cpp::Priority::ERROR
Expand Down Expand Up @@ -137,10 +142,10 @@ void task_runner(std::shared_ptr<ts_queue<action::TriggerJob>> task_list)
int main(int argc, char** argv) {
// Default settings
std::string interface = "";
std::string config_file = "/etc/ddosdetector.conf";
std::string rules_file = "/etc/ddosdetector.rules";
std::string config_file = "/etc/ddosdetector/conf.ini";
std::string rules_file = "/etc/ddosdetector/rules.conf";
std::string log_file = "";
std::string port = "9090";
std::string controld_serv = "127.0.0.1:9090";
bool debug_mode = false;
// Default for InfluxDB
std::string influx_enable = "no";
Expand All @@ -157,10 +162,10 @@ int main(int argc, char** argv) {
argv_opt.add_options()
("help,h", "show this help")
("interface,i", po::value<std::string>(&interface), "network interface (default eth4)")
//("config,c", po::value<std::string>(&config_file), "load config (default /etc/ddosdetector.conf)")
("rules,r", po::value<std::string>(&rules_file), "load rules from file (default /etc/ddosdetector.rules)")
//("config,c", po::value<std::string>(&config_file), "load config (default /etc/ddosdetector/conf.ini)")
("rules,r", po::value<std::string>(&rules_file), "load rules from file (default /etc/ddosdetector/rules.conf)")
("log,l", po::value<std::string>(&log_file), "log file (default output to console)")
("port,p", po::value<std::string>(&port), "port for controld tcp server (may be unix socket file)")
("server,s", po::value<std::string>(&controld_serv), "ip:port or unix socket file for controld server")
("debug,d", "enable debug output")
;
// Configuration file options
Expand All @@ -169,7 +174,7 @@ int main(int argc, char** argv) {
("Main.Interface", po::value<std::string>(&interface))
("Main.Rules", po::value<std::string>(&rules_file))
("Main.Log", po::value<std::string>(&log_file))
("Main.Port", po::value<std::string>(&port))
("Main.Listen", po::value<std::string>(&controld_serv))
("IndluxDB.Enable", po::value<std::string>(&influx_enable))
("IndluxDB.User", po::value<std::string>(&influx_user))
("IndluxDB.Password", po::value<std::string>(&influx_pass))
Expand Down Expand Up @@ -368,7 +373,7 @@ int main(int argc, char** argv) {

// run control server
threads.add_thread(new boost::thread(start_control,
std::ref(io_s), port, main_collect));
std::ref(io_s), controld_serv, main_collect));

// run triggerjob watcher thread
threads.add_thread(new boost::thread(task_runner, task_list));
Expand Down
4 changes: 2 additions & 2 deletions docs/EXAMPLE_RULES.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ TCP -d 92.53.116.23/32 --bps-th 100Mb --action log:/tmp/test.log
TCP -d 92.53.116.22/32 --bps-th 100Mb --action log:/tmp/test.log
TCP -d 92.53.116.40/32 --bps-th 100Mb --action log:/tmp/test.log
TCP -d 92.53.98.109/32 --bps-th 100Mb --action log:/tmp/test.log
TCP -d 92.53.98.104/32 --bps-th 100Mb --action log:/tmp/test.log
TCP -d 92.53.116.66/32 --bps-th 100Mb --action log:/tmp/test.log
TCP 10 -d 92.53.98.104/32 --bps-th 100Mb --action log:/tmp/test.log
TCP 11 -d 92.53.116.66/32 --bps-th 100Mb --action log:/tmp/test.log
TCP -d 92.53.116.67/32 --bps-th 100Mb --action log:/tmp/test.log
TCP -d 92.53.116.68/32 --bps-th 100Mb --action log:/tmp/test.log
TCP -d 92.53.116.69/32 --bps-th 100Mb --action log:/tmp/test.log
Expand Down
2 changes: 1 addition & 1 deletion docs/INFLUXDB.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ auth-enabled = false
```
/etc/init.d/influxdb restart
```
настраиваем доступ в конфигурационном файле ddosdetector (/etc/ddosdetector.conf)
настраиваем доступ в конфигурационном файле ddosdetector (/etc/ddosdetector/conf.ini)
```bash
[IndluxDB]
Enable = yes
Expand Down
15 changes: 8 additions & 7 deletions docs/README_RUS.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Детектор DDoS атак #
Система **ddosdetector** - это гибкий инструмент для анализа сетевого трафика и автоматизации процесса защиты от DDoS атак. Система основана на фреимворке [Luigi Rizzo](https://github.com/luigirizzo/netmap) [netmap](https://habrahabr.ru/post/183832/) и спроектирована для работы с большим объемом трафика (10Гб/сек и больше) без потерь производительности.

Система написана на языке C++ (стандарт 11) с использованием OpenSource библиотек *STL* и *Boost (1.55)*. Написание и сборка производилось на *Ubuntu 12.04.5 LTS* и компиляторе *g++-4.8*. Для статического анализа кода, проверки стиля и поиска грубых ошибок использовался *cppcheck* версии 1.73.
Система написана на языке C++ (стандарт 11) с использованием OpenSource библиотек *STL* и *Boost (1.58)*. Написание и сборка производилось на *Ubuntu 16.04 LTS* и компиляторе *g++-5*. Для статического анализа кода, проверки стиля и поиска грубых ошибок использовался *cppcheck* версии 1.73.

Для мониторинга и сбора статистики используется InfluxDB.
![Grafana](images/grafana.png)
Expand Down Expand Up @@ -71,6 +71,7 @@ rmmod e1000e && insmod /usr/src/netmap/LINUX/e1000e/e1000e.ko
### Установка ddosdetector ###
собираем ddosdetector:
```bash
sudo apt-get install g++ libboost-all-dev libcurl4-gnutls-dev liblog4cpp5-dev
git clone https://velizarx@bitbucket.org/velizarx/ddosdetector.git
cd ./ddosdetector
make
Expand All @@ -93,7 +94,7 @@ cd <path_to_ddosdetector_directory>
```
где:
* *-i eth4 (**параметр обязателен**)* - *eth4* интерфейс запуска системы (на этом интерфейсе должен быть драйвер netmap см. README);
* *-r ~/ddosdetector.rules* - файл откуда будут загружены правила (этот параметр необязателен, по-умолчанию поиск файла производится по пути */etc/ddosdetector.rules*);
* *-r ~/ddosdetector.rules* - файл откуда будут загружены правила (этот параметр необязателен, по-умолчанию поиск файла производится по пути */etc/ddosdetector/rules.conf*);
* *-p /tmp/ddosd.sock* - как запустить консоль (в данном случае UNIX socket, файл */tmp/ddosd.sock*), может быть путем к файлу, либо номером порта (тогда запускается TCP сервер на 127.0.0.1 и указанном порту), параметр необязателен, по-умолчанию запускается TCP сервер на порту 9090;
* *-l ~/ddosdetector.log* - путь к лог файлу, по-умолчанию вывод в консоль

Expand All @@ -105,14 +106,14 @@ socat - UNIX-CONNECT:/tmp/ddosd.sock
## Управление ##
### Конфигурационные файлы ###
При запуске система пытается прочитать два конфигурационных файла:
* /etc/ddosdetector.conf - общие настройки системы
* /etc/ddosdetector.rules - сохраненные правила
* /etc/ddosdetector/conf.ini - общие настройки системы
* /etc/ddosdetector/rules.conf - сохраненные правила

Файл */etc/ddosdetector.conf* сожет содержать следующие настройки (значение натроек понятно из названия):
Файл */etc/ddosdetector/conf.ini* сожет содержать следующие настройки (значение натроек понятно из названия):
```ini
[Main]
Interface = eth0
Rules = /etc/ddosdetector.rules
Rules = /etc/ddosdetector/rules.conf
Log = /var/log/ddosdetector.log
Port = 9090

Expand Down Expand Up @@ -282,7 +283,7 @@ ICMP rules (num, rule, counter):
1: -d 92.53.96.141/32 --pps-th 100p --type =0 --code =0 : 0.00p/s (0.00b/s), 0 packets, 0 bytes
```
#### Перезагрузка правил из файла ####
При запуске, система проверяет конфигурационный файл сохраненных ранее правил (по умолчанию */etc/ddosdetector.rules*). Если сиситема уже запущена, можно перезагрузить правила из файла вручную. Перезагрузка правил из файла выполняется либо из консоли управления командой **reload rules** либо отправкой сигнала SIGHUP демону. Например файл правил имеет содержимое:
При запуске, система проверяет конфигурационный файл сохраненных ранее правил (по умолчанию */etc/ddosdetector/rules.conf*). Если сиситема уже запущена, можно перезагрузить правила из файла вручную. Перезагрузка правил из файла выполняется либо из консоли управления командой **reload rules** либо отправкой сигнала SIGHUP демону. Например файл правил имеет содержимое:
```bash
$ cat ~/ddosdetector.rules
TCP -d 92.53.96.141/32 --pps-th 100p --seq =0 --pps-th-period 60 --action log:/tmp/test.log --next
Expand Down
Binary file added docs/images/dev-scheme.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/images/grafana.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading