Skip to content
Closed
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
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[package]
name = "suriconf"
edition = "2024"
version = "1.1.0-dev"
version = "1.1.0-dev.2"
authors = ["Eliška Červinková <eliska.cervinkova@cesnet.cz>"]
license = "BSD-3-Clause"
description = "A tool for automating Suricata setup and configuration."
Expand Down
5 changes: 3 additions & 2 deletions ISSUES.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,17 @@
---

## Bugs
- The YAML file is converted to JSON and then back to YAML for searching, which can alter the original formatting and is therefore not fully correct. A hotfix function was introduced specifically for the purposes of the bachelor’s thesis.
- The regression sometimes has fewer samples than is required.
- The YAML file is converted to JSON and then back to YAML for searching, which can alter the original formatting and is therefore not fully correct. A hotfix function was introduced specifically for the purposes of the bachelor’s thesis.
- Disable syslog and suricata.log logging after configuration.
- Better estimation of TCP overhead.
- CPU affinity module should work with `check_nic_warning_counter`, `get_capture_errors_stat` functions.
- Flow module should use sync counters.
- The `tcp_reuse` timeout is not considered.
- The calculations for flow_memcap and stream_memcap do not account for all memory components in some cases.
- Fragment structures are not included in `defrag_memuse` at all. (Suricata)
- Hotfix for defrag_memcap, needs further analysis.
- Do not log counters with zero values. Adapt the program to handle missing counters.
- Check for parameter changes (CLI) in Suriconf. (CPU affinity module)

## Future work
- Add load factor for hash tables in memory module.
Expand Down
12 changes: 6 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
[![Rust](https://img.shields.io/badge/rust-1.88+-orange.svg)](https://rustup.rs/)
[![Bachelor's Thesis](https://img.shields.io/badge/thesis-completed-success)](https://www.vut.cz/studenti/zav-prace/detail/170986)

Suriconf is an automated configuration assistant for [Suricata](https://github.com/OISF/suricata). It analyzes network traffic and system resources to optimize Suricata's configuration through a modular approach. Each module uses mathematical methods and performance metrics to configure specific Suricata components. Testing showed Suriconf v1.1.0-dev successfully configured Suricata in 80.8% of test cases with [rules](https://community.emergingthreats.net/).
Suriconf is an automated configuration assistant for [Suricata](https://github.com/OISF/suricata). It analyzes network traffic and system resources to optimize Suricata's configuration through a modular approach. Each module uses mathematical methods and performance metrics to configure specific Suricata components. Testing showed Suriconf v1.1.0-dev.2 successfully configured Suricata in 80.8% of test cases with [rules](https://community.emergingthreats.net/).

## Contents

Expand Down Expand Up @@ -43,14 +43,14 @@ The following tools must be installed, and their paths must be accessible and sp

### System

Suriconf v1.1.0-dev requires the network interface to be bound to a specific NUMA node.
Suriconf v1.1.0-dev.2 requires the network interface to be bound to a specific NUMA node.

### Suricata configuration file

> [!WARNING]
> Consider stream and reassembly memcap in Suricata configuration file. (host and IPpair memcap).

Configure these with high values first. Suriconf will automatically reduce them if needed. This is necessary because Suriconf v1.1.0-dev currently lacks dynamic memory reallocation between these pools. Once allocated, memory assigned to one memcap cannot be reassigned to another at runtime.
Configure these with high values first. Suriconf will automatically reduce them if needed. This is necessary because Suriconf v1.1.0-dev.2 currently lacks dynamic memory reallocation between these pools. Once allocated, memory assigned to one memcap cannot be reassigned to another at runtime.

## Configuration

Expand All @@ -69,8 +69,8 @@ The entire configuration is defined in a YAML file, typically named `suriconf.ya

> [!WARNING]
> - Flow threads module requires minimum 6 minutes (`preconf-time`).
> - Version 1.1.0-dev supports only `static` analysis.
> - Version 1.1.0-dev supports only `modify` mode with `yaml_change: force`.
> - Version 1.1.0-dev.2 supports only `static` analysis.
> - Version 1.1.0-dev.2 supports only `modify` mode with `yaml_change: force`.


### Modules
Expand Down Expand Up @@ -116,7 +116,7 @@ sudo grubby --update-kernel=ALL --args="isolcpus=2-4" && sudo reboot
Install Suriconf:

```bash
cargo install suriconf@1.1.0-dev
cargo install suriconf@1.1.0-dev.2
```

To display available options, execute:
Expand Down
32 changes: 28 additions & 4 deletions src/cpu_affinity.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ This file represents a CPU affinity module.
*/

use chrono::{DateTime, Utc};
use std::collections::{HashMap};
use std::collections::{HashMap, HashSet};
use serde_json::{Value, Number};
use std::fs;
use crate::json::CpuThread;
Expand Down Expand Up @@ -453,10 +453,34 @@ impl CpuAffinityModule {
.map(|a| a.as_u64().expect("Expected u64 value")).collect()
}

fn get_max_cpu_usage_vec(&self, answers: &Vec<Answer<'_>>) -> Vec<u64> {
let value = answers.iter().find(|h| h.key == &Keys::max_cpu_usage_vec)
.expect("Max cpu usage vector cannot be found.").value;

let seq = value.as_array().expect("Unable to get max_cpu_usage_vec as array.");

let mut cpus: Vec<u64> = Vec::new();
let mut seen = HashSet::new();

for item in seq {
let s = match item {
Value::Number(n) => n.to_string(),
Value::String(s) => s.clone(),
u => panic!("Invalid CPU {:?}.", u)
};
yaml::insert_cpu(&s, &mut seen, &mut cpus)
.expect("Unable to parse max_cpu_usage_vec as u64 vector.");
}

if self.debug {
println!("max_cpu_usage_vec: {:?}", cpus);
}

cpus
}

pub fn set_new_cpu_set(&self, answers: &Vec<Answer<'_>>, mut new_workers: u64) -> Vec<u64> {
let max_cpu_usage_vec: Vec<u64> = answers.iter().find(|h| h.key == &Keys::max_cpu_usage_vec)
.expect("Max cpu usage vector cannot be found.").value.as_array().expect("Unable to get array from max cpu usage vector.")
.iter().map(|a| a.as_u64().expect("Expected u64 value")).collect();
let max_cpu_usage_vec = self.get_max_cpu_usage_vec(answers);

if self.debug {
println!("new_workers: {new_workers}");
Expand Down
2 changes: 1 addition & 1 deletion src/memory_usage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -452,7 +452,7 @@ impl MemoryModule {
};
let hashsize = self.questions.get(&Keys::defrag_hashsize).expect("Unable to get defrag.").as_f64().expect("Unable to get defrag hash_size as f64.");

hashsize*DEFRAG_TRACKER_HASHROW+(max_defrag_tracker_active+(self.get_ippair_host_defrag_stream_reassembly_prealloc(answers, &HashType::Defrag) as f64)*MULTIPLIER)*DEFRAG_TRACKER
hashsize*DEFRAG_TRACKER_HASHROW+(max_defrag_tracker_active+(self.get_ippair_host_defrag_stream_reassembly_prealloc(answers, &HashType::Defrag) as f64)*MULTIPLIER)*DEFRAG_TRACKER*4.0
}

fn get_stream_memcap(&self, answers: &Vec<Answer<'_>>) -> f64 {
Expand Down
2 changes: 1 addition & 1 deletion src/suricata.rs
Original file line number Diff line number Diff line change
Expand Up @@ -388,7 +388,7 @@ fn get_cores_with_threads(suri_pid: i32, sys: &mut SystemVar) {
}

pub fn kill_suricata(child: &mut Child) {
let end_timeout = Duration::from_secs(30);
let end_timeout = Duration::from_secs(300);
let pid = child.id();
let mut output = Command::new("sudo")
.arg("pkill")
Expand Down
4 changes: 2 additions & 2 deletions src/yaml.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1058,7 +1058,7 @@ fn parse_cpu_list(items: &[String]) -> Result<Vec<u64>, String> {
Ok(cpus)
}

fn expand_cpu_range(s: &str) -> Result<Vec<u64>, String> {
pub fn expand_cpu_range(s: &str) -> Result<Vec<u64>, String> {
let system_cpus = num_cpus::get();
let s = s.trim();
match s.split_once('-') {
Expand Down Expand Up @@ -1086,7 +1086,7 @@ fn expand_cpu_range(s: &str) -> Result<Vec<u64>, String> {
}
}

fn insert_cpu(s: &str, seen: &mut HashSet<u64>, cpus: &mut Vec<u64>) -> Result<(), String> {
pub fn insert_cpu(s: &str, seen: &mut HashSet<u64>, cpus: &mut Vec<u64>) -> Result<(), String> {
for cpu in expand_cpu_range(s)? {
if seen.insert(cpu) {
cpus.push(cpu);
Expand Down
4 changes: 2 additions & 2 deletions suriconf.yaml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
%YAML 1.1
---

suriconf-version: 1.1.0-dev
suriconf-version: 1.1.0-dev.2

suri-configuration: suricata.yaml
suricata-bin: /usr/bin/suricata
Expand Down Expand Up @@ -37,4 +37,4 @@ variables:
interface: eth0
capture_mode: af_packet # dpdk
max_memory_usage: 1 GiB
max_cpu_usage_vec: [0] # [0-6]
max_cpu_usage_vec: [0-2] # [0-6]
Loading