diff --git a/.github/workflows/unit-tests.yml b/.github/workflows/unit-tests.yml
index 6e88dc93f1..4751a43e25 100644
--- a/.github/workflows/unit-tests.yml
+++ b/.github/workflows/unit-tests.yml
@@ -37,6 +37,7 @@ jobs:
- test_whitelist.py
- test_arp.py
- test_arp_poisoner.py
+ - test_arp_filter.py
- test_blocking.py
- test_unblocker.py
- test_flow_handler.py
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index 3567eb858d..31cc6c5f75 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -43,3 +43,11 @@ repos:
- id: yamllint
args: ["-d", "{rules: {line-length: {max: 100}}}"]
files: "slips.yaml"
+
+- repo: local
+ hooks:
+ - id: vulture
+ name: vulture dead code check
+ entry: bash -c 'files=$(git diff --cached --name-only --diff-filter=ACM | grep -E "\.py$" | grep -vE "^(tests/|migrations/)"); [ -n "$files" ] && vulture --exclude "tests/*,venv/*" $files || true'
+ language: system
+ types: [python]
diff --git a/CHANGELOG.md b/CHANGELOG.md
index becc140b57..f07715f888 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,9 @@
+1.1.11 (July 3rd, 2025)
+- Fix local P2P trust model.
+- Fix SQLite cursor errors.
+- Avoid reporting own self or other slips peers when arp poisoning attackers.
+
+
1.1.10 (May 26, 2025)
- Add support for unblocking attackers using IP tables after a probation period.
- Add support for blocking attackers using ARP poisoning.
diff --git a/README.md b/README.md
index dfa9871c01..f06ba7f21b 100644
--- a/README.md
+++ b/README.md
@@ -1,5 +1,5 @@
-Slips v1.1.10
+Slips v1.1.11
diff --git a/VERSION b/VERSION
index 5ed5faa5f1..9ee1f786d5 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-1.1.10
+1.1.11
diff --git a/conftest.py b/conftest.py
index 3ce9d71fcf..b0178d1527 100644
--- a/conftest.py
+++ b/conftest.py
@@ -67,14 +67,6 @@ def profiler_queue():
profiler_queue.put = do_nothing
return profiler_queue
-
-@pytest.fixture
-def database():
- db = DBManager(Output(), "output/", 6379)
- db.print = do_nothing
- return db
-
-
@pytest.fixture
def flow():
"""returns a dummy flow for testing"""
diff --git a/docker/Dockerfile b/docker/Dockerfile
index 4482e786e9..a6731bce61 100644
--- a/docker/Dockerfile
+++ b/docker/Dockerfile
@@ -59,6 +59,7 @@ RUN apt update && apt install -y --no-install-recommends \
nano \
tree \
tmux \
+ arp-scan \
&& echo 'deb http://download.opensuse.org/repositories/security:/zeek/xUbuntu_22.04/ /' | tee /etc/apt/sources.list.d/security:zeek.list \
&& curl -fsSL https://download.opensuse.org/repositories/security:zeek/xUbuntu_22.04/Release.key | gpg --dearmor | tee /etc/apt/trusted.gpg.d/security_zeek.gpg > /dev/null \
&& apt update \
diff --git a/docs/create_new_module.md b/docs/create_new_module.md
index 3646c96cbb..2df387b024 100644
--- a/docs/create_new_module.md
+++ b/docs/create_new_module.md
@@ -365,7 +365,8 @@ import json
from slips_files.common.flow_classifier import FlowClassifier
from slips_files.core.structures.evidence import
- (
+
+(
Evidence,
ProfileID,
TimeWindow,
@@ -378,7 +379,7 @@ from slips_files.core.structures.evidence import
)
from slips_files.common.parsers.config_parser import ConfigParser
from slips_files.common.slips_utils import utils
-from slips_files.common.abstracts.module import IModule
+from slips_files.common.abstracts.imodule import IModule
class LocalConnectionDetector(
diff --git a/docs/images/immune/models_heatmap_rpi5_Q4.png b/docs/images/immune/models_heatmap_rpi5_Q4.png
new file mode 100644
index 0000000000..bf72412c38
Binary files /dev/null and b/docs/images/immune/models_heatmap_rpi5_Q4.png differ
diff --git a/docs/images/immune/models_score.png b/docs/images/immune/models_score.png
new file mode 100644
index 0000000000..7f25ae6ea1
Binary files /dev/null and b/docs/images/immune/models_score.png differ
diff --git a/docs/images/immune/perf_test_model.png b/docs/images/immune/perf_test_model.png
new file mode 100644
index 0000000000..c6624333f0
Binary files /dev/null and b/docs/images/immune/perf_test_model.png differ
diff --git a/docs/images/immune/trade_off.png b/docs/images/immune/trade_off.png
new file mode 100644
index 0000000000..7bfa9dfb55
Binary files /dev/null and b/docs/images/immune/trade_off.png differ
diff --git a/docs/images/slips.gif b/docs/images/slips.gif
index 2c0c1239ab..f4f92d4475 100644
Binary files a/docs/images/slips.gif and b/docs/images/slips.gif differ
diff --git a/docs/immune/Immune.md b/docs/immune/Immune.md
index 22263d2712..878555c3cd 100644
--- a/docs/immune/Immune.md
+++ b/docs/immune/Immune.md
@@ -5,4 +5,5 @@
- [Slips Compatibility In The RPI](https://stratospherelinuxips.readthedocs.io/en/develop/immune/reimplement_slips_features_incompatible_with_the_rpi.html)
- [Installing Slips On the RPI](https://stratospherelinuxips.readthedocs.io/en/develop/immune/installing_slips_in_the_rpi.html)
- [LLM Research and Selection](https://stratospherelinuxips.readthedocs.io/en/develop/immune/research_and_selection_of_llm_candidates.html)
+- [LLM RPI Performance](https://stratospherelinuxips.readthedocs.io/en/develop/immune/research_rpi_llm_performance.html)
- [ARP Poisoning](https://stratospherelinuxips.readthedocs.io/en/develop/immune/arp_poisoning.html)
diff --git a/docs/immune/research_rpi_llm_performance.md b/docs/immune/research_rpi_llm_performance.md
new file mode 100644
index 0000000000..7421e0e0f8
--- /dev/null
+++ b/docs/immune/research_rpi_llm_performance.md
@@ -0,0 +1,159 @@
+
+# Research and analysis of performance of LLM on the Raspberry Pi 5
+
+## Table of Contents
+ * [Inference Engines Considered on Raspberry Pi 5](#inference-engines-considered-on-raspberry-pi-5)
+ * [Performance on RPI](#performance-on-rpi)
+ - [System Resource Utilization](#system-resource-utilization)
+ - [Task-Specific Performance evaluation](#task-specific-performance-evaluation)
+ - [Per test Analysis](#per-test-analysis)
+ - [Overall Score](#overall-score)
+ * [Trade off analysis](#trade-off-analysis)
+ * [Finals remarks](#finals-remarks)
+ * [References](#references)
+
+## Inference Engines Considered on Raspberry Pi 5
+
+Several inference engines were evaluated for running language models efficiently on the Raspberry Pi 5. The key focus areas included CPU quantization support, inference speed, memory usage, and overall system stability under sustained workloads.
+
+`Ollama` was used as the initial baseline. It supports CPU and GUFF quantization and provides a simple interface for deploying models. However, in comparative testing, `llama.cpp`demonstrated slightly better performance. Although it shares a common foundation wit`h Ollama`, `llama.cpp` delivered improved inference speeds and more efficient use of system resources. These advantages, combined with active community support, led to its selection as the preferred engine for further development.
+
+[Transformers](https://huggingface.co/docs/transformers/en/index) from HuggingFace were also considered. Despite their popularity and flexibility, the lack of CPU quantization support made them impractical for the Raspberry Pi 5. Models were too large and slow for this constrained environment. Other engines built on similar foundations, such as [vLLM](https://docs.vllm.ai/en/latest/contributing/) solutions and frameworks like [unsloth](https://unsloth.ai/), faced similar limitations and were not pursued further.
+
+An additional engine, [bitnet.cpp](https://github.com/microsoft/BitNet), was tested for its innovative support of 1.58-bit quantization. It is tailored specifically for BitNet models, such as the [bitnet-b1.58-2B-4T](https://huggingface.co/microsoft/bitnet-b1.58-2B-4T). This engine provides fast and lossless inference optimized for CPUs and GPUs. BitNet models demonstrated strong potential on the Raspberry Pi 5, achieving around 8 tokens per second (TPS) with a low memory footprint. However, broader adoption is limited by the current lack of available models and incomplete fine-tuning support.
+
+The table below summarizes the characteristics of the main inference engines considered:
+
+| Engine | | CPU Quantization | | Speed (TPS) | | Memory Usage | Notes |
+|---------|---------|---------|---------|---------|---------|---------|---------|
+| Ollama | | Yes | | Moderate | | Moderate | Baseline engine; stable but slightly slower |
+| llama.cpp | | Yes | | Slightly higher | | Lower | Preferred engine; fast and efficient |
+| Transformers HF | | No | | Low | | High | Too large for RPi5 without quantization |
+| bitnet.cpp | | Yes (1.58-bit) | | High (\~10) | | Very low | Promising, but limited to BitNet models |
+| LLVM/insloth | | No | | N/A | | N/A | Experimental; no CPU quantization available |
+
+`Ollama` initially appeared to be the most balanced option, offering a good trade-off between performance, ease of management, and future upgradability. However, several limitations in its default configuration led to reconsideration. Since `Ollama` is under active development, many default settings are not optimized for low-resource environments like the Raspberry Pi 5. One major issue is that `Ollama` defaults to a context window of 4096 tokens for all models, regardless of their actual capabilities. This constraint can significantly limit performance on tasks requiring longer context lengths, and the discrepancy is only noticeable in runtime logs. To overcome this, the environment variable `OLLAMA_CONTEXT_LENGTH` must be manually configured to match the model's maximum context.
+
+Additionally, `Ollama` does not provide an intuitive way to control CPU thread usage. By default, it utilizes all four threads available on the Pi, which can be problematic when other lightweight background processes (such as system monitors or schedulers) need to run concurrently.
+
+As a result, `llama.cpp` was chosen as the primary inference engine for current use. Although slightly more complex to configure, it offers full control over parameters such as context length, thread count, and memory allocation. Performance benchmarks also show llama.cpp is approximately 10% to 20% faster than `Ollama`. While these limitations in `Ollama` may be resolved in future updates, llama.cpp currently provides better performance and configurability, making it the most suitable choice for sustained deployment on the Raspberry Pi 5.
+
+## Performance on RPI
+
+The performance analysis of LLMs on the Raspberry Pi 5 focuses on balancing **limited hardware resources** with the **effectiveness of each model across various tasks**. The goal is to identify models that offer the best trade-off between speed, memory usage, and task-specific accuracy within the constraints of the device.
+
+#### System Resource Utilization
+
+A [set of evaluation scripts](https://github.com/stratosphereips/Slips-tools/tree/main/benchmark_models) was developed to assess model performance on the Raspberry Pi 5. While the final deployment will use `llama.cpp`, all models were tested using the `Ollama` engine because it is simple to configure. The only exception was BitNet, which was tested using `bitnet.cpp` due to compatibility requirements.
+
+The script reports the quantization method used by each model, the tokens per second for a simple prompt, and the memory footprint. It was executed on the Raspberry Pi 5, and the results are summarized in the following table..
+
+| model | quantization | disk_size_mb | ram_size_mb | tokens_per_second |
+|:--------------|:--------------|--------------:|--------------:|--------------:|
+| qwen2.5:3b | Q4_K_M | 1840.5 | 3025.9 | 5.2 |
+| llama3.2:1b-instruct-q4_K_M | Q4_K_M | **770.3** | 2415.8 | 11.22 |
+| smollm2:1.7b-instruct-q4_K_M | Q4_K_M | 1006.7 | 5318.2 | 8.23 |
+| granite3.1-dense:2b | Q4_K_M | 1497 | 3697.7 | 5.81 |
+| llama3.2:3b | Q4_K_M | 1925.8 | 4659.3 | 4.69 |
+| qwen2.5:1.5b | Q4_K_M | 940.4 | 1849.3 | 9.97 |
+| gemma3:1b | Q4_K_M | 777.5 | **1393.8** | **11.53** |
+| bitnet-b1.58-2B-4T | Q1.5 | 1200 | 1500 | 8.13 |
+
+In summary, **gemma3:1b** stands out as the most efficient model, combining low resource usage with the highest token throughput, making it ideal for lightweight and responsive applications. Models like **llama3.2:1b-instruct** also perform well, offering strong speed-to-resource ratios. Overall, these models provide a good mix of efficiency and performance, allowing for flexible deployment depending on hardware constraints and task requirements.
+
+Smaller models like **gemma3:1b** and **qwen2.5:1.5b** offer the best balance of speed and low resource usage. While **3B models** like **llama3.2:3b** and **qwen2.5:3b** require more memory, **Qwen models** remain impressively efficient even at larger scales.
+
+In contrast, **smollm2:1.7b-instruct** has a high memory footprint (over 5 GB), making it less ideal for limited-resource environments like the Rpi.
+
+Finally, **BitNet B1.58 2B 4T** offers a good trade-off between memory footprint and tokens per second. Compared to other 2B models like **granite**, it has less than half the memory footprint while being approximately 1.5 times faster in token generation. The model is also competitive compared with models like **qwen2.5:1.5b**
+
+Overall, the **Qwen** models stand out for their strong performance combined with excellent memory efficiency, and **BitNet B1.58 2B 4T** emerges as a strong contender in this space.
+
+#### Task-Specific Performance evaluation
+
+To evaluate task-specific performance, [Promptfoo](https://www.promptfoo.dev/) [tests](https://github.com/stratosphereips/Slips-tools/tree/main/llm-unittest) were replicated on the Raspberry Pi 5. `Ollama` was used as the baseline engine via its OpenAI-compatible API. To accommodate the limitations of the RPi5, specific environment variables were configured during execution.
+
+##### Ollama Environment Variable Descriptions
+
+- **`OLLAMA_HOST=0.0.0.0:11434`**\
+ Sets the network address and port the Ollama server will bind to.
+
+ - `0.0.0.0` listens on all available network interfaces.
+ - `11434` is the port number.
+
+- **`OLLAMA_MAX_LOADED_MODELS=1`**\
+ Limits the number of models that can be loaded into memory simultaneously.\
+ Helps conserve memory by restricting model concurrency.
+
+- **`OLLAMA_MAX_QUEUE=2`**\
+ Sets the maximum number of queued requests waiting to be processed.\
+ Requests exceeding this limit may be delayed or rejected.
+
+- **`OLLAMA_KEEP_ALIVE=0`**\
+ Determines whether idle models remain loaded in memory.
+
+ - `0` disables keep-alive (unloads idle models). This setup was used for running the tests, because we found some issues with ollama automatic unloading.
+ - Another value, will save memory at the cost of reload time.
+
+- **`OLLAMA_DEBUG=1`**\
+ Enables debug mode for more verbose logging.\
+ Useful for development and troubleshooting trough `journalctl -f -b -u ollama`\`
+
+- **`OLLAMA_LOAD_TIMEOUT=60m0s`**\
+ Specifies the maximum amount of time to wait for a model to load.\
+ Set to **60 minutes** in this case, which is necessary because some models load very slowly on the Raspberry Pi. Without this extended timeout, tools like **Promptfoo** may prematurely terminate the connection.
+
+- **`OLLAMA_CONTEXT_LENGTH=8192`**\
+ Defines the maximum token context length that models can process. A length of `8192 tokens` supports long-form prompts or conversations. By default `ollama`\` uses `4096`\` in the Pi.
+
+The results of the `Promptfoo` tests are presented in the heatmap below. In addition to the previously evaluated models, BitNet B1.58 2B 4T was included using 1.58-bit quantization with `bitnet.cpp`. Note that not all models are compatible with 1.58-bit quantization.
+
+
+
+Results from Promptfoo on the Raspberry Pi 5 were consistent with those reported for x86 architecture.
+
+The test involving the function calling failed in most of the considered models except **BitNet B1.58 2B** 4T and **SmolLm2:1.7b.**
+
+The test involving the analysis of [Zeek logs](https://docs.zeek.org/en/master/logs/index.html) and performing classifications, failed across all models with 3B parameters, including **Qwen2.5 3B**. The failure is due to the test requiring the processing of a prompt of approximately 5000 tokens. At a generation rate of about 5 tokens per second, the test takes roughly 15 minutes to complete. `Promptfoo`, however, terminates the connection before the models can finish processing.
+
+#### Per test Analysis
+
+This analysis considers performance on a per-test basis, highlighting two key models: t**he overall best-performing mode**l, and **the best model capable of achieving at least 8 tokens per second**. The goal is to identify viable alternatives depending on specific needs. In some cases, speed may be the priority, while in others, accuracy or depth of understanding may take precedence. The choice of model will depend on the nature and requirements of each test.
+
+
+
+The chart shows that **Qwen2 models** consistently deliver the highest performance across most tasks, particularly in structured output scenarios like generating function calls or JSON data. However, when speed is a priority, **BitNet B1.58 2B 4**T emerges as a strong alternative, maintaining over 8 tokens per second while delivering reasonably competitive results. In tasks like interpreting or summarizing logs, **Gemma** and **Granite3.1** also show up, but less frequently. The narrow performance gap in many cases suggests that faster models like **BitNet B1.58 2B 4T** can often be used without significant loss in accuracy, offering a practical trade-off between speed and precision depending on task demands.
+
+#### Overall Score
+
+To simplify the overall analysis, a single performance score was calculated for each model by *averaging the results across all tests*. These mean scores are presented in the figure below, providing a clear comparison of overall model performance.
+
+
+
+As expected, the larger models such as **LLaMA 3.2 3B** and **Qwen2.5 3B** demonstrated the highest average score. These were followed by the 2B models, including Granite 3.1 Dense and **BitNet B1.58 2B 4T**, which also showed competitive results relative to their size.
+
+## Trade off analysis
+
+
+
+The figure below analyzes model performance using two key metrics: **overall score** and **tokens per second**. These highlight the balance between resource use and speed. Additionally, **RAM usage** is plotted to visualize each model’s memory footprint.
+
+This review highlights the balance between performance, speed, and resource usage across various language models. **Qwen2.5** models consistently lead in overall performance, especially in structured tasks, while maintaining good efficiency. In particular, **qwen2.5:1.5b** offers both high throughput and low memory consumption, making it a strong all-around choice. **Gemma3:1b-instruct** also shows solid efficiency, making it suitable for lightweight deployments.
+
+**BitNet B1.58 2B 4T** stands out for its exceptional memory efficiency, achieving over 8 tokens per second with one of the smallest RAM footprints. This makes it well-suited for environments with limited resources. In contrast, **Smollm2:1.7b-instruct** delivers reasonable performance but requires significantly more memory, which can limit its usability.
+
+Overall, Qwen models dominate in balanced performance. BitNet is ideal for fast, low-resource scenarios. The best model choice depends on the specific needs of each task, with some favoring speed and others requiring greater accuracy or capability.
+
+## Finals remarks
+
+`Llama.cpp` was chosen as the primary inference engine for production use. Although it requires a more complex setup, it provides full control over key parameters such as context length, thread count, and memory allocation. `Ollama` will continue to be used during development and testing due to its simplicity in managing models, but llama.cpp will be preferred for deployment.
+
+**Qwen** models stand out as the most effective overall. The **3B version** consistently achieves the highest average scores, making it ideal for tasks that prioritize accuracy. The **1.5B version** offers a strong balance between performance and speed, while maintaining a relatively low memory footprint. Rather than relying on a single model for all tasks, the strategy is to **adapt model selection based on specific requirements**. The combination of Qwen 3B and 1.5B allows for flexibility in choosing between higher accuracy and better efficiency as needed.
+
+**BitNet models** also show promise, especially in terms of speed and memory efficiency. However, the lack of a clear fine-tuning path limits their current utility. They will continue to be monitored, but for now, **Qwen models remain the preferred choice** for both versatility and reliability.
+
+## References
+
+[\[1\]](https://github.com/stratosphereips/Slips-tools/tree/main/benchmark_models) Scripts for testing hardware resources in Rpi5
+
+[\[2\]](https://github.com/stratosphereips/Slips-tools/tree/main/llm-unittest) Promptfoo tests
diff --git a/install/requirements.txt b/install/requirements.txt
index 47e1db470d..279e1cd167 100644
--- a/install/requirements.txt
+++ b/install/requirements.txt
@@ -19,11 +19,11 @@ psutil==7.0.0
six==1.17.0
pytest==8.3.5
pytest-mock==3.14.0
-pytest-xdist==3.6.1
+pytest-xdist==3.8.0
scipy==1.15.1
scikit-learn==1.6.1
GitPython==3.1.44
-protobuf==4.25.3
+protobuf==4.25.8
exclusiveprocess==0.9.4
pytest-dependency==0.6.0
whois==1.20240129.2
@@ -36,9 +36,10 @@ aid_hash
black==24.10.0
ruff==0.11.11
pre-commit==4.0.1
-coverage==7.8.1
+coverage==7.9.1
netifaces==0.11.0
scapy==2.6.1
pyyaml
pytest-asyncio
+vulture
git+https://github.com/SECEF/python-idmefv2.git
diff --git a/managers/process_manager.py b/managers/process_manager.py
index 5bd3067ccf..be02f42c0d 100644
--- a/managers/process_manager.py
+++ b/managers/process_manager.py
@@ -33,7 +33,7 @@
import modules
from modules.update_manager.update_manager import UpdateManager
from slips_files.common.slips_utils import utils
-from slips_files.common.abstracts.module import (
+from slips_files.common.abstracts.imodule import (
IModule,
)
@@ -106,6 +106,7 @@ def start_profiler_process(self):
self.main.redis_port,
self.termination_event,
self.main.args,
+ self.main.conf,
is_profiler_done=self.is_profiler_done,
profiler_queue=self.profiler_queue,
is_profiler_done_event=self.is_profiler_done_event,
@@ -127,6 +128,7 @@ def start_evidence_process(self):
self.main.redis_port,
self.evidence_handler_termination_event,
self.main.args,
+ self.main.conf,
)
evidence_process.start()
self.main.print(
@@ -145,6 +147,7 @@ def start_input_process(self):
self.main.redis_port,
self.termination_event,
self.main.args,
+ self.main.conf,
is_input_done=self.is_input_done,
profiler_queue=self.profiler_queue,
input_type=self.main.input_type,
@@ -389,6 +392,7 @@ def load_modules(self):
self.main.redis_port,
self.termination_event,
self.main.args,
+ self.main.conf,
)
module.start()
self.main.db.store_pid(module_name, int(module.pid))
@@ -444,6 +448,7 @@ def start_update_manager(self, local_files=False, ti_feeds=False):
self.main.redis_port,
multiprocessing.Event(),
self.main.args,
+ self.main.conf,
)
if local_files:
@@ -821,7 +826,7 @@ def shutdown_gracefully(self):
self.main.profilers_manager.cpu_profiler_release()
self.main.profilers_manager.memory_profiler_release()
- self.main.db.close_redis_and_sqlite()
+ self.main.db.close_all_dbs()
if graceful_shutdown:
print(
"[Process Manager] Slips shutdown gracefully\n",
diff --git a/modules/arp/arp.py b/modules/arp/arp.py
index 8b4bdde752..f6ae2567aa 100644
--- a/modules/arp/arp.py
+++ b/modules/arp/arp.py
@@ -8,10 +8,11 @@
from multiprocessing import Queue
from typing import List
+from modules.arp.filter import ARPEvidenceFilter
from slips_files.common.flow_classifier import FlowClassifier
from slips_files.common.parsers.config_parser import ConfigParser
from slips_files.common.slips_utils import utils
-from slips_files.common.abstracts.module import IModule
+from slips_files.common.abstracts.imodule import IModule
from slips_files.core.structures.evidence import (
Evidence,
ProfileID,
@@ -26,7 +27,7 @@
class ARP(IModule):
- # Name: short name of the module. Do not use spaces
+
name = "ARP"
description = "Detect ARP attacks"
authors = ["Alya Gomaa"]
@@ -64,6 +65,7 @@ def init(self):
# wait 10s for mmore arp scan evidence to come
self.time_to_wait = 10
self.is_zeek_running: bool = self.is_running_zeek()
+ self.evidence_filter = ARPEvidenceFilter(self.conf, self.args, self.db)
def read_configuration(self):
conf = ConfigParser()
@@ -247,7 +249,7 @@ def set_evidence_arp_scan(self, ts, profileid, twid, uids: List[str]):
timestamp=ts,
)
- self.db.set_evidence(evidence)
+ self.set_evidence(evidence)
# after we set evidence, clear the dict so we can detect if it
# does another scan
try:
@@ -315,7 +317,7 @@ def check_dstip_outside_localnet(self, twid, flow):
timestamp=flow.starttime,
victim=victim,
)
- self.db.set_evidence(evidence)
+ self.set_evidence(evidence)
return True
return False
@@ -357,7 +359,7 @@ def detect_unsolicited_arp(self, twid: str, flow):
timestamp=flow.starttime,
)
- self.db.set_evidence(evidence)
+ self.set_evidence(evidence)
return True
def detect_mitm_arp_attack(self, twid: str, flow):
@@ -460,7 +462,7 @@ def detect_mitm_arp_attack(self, twid: str, flow):
victim=victim,
)
- self.db.set_evidence(evidence)
+ self.set_evidence(evidence)
return True
def check_if_gratutitous_arp(self, flow):
@@ -514,6 +516,13 @@ def clear_arp_logfile(self):
# update ts of the new arp.log
self.arp_log_creation_time = time.time()
+ def set_evidence(self, evidence: Evidence):
+ """the goal of this function is to discard evidence of other slips
+ peers doing arp scans because that's slips attacking back attackers"""
+ if self.evidence_filter.should_discard_evidence(evidence.profile.ip):
+ return
+ self.db.set_evidence(evidence)
+
def pre_main(self):
"""runs once before the main() is executed in a loop"""
utils.drop_root_privs()
diff --git a/modules/arp/filter.py b/modules/arp/filter.py
new file mode 100644
index 0000000000..5e67e79123
--- /dev/null
+++ b/modules/arp/filter.py
@@ -0,0 +1,58 @@
+from typing import List
+
+from slips_files.common.slips_utils import utils
+from slips_files.core.database.database_manager import DBManager
+
+
+class ARPEvidenceFilter:
+ """
+ A class to filter ARP evidence coming from a peer slips.
+ Slips uses arp poisoning, arp spoofing, and arp scans to discover
+ attackers and isolate them from the network, we don't want this
+ instance of Slips to block other Slips instances, so we discard
+ evidence about other slips attacking.
+ """
+
+ def __init__(self, conf, slips_args, db: DBManager):
+ self.db = db
+ self.conf = conf
+ self.args = slips_args
+ # p2p needs to be enabled for slips to be able to recognize slips peers
+ self.p2p_enabled = False
+ if self.conf.use_local_p2p():
+ self.p2p_enabled = True
+ self.our_ips: List[str] = utils.get_own_ips(ret="List")
+
+ def should_discard_evidence(self, ip: str) -> bool:
+ return self.is_slips_peer(ip) or self.is_self_defense(ip)
+
+ def is_self_defense(self, ip: str):
+ """
+ slips uses arp poison to defend itself and th enetwork,
+ check arp_poison.py for more details.
+ goal of this function is to discard evidence about slips doing arp
+ attacks when it's just attacking attackers
+ """
+ loaded_modules = self.db.get_pids().keys()
+ return (
+ ip in self.our_ips
+ and self.args.blocking
+ and "ARP Poisoner" in loaded_modules
+ )
+
+ def is_slips_peer(self, ip: str) -> bool:
+ """
+ Check if the given IP address is a trusted Slips peer.
+ Trust here is defined from the p2p network (trust model).
+ Only works if the local p2p is enabled.
+
+ :param ip: The IP address to check.
+ """
+ if not self.p2p_enabled or not utils.is_private_ip(ip):
+ return False
+
+ trust = self.db.get_peer_trust(ip)
+ if not trust:
+ return False
+
+ return trust >= 0.3
diff --git a/modules/arp_poisoner/arp_poisoner.py b/modules/arp_poisoner/arp_poisoner.py
index bc14402ba9..dc72bfb8d5 100644
--- a/modules/arp_poisoner/arp_poisoner.py
+++ b/modules/arp_poisoner/arp_poisoner.py
@@ -12,7 +12,7 @@
from scapy.all import ARP, Ether
from scapy.sendrecv import sendp, srp
-from slips_files.common.abstracts.module import IModule
+from slips_files.common.abstracts.imodule import IModule
from modules.arp_poisoner.unblocker import ARPUnblocker
from slips_files.common.slips_utils import utils
@@ -195,6 +195,7 @@ def _arp_poison(self, target_ip: str, first_time=False):
repoisoning every x seconds.
"""
fake_mac = "aa:aa:aa:aa:aa:aa"
+
# it makes sense here to get the mac using cache, because if we
# reached this function, means there's an alert, means slips seen
# traffic from that target_ip and has itsmac in the arp cache.
diff --git a/modules/arp_poisoner/unblocker.py b/modules/arp_poisoner/unblocker.py
index ba02ed32b1..ee3defc0ed 100644
--- a/modules/arp_poisoner/unblocker.py
+++ b/modules/arp_poisoner/unblocker.py
@@ -1,7 +1,7 @@
from threading import Lock
import time
from typing import Callable, Optional
-from slips_files.common.abstracts.unblocker import IUnblocker
+from slips_files.common.abstracts.iunblocker import IUnblocker
from slips_files.common.printer import Printer
from slips_files.common.slips_utils import utils
from slips_files.core.structures.evidence import TimeWindow
diff --git a/modules/blocking/blocking.py b/modules/blocking/blocking.py
index 376e6620d9..35aaa3b70b 100644
--- a/modules/blocking/blocking.py
+++ b/modules/blocking/blocking.py
@@ -10,7 +10,7 @@
import time
from threading import Lock
-from slips_files.common.abstracts.module import IModule
+from slips_files.common.abstracts.imodule import IModule
from slips_files.common.slips_utils import utils
from .exec_iptables_cmd import exec_iptables_command
from modules.blocking.unblocker import Unblocker
diff --git a/modules/blocking/unblocker.py b/modules/blocking/unblocker.py
index e39d195d91..68f6bcfcf1 100644
--- a/modules/blocking/unblocker.py
+++ b/modules/blocking/unblocker.py
@@ -2,7 +2,7 @@
import time
import threading
from typing import Dict, Callable
-from slips_files.common.abstracts.unblocker import IUnblocker
+from slips_files.common.abstracts.iunblocker import IUnblocker
from slips_files.common.printer import Printer
from slips_files.common.slips_utils import utils
from slips_files.core.structures.evidence import TimeWindow
diff --git a/modules/cesnet/cesnet.py b/modules/cesnet/cesnet.py
index 399763fd52..55db0796b8 100644
--- a/modules/cesnet/cesnet.py
+++ b/modules/cesnet/cesnet.py
@@ -9,7 +9,7 @@
import validators
from slips_files.common.parsers.config_parser import ConfigParser
-from slips_files.common.abstracts.module import IModule
+from slips_files.common.abstracts.imodule import IModule
from slips_files.core.structures.evidence import (
ThreatLevel,
Evidence,
diff --git a/modules/cyst/cyst.py b/modules/cyst/cyst.py
index da10bb3017..d43631f155 100644
--- a/modules/cyst/cyst.py
+++ b/modules/cyst/cyst.py
@@ -1,6 +1,6 @@
# SPDX-FileCopyrightText: 2021 Sebastian Garcia
# SPDX-License-Identifier: GPL-2.0-only
-from slips_files.common.abstracts.module import IModule
+from slips_files.common.abstracts.imodule import IModule
import socket
import json
import os
diff --git a/modules/exporting_alerts/exporting_alerts.py b/modules/exporting_alerts/exporting_alerts.py
index 94ebff6260..3390b4408b 100644
--- a/modules/exporting_alerts/exporting_alerts.py
+++ b/modules/exporting_alerts/exporting_alerts.py
@@ -5,7 +5,7 @@
from modules.exporting_alerts.slack_exporter import SlackExporter
from modules.exporting_alerts.stix_exporter import StixExporter
from slips_files.common.slips_utils import utils
-from slips_files.common.abstracts.module import IModule
+from slips_files.common.abstracts.imodule import IModule
class ExportingAlerts(IModule):
diff --git a/modules/exporting_alerts/slack_exporter.py b/modules/exporting_alerts/slack_exporter.py
index 595362c74f..4ac48d6dc7 100644
--- a/modules/exporting_alerts/slack_exporter.py
+++ b/modules/exporting_alerts/slack_exporter.py
@@ -3,7 +3,7 @@
from slack import WebClient
from slack.errors import SlackApiError
from slips_files.common.slips_utils import utils
-from slips_files.common.abstracts.exporter import IExporter
+from slips_files.common.abstracts.iexporter import IExporter
from slips_files.common.parsers.config_parser import ConfigParser
diff --git a/modules/exporting_alerts/stix_exporter.py b/modules/exporting_alerts/stix_exporter.py
index 457ac1abd7..1833258983 100644
--- a/modules/exporting_alerts/stix_exporter.py
+++ b/modules/exporting_alerts/stix_exporter.py
@@ -6,7 +6,7 @@
import threading
import os
-from slips_files.common.abstracts.exporter import IExporter
+from slips_files.common.abstracts.iexporter import IExporter
from slips_files.common.parsers.config_parser import ConfigParser
from slips_files.common.slips_utils import utils
diff --git a/modules/fidesModule/fidesModule.py b/modules/fidesModule/fidesModule.py
index a4817f6f97..54da822267 100644
--- a/modules/fidesModule/fidesModule.py
+++ b/modules/fidesModule/fidesModule.py
@@ -1,10 +1,9 @@
import os
import json
-from dataclasses import asdict
from pathlib import Path
from slips_files.common.slips_utils import utils
-from slips_files.common.abstracts.module import IModule
+from slips_files.common.abstracts.imodule import IModule
from slips_files.common.parsers.config_parser import (
ConfigParser,
)
@@ -12,11 +11,10 @@
dict_to_alert,
Alert,
)
-from .messaging.model import NetworkMessage
from ..fidesModule.messaging.message_handler import MessageHandler
from ..fidesModule.messaging.network_bridge import NetworkBridge
from ..fidesModule.model.configuration import load_configuration
-from ..fidesModule.model.threat_intelligence import SlipsThreatIntelligence, ThreatIntelligence
+from ..fidesModule.model.threat_intelligence import SlipsThreatIntelligence
from ..fidesModule.protocols.alert import AlertProtocol
from ..fidesModule.protocols.initial_trusl import InitialTrustProtocol
from ..fidesModule.protocols.opinion import OpinionAggregator
@@ -26,15 +24,13 @@
ThreatIntelligenceProtocol,
)
from ..fidesModule.utils.logger import LoggerPrintCallbacks
-from ..fidesModule.messaging.redis_simplex_queue import RedisSimplexQueue, RedisDuplexQueue
+from ..fidesModule.messaging.redis_simplex_queue import RedisSimplexQueue
from ..fidesModule.persistence.threat_intelligence_db import (
SlipsThreatIntelligenceDatabase,
)
from ..fidesModule.persistence.trust_db import SlipsTrustDatabase
from ..fidesModule.persistence.sqlite_db import SQLiteDB
-from ..fidesModule.model.alert import Alert as FidesAlert
-
class FidesModule(IModule):
"""
diff --git a/modules/flowalerts/conn.py b/modules/flowalerts/conn.py
index bf5a428a12..1519601c06 100644
--- a/modules/flowalerts/conn.py
+++ b/modules/flowalerts/conn.py
@@ -9,7 +9,7 @@
import validators
from modules.flowalerts.dns import DNS
-from slips_files.common.abstracts.flowalerts_analyzer import (
+from slips_files.common.abstracts.iflowalerts_analyzer import (
IFlowalertsAnalyzer,
)
from slips_files.common.parsers.config_parser import ConfigParser
@@ -40,7 +40,7 @@ def init(self):
self.dns_analyzer = DNS(self.db, flowalerts=self)
self.is_running_non_stop: bool = self.db.is_running_non_stop()
self.classifier = FlowClassifier()
- self.our_ips: List[str] = utils.get_own_ips(ret=List)
+ self.our_ips: List[str] = utils.get_own_ips(ret="List")
self.input_type: str = self.db.get_input_type()
self.multiple_reconnection_attempts_threshold = 5
# we use this to try to detect if there's dns server that has a
diff --git a/modules/flowalerts/dns.py b/modules/flowalerts/dns.py
index b4cca77289..bc8a42ce37 100644
--- a/modules/flowalerts/dns.py
+++ b/modules/flowalerts/dns.py
@@ -16,7 +16,7 @@
from multiprocessing import Queue
from threading import Thread, Event
-from slips_files.common.abstracts.flowalerts_analyzer import (
+from slips_files.common.abstracts.iflowalerts_analyzer import (
IFlowalertsAnalyzer,
)
from slips_files.common.flow_classifier import FlowClassifier
@@ -40,7 +40,7 @@ def init(self):
self.arpa_scan_threshold = 10
self.is_running_non_stop: bool = self.db.is_running_non_stop()
self.classifier = FlowClassifier()
- self.our_ips: List[str] = utils.get_own_ips(ret=List)
+ self.our_ips: List[str] = utils.get_own_ips(ret="List")
# In mins
self.dns_without_conn_interface_wait_time = 30
# to store dns queries that we should check later. the purpose of
diff --git a/modules/flowalerts/downloaded_file.py b/modules/flowalerts/downloaded_file.py
index 8a14eb4151..066057cb6e 100644
--- a/modules/flowalerts/downloaded_file.py
+++ b/modules/flowalerts/downloaded_file.py
@@ -2,7 +2,7 @@
# SPDX-License-Identifier: GPL-2.0-only
import json
-from slips_files.common.abstracts.flowalerts_analyzer import (
+from slips_files.common.abstracts.iflowalerts_analyzer import (
IFlowalertsAnalyzer,
)
from slips_files.common.flow_classifier import FlowClassifier
diff --git a/modules/flowalerts/flowalerts.py b/modules/flowalerts/flowalerts.py
index dc132058dd..92368027b5 100644
--- a/modules/flowalerts/flowalerts.py
+++ b/modules/flowalerts/flowalerts.py
@@ -6,7 +6,7 @@
from typing import List
from slips_files.common.slips_utils import utils
-from slips_files.common.abstracts.async_module import AsyncModule
+from slips_files.common.abstracts.iasync_module import AsyncModule
from .conn import Conn
from .dns import DNS
from .downloaded_file import DownloadedFile
diff --git a/modules/flowalerts/notice.py b/modules/flowalerts/notice.py
index 959a6ed4d9..ff5259a638 100644
--- a/modules/flowalerts/notice.py
+++ b/modules/flowalerts/notice.py
@@ -2,7 +2,7 @@
# SPDX-License-Identifier: GPL-2.0-only
import json
-from slips_files.common.abstracts.flowalerts_analyzer import (
+from slips_files.common.abstracts.iflowalerts_analyzer import (
IFlowalertsAnalyzer,
)
from slips_files.common.flow_classifier import FlowClassifier
diff --git a/modules/flowalerts/smtp.py b/modules/flowalerts/smtp.py
index a73ecb9308..0511682044 100644
--- a/modules/flowalerts/smtp.py
+++ b/modules/flowalerts/smtp.py
@@ -3,7 +3,7 @@
import json
-from slips_files.common.abstracts.flowalerts_analyzer import (
+from slips_files.common.abstracts.iflowalerts_analyzer import (
IFlowalertsAnalyzer,
)
from slips_files.common.slips_utils import utils
diff --git a/modules/flowalerts/software.py b/modules/flowalerts/software.py
index 2274a6bd8b..8258e599f3 100644
--- a/modules/flowalerts/software.py
+++ b/modules/flowalerts/software.py
@@ -2,7 +2,7 @@
# SPDX-License-Identifier: GPL-2.0-only
import json
-from slips_files.common.abstracts.flowalerts_analyzer import (
+from slips_files.common.abstracts.iflowalerts_analyzer import (
IFlowalertsAnalyzer,
)
from slips_files.common.flow_classifier import FlowClassifier
diff --git a/modules/flowalerts/ssh.py b/modules/flowalerts/ssh.py
index f134806e6b..f526a16ace 100644
--- a/modules/flowalerts/ssh.py
+++ b/modules/flowalerts/ssh.py
@@ -3,7 +3,7 @@
import asyncio
import json
-from slips_files.common.abstracts.flowalerts_analyzer import (
+from slips_files.common.abstracts.iflowalerts_analyzer import (
IFlowalertsAnalyzer,
)
from slips_files.common.flow_classifier import FlowClassifier
diff --git a/modules/flowalerts/ssl.py b/modules/flowalerts/ssl.py
index e4bb7cec2a..e71850e677 100644
--- a/modules/flowalerts/ssl.py
+++ b/modules/flowalerts/ssl.py
@@ -9,7 +9,7 @@
import time
from multiprocessing import Lock
import tldextract
-from slips_files.common.abstracts.flowalerts_analyzer import (
+from slips_files.common.abstracts.iflowalerts_analyzer import (
IFlowalertsAnalyzer,
)
from slips_files.common.flow_classifier import FlowClassifier
diff --git a/modules/flowalerts/tunnel.py b/modules/flowalerts/tunnel.py
index 340a32dbb4..346e6f23f4 100644
--- a/modules/flowalerts/tunnel.py
+++ b/modules/flowalerts/tunnel.py
@@ -2,7 +2,7 @@
# SPDX-License-Identifier: GPL-2.0-only
import json
-from slips_files.common.abstracts.flowalerts_analyzer import (
+from slips_files.common.abstracts.iflowalerts_analyzer import (
IFlowalertsAnalyzer,
)
from slips_files.common.slips_utils import utils
diff --git a/modules/flowmldetection/flowmldetection.py b/modules/flowmldetection/flowmldetection.py
index e44ac83f4d..5ca5a2425b 100644
--- a/modules/flowmldetection/flowmldetection.py
+++ b/modules/flowmldetection/flowmldetection.py
@@ -13,7 +13,7 @@
from slips_files.common.parsers.config_parser import ConfigParser
from slips_files.common.slips_utils import utils
-from slips_files.common.abstracts.module import IModule
+from slips_files.common.abstracts.imodule import IModule
from slips_files.core.structures.evidence import (
Evidence,
ProfileID,
diff --git a/modules/http_analyzer/http_analyzer.py b/modules/http_analyzer/http_analyzer.py
index 9772e733ee..e9423b378a 100644
--- a/modules/http_analyzer/http_analyzer.py
+++ b/modules/http_analyzer/http_analyzer.py
@@ -13,7 +13,7 @@
from slips_files.common.flow_classifier import FlowClassifier
from slips_files.common.parsers.config_parser import ConfigParser
from slips_files.common.slips_utils import utils
-from slips_files.common.abstracts.async_module import AsyncModule
+from slips_files.common.abstracts.iasync_module import AsyncModule
ESTAB = "Established"
diff --git a/modules/ip_info/ip_info.py b/modules/ip_info/ip_info.py
index 3a4a276ccb..9ec5d6ab89 100644
--- a/modules/ip_info/ip_info.py
+++ b/modules/ip_info/ip_info.py
@@ -26,7 +26,7 @@
from slips_files.common.flow_classifier import FlowClassifier
from slips_files.core.helpers.whitelist.whitelist import Whitelist
from .asn_info import ASN
-from slips_files.common.abstracts.async_module import AsyncModule
+from slips_files.common.abstracts.iasync_module import AsyncModule
from slips_files.common.slips_utils import utils
from slips_files.core.structures.evidence import (
Evidence,
diff --git a/modules/irisModule/irisModule.py b/modules/irisModule/irisModule.py
index eed75559d5..2e766e4b21 100644
--- a/modules/irisModule/irisModule.py
+++ b/modules/irisModule/irisModule.py
@@ -4,7 +4,7 @@
from slips_files.common.parsers.config_parser import ConfigParser
-from slips_files.common.abstracts.module import IModule
+from slips_files.common.abstracts.imodule import IModule
import json
import os
import subprocess
@@ -61,7 +61,7 @@ def _iris_configurator(self, config_path: str, redis_port: int):
"Tl2NlChannel": "iris_internal",
}
if "Server" in config:
- #config["Server"]["Port"] = 9010
+ # config["Server"]["Port"] = 9010
config["Server"]["Host"] = self.db.get_host_ip()
config["Server"]["DhtServerMode"] = "true"
else:
diff --git a/modules/leak_detector/leak_detector.py b/modules/leak_detector/leak_detector.py
index fa202f70bf..0b72a0443d 100644
--- a/modules/leak_detector/leak_detector.py
+++ b/modules/leak_detector/leak_detector.py
@@ -15,7 +15,7 @@
from uuid import uuid4
from slips_files.common.slips_utils import utils
-from slips_files.common.abstracts.module import IModule
+from slips_files.common.abstracts.imodule import IModule
from slips_files.core.structures.evidence import (
Evidence,
ProfileID,
diff --git a/modules/network_discovery/network_discovery.py b/modules/network_discovery/network_discovery.py
index 8afa80d692..da2f1c0c9a 100644
--- a/modules/network_discovery/network_discovery.py
+++ b/modules/network_discovery/network_discovery.py
@@ -5,7 +5,7 @@
from slips_files.common.flow_classifier import FlowClassifier
from slips_files.common.slips_utils import utils
-from slips_files.common.abstracts.module import IModule
+from slips_files.common.abstracts.imodule import IModule
from modules.network_discovery.horizontal_portscan import HorizontalPortscan
from modules.network_discovery.vertical_portscan import VerticalPortscan
from slips_files.core.structures.evidence import (
diff --git a/modules/p2ptrust/p2ptrust.py b/modules/p2ptrust/p2ptrust.py
index ef357db919..9935cae8b4 100644
--- a/modules/p2ptrust/p2ptrust.py
+++ b/modules/p2ptrust/p2ptrust.py
@@ -6,14 +6,13 @@
import signal
import subprocess
import time
-from pathlib import Path
from typing import Dict, Optional, Tuple
import json
import socket
from slips_files.common.parsers.config_parser import ConfigParser
from slips_files.common.slips_utils import utils
-from slips_files.common.abstracts.module import IModule
+from slips_files.common.abstracts.imodule import IModule
import modules.p2ptrust.trust.base_model as reputation_model
import modules.p2ptrust.trust.trustdb as trustdb
import modules.p2ptrust.utils.utils as p2p_utils
@@ -83,25 +82,21 @@ class Trust(IModule):
pigeon_binary = os.path.join(os.getcwd(), "p2p4slips/p2p4slips")
pigeon_key_file = "pigeon.keys"
rename_redis_ip_info = False
- rename_sql_db_file = False
override_p2p = False
def init(self, *args, **kwargs):
- output_dir = self.db.get_output_dir()
- # flag to ensure slips prints multiaddress only once
- self.mutliaddress_printed = False
- self.pigeon_logfile_raw = os.path.join(output_dir, "p2p.log")
-
- self.p2p_reports_logfile = os.path.join(output_dir, "p2p_reports.log")
- # pigeon generate keys and stores them in the following dir, if this is placed in the