Goal: Detect distributed denial-of-service (DDoS) attacks by analyzing traffic flow anomalies using flow-level features (packet rate, SYN flags, etc.).
Example Scenario: A SYN flood attack begins targeting a public-facing web server. Suddenly, the number of incoming packets per second spikes, SYN flag counts increase dramatically, and the server is overwhelmed by half-open connections. This deviates from normal traffic patterns, which are stable and predictable during regular hours. For instance, a web server normally receives 200 requests/minute, but under attack, this reaches 10,000/minute, mostly SYNs without completing handshakes.
To simulate today’s DDoS traffic data and feed it into Wazuh Anomaly Detection, we use a date-shifting ingestion script located in ddos_detection/wazuh_ingest.py. Run it from the soar-radar root:
python3 ./ddos_detection/wazuh_ingest.py
@timestamp (ISO), and event_hourwazuh-ad-ddos-detection-YYYY.MM.DDwazuh-ad-ddos-detection-*@timestamp (datetime)Source_IP, Destination_IP, and traffic features (e.g., Flow_Packets_s, SYN_Flag_Count)ddos-detectorwazuh-ad-ddos-detection-*@timestamp5m with 1m window delayflow_packets_per_second – average – field: Flow_Packets_s
flow_bytes_per_second – average – field: Flow_Bytes_s
syn_flag_count – sum – field: SYN_Flag_Count
packet_length_average – average – field: Packet_Length_Mean
total_bwd_packets – average – field: Total_Backward_Packets
Enable the Categorical field option and select Destination_IP.keyword.
This builds a separate anomaly model per destination IP (victim). Each host is monitored independently, allowing for better sensitivity to changes in its own traffic pattern.
Click Next and Create. The detector validates features and starts model training.
ddos-detector page, click Set up alertDDoS-Detectedanomaly_grade >= 0.8 and confidence >= 0.85
http://<wazuh-manager>:8888/opensearch-alert{
"monitor": {"name": ""},
"trigger": {"name": ""},
"entity": "",
"periodStart": "",
"periodEnd": ""
}
Deploy the ad_alerts_webhook.py listener from webhook/ in the Wazuh manager:
python3 webhook/ad_alerts_webhook.py
Log file: /var/log/ad_alerts.log
Configure Wazuh to watch it:
<localfile>
<log_format>syslog</log_format>
<location>/var/log/ad_alerts.log</location>
</localfile>
Add the content of the file local_decoder.xml in this repository into the file /var/ossec/etc/decoders/local_decoder.xml in the Wazuh manager.
Add the content of the file local_rules.xml in this repository into the file /var/ossec/etc/rules/local_rules.xml in the Wazuh manager.
var/ossec/bin/wazuh-control restart in Docker or systemctl restart wazuh-manager)./var/log/ad_alerts.log.ossec.conf:<command>
<name>ad_enrich</name>
<executable>ad_context_ddos_active_response.py</executable>
<timeout_allowed>yes</timeout_allowed>
</command>
<active-response>
<disabled>no</disabled>
<command>ad_enrich</command>
<location>server</location>
<rules_id>100303</rules_id>
<timeout>120</timeout>
</active-response>
ad_context_ddos_active_response.py to /var/ossec/active-response/bin and make executable.requests module.pip3 install requests
chmod 750 /var/ossec/active-response/bin/ad_context_ddos_active_response.py
chown root:wazuh /var/ossec/active-response/bin/ad_context_ddos_active_response.py
/var/ossec/bin/wazuh-control restart
To prepare Wazuh agents to handle contextual logging and active defense during DDoS detection:
Edit (or create if missing) the file:
/var/ossec/etc/local_internal_options.conf
Add the following line:
wazuh_command.remote_commands=1
sudo touch /var/ossec/logs/ad_pc_enriched.log
sudo chown root:wazuh /var/ossec/logs/ad_pc_enriched.log
sudo chmod 664 /var/ossec/logs/ad_pc_enriched.log
Copy the scripts to the agent’s AR directory:
sudo cp write_contextual_logs_ddos_active_response.sh /var/ossec/active-response/bin/
sudo cp rate_limit.sh /var/ossec/active-response/bin/
sudo chown root:wazuh /var/ossec/active-response/bin/write_contextual_logs_ddos_active_response.sh
sudo chmod 750 /var/ossec/active-response/bin/write_contextual_logs_ddos_active_response.sh
sudo chown root:wazuh /var/ossec/active-response/bin/rate_limit.sh
sudo chmod 750 /var/ossec/active-response/bin/rate_limit.sh
ossec.confEdit the agent’s /var/ossec/etc/ossec.conf and ensure the following is added inside <ossec_config>:
<command>
<name>write_contextual_logs_ddos_active_response.sh</name>
<executable>write_contextual_logs_ddos_active_response.sh</executable>
<timeout_allowed>yes</timeout_allowed>
</command>
<command>
<name>rate_limit.sh</name>
<executable>rate_limit.sh</executable>
<timeout_allowed>yes</timeout_allowed>
</command>
sudo systemctl restart wazuh-agent
This completes the setup for executing rate limiting, firewall dropping, and logging actions on agents when a DDoS anomaly is detected.
To minimize the operational risk while still responding decisively to confirmed threats, this setup implements a two-tier active response strategy for DDoS:
Trigger condition:
Response actions:
write_contextual_logs_ddos_active_response.sh to store detailed traffic data from each source IP into ad_pc_enriched.log for later analysis.rate_limit.sh to apply iptables-based rate limiting for the source IPs that participated in the anomaly window.This tier prioritizes observation and mitigation without outright denial of traffic, helping analysts assess intent before escalation.
Trigger Condition:
Response actions:
firewall_drop.sh to block offending IPs at the iptables level via a DROP rule.This level is reserved for confirmed, high-confidence DDoS attacks.
ip_keywordperiod_startperiod_endQuery events: The server-side script queries OpenSearch for all flow logs matching the anomaly window and destination IP.
Resolve agent: From the destination IP, the system maps to a Wazuh agent using the API. This becomes the enforcement point.
Identify source IPs:
The script extracts all unique Source_IP fields from the matched flows — these are potential attackers.
Source_IP:
rate_limit.shfirewall_drop.shLog Enrichment:
Additionally, one contextual log is sent to the agent via write_contextual_logs_ddos_active_response.sh for the entire event set.
Since hashlimit is unsupported on WSL, the script falls back to limit with per-IP filtering. Example inserted rule:
ACCEPT tcp -- 172.16.0.9 0.0.0.0/0 tcp dpt:80 limit: avg 20/min burst 10
Rules can be removed via:
sudo iptables -D INPUT <rule-number>
In a scenario where a public-facing web server is subjected to a SYN‑flood or volumetric DDoS attack, we model the risk using the classical risk formulation:
R = C × I
Here, C is the anomaly detection model’s confidence score, used as a direct proxy for the likelihood of a genuine attack, and I is the impact severity, determined via the Common Vulnerability Scoring System (CVSS). Although CVSS traditionally applies to software vulnerabilities, its framework for quantifying impact via the Confidentiality‑Integrity‑Availability (CIA) triad has been adapted in research to assess the severity of denial‑of‑service incidents based on availability impact .
In the DDoS scenario, the characteristics are:
This aligns with a high‑severity profile under CVSS, reflected in documented examples where a full denial of service yields a Base Score ≈ 9.0 . Accordingly, we assign:
I = 9.0
Thus, the risk score computes as:
R = C × 9.0
Under this tiering scheme, high-confidence detections of traffic anomalies that suggest a volumetric flood generate elevated risk scores (close to 9.0) and should typically fall into Tier 3, prompting immediate mitigation. This methodology ensures that alert prioritization remains statistically grounded, transparent, and aligned with the classical risk principle Likelihood × Impact, applying detection certainty and standardized severity consistently across distinct threat types.
The dataset used is the CIC-DDoS2019 dataset, specifically the SYN flood CSVs. These are publicly available from https://www.unb.ca/cic/datasets/ddos-2019.html. The data was shifted and ingested to simulate modern traffic patterns for anomaly-based detection.