1
0
Fork 0
mirror of https://github.com/pavel-odintsov/fastnetmon synced 2024-06-09 21:56:10 +02:00

Deprecated PF_RING plugin for new versions. We switched to AF_PACKET which is compeltely open source and worse way better (#929)

This commit is contained in:
Pavel Odintsov 2022-04-04 15:30:23 +01:00 committed by GitHub
parent 481428dca4
commit 54da2b6cad
Signed by: GitHub
GPG Key ID: 4AEE18F83AFDEB23
21 changed files with 26 additions and 1141 deletions

View File

@ -11,7 +11,8 @@ perform a configurable action to handle that event. These configurable actions i
Flow is one or more ICMP, UDP, or TCP packets which can be identified via their unique src IP, dst IP, src port, dst port, and protocol fields. Flow is one or more ICMP, UDP, or TCP packets which can be identified via their unique src IP, dst IP, src port, dst port, and protocol fields.
![CI status](https://circleci.com/gh/pavel-odintsov/fastnetmon.svg) [CI status](https://app.circleci.com/pipelines/github/pavel-odintsov/fastnetmon) ![CI status](https://circleci.com/gh/pavel-odintsov/fastnetmon.svg)
[CI status](https://app.circleci.com/pipelines/github/pavel-odintsov/fastnetmon)
Project Project
------- -------
@ -28,7 +29,7 @@ Supported packet capture engines
- PCAP - PCAP
- AF_PACKET - AF_PACKET
- Netmap - Netmap
- PF_RING / PF_RING ZC (available only for CentOS 6 for compatibiliy, otherwise use AF_PACKET) - PF_RING / PF_RING ZC (CentOS 6 only)
You can check out the [comparison table](https://fastnetmon.com/docs/capture_backends/) for all available packet capture engines. You can check out the [comparison table](https://fastnetmon.com/docs/capture_backends/) for all available packet capture engines.

2
debian/rules vendored
View File

@ -2,4 +2,4 @@
%: %:
dh $@ --buildsystem=cmake --sourcedirectory=src dh $@ --buildsystem=cmake --sourcedirectory=src
override_dh_auto_configure: override_dh_auto_configure:
dh_auto_configure -- -DDISABLE_PF_RING_SUPPORT=yes dh_auto_configure --

View File

@ -27,7 +27,6 @@ set (FASTNETMON_VERSION_MINOR 1)
set(HIREDIS_CUSTOM_INSTALL_PATH "${FASTNETMON_LIBRARIES_GLOBAL_PATH}/libhiredis_0_13") set(HIREDIS_CUSTOM_INSTALL_PATH "${FASTNETMON_LIBRARIES_GLOBAL_PATH}/libhiredis_0_13")
set(LOG4CPP_CUSTOM_INSTALL_PATH "${FASTNETMON_LIBRARIES_GLOBAL_PATH}/log4cpp1.1.1") set(LOG4CPP_CUSTOM_INSTALL_PATH "${FASTNETMON_LIBRARIES_GLOBAL_PATH}/log4cpp1.1.1")
set(JSONC_CUSTOM_INSTALL_PATH "${FASTNETMON_LIBRARIES_GLOBAL_PATH}/json-c-0.13") set(JSONC_CUSTOM_INSTALL_PATH "${FASTNETMON_LIBRARIES_GLOBAL_PATH}/json-c-0.13")
set(PFRING_CUSTOM_INSTALL_PATH "${FASTNETMON_LIBRARIES_GLOBAL_PATH}/pf_ring_6.0.3")
set(LIBPCAP_CUSTOM_INSTALL_PATH "${FASTNETMON_LIBRARIES_GLOBAL_PATH}/libpcap_1.7.4") set(LIBPCAP_CUSTOM_INSTALL_PATH "${FASTNETMON_LIBRARIES_GLOBAL_PATH}/libpcap_1.7.4")
set(MONGO_C_CUSTOM_INSTALL_PATH "${FASTNETMON_LIBRARIES_GLOBAL_PATH}/mongo_c_driver_1_16_1") set(MONGO_C_CUSTOM_INSTALL_PATH "${FASTNETMON_LIBRARIES_GLOBAL_PATH}/mongo_c_driver_1_16_1")
set(CAPNP_CUSTOM_INSTALL_PATH "${FASTNETMON_LIBRARIES_GLOBAL_PATH}/capnproto_0_8_0") set(CAPNP_CUSTOM_INSTALL_PATH "${FASTNETMON_LIBRARIES_GLOBAL_PATH}/capnproto_0_8_0")
@ -87,7 +86,7 @@ SET(CMAKE_SKIP_BUILD_RPATH FALSE)
# Create builds in current folder with install RPATH # Create builds in current folder with install RPATH
SET(CMAKE_BUILD_WITH_INSTALL_RPATH TRUE) SET(CMAKE_BUILD_WITH_INSTALL_RPATH TRUE)
SET(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_RPATH};${FASTNETMON_LIBRARIES_GLOBAL_PATH}/libhiredis_0_13/lib;${FASTNETMON_LIBRARIES_GLOBAL_PATH}/log4cpp1.1.1/lib;${FASTNETMON_LIBRARIES_GLOBAL_PATH}/pf_ring_6.0.3/lib;${FASTNETMON_LIBRARIES_GLOBAL_PATH}/json-c-0.13/lib;${MONGO_C_CUSTOM_INSTALL_PATH}/lib;${MONGO_C_CUSTOM_INSTALL_PATH}/lib64;${GRPC_CUSTOM_INSTALL_PATH}/lib;${FASTNETMON_LIBRARIES_GLOBAL_PATH}/protobuf_3.11.4/lib;${CAPNP_CUSTOM_INSTALL_PATH}/lib;${OPENSSL_CUSTOM_INSTALL_PATH}/lib") SET(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_RPATH};${FASTNETMON_LIBRARIES_GLOBAL_PATH}/libhiredis_0_13/lib;${FASTNETMON_LIBRARIES_GLOBAL_PATH}/log4cpp1.1.1/lib;${FASTNETMON_LIBRARIES_GLOBAL_PATH}/json-c-0.13/lib;${MONGO_C_CUSTOM_INSTALL_PATH}/lib;${MONGO_C_CUSTOM_INSTALL_PATH}/lib64;${GRPC_CUSTOM_INSTALL_PATH}/lib;${FASTNETMON_LIBRARIES_GLOBAL_PATH}/protobuf_3.11.4/lib;${CAPNP_CUSTOM_INSTALL_PATH}/lib;${OPENSSL_CUSTOM_INSTALL_PATH}/lib")
message(STATUS "C++ compilation flags: ${CMAKE_CXX_FLAGS_RELEASE}") message(STATUS "C++ compilation flags: ${CMAKE_CXX_FLAGS_RELEASE}")
message(STATUS "C++ debug compilation flags: ${CMAKE_CXX_FLAGS_DEBUG}") message(STATUS "C++ debug compilation flags: ${CMAKE_CXX_FLAGS_DEBUG}")
@ -145,9 +144,6 @@ if (NOT HAVE__ATOMIC_ADD_FETCH)
endif() endif()
endif() endif()
# With this flag we can enable PF_RING build via console: cmake .. -DENABLE_PF_RING_SUPPORT=ON
option(ENABLE_PF_RING_SUPPORT "Enable PF_RING build" OFF)
option(ENABLE_NETMAP_SUPPORT "Enable Netmap support" ON) option(ENABLE_NETMAP_SUPPORT "Enable Netmap support" ON)
CHECK_CXX_SOURCE_COMPILES(" CHECK_CXX_SOURCE_COMPILES("
@ -169,32 +165,6 @@ if (ENABLE_NETMAP_SUPPORT)
add_definitions(-DNETMAP_PLUGIN) add_definitions(-DNETMAP_PLUGIN)
endif() endif()
if (ENABLE_PF_RING_SUPPORT)
# Set path to manually compiled PF_RING
set(PFRING_INCLUDE_DIRS "${PFRING_CUSTOM_INSTALL_PATH}/include")
find_library(PFRING_LIBRARIES NAMES pfring PATHS "${PFRING_CUSTOM_INSTALL_PATH}/lib" NO_DEFAULT_PATH)
if (NOT PFRING_LIBRARIES)
message(FATAL_ERROR "Could not find PF_RING")
endif()
link_directories("${PFRING_CUSTOM_INSTALL_PATH}/lib")
add_definitions(-DPF_RING)
if (EXISTS "${PFRING_CUSTOM_INSTALL_PATH}/include/pfring_zc.h" OR EXISTS "/usr/local/include/pfring_zc.h")
message(STATUS "We found PF_RING ZC headers and will build PF_RING ZC support")
# Enable ZC support
add_definitions(-DPF_RING_ZC)
else()
message(WARNING "We can't find PF_RING ZC header pfring_zc.h. Will not compile ZC support")
endif()
include_directories(${PFRING_INCLUDE_DIRS})
message(STATUS "We have enabled PF_RING's hardware filtering option")
endif()
add_library(simple_packet_capnp STATIC simple_packet_capnp/simple_packet.capnp.c++) add_library(simple_packet_capnp STATIC simple_packet_capnp/simple_packet.capnp.c++)
# Our LPM library # Our LPM library
@ -283,13 +253,6 @@ target_link_libraries(pcap_plugin pcap)
find_package(Threads) find_package(Threads)
if (ENABLE_PF_RING_SUPPORT)
add_library(pfring_plugin STATIC pfring_plugin/pfring_collector.cpp)
target_link_libraries(pfring_plugin ${PFRING_LIBRARIES})
target_link_libraries(pfring_plugin numa)
target_link_libraries(pfring_plugin ${CMAKE_THREAD_LIBS_INIT})
endif()
add_library(exabgp_action STATIC actions/exabgp_action.cpp) add_library(exabgp_action STATIC actions/exabgp_action.cpp)
if (ENABLE_GOBGP_SUPPORT) if (ENABLE_GOBGP_SUPPORT)
@ -593,10 +556,6 @@ target_link_libraries(fastnetmon fast_library)
# link to our unified parser # link to our unified parser
target_link_libraries(fastnetmon unified_parser) target_link_libraries(fastnetmon unified_parser)
if (ENABLE_PF_RING_SUPPORT)
target_link_libraries(fastnetmon pfring_plugin)
endif()
target_link_libraries(fastnetmon ${OPENSSL_LIBRARY_PATH}) target_link_libraries(fastnetmon ${OPENSSL_LIBRARY_PATH})
target_link_libraries(fastnetmon ${OPENSSL_CRYPTO_LIBRARY_PATH}) target_link_libraries(fastnetmon ${OPENSSL_CRYPTO_LIBRARY_PATH})
@ -638,11 +597,6 @@ if (BUILD_PLUGIN_RUNNER)
if (ENABLE_NETMAP_SUPPORT) if (ENABLE_NETMAP_SUPPORT)
target_link_libraries(fastnetmon_plugin_runner netmap_plugin) target_link_libraries(fastnetmon_plugin_runner netmap_plugin)
endif() endif()
if (ENABLE_PF_RING_SUPPORT)
target_link_libraries(fastnetmon_plugin_runner ${PFRING_LIBRARIES})
target_link_libraries(fastnetmon_plugin_runner pfring_plugin)
endif()
endif() endif()
# cmake .. -DBUILD_PCAP_READER=ON # cmake .. -DBUILD_PCAP_READER=ON

View File

@ -32,7 +32,7 @@ RUN cd /usr/src; git clone https://github.com/pavel-odintsov/fastnetmon.git
#COPY exabgp_blackhole.conf /etc/exabgp_blackhole.conf #COPY exabgp_blackhole.conf /etc/exabgp_blackhole.conf
RUN cd /usr/src/fastnetmon/src; mkdir build; cd build; cmake .. -DDISABLE_PF_RING_SUPPORT=ON; make RUN cd /usr/src/fastnetmon/src; mkdir build; cd build; cmake ..; make
RUN cp /usr/src/fastnetmon/src/fastnetmon.conf /etc/ RUN cp /usr/src/fastnetmon/src/fastnetmon.conf /etc/
RUN cp /usr/src/fastnetmon/src/build/fastnetmon /usr/bin/ RUN cp /usr/src/fastnetmon/src/build/fastnetmon /usr/bin/

View File

@ -1,5 +1,4 @@
FastNetMon - A high performance DoS/DDoS load analyzer built on top FastNetMon - A high performance DoS/DDoS load analyzer built on top
of multiple packet capture engines (NetFlow, IPFIX, sFLOW, netmap, of multiple packet capture engines (NetFlow, IPFIX, sFlow, Netmap, PCAP).
PF_RING, PCAP).
WWW: https://fastnetmon.com WWW: https://fastnetmon.com

View File

@ -449,7 +449,7 @@ std::string print_simple_packet(simple_packet_t packet) {
std::stringstream buffer; std::stringstream buffer;
if (packet.ts.tv_sec == 0) { if (packet.ts.tv_sec == 0) {
// PF_RING and netmap do not generate timestamp for all packets because it's very CPU // Netmap does not generate timestamp for all packets because it's very CPU
// intensive operation // intensive operation
// But we want pretty attack report and fill it there // But we want pretty attack report and fill it there
gettimeofday(&packet.ts, NULL); gettimeofday(&packet.ts, NULL);

View File

@ -86,12 +86,6 @@ ban_for_icmp_pps = off
### Traffic capture methods ### Traffic capture methods
### ###
# PF_RING traffic capture, fast enough but the wirespeed version needs a paid license
mirror = off
# Port mirroring sample rate
pfring_sampling_ratio = 1
# Netmap traffic capture (very fast but needs patched drivers) # Netmap traffic capture (very fast but needs patched drivers)
mirror_netmap = off mirror_netmap = off
@ -124,13 +118,9 @@ netflow = off
# sFLOW capture suitable for switches # sFLOW capture suitable for switches
sflow = off sflow = off
# PF_RING configuration
# If you have a license for PF_RING ZC, enable this mode and it might achieve wire speed for 10GE
enable_pf_ring_zc_mode = off
# Configuration for netmap, mirror, pcap modes # Configuration for netmap, mirror, pcap modes
# For pcap and PF_RING we could specify "any" # For pcap we could specify "any"
# For netmap and PF_RING we could specify multiple interfaces separated by comma # For Netmap we could specify multiple interfaces separated by comma
interfaces = eth3,eth4 interfaces = eth3,eth4
# We use average values for traffic speed to certain IP and we calculate average over this time slice # We use average values for traffic speed to certain IP and we calculate average over this time slice

View File

@ -62,10 +62,6 @@
#include "netmap_plugin/netmap_collector.h" #include "netmap_plugin/netmap_collector.h"
#endif #endif
#ifdef PF_RING
#include "pfring_plugin/pfring_collector.h"
#endif
#ifdef FASTNETMON_ENABLE_AFPACKET #ifdef FASTNETMON_ENABLE_AFPACKET
#include "afpacket_plugin/afpacket_collector.h" #include "afpacket_plugin/afpacket_collector.h"
#endif #endif
@ -1690,12 +1686,6 @@ int main(int argc, char** argv) {
set_boost_process_name(check_traffic_buckets_thread, "check_buckets"); set_boost_process_name(check_traffic_buckets_thread, "check_buckets");
service_thread_group.add_thread(check_traffic_buckets_thread); service_thread_group.add_thread(check_traffic_buckets_thread);
#ifdef PF_RING
if (enable_data_collection_from_mirror) {
packet_capture_plugin_thread_group.add_thread(new boost::thread(start_pfring_collection, process_packet));
}
#endif
#ifdef NETMAP_PLUGIN #ifdef NETMAP_PLUGIN
// netmap processing // netmap processing
if (enable_netmap_collection) { if (enable_netmap_collection) {

View File

@ -56,10 +56,6 @@ sub fast_die {
exit(1); exit(1);
} }
my $pf_ring_version = '6.0.3';
my $pf_ring_url = "https://github.com/ntop/PF_RING/archive/v$pf_ring_version.tar.gz";
my $pf_ring_sha = '9fb8080defd1a079ad5f0097e8a8adb5bc264d00';
my $fastnetmon_git_path = 'https://github.com/pavel-odintsov/fastnetmon.git'; my $fastnetmon_git_path = 'https://github.com/pavel-odintsov/fastnetmon.git';
my $temp_folder_for_building_project = `mktemp -d /tmp/fastnetmon.build.dir.XXXXXXXXXX`; my $temp_folder_for_building_project = `mktemp -d /tmp/fastnetmon.build.dir.XXXXXXXXXX`;
@ -91,8 +87,6 @@ my $make_options = '';
# We could pass options to configure with this variable # We could pass options to configure with this variable
my $configure_options = ''; my $configure_options = '';
my $use_modern_pf_ring = '';
my $show_help = ''; my $show_help = '';
my $install_dependency_packages_only = ''; my $install_dependency_packages_only = '';
@ -106,7 +100,6 @@ my $build_dependencies_only = '';
# Get options from command line # Get options from command line
GetOptions( GetOptions(
'use-git-master' => \$we_use_code_from_master, 'use-git-master' => \$we_use_code_from_master,
'use-modern-pf-ring' => \$use_modern_pf_ring,
'use-mirror' => \$use_mirror, 'use-mirror' => \$use_mirror,
'build_fastnetmon_only' => \$build_fastnetmon_only, 'build_fastnetmon_only' => \$build_fastnetmon_only,
'build_dependencies_only' => \$build_dependencies_only, 'build_dependencies_only' => \$build_dependencies_only,
@ -129,13 +122,6 @@ if ($show_help) {
welcome_message(); welcome_message();
# Bump PF_RING version
if ($use_modern_pf_ring) {
$pf_ring_version = '6.6.0';
$pf_ring_url = "https://github.com/ntop/PF_RING/archive/$pf_ring_version.tar.gz";
$pf_ring_sha = '79ff86e48df857e4e884646accfc97bdcdc54b04';
}
my $we_have_hiredis_support = '1'; my $we_have_hiredis_support = '1';
my $we_have_log4cpp_support = '1'; my $we_have_log4cpp_support = '1';
my $we_have_mongo_support = '1'; my $we_have_mongo_support = '1';
@ -143,9 +129,6 @@ my $we_have_protobuf_support = '1';
my $we_have_grpc_support = '1'; my $we_have_grpc_support = '1';
my $we_have_gobgp_support = '1'; my $we_have_gobgp_support = '1';
# We allow it only for legacy systems
my $we_have_pfring_support = '';
main(); main();
# Applies colors to terminal if we have this module # Applies colors to terminal if we have this module
@ -290,17 +273,6 @@ sub main {
} }
} }
# We use PF_RING only for very old Linux distros, all new one should use AF_PACKET
if ($os_type eq 'linux') {
if ($distro_type eq 'ubuntu' && $distro_version =~ m/^12\.04/) {
$we_have_pfring_support = 1;
}
if ($distro_type eq 'centos' && $distro_version == 6) {
$we_have_pfring_support = 1;
}
}
# CentOS base repository is very very poor and we need EPEL for some dependencies # CentOS base repository is very very poor and we need EPEL for some dependencies
install_additional_repositories(); install_additional_repositories();
@ -329,10 +301,6 @@ sub main {
# Install only depencdency packages, we need it to cache installed packages in CI # Install only depencdency packages, we need it to cache installed packages in CI
if ($install_dependency_packages_only) { if ($install_dependency_packages_only) {
if ($we_have_pfring_support) {
install_pf_ring_dependencies();
}
if ($we_have_protobuf_support) { if ($we_have_protobuf_support) {
install_protobuf_dependencies(); install_protobuf_dependencies();
} }
@ -347,11 +315,6 @@ sub main {
} }
if ($build_dependencies_only) { if ($build_dependencies_only) {
if ($we_have_pfring_support) {
install_pf_ring_dependencies();
install_pf_ring();
}
install_json_c(); install_json_c();
install_openssl(); install_openssl();
@ -1049,110 +1012,6 @@ sub detect_distribution {
} }
} }
sub install_pf_ring_dependencies {
my $kernel_version = `uname -r`;
chomp $kernel_version;
print "Install PF_RING dependencies with package manager\n";
if ($distro_type eq 'debian' or $distro_type eq 'ubuntu') {
my @debian_packages_for_pfring = ('build-essential', 'bison', 'flex', 'subversion',
'libnuma-dev', 'wget', 'tar', 'make', 'dpkg-dev', 'dkms', 'debhelper');
# Install kernel headers only when we could compile kernel modules there
my $kernel_headers_package_name = "linux-headers-$kernel_version";
push @debian_packages_for_pfring, $kernel_headers_package_name;
apt_get(@debian_packages_for_pfring);
} elsif ($distro_type eq 'centos') {
my @centos_dependency_packages = ('make', 'bison', 'flex', 'gcc', 'gcc-c++', 'dkms', 'numactl-devel', 'subversion');
# This package is not going to install devel headers for current kernel!
my $kernel_package_name = 'kernel-devel';
# Fix deplist for OpenVZ
if ($kernel_version =~ /stab/) {
$kernel_package_name = "vzkernel-devel-$kernel_version";
}
push @centos_dependency_packages, $kernel_package_name;
my $centos_kernel_version = `uname -r`;
chomp $centos_kernel_version;
# But this package will install kernel devel headers for current kernel version!
push @centos_dependency_packages, "$kernel_package_name-$centos_kernel_version";
yum(@centos_dependency_packages);
}
}
sub install_pf_ring {
my $pf_ring_archive_path = "$temp_folder_for_building_project/PF_RING-$pf_ring_version.tar.gz";
my $pf_ring_sources_path = "$temp_folder_for_building_project/PF_RING-$pf_ring_version";
my $pf_ring_install_path = "$library_install_folder/pf_ring_$pf_ring_version";
if (-e $pf_ring_install_path) {
print "PF_RING was already installed\n";
return 1;
}
# Sometimes we do not want to build kernel module (Docker, KVM and other cases)
my $we_could_install_kernel_modules = 1;
if ($we_could_install_kernel_modules) {
print "Download PF_RING $pf_ring_version sources\n";
my $pfring_download_result = download_file($pf_ring_url, $pf_ring_archive_path, $pf_ring_sha);
unless ($pfring_download_result) {
fast_die("Can't download PF_RING sources");
}
my $archive_file_name = $pf_ring_archive_path;
if ($? == 0) {
print "Unpack PF_RING\n";
mkdir $pf_ring_sources_path;
exec_command("tar -xf $pf_ring_archive_path -C $temp_folder_for_building_project");
print "Build PF_RING kernel module\n";
exec_command("make $make_options -C $pf_ring_sources_path/kernel clean");
exec_command("make $make_options -C $pf_ring_sources_path/kernel");
exec_command("make $make_options -C $pf_ring_sources_path/kernel install");
print "Unload PF_RING if it was installed earlier\n";
exec_command("rmmod pf_ring 2>/dev/null");
print "Load PF_RING module into kernel\n";
exec_command("modprobe pf_ring");
my @dmesg = `dmesg`;
chomp @dmesg;
if (scalar grep (/\[PF_RING\] Initialized correctly/, @dmesg) > 0) {
print "PF_RING loaded correctly\n";
} else {
warn "PF_RING load error! Please fix this issue manually\n";
# We need this headers for building userspace libs
exec_command("cp $pf_ring_sources_path/kernel/linux/pf_ring.h /usr/include/linux");
}
} else {
warn "Can't download PF_RING source code. Disable support of PF_RING\n";
}
}
print "Build PF_RING lib\n";
# Because we can't run configure from another folder because it can't find ZC dependency :(
chdir "$pf_ring_sources_path/userland/lib";
exec_command("$configure_options ./configure --prefix=$pf_ring_install_path");
exec_command("make $make_options");
exec_command("make $make_options install");
}
sub apt_get { sub apt_get {
my @packages_list = @_; my @packages_list = @_;
@ -1714,21 +1573,12 @@ sub install_fastnetmon {
my $cmake_params = ""; my $cmake_params = "";
if ($we_have_pfring_support) {
$cmake_params .= " -DENABLE_PF_RING_SUPPORT=ON";
}
if ($distro_type eq 'centos' && $distro_version == 6) { if ($distro_type eq 'centos' && $distro_version == 6) {
# Disable cmake script from Boost package because it's broken: # Disable cmake script from Boost package because it's broken:
# http://public.kitware.com/Bug/view.php?id=15270 # http://public.kitware.com/Bug/view.php?id=15270
$cmake_params .= " -DBoost_NO_BOOST_CMAKE=BOOL:ON"; $cmake_params .= " -DBoost_NO_BOOST_CMAKE=BOOL:ON";
} }
# Bump version in cmake build system
if ($use_modern_pf_ring) {
system("sed -i 's/pf_ring_6.0.3/pf_ring_$pf_ring_version/' ../CMakeLists.txt")
}
# Fix dependencies for Netmap in 1.1.4 # Fix dependencies for Netmap in 1.1.4
if ($distro_type eq 'centos' && int($distro_version) == 6) { if ($distro_type eq 'centos' && int($distro_version) == 6) {
system("sed -i 's/netmap_plugin fastnetmon_packet_parser/netmap_plugin fastnetmon_packet_parser unified_parser/' ../CMakeLists.txt") system("sed -i 's/netmap_plugin fastnetmon_packet_parser/netmap_plugin fastnetmon_packet_parser unified_parser/' ../CMakeLists.txt")

View File

@ -11,7 +11,7 @@ Name: fastnetmon
Version: 1.1.1 Version: 1.1.1
Release: 1%{?dist} Release: 1%{?dist}
Summary: A high performance DoS/DDoS load analyzer built on top of multiple packet capture engines (NetFlow, IPFIX, sFLOW, netmap, PF_RING, PCAP). Summary: A high performance DoS/DDoS load analyzer built on top of multiple packet capture engines (NetFlow, IPFIX, sFlow, Netmap, PCAP).
Group: System Environment/Daemons Group: System Environment/Daemons
License: GPLv2 License: GPLv2
URL: https://fastnetmon.com URL: https://fastnetmon.com
@ -20,13 +20,9 @@ URL: https://fastnetmon.com
#Source0: https://github.com/pavel-odintsov/fastnetmon/archive/v%{version}.tar.gz #Source0: https://github.com/pavel-odintsov/fastnetmon/archive/v%{version}.tar.gz
Source0: https://github.com/pavel-odintsov/fastnetmon/archive/fastnetmon-%{version}.tar.gz Source0: https://github.com/pavel-odintsov/fastnetmon/archive/fastnetmon-%{version}.tar.gz
# Yes, it's bad idea to specify fixed version of PF_RING but they have strange issue when we use another library version
BuildRequires: git, make, gcc, gcc-c++, boost-devel, GeoIP-devel, log4cpp-devel BuildRequires: git, make, gcc, gcc-c++, boost-devel, GeoIP-devel, log4cpp-devel
BuildRequires: ncurses-devel, boost-thread, boost-regex, libpcap-devel, gpm-devel, clang, cmake BuildRequires: ncurses-devel, boost-thread, boost-regex, libpcap-devel, gpm-devel, clang, cmake
BuildRequires: pfring >= 6.0.3-9154
Requires: pfring >= 6.0.3-9154
Requires: log4cpp, daemonize, libpcap, boost-thread, boost-thread, boost-regex Requires: log4cpp, daemonize, libpcap, boost-thread, boost-thread, boost-regex
Requires(pre): shadow-utils Requires(pre): shadow-utils
Requires(post): chkconfig Requires(post): chkconfig
@ -36,7 +32,7 @@ Provides: fastnetmon
%description %description
A high performance DoS/DDoS load analyzer built on top of multiple packet capture A high performance DoS/DDoS load analyzer built on top of multiple packet capture
engines (NetFlow, IPFIX, sFLOW, netmap, PF_RING, PCAP). engines (NetFlow, IPFIX, sFlow, Netmap, PCAP).
%prep %prep
# For production # For production
@ -49,10 +45,7 @@ engines (NetFlow, IPFIX, sFLOW, netmap, PF_RING, PCAP).
cd src cd src
mkdir build mkdir build
cd build cd build
# You could disable PF_RING support with param: -DDISABLE_PF_RING_SUPPORT=ON cmake .. -DBoost_NO_BOOST_CMAKE=BOOL:ON
# WE have broken cmake library with Boost on CentOS 6 and should use library from cmake
# http://public.kitware.com/Bug/view.php?id=15270
cmake .. -DWE_USE_PFRING_FROM_NTOP=ON -DBoost_NO_BOOST_CMAKE=BOOL:ON
make make
%install %install

View File

@ -11,7 +11,7 @@ Name: fastnetmon
Version: 1.1.1 Version: 1.1.1
Release: 1%{?dist} Release: 1%{?dist}
Summary: A high performance DoS/DDoS load analyzer built on top of multiple packet capture engines (NetFlow, IPFIX, sFLOW, netmap, PF_RING, PCAP). Summary: A high performance DoS/DDoS load analyzer built on top of multiple packet capture engines (NetFlow, IPFIX, sFlow, Netmap, PCAP).
Group: System Environment/Daemons Group: System Environment/Daemons
License: GPLv2 License: GPLv2
URL: https://fastnetmon.com URL: https://fastnetmon.com
@ -20,14 +20,10 @@ URL: https://fastnetmon.com
#Source0: https://github.com/pavel-odintsov/fastnetmon/archive/v%{version}.tar.gz #Source0: https://github.com/pavel-odintsov/fastnetmon/archive/v%{version}.tar.gz
Source0: https://github.com/pavel-odintsov/fastnetmon/archive/fastnetmon-%{version}.tar.gz Source0: https://github.com/pavel-odintsov/fastnetmon/archive/fastnetmon-%{version}.tar.gz
# Yes, it's bad idea to specify fixed version of PF_RING but they have strange issue when we use another library version
BuildRequires: git, make, gcc, gcc-c++, boost-devel, GeoIP-devel, log4cpp-devel BuildRequires: git, make, gcc, gcc-c++, boost-devel, GeoIP-devel, log4cpp-devel
BuildRequires: ncurses-devel, boost-thread, boost-regex, libpcap-devel, gpm-devel, clang, cmake BuildRequires: ncurses-devel, boost-thread, boost-regex, libpcap-devel, gpm-devel, clang, cmake
BuildRequires: pfring >= 6.0.3-9154
BuildRequires: systemd BuildRequires: systemd
Requires: pfring >= 6.0.3-9154
Requires: log4cpp, libpcap, boost-thread, boost-thread, boost-regex Requires: log4cpp, libpcap, boost-thread, boost-thread, boost-regex
Requires(pre): shadow-utils Requires(pre): shadow-utils
Requires(post): systemd Requires(post): systemd
@ -38,7 +34,7 @@ Provides: fastnetmon
%description %description
A high performance DoS/DDoS load analyzer built on top of multiple packet capture A high performance DoS/DDoS load analyzer built on top of multiple packet capture
engines (NetFlow, IPFIX, sFLOW, netmap, PF_RING, PCAP). engines (NetFlow, IPFIX, sFLOW, netmap, PCAP).
%prep %prep
# For production # For production
@ -51,8 +47,7 @@ engines (NetFlow, IPFIX, sFLOW, netmap, PF_RING, PCAP).
cd src cd src
mkdir build mkdir build
cd build cd build
# You could disable PF_RING support with param: -DDISABLE_PF_RING_SUPPORT=ON cmake ..
cmake .. -DWE_USE_PFRING_FROM_NTOP=ON
make make
%install %install

View File

@ -11,7 +11,7 @@ Name: fastnetmon
Version: 1.1.1 Version: 1.1.1
Release: 1%{?dist} Release: 1%{?dist}
Summary: A high performance DoS/DDoS load analyzer built on top of multiple packet capture engines (NetFlow, IPFIX, sFLOW, netmap, PF_RING, PCAP). Summary: A high performance DoS/DDoS load analyzer built on top of multiple packet capture engines (NetFlow, IPFIX, sFlow, Netmap, PCAP).
Group: System Environment/Daemons Group: System Environment/Daemons
License: GPLv2 License: GPLv2
URL: https://fastnetmon.com URL: https://fastnetmon.com
@ -32,7 +32,7 @@ Provides: fastnetmon
%description %description
A high performance DoS/DDoS load analyzer built on top of multiple packet capture A high performance DoS/DDoS load analyzer built on top of multiple packet capture
engines (NetFlow, IPFIX, sFLOW, netmap, PF_RING, PCAP). engines (NetFlow, IPFIX, sFlow, Netmap, PCAP).
%prep %prep
%setup -n %{name}-%{fastnetmon_commit} %setup -n %{name}-%{fastnetmon_commit}
@ -41,8 +41,7 @@ engines (NetFlow, IPFIX, sFLOW, netmap, PF_RING, PCAP).
cd src cd src
mkdir build mkdir build
cd build cd build
# We should disable PF_RING plugon support because we did not have it in repository cmake ..
cmake .. -DDISABLE_PF_RING_SUPPORT=ON
make make
%install %install

View File

@ -20,10 +20,6 @@
#include "netmap_plugin/netmap_collector.h" #include "netmap_plugin/netmap_collector.h"
#endif #endif
#ifdef PF_RING
#include "pfring_plugin/pfring_collector.h"
#endif
#ifdef FASTNETMON_ENABLE_AFPACKET #ifdef FASTNETMON_ENABLE_AFPACKET
#include "afpacket_plugin/afpacket_collector.h" #include "afpacket_plugin/afpacket_collector.h"
#endif #endif
@ -1982,12 +1978,6 @@ void traffic_draw_ipv4_program() {
output_buffer << get_pcap_stats() << "\n"; output_buffer << get_pcap_stats() << "\n";
} }
#ifdef PF_RING
if (enable_data_collection_from_mirror) {
output_buffer << get_pf_ring_stats();
}
#endif
if (!ban_list.empty()) { if (!ban_list.empty()) {
output_buffer << std::endl << "Ban list:" << std::endl; output_buffer << std::endl << "Ban list:" << std::endl;
output_buffer << print_ddos_attack_details(); output_buffer << print_ddos_attack_details();

View File

@ -6,7 +6,7 @@ FastNetMon \- a high performance DoS/DDoS load analyzer built on top of multiple
.SH SYNOPSIS .SH SYNOPSIS
fastnetmon [--daemonize] fastnetmon [--daemonize]
.SH DESCRIPTION .SH DESCRIPTION
FastNetMon - a high performance DoS/DDoS load analyzer built on top of multiple packet capture engines (NetFlow, IPFIX, sFLOW, netmap, PF_RING, PCAP). FastNetMon - a high performance DoS/DDoS load analyzer built on top of multiple packet capture engines (NetFlow, IPFIX, sFlow, Netmap, PCAP).
For more information about configuration, please look at the comments in /etc/fastnetmon.conf and check the project GitHub page: https://github.com/pavel-odintsov/fastnetmon. For more information about configuration, please look at the comments in /etc/fastnetmon.conf and check the project GitHub page: https://github.com/pavel-odintsov/fastnetmon.
.SH OPTIONS .SH OPTIONS

View File

@ -1,767 +0,0 @@
// log4cpp logging facility
#include "log4cpp/Appender.hh"
#include "log4cpp/BasicLayout.hh"
#include "log4cpp/Category.hh"
#include "log4cpp/FileAppender.hh"
#include "log4cpp/Layout.hh"
#include "log4cpp/OstreamAppender.hh"
#include "log4cpp/PatternLayout.hh"
#include "log4cpp/Priority.hh"
#include "../fast_library.h"
// For support uint32_t, uint16_t
#include <sys/types.h>
#include <iomanip>
#include <iostream>
// For config map operations
#include <map>
#include <string>
// For support: IPPROTO_TCP, IPPROTO_ICMP, IPPROTO_UDP
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/types.h>
#include "pfring_collector.h"
#include "pfring.h"
#ifdef PF_RING_ZC
#include "pfring_zc.h"
#endif
#include <numa.h>
uint32_t pfring_sampling_ratio = 1;
// Get log4cpp logger from main program
extern log4cpp::Category& logger;
extern uint64_t total_unparsed_packets;
// Global configuration map
extern std::map<std::string, std::string> configuration_map;
// Interface name or interface list (delimitered by comma)
std::string work_on_interfaces = "";
// This variable name should be uniq for every plugin!
process_packet_pointer pfring_process_func_ptr = NULL;
// We can look inside L2TP packets with IP encapsulation
// And do it by default
bool do_unpack_l2tp_over_ip = true;
// Variable from PF_RING multi channel mode
int num_pfring_channels = 0;
// We can use software or hardware (in kernel module) packet parser
bool we_use_pf_ring_in_kernel_parser = true;
// By default we pool PF_RING on one thread
bool enable_pfring_multi_channel_mode = false;
struct thread_stats {
u_int64_t __padding_0[8];
u_int64_t numPkts;
u_int64_t numBytes;
pfring* ring;
pthread_t pd_thread;
int core_affinity;
volatile u_int64_t do_shutdown;
u_int64_t __padding_1[3];
};
struct thread_stats* threads;
pfring* pf_ring_descr = NULL;
// We can use ZC api
bool pf_ring_zc_api_mode = false;
#ifdef PF_RING_ZC
u_int32_t zc_num_threads = 0;
pthread_t* zc_threads;
pfring_zc_cluster* zc;
pfring_zc_worker* zw;
pfring_zc_queue** inzq;
pfring_zc_queue** outzq;
pfring_zc_multi_queue* outzmq; /* fanout */
pfring_zc_buffer_pool* wsp;
pfring_zc_pkt_buff** buffers;
#endif
// Prototypes
#ifdef PF_RING_ZC
bool zc_main_loop(const char* device);
#endif
bool pf_ring_main_loop(const char* dev);
bool pf_ring_main_loop_multi_channel(const char* dev);
void* pf_ring_packet_consumer_thread(void* _id);
void pfring_main_packet_process_task();
void start_pfring_collection(process_packet_pointer func_ptr) {
logger << log4cpp::Priority::INFO << "PF_RING plugin started";
pfring_process_func_ptr = func_ptr;
#ifdef PF_RING_ZC
if (configuration_map.count("enable_pf_ring_zc_mode")) {
if (configuration_map["enable_pf_ring_zc_mode"] == "on") {
pf_ring_zc_api_mode = true;
} else {
pf_ring_zc_api_mode = false;
}
}
#endif
if (configuration_map.count("interfaces") != 0) {
work_on_interfaces = configuration_map["interfaces"];
// We should check all interfaces and check zc flag for all
if (work_on_interfaces.find("zc:") != std::string::npos) {
we_use_pf_ring_in_kernel_parser = false;
logger << log4cpp::Priority::INFO
<< "We detect run in PF_RING Zero Copy or DNA mode and we enable packet parser!";
}
logger << log4cpp::Priority::INFO << "We selected interface:" << work_on_interfaces;
}
if (configuration_map.count("pfring_sampling_ratio") != 0) {
pfring_sampling_ratio =
convert_string_to_integer(configuration_map["pfring_sampling_ratio"]);
}
if (work_on_interfaces == "") {
logger << log4cpp::Priority::ERROR << "Please specify interface";
exit(1);
}
pfring_main_packet_process_task();
}
void stop_pfring_collection() {
pfring_breakloop(pf_ring_descr);
}
void parse_packet_pf_ring(const struct pfring_pkthdr* h, const u_char* p, const u_char* user_bytes) {
// Description of all fields: http://www.ntop.org/pfring_api/structpkt__parsing__info.html
simple_packet_t packet;
// We pass only one packet to processing
packet.number_of_packets = 1;
// Now we support only non sampled input from PF_RING
packet.sample_ratio = pfring_sampling_ratio;
if (!pf_ring_zc_api_mode) {
if (!we_use_pf_ring_in_kernel_parser) {
// In ZC (zc:eth0) mode you should manually add packet parsing here
// Because it disabled by default: "parsing already disabled in zero-copy"
// http://www.ntop.org/pfring_api/pfring_8h.html
// Parse up to L3, no timestamp, no hashing
// 1 - add timestamp, 0 - disable hash
// We should zeroify packet header because PFRING ZC did not do this!
memset((void*)&h->extended_hdr.parsed_pkt, 0, sizeof(h->extended_hdr.parsed_pkt));
// We do not calculate timestamps here because it's useless and consumes so much cpu
// https://github.com/ntop/PF_RING/issues/9
u_int8_t timestamp = 0;
u_int8_t add_hash = 0;
pfring_parse_pkt((u_char*)p, (struct pfring_pkthdr*)h, 4, timestamp, add_hash);
}
}
if (do_unpack_l2tp_over_ip) {
// 2014-12-08 13:36:53,537 [INFO] [00:1F:12:84:E2:E7 -> 90:E2:BA:49:85:C8]
// [IPv4][5.254.105.102:0 -> 159.253.17.251:0]
// [l3_proto=115][hash=2784721876][tos=32][tcp_seq_num=0]
// [caplen=128][len=873][parsed_header_len=0][eth_offset=-14][l3_offset=14][l4_offset=34][payload_offset=0]
// L2TP has an proto number 115
if (h->extended_hdr.parsed_pkt.l3_proto == 115) {
// pfring_parse_pkt expects that the hdr memory is either zeroed or contains valid
// values
// for the current packet, in order to avoid parsing twice the same packet headers.
struct pfring_pkthdr l2tp_header;
memset(&l2tp_header, 0, sizeof(l2tp_header));
int16_t l4_offset = h->extended_hdr.parsed_pkt.offset.l4_offset;
// L2TP has two headers: L2TP and default L2-Specific Sublayer: every header for 4bytes
int16_t l2tp_header_size = 8;
l2tp_header.len = h->len - (l4_offset + l2tp_header_size);
l2tp_header.caplen = h->caplen - (l4_offset + l2tp_header_size);
const u_char* l2tp_tunnel_payload = p + l4_offset + l2tp_header_size;
// 1 - add timestamp, 0 - disable hash
pfring_parse_pkt((u_char*)l2tp_tunnel_payload, &l2tp_header, 4, 1, 0);
// Copy data back
// TODO: it's not fine solution and I should redesign this code
memcpy((struct pfring_pkthdr*)h, &l2tp_header, sizeof(l2tp_header));
// TODO: Global pfring_print_parsed_pkt can fail because we did not shift 'p' pointer
// Uncomment this line for deep inspection of all packets
/*
char buffer[512];
pfring_print_parsed_pkt(buffer, 512, l2tp_tunnel_payload, h);
logger<<log4cpp::Priority::INFO<<buffer;
*/
}
}
if (h->extended_hdr.parsed_pkt.ip_version != 4 && h->extended_hdr.parsed_pkt.ip_version != 6) {
total_unparsed_packets++;
return;
}
packet.ip_protocol_version = h->extended_hdr.parsed_pkt.ip_version;
if (packet.ip_protocol_version == 4) {
// IPv4
/* PF_RING stores data in host byte order but we use network byte order */
packet.src_ip = htonl(h->extended_hdr.parsed_pkt.ip_src.v4);
packet.dst_ip = htonl(h->extended_hdr.parsed_pkt.ip_dst.v4);
} else {
// IPv6
memcpy(packet.src_ipv6.s6_addr, h->extended_hdr.parsed_pkt.ip_src.v6.s6_addr, 16);
memcpy(packet.dst_ipv6.s6_addr, h->extended_hdr.parsed_pkt.ip_dst.v6.s6_addr, 16);
}
packet.source_port = h->extended_hdr.parsed_pkt.l4_src_port;
packet.destination_port = h->extended_hdr.parsed_pkt.l4_dst_port;
// We need this for deep packet inspection
packet.packet_payload_length = h->len;
packet.packet_payload_pointer = (void*)p;
packet.length = h->len;
packet.protocol = h->extended_hdr.parsed_pkt.l3_proto;
packet.ts = h->ts;
// Copy flags from PF_RING header to our pseudo header
if (packet.protocol == IPPROTO_TCP) {
packet.flags = h->extended_hdr.parsed_pkt.tcp.flags;
} else {
packet.flags = 0;
}
pfring_process_func_ptr(packet);
}
// Main worker thread for packet handling
void pfring_main_packet_process_task() {
const char* device_name = work_on_interfaces.c_str();
bool pf_ring_init_result = false;
if (pf_ring_zc_api_mode) {
#ifdef PF_RING_ZC
pf_ring_init_result = zc_main_loop((char*)device_name);
#else
logger << log4cpp::Priority::ERROR << "PF_RING library hasn't ZC support, please try SVN version";
#endif
} else {
if (enable_pfring_multi_channel_mode) {
pf_ring_init_result = pf_ring_main_loop_multi_channel(device_name);
} else {
pf_ring_init_result = pf_ring_main_loop(device_name);
}
}
if (!pf_ring_init_result) {
// Internal error in PF_RING
logger << log4cpp::Priority::ERROR << "PF_RING initilization failed, exit from program";
exit(1);
}
}
std::string get_pf_ring_stats() {
std::stringstream output_buffer;
if (pf_ring_zc_api_mode) {
#ifdef PF_RING_ZC
pfring_zc_stat stats;
// We have elements in insq for every hardware device! We shoulw add ability to configure ot
int stats_res = pfring_zc_stats(inzq[0], &stats);
if (stats_res) {
logger << log4cpp::Priority::ERROR << "Can't get PF_RING ZC stats for in queue";
} else {
double dropped_percent = 0;
if (stats.recv + stats.sent > 0) {
dropped_percent = (double)stats.drop / ((double)stats.recv + (double)stats.sent) * 100;
}
output_buffer << "\n";
output_buffer << "PF_RING ZC in queue statistics\n";
output_buffer << "Received:\t" << stats.recv << "\n";
output_buffer << "Sent:\t\t" << stats.sent << "\n";
output_buffer << "Dropped:\t" << stats.drop << "\n";
output_buffer << "Dropped:\t" << std::fixed << std::setprecision(2) << dropped_percent << " %\n";
}
output_buffer << "\n";
output_buffer << "PF_RING ZC out queue statistics\n";
u_int64_t total_recv = 0;
u_int64_t total_sent = 0;
u_int64_t total_drop = 0;
for (int i = 0; i < zc_num_threads; i++) {
pfring_zc_stat outq_stats;
int outq_stats_res = pfring_zc_stats(outzq[0], &outq_stats);
if (stats_res) {
logger << log4cpp::Priority::ERROR << "Can't get PF_RING ZC stats for out queue";
} else {
total_recv += outq_stats.recv;
total_sent += outq_stats.sent;
total_drop += outq_stats.drop;
}
}
double total_drop_percent = 0;
if (total_recv + total_sent > 0) {
total_drop_percent = (double)total_drop / ((double)total_recv + (double)total_sent) * 100;
}
output_buffer << "Received:\t" << total_recv << "\n";
output_buffer << "Sent:\t\t" << total_sent << "\n";
output_buffer << "Dropped:\t" << total_drop << "\n";
output_buffer << "Dropped:\t" << std::fixed << std::setprecision(2) << total_drop_percent << " %\n";
#endif
}
// Getting stats for multi channel mode is so complex task
if (!enable_pfring_multi_channel_mode && !pf_ring_zc_api_mode) {
pfring_stat pfring_status_data;
if (pfring_stats(pf_ring_descr, &pfring_status_data) >= 0) {
char stats_buffer[256];
double packets_dropped_percent = 0;
if (pfring_status_data.recv > 0) {
packets_dropped_percent = (double)pfring_status_data.drop / pfring_status_data.recv * 100;
}
sprintf(stats_buffer,
"Packets received:\t%lu\n"
"Packets dropped:\t%lu\n"
"Packets dropped:\t%.1f %%\n",
(long unsigned int)pfring_status_data.recv,
(long unsigned int)pfring_status_data.drop, packets_dropped_percent);
output_buffer << stats_buffer;
} else {
logger << log4cpp::Priority::ERROR << "Can't get PF_RING stats";
}
}
return output_buffer.str();
}
bool pf_ring_main_loop_multi_channel(const char* dev) {
int MAX_NUM_THREADS = 64;
if ((threads = (struct thread_stats*)calloc(MAX_NUM_THREADS, sizeof(struct thread_stats))) == NULL) {
logger << log4cpp::Priority::ERROR << "Can't allocate memory for threads structure";
return false;
}
u_int32_t flags = 0;
flags |= PF_RING_PROMISC; /* hardcode: promisc=1 */
flags |= PF_RING_DNA_SYMMETRIC_RSS; /* Note that symmetric RSS is ignored by non-DNA drivers */
flags |= PF_RING_LONG_HEADER;
packet_direction direction = rx_only_direction;
pfring* ring_array[MAX_NUM_RX_CHANNELS];
unsigned int snaplen = 128;
num_pfring_channels = pfring_open_multichannel(dev, snaplen, flags, ring_array);
if (num_pfring_channels <= 0) {
logger << log4cpp::Priority::INFO << "pfring_open_multichannel returned: " << num_pfring_channels
<< " and error:" << strerror(errno);
return false;
}
u_int num_cpus = sysconf(_SC_NPROCESSORS_ONLN);
logger << log4cpp::Priority::INFO << "We have: " << num_cpus << " logical cpus in this server";
logger << log4cpp::Priority::INFO << "We have: " << num_pfring_channels << " channels from pf_ring NIC";
// We should not start more processes then we have kernel cores
// if (num_pfring_channels > num_cpus) {
// num_pfring_channels = num_cpus;
//}
for (int i = 0; i < num_pfring_channels; i++) {
// char buf[32];
threads[i].ring = ring_array[i];
// threads[i].core_affinity = threads_core_affinity[i];
int rc = 0;
if ((rc = pfring_set_direction(threads[i].ring, direction)) != 0) {
logger << log4cpp::Priority::INFO << "pfring_set_direction returned: " << rc;
}
if ((rc = pfring_set_socket_mode(threads[i].ring, recv_only_mode)) != 0) {
logger << log4cpp::Priority::INFO << "pfring_set_socket_mode returned: " << rc;
}
int rehash_rss = 0;
if (rehash_rss) pfring_enable_rss_rehash(threads[i].ring);
int poll_duration = 0;
if (poll_duration > 0) pfring_set_poll_duration(threads[i].ring, poll_duration);
pfring_enable_ring(threads[i].ring);
unsigned long thread_id = i;
pthread_create(&threads[i].pd_thread, NULL, pf_ring_packet_consumer_thread, (void*)thread_id);
}
for (int i = 0; i < num_pfring_channels; i++) {
pthread_join(threads[i].pd_thread, NULL);
pfring_close(threads[i].ring);
}
return true;
}
void* pf_ring_packet_consumer_thread(void* _id) {
long thread_id = (long)_id;
int wait_for_packet = 1;
// TODO: fix it
bool do_shutdown = false;
while (!do_shutdown) {
u_char* buffer = NULL;
struct pfring_pkthdr hdr;
if (pfring_recv(threads[thread_id].ring, &buffer, 0, &hdr, wait_for_packet) > 0) {
// TODO: pass (u_char*)thread_id)
parse_packet_pf_ring(&hdr, buffer, 0);
} else {
if (wait_for_packet == 0) {
usleep(1); // sched_yield();
}
}
}
return NULL;
}
#ifdef PF_RING_ZC
int rr = -1;
int32_t rr_distribution_func(pfring_zc_pkt_buff* pkt_handle, pfring_zc_queue* in_queue, void* user) {
long num_out_queues = (long)user;
if (++rr == num_out_queues) {
rr = 0;
}
return rr;
}
#endif
#ifdef PF_RING_ZC
int bind2core(int core_id) {
cpu_set_t cpuset;
int s;
if (core_id < 0) return -1;
CPU_ZERO(&cpuset);
CPU_SET(core_id, &cpuset);
if ((s = pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset)) != 0) {
logger << log4cpp::Priority::INFO << "Error while binding to core:" << core_id;
return -1;
} else {
return 0;
}
}
#endif
#ifdef PF_RING_ZC
void* zc_packet_consumer_thread(void* _id) {
long id = (long)_id;
pfring_zc_pkt_buff* b = buffers[id];
// Bind to core with thread number
bind2core(id);
u_int8_t wait_for_packet = 1;
struct pfring_pkthdr zc_header;
memset(&zc_header, 0, sizeof(zc_header));
while (true) {
if (pfring_zc_recv_pkt(outzq[id], &b, wait_for_packet) > 0) {
u_char* pkt_data = pfring_zc_pkt_buff_data(b, outzq[id]);
memset(&zc_header, 0, sizeof(zc_header));
zc_header.len = b->len;
zc_header.caplen = b->len;
pfring_parse_pkt(pkt_data, (struct pfring_pkthdr*)&zc_header, 4, 1, 0);
parse_packet_pf_ring(&zc_header, pkt_data, 0);
}
}
pfring_zc_sync_queue(outzq[id], rx_only);
return NULL;
}
#endif
int max_packet_len(const char* device) {
int max_len = 0;
pfring* ring = pfring_open(device, 1536, PF_RING_PROMISC);
if (ring == NULL) return 1536;
// pfring_get_card_settings have added in 6.0.3
// We should not use 6.0.3 API for PF_RING library from ntop because it announces "6.0.3" but lack
// of many 6.0.3 features
#if RING_VERSION_NUM >= 0x060003 and !defined(WE_USE_PFRING_FROM_NTOP)
pfring_card_settings settings;
pfring_get_card_settings(ring, &settings);
max_len = settings.max_packet_size;
#else
if (ring->dna.dna_mapped_device) {
max_len = ring->dna.dna_dev.mem_info.rx.packet_memory_slot_len;
} else {
max_len = pfring_get_mtu_size(ring);
if (max_len == 0) max_len = 9000 /* Jumbo */;
max_len += 14 /* Eth */ + 4 /* VLAN */;
}
#endif
pfring_close(ring);
return max_len;
}
#define MAX_CARD_SLOTS 32768
#define PREFETCH_BUFFERS 8
#define QUEUE_LEN 8192
#ifdef PF_RING_ZC
bool zc_main_loop(const char* device) {
u_int32_t cluster_id = 0;
int bind_core = -1;
u_int num_cpus = sysconf(_SC_NPROCESSORS_ONLN);
logger << log4cpp::Priority::INFO << "We have: " << num_cpus << " logical cpus in this server";
// TODO: add support for multiple devices!
u_int32_t num_devices = 1;
zc_num_threads = num_cpus - 1;
logger << log4cpp::Priority::INFO << "We will start " << zc_num_threads << " worker threads";
u_int32_t tot_num_buffers =
(num_devices * MAX_CARD_SLOTS) + (zc_num_threads * QUEUE_LEN) + zc_num_threads + PREFETCH_BUFFERS;
u_int32_t buffer_len = max_packet_len(device);
logger << log4cpp::Priority::INFO << "We got max packet len from device: " << buffer_len;
logger << log4cpp::Priority::INFO << "We will use total number of ZC buffers: " << tot_num_buffers;
zc = pfring_zc_create_cluster(cluster_id, buffer_len, 0, tot_num_buffers,
numa_node_of_cpu(bind_core), NULL /* auto hugetlb mountpoint */
);
if (zc == NULL) {
logger << log4cpp::Priority::INFO << "pfring_zc_create_cluster error: " << strerror(errno)
<< " Please check that pf_ring.ko is loaded and hugetlb fs is mounted";
return false;
}
zc_threads = (pthread_t*)calloc(zc_num_threads, sizeof(pthread_t));
buffers = (pfring_zc_pkt_buff**)calloc(zc_num_threads, sizeof(pfring_zc_pkt_buff*));
inzq = (pfring_zc_queue**)calloc(num_devices, sizeof(pfring_zc_queue*));
outzq = (pfring_zc_queue**)calloc(zc_num_threads, sizeof(pfring_zc_queue*));
for (int i = 0; i < zc_num_threads; i++) {
buffers[i] = pfring_zc_get_packet_handle(zc);
if (buffers[i] == NULL) {
logger << log4cpp::Priority::ERROR << "pfring_zc_get_packet_handle failed";
return false;
}
}
for (int i = 0; i < num_devices; i++) {
u_int32_t zc_flags = 0;
inzq[i] = pfring_zc_open_device(zc, device, rx_only, zc_flags);
if (inzq[i] == NULL) {
logger << log4cpp::Priority::ERROR << "pfring_zc_open_device error " << strerror(errno)
<< " Please check that device is up and not already used";
return false;
}
#if RING_VERSION_NUM >= 0x060003
int pf_ring_license_state = pfring_zc_check_license();
if (!pf_ring_license_state) {
logger << log4cpp::Priority::WARN << "PF_RING ZC haven't license for device" << device
<< " and running in trial mode and will work only 5 minutes! Please buy license "
"or switch to vanilla PF_RING";
}
#endif
}
for (int i = 0; i < zc_num_threads; i++) {
outzq[i] = pfring_zc_create_queue(zc, QUEUE_LEN);
if (outzq[i] == NULL) {
logger << log4cpp::Priority::ERROR << "pfring_zc_create_queue error: " << strerror(errno);
return false;
}
}
wsp = pfring_zc_create_buffer_pool(zc, PREFETCH_BUFFERS);
if (wsp == NULL) {
logger << log4cpp::Priority::ERROR << "pfring_zc_create_buffer_pool error";
return false;
}
logger << log4cpp::Priority::INFO << "We are starting balancer with: " << zc_num_threads << " threads";
pfring_zc_distribution_func func = rr_distribution_func;
u_int8_t wait_for_packet = 1;
// We run balancer at last thread
int32_t bind_worker_core = zc_num_threads;
logger << log4cpp::Priority::INFO << "We will run balancer on core: " << bind_worker_core;
zw = pfring_zc_run_balancer(inzq, outzq, num_devices, zc_num_threads, wsp,
round_robin_bursts_policy, NULL /* idle callback */, func,
(void*)((long)zc_num_threads), !wait_for_packet, bind_worker_core);
if (zw == NULL) {
logger << log4cpp::Priority::ERROR << "pfring_zc_run_balancer error:" << strerror(errno);
return false;
}
for (int i = 0; i < zc_num_threads; i++) {
pthread_create(&zc_threads[i], NULL, zc_packet_consumer_thread, (void*)(long)i);
}
for (int i = 0; i < zc_num_threads; i++) {
pthread_join(zc_threads[i], NULL);
}
pfring_zc_kill_worker(zw);
pfring_zc_destroy_cluster(zc);
return true;
}
#endif
bool pf_ring_main_loop(const char* dev) {
// We could pool device in multiple threads
unsigned int num_threads = 1;
bool promisc = true;
/* This flag manages packet parser for extended_hdr */
bool use_extended_pkt_header = true;
bool enable_hw_timestamp = false;
bool dont_strip_timestamps = false;
u_int32_t flags = 0;
if (num_threads > 1) flags |= PF_RING_REENTRANT;
if (use_extended_pkt_header) flags |= PF_RING_LONG_HEADER;
if (promisc) flags |= PF_RING_PROMISC;
if (enable_hw_timestamp) flags |= PF_RING_HW_TIMESTAMP;
if (!dont_strip_timestamps) flags |= PF_RING_STRIP_HW_TIMESTAMP;
if (!we_use_pf_ring_in_kernel_parser) {
flags |= PF_RING_DO_NOT_PARSE;
}
flags |= PF_RING_DNA_SYMMETRIC_RSS; /* Note that symmetric RSS is ignored by non-DNA drivers */
// use default value from pfcount.c
unsigned int snaplen = 128;
pf_ring_descr = pfring_open(dev, snaplen, flags);
if (pf_ring_descr == NULL) {
logger
<< log4cpp::Priority::INFO << "pfring_open error: " << strerror(errno)
<< " (pf_ring not loaded or perhaps you use quick mode and have already a socket bound to: " << dev
<< ")";
return false;
}
logger << log4cpp::Priority::INFO << "Successully binded to: " << dev;
// We need cast to int because in other way it will be interpreted as char :(
logger << log4cpp::Priority::INFO
<< "Device RX channels number: " << int(pfring_get_num_rx_channels(pf_ring_descr));
u_int32_t version;
// Set spplication name in /proc
int pfring_set_application_name_result =
pfring_set_application_name(pf_ring_descr, (char*)"fastnetmon");
if (pfring_set_application_name_result != 0) {
logger << log4cpp::Priority::ERROR << "Can't set program name for PF_RING: pfring_set_application_name";
}
pfring_version(pf_ring_descr, &version);
logger.info("Using PF_RING v.%d.%d.%d", (version & 0xFFFF0000) >> 16,
(version & 0x0000FF00) >> 8, version & 0x000000FF);
int pfring_set_socket_mode_result = pfring_set_socket_mode(pf_ring_descr, recv_only_mode);
if (pfring_set_socket_mode_result != 0) {
logger.info("pfring_set_socket_mode returned [rc=%d]\n", pfring_set_socket_mode_result);
}
// enable ring
if (pfring_enable_ring(pf_ring_descr) != 0) {
logger << log4cpp::Priority::INFO << "Unable to enable ring :-(";
pfring_close(pf_ring_descr);
return false;
}
// Active wait wor packets. But I did not know what is mean..
u_int8_t wait_for_packet = 1;
pfring_loop(pf_ring_descr, parse_packet_pf_ring, (u_char*)NULL, wait_for_packet);
return true;
}

View File

@ -1,10 +0,0 @@
#ifndef PFRING_PLUGIN_H
#define PFRING_PLUGIN_H
#include "../fastnetmon_types.h"
// This function should be implemented in plugin
void start_pfring_collection(process_packet_pointer func_ptr);
void stop_pfring_collection();
std::string get_pf_ring_stats();
#endif

View File

@ -17,10 +17,6 @@
#include "pcap_plugin/pcap_collector.h" #include "pcap_plugin/pcap_collector.h"
#include "sflow_plugin/sflow_collector.h" #include "sflow_plugin/sflow_collector.h"
#ifdef PF_RING
#include "pfring_plugin/pfring_collector.h"
#endif
#ifdef FASTNETMON_ENABLE_AFPACKET #ifdef FASTNETMON_ENABLE_AFPACKET
#include "afpacket_plugin/afpacket_collector.h" #include "afpacket_plugin/afpacket_collector.h"
#endif #endif
@ -121,7 +117,7 @@ int main(int argc, char* argv[]) {
} }
#endif #endif
// Required by Netmap and PF_RING plugins // Required by Netmap plugin
// We use fake interface name here because netmap could make server unreachable :) // We use fake interface name here because netmap could make server unreachable :)
configuration_map["interfaces"] = "ethXXX"; configuration_map["interfaces"] = "ethXXX";
@ -134,13 +130,6 @@ int main(int argc, char* argv[]) {
} else if (strstr(argv[1], "pcap") != NULL) { } else if (strstr(argv[1], "pcap") != NULL) {
std::cout << "Starting pcap" << std::endl; std::cout << "Starting pcap" << std::endl;
start_pcap_collection(process_packet); start_pcap_collection(process_packet);
} else if (strstr(argv[1], "pfring") != NULL) {
#ifdef PF_RING
std::cout << "Starting pf_ring" << std::endl;
start_pfring_collection(process_packet);
#else
std::cout << "PF_RING support disabled here" << std::endl;
#endif
} else if (strstr(argv[1], "afpacket") != NULL) { } else if (strstr(argv[1], "afpacket") != NULL) {
#ifdef FASTNETMON_ENABLE_AFPACKET #ifdef FASTNETMON_ENABLE_AFPACKET
std::cout << "Starting afpacket" << std::endl; std::cout << "Starting afpacket" << std::endl;

View File

@ -210,7 +210,7 @@ DOC
my $spec_file_summary_section = <<'DOC'; my $spec_file_summary_section = <<'DOC';
Release: 1%{?dist} Release: 1%{?dist}
Summary: A high performance DoS/DDoS load analyzer built on top of multiple packet capture engines (NetFlow, IPFIX, sFLOW, netmap, PF_RING, PCAP). Summary: A high performance DoS/DDoS load analyzer built on top of multiple packet capture engines (NetFlow, IPFIX, sFLOW, netmap, PCAP).
Group: System Environment/Daemons Group: System Environment/Daemons
License: GPLv2 License: GPLv2
URL: https://fastnetmon.com URL: https://fastnetmon.com
@ -239,7 +239,7 @@ DOC
%description %description
A high performance DoS/DDoS load analyzer built on top of multiple packet capture A high performance DoS/DDoS load analyzer built on top of multiple packet capture
engines (NetFlow, IPFIX, sFLOW, netmap, PF_RING, PCAP). engines (NetFlow, IPFIX, sFlow, Netmap, PCAP).
DOC DOC
@ -509,7 +509,7 @@ my $fastnetmon_systemv_init = <<'DOC';
# Default-Start: 2 3 4 5 # Default-Start: 2 3 4 5
# Default-Stop: 0 1 6 # Default-Stop: 0 1 6
# Short-Description: Fast DDoS detection toolkit. # Short-Description: Fast DDoS detection toolkit.
# Description: Fast DDoS detection toolkit with sFLOW/Netflow/netmap/pf_ring support. # Description: Fast DDoS detection toolkit with sFLOW/Netflow/Netmap support.
### END INIT INFO ### END INIT INFO
# test -r /etc/default/fastnetmon && . /etc/default/fastnetmon # test -r /etc/default/fastnetmon && . /etc/default/fastnetmon

View File

@ -39,7 +39,6 @@ boost_1_74_0
json-c-0.13 json-c-0.13
libicu_65_1 libicu_65_1
log4cpp1.1.1 log4cpp1.1.1
pf_ring_6.0.3
gobgp_2_17_0 gobgp_2_17_0
grpc_1_30_2 grpc_1_30_2
libhiredis_0_13 libhiredis_0_13
@ -55,12 +54,7 @@ for my $library (@our_libraries) {
unless (-e $library_path) { unless (-e $library_path) {
warn "Can't find library $library please check\n"; warn "Can't find library $library please check\n";
die "Some required libraries are missing\n";
if ($library eq 'pf_ring_6.0.3') {
next;
} else {
die "Some required libraries are missing\n";
}
} }
print "Library: $library\n"; print "Library: $library\n";

View File

@ -1,78 +0,0 @@
#include "pfring.h"
#include <iostream>
/* How to compile me:
g++ pfring_parser_zc_issue.c -I/opt/pf_ring/include -L/opt/pf_ring/lib/ -lpfring -lnuma
*/
void parse_packet_pf_ring(const struct pfring_pkthdr* h, const u_char* p, const u_char* user_bytes) {
memset((void*)&h->extended_hdr.parsed_pkt, 0, sizeof(h->extended_hdr.parsed_pkt));
pfring_parse_pkt((u_char*)p, (struct pfring_pkthdr*)h, 4, 1, 0);
char buffer[512];
pfring_print_parsed_pkt(buffer, 512, p, h);
std::cout << buffer;
}
int main() {
char* dev = "zc:eth3";
// We could pool device in multiple threads
unsigned int num_threads = 1;
bool promisc = true;
/* This flag manages packet parser for extended_hdr */
bool use_extended_pkt_header = true;
bool enable_hw_timestamp = false;
bool dont_strip_timestamps = false;
u_int32_t flags = 0;
if (num_threads > 1) flags |= PF_RING_REENTRANT;
if (use_extended_pkt_header) flags |= PF_RING_LONG_HEADER;
if (promisc) flags |= PF_RING_PROMISC;
if (enable_hw_timestamp) flags |= PF_RING_HW_TIMESTAMP;
if (!dont_strip_timestamps) flags |= PF_RING_STRIP_HW_TIMESTAMP;
// if (!we_use_pf_ring_in_kernel_parser) {
// flags != PF_RING_DO_NOT_PARSE;
//}
// flags |= PF_RING_DNA_SYMMETRIC_RSS; /* Note that symmetric RSS is ignored by non-DNA drivers
// */
// use default value from pfcount.c
unsigned int snaplen = 128;
pfring* pf_ring_descr = pfring_open(dev, snaplen, flags);
if (pf_ring_descr == NULL) {
std::cout
<< "pfring_open error: " << strerror(errno)
<< " (pf_ring not loaded or perhaps you use quick mode and have already a socket bound to: " << dev
<< ")";
return false;
}
u_int32_t version;
// Set spplication name in /proc
int pfring_set_application_name_result =
pfring_set_application_name(pf_ring_descr, (char*)"fastnetmon");
if (pfring_set_application_name_result != 0) {
std::cout << "Can't set program name for PF_RING: pfring_set_application_name";
}
pfring_version(pf_ring_descr, &version);
int pfring_set_socket_mode_result = pfring_set_socket_mode(pf_ring_descr, recv_only_mode);
// enable ring
if (pfring_enable_ring(pf_ring_descr) != 0) {
std::cout << "Unable to enable ring :-(";
pfring_close(pf_ring_descr);
return false;
}
u_int8_t wait_for_packet = 1;
pfring_loop(pf_ring_descr, parse_packet_pf_ring, (u_char*)NULL, wait_for_packet);
}

View File

@ -17,10 +17,6 @@
#include "../pcap_plugin/pcap_collector.h" #include "../pcap_plugin/pcap_collector.h"
#include "../sflow_plugin/sflow_collector.h" #include "../sflow_plugin/sflow_collector.h"
#ifdef PF_RING
#include "../pfring_plugin/pfring_collector.h"
#endif
#include "../netmap_plugin/netmap_collector.h" #include "../netmap_plugin/netmap_collector.h"
#include <boost/atomic.hpp> #include <boost/atomic.hpp>
@ -128,7 +124,7 @@ int main(int argc, char* argv[]) {
init_logging(); init_logging();
// Required by Netmap and PF_RING plugins // Required by Netmap plugin
// We use fake interface name here because netmap could make server unreachable :) // We use fake interface name here because netmap could make server unreachable :)
configuration_map["interfaces"] = "eth5"; configuration_map["interfaces"] = "eth5";
start_netmap_collection(process_packet); start_netmap_collection(process_packet);