Skip to content

Commit 1cbb62c

Browse files
mbertroneacloudiator
authored andcommitted
SYN Flood Detector (#152)
* pcn-synflood: datamodel and generated code add datamodel draft add stub for service datamodel: use uint64 everywhere, since float are not supported by yang and decimal64 are not supported by our codegen toolchain Signed-off-by: Matteo Bertrone <m.bertrone@gmail.com> * pcn-synflood: implement get timestamp Signed-off-by: Matteo Bertrone <m.bertrone@gmail.com> * pcn-synflood: implement get metrics Signed-off-by: Matteo Bertrone <m.bertrone@gmail.com> * pcn-synflood: add test Signed-off-by: Matteo Bertrone <m.bertrone@gmail.com> * pcn-synflood: add documentation Signed-off-by: Matteo Bertrone <m.bertrone@gmail.com> Signed-off-by: Fulvio Risso <fulvio.risso@polito.it>
1 parent d8ddb44 commit 1cbb62c

31 files changed

Lines changed: 2848 additions & 0 deletions

Documentation/services/index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,3 +21,4 @@ This folder contains the list of services (a.k.a. *cubes*) currently available i
2121
pcn-router/router
2222
pcn-simplebridge/simplebridge
2323
pcn-simpleforwarder/simpleforwarder
24+
pcn-synflood/synflood
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
SYN Flood Monitor
2+
=================
3+
4+
This service exports some metrics that can be used to detect a possible SYN Flood attack.
5+
6+
7+
Features
8+
--------
9+
- Retrieves a set of TCP/IP parameters that can be used to detect SYN flooding attacks
10+
11+
12+
Limitations
13+
-----------
14+
- It must be launched on the host that needs to be monitored. It cannot operate as a 'main in the middle' mode, i.e., inspecting network traffic directed toward a remote host.
15+
16+
17+
How to use
18+
----------
19+
Technically, ``pcn-synflood`` is a transparent service, hence it should be attached to an existing network interface (e.g., netdev or a virtual link between Polycube services).
20+
However, given that the current implementation retrieves traffic statistics using the metrics provided by the operating system, it can be even instantiated without attaching it to any network interface.
21+
22+
23+
Exported metrics
24+
----------------
25+
- ``tcpAttemptFails``: number of failed TCP connections [1].
26+
- ``tcpOutRsts``: number of TCP segments sent, containing RST flag.
27+
- ``deliverRatio``: ratio between the number of IP pkts delivered to application protocols and the total number of received pkts.
28+
- ``responseRatio``: ratio between the number of IP pkts requests to send by application protocols and the total number of received pkts.
29+
30+
31+
Additional details
32+
------------------
33+
34+
[1] ``tcpAttemptFails``
35+
36+
It measures the number of times TCP connections have made a direct transition to the CLOSED state from either the SYN-SENT state or the SYN-RCVD state, plus the number of times TCP connections have made a direct transition to the LISTEN state from the SYN-RCVD state. It refers to variable ``tcpAttemptFails`` documented in RFC 1213.
37+
38+
It is worth mentioning that this parameter is rather general and can be used to check for unusual situations on both client and server side. For instance, it can be used to detect either (1) that a server is under attack (e.g., TCP state machine goes from SYN-RCVD to LISTEN or CLOSED), or (2) that a client is currently attacking a remote target (e.g., TCP state machine goes from SYN-SENT to CLOSED).
39+
40+
The most common case, i.e., that a server is under attack, corresponds at least to the following unusual TCP sequences:
41+
- [SYN, timeout]. The server receives a SYN packet, but it cannot answer any more because it is overwhelmed. This connection will be ended after server time‐out, as described earlier.
42+
- [SYN (Client, Server), RST (Server, Client)]. This sequence means either that the server is the victim of a DoS attack because it cannot reply to the legitimate client any more, or that there is not applications listening on that port.
43+
- [SYN, SYN/ACK, timeout]. The server waits indefinitely for the ACK packet, either because the IP source address is spoofed or because the ACK packet is rejected because of network congestion. This sequence can correspond to a DoS attack. This connection will be ended after server time‐out.
44+
- [SYN, SYN/ACK, RST]. This handshake sequence can correspond to a DDoS attack. At the reception of the SYN/ACK packet, the client host then transmits an RST packet to the server because it never sent a SYN packet.

src/services/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ add_service(simplebridge pcn-simplebridge)
3434
add_service(simpleforwarder pcn-simpleforwarder)
3535
add_service(iptables pcn-iptables)
3636
add_service(transparenthelloworld pcn-transparent-helloworld)
37+
add_service(synflood pcn-synflood)
3738

3839
# save string to create code that load the services
3940
SET_PROPERTY(GLOBAL PROPERTY LOAD_SERVICES_ ${LOAD_SERVICES})
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# Swagger Codegen Ignore
2+
# Generated by swagger-codegen https://github.com/swagger-api/swagger-codegen
3+
4+
# Use this file to prevent files from being overwritten by the generator.
5+
6+
.swagger-codegen-ignore
7+
8+
src/*.cpp
9+
src/*.h
10+
11+
!src/*Interface.h
12+
!src/*JsonObject.h
13+
!src/*JsonObject.cpp
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
cmake_minimum_required (VERSION 3.2)
2+
3+
set (CMAKE_CXX_STANDARD 11)
4+
5+
add_subdirectory(src)
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
# Loads the contents of a file into a std::string variable
2+
#
3+
# It creates a header file in ${CMAKE_CURRENT_BINARY_DIR}/${file}.h
4+
# that wrapps the contents of the file in a std::string using the raw
5+
# string literal feature of C++11. The user needs to include that file
6+
# into the source code in order to see the variable.
7+
#
8+
# parameters:
9+
# target: target to add a dependency on file
10+
# file: file to be loaded
11+
# variable_name: name variable where the file is loaded
12+
#
13+
# example:
14+
# load_file_as_variable(my-lib resource.c my_resource)
15+
# Creates a resource.h in CMAKE_CURRENT_BINARY_DIR with a string variable
16+
# my_resource with the contents of resource.c
17+
# A dependency in resource.c is added to my-lib
18+
19+
function(load_file_as_variable target file variable_name)
20+
get_filename_component(file_name ${file} NAME_WE)
21+
get_filename_component(file_dir ${file} DIRECTORY)
22+
23+
set(new_path ${file_dir}/${file_name}.h)
24+
25+
add_custom_command(
26+
OUTPUT
27+
${CMAKE_CURRENT_BINARY_DIR}/${new_path}
28+
COMMAND
29+
mkdir -p ${CMAKE_CURRENT_BINARY_DIR}/${file_dir}
30+
COMMAND
31+
echo "#pragma once" > ${CMAKE_CURRENT_BINARY_DIR}/${new_path}
32+
COMMAND
33+
echo "#include <string>" >> ${CMAKE_CURRENT_BINARY_DIR}/${new_path}
34+
COMMAND
35+
echo "const std::string ${variable_name} = R\"POLYCUBE_DP(" >> ${CMAKE_CURRENT_BINARY_DIR}/${new_path}
36+
COMMAND
37+
cat ${CMAKE_CURRENT_SOURCE_DIR}/${file} >> ${CMAKE_CURRENT_BINARY_DIR}/${new_path}
38+
COMMAND
39+
cmake -E echo ")POLYCUBE_DP\";" >> ${CMAKE_CURRENT_BINARY_DIR}/${new_path}
40+
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${file}
41+
VERBATIM
42+
)
43+
44+
string(REPLACE "/" "-" path_replaced ${new_path})
45+
46+
add_custom_target(
47+
generate_${path_replaced}
48+
DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${new_path}
49+
)
50+
51+
add_dependencies(${target} generate_${path_replaced})
52+
endfunction()
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
module synflood {
2+
yang-version 1.1;
3+
namespace "http://polycube.network/synflood";
4+
prefix "synflood";
5+
6+
import polycube-base { prefix "polycube-base"; }
7+
import polycube-transparent-base { prefix "polycube-transparent-base"; }
8+
9+
organization "Polycube open source project";
10+
description "YANG data model for the Network Monitor";
11+
12+
polycube-base:service-description "TCP SYN Flood Monitor Service";
13+
polycube-base:service-version "2.0";
14+
polycube-base:service-name "synflood";
15+
polycube-base:service-min-kernel-version "4.11.0";
16+
17+
uses "polycube-transparent-base:transparent-base-yang-module";
18+
19+
container stats {
20+
description "Statistics for SYN Flood Monitor";
21+
config false;
22+
23+
leaf tcpattemptfails {
24+
type uint64;
25+
description "TCP attempts fails";
26+
config false;
27+
}
28+
29+
leaf tcpoutrsts {
30+
type uint64;
31+
description "TCP sent with RST flag";
32+
config false;
33+
}
34+
35+
leaf deliverratio {
36+
type uint64;
37+
description "pkts delivered to application over total received pkts";
38+
config false;
39+
}
40+
41+
leaf responseratio {
42+
type uint64;
43+
description "pkts requests to send over total received pkts";
44+
config false;
45+
}
46+
47+
leaf lastupdate {
48+
type uint64;
49+
description "last update (time from epoch in milliseconds)";
50+
config false;
51+
}
52+
}
53+
}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
include(${PROJECT_SOURCE_DIR}/cmake/LoadFileAsVariable.cmake)
2+
3+
aux_source_directory(serializer SERIALIZER_SOURCES)
4+
aux_source_directory(api API_SOURCES)
5+
aux_source_directory(base BASE_SOURCES)
6+
7+
include_directories(serializer)
8+
9+
if (NOT DEFINED POLYCUBE_STANDALONE_SERVICE OR POLYCUBE_STANDALONE_SERVICE)
10+
find_package(PkgConfig REQUIRED)
11+
pkg_check_modules(POLYCUBE libpolycube)
12+
include_directories(${POLYCUBE_INCLUDE_DIRS})
13+
endif(NOT DEFINED POLYCUBE_STANDALONE_SERVICE OR POLYCUBE_STANDALONE_SERVICE)
14+
15+
# Needed to load files as variables
16+
include_directories(${CMAKE_CURRENT_BINARY_DIR})
17+
18+
add_library(pcn-synflood SHARED
19+
${SERIALIZER_SOURCES}
20+
${API_SOURCES}
21+
${BASE_SOURCES}
22+
Stats.cpp
23+
Synflood.cpp
24+
Synflood-lib.cpp
25+
Utils.cpp)
26+
27+
# load ebpf datapath code a variable
28+
load_file_as_variable(pcn-synflood
29+
Synflood_dp.c
30+
synflood_code)
31+
32+
# load datamodel in a variable
33+
load_file_as_variable(pcn-synflood
34+
../datamodel/synflood.yang
35+
synflood_datamodel)
36+
37+
target_link_libraries(pcn-synflood ${POLYCUBE_LIBRARIES})
38+
39+
# Specify shared library install directory
40+
41+
set(CMAKE_INSTALL_LIBDIR /usr/lib)
42+
43+
install(
44+
TARGETS
45+
pcn-synflood
46+
DESTINATION
47+
"${CMAKE_INSTALL_LIBDIR}"
48+
)
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
/**
2+
* synflood API generated from synflood.yang
3+
*
4+
* NOTE: This file is auto generated by polycube-codegen
5+
* https://github.com/polycube-network/polycube-codegen
6+
*/
7+
8+
9+
// TODO: Modify these methods with your own implementation
10+
11+
12+
#include "Stats.h"
13+
#include "Synflood.h"
14+
15+
16+
Stats::Stats(Synflood &parent, const StatsJsonObject &conf)
17+
: StatsBase(parent) {
18+
}
19+
20+
Stats::~Stats() {}
21+
22+
const uint64_t ratioMultiplier = 1000;
23+
24+
uint64_t Stats::getTcpattemptfails() {
25+
try {
26+
return std::stoull(Synflood::exec("nstat -a | grep TcpAttemptFails | awk '{print $2}'"));
27+
} catch (...) {
28+
return 0;
29+
}
30+
}
31+
32+
uint64_t Stats::getTcpoutrsts() {
33+
try {
34+
return std::stoull(Synflood::exec("nstat -a | grep TcpOutRsts | awk '{print $2}'"));
35+
} catch (...) {
36+
return 0;
37+
}
38+
}
39+
40+
uint64_t Stats::getDeliverratio() {
41+
try {
42+
std::istringstream ipInDeliversStream(Synflood::exec("nstat -a | grep IpInDelivers | awk '{print $2}'"));
43+
std::istringstream ipInReceivesStream(Synflood::exec("nstat -a | grep IpInReceives | awk '{print $2}'"));
44+
45+
uint64_t ipInDelivers;
46+
uint64_t ipInReceives;
47+
48+
ipInDeliversStream >> ipInDelivers;
49+
ipInReceivesStream >> ipInReceives;
50+
51+
float ratio = ((float) ipInDelivers / ((float) ipInReceives + 1.0)) * ratioMultiplier;
52+
return (uint64_t) (ratio);
53+
} catch (...) {
54+
return 0;
55+
}
56+
}
57+
58+
uint64_t Stats::getResponseratio() {
59+
try {
60+
std::istringstream ipOutRequestsStream(Synflood::exec("nstat -a | grep IpOutRequests | awk '{print $2}'"));
61+
std::istringstream ipInReceivesStream(Synflood::exec("nstat -a | grep IpInReceives | awk '{print $2}'"));
62+
63+
uint64_t ipOutRequests;
64+
uint64_t ipInReceives;
65+
66+
ipOutRequestsStream >> ipOutRequests;
67+
ipInReceivesStream >> ipInReceives;
68+
69+
float ratio = ((float)ipOutRequests / ((float)ipInReceives + 1.0)) * ratioMultiplier;
70+
return (uint64_t)(ratio);
71+
} catch (...) {
72+
return 0;
73+
}
74+
}
75+
76+
uint64_t Stats::getLastupdate() {
77+
return std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch()).count();
78+
}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
/**
2+
* synflood API generated from synflood.yang
3+
*
4+
* NOTE: This file is auto generated by polycube-codegen
5+
* https://github.com/polycube-network/polycube-codegen
6+
*/
7+
8+
9+
#pragma once
10+
11+
12+
#include "../base/StatsBase.h"
13+
14+
15+
class Synflood;
16+
17+
using namespace polycube::service::model;
18+
19+
class Stats : public StatsBase {
20+
public:
21+
Stats(Synflood &parent, const StatsJsonObject &conf);
22+
virtual ~Stats();
23+
24+
/// <summary>
25+
/// TCP attempts fails
26+
/// </summary>
27+
uint64_t getTcpattemptfails() override;
28+
29+
/// <summary>
30+
/// TCP sent with RST flag
31+
/// </summary>
32+
uint64_t getTcpoutrsts() override;
33+
34+
/// <summary>
35+
/// pkts delivered to application over total received pkts
36+
/// </summary>
37+
uint64_t getDeliverratio() override;
38+
39+
/// <summary>
40+
/// pkts requests to send over total received pkts
41+
/// </summary>
42+
uint64_t getResponseratio() override;
43+
44+
/// <summary>
45+
/// last update (time from epoch in milliseconds)
46+
/// </summary>
47+
uint64_t getLastupdate() override;
48+
};

0 commit comments

Comments
 (0)