Wazuh is a free, open-source security monitoring platform that provides intrusion detection, compliance checks, log analysis, and vulnerability detection. It consists of a manager, agents, and an indexer/dashboard based on the ELK stack.
| Component | File/Directory | Path | Purpose |
|---|---|---|---|
| Manager main | /var/ossec/etc/ossec.conf |
Main Wazuh manager configuration | |
| Manager internal | /var/ossec/etc/internal_options.conf |
Internal tuning options | |
| Manager local | /var/ossec/etc/local_internal_options.conf |
Local overrides | |
| Rules | /var/ossec/etc/rules/ |
Detection rules | |
| Decoders | /var/ossec/etc/decoders/ |
Log decoders | |
| Agent config | /var/ossec/etc/ossec.conf |
Agent configuration (same path) | |
| Agent auth | /var/ossec/etc/client.keys |
Agent authentication keys | |
| SSL certificates | /var/ossec/etc/sslmanager.cert |
Manager SSL certificate | |
| SSL key | /var/ossec/etc/sslmanager.key |
Manager SSL key | |
| Rootcheck | /var/ossec/etc/shared/rootcheck.txt |
Rootcheck configuration | |
| Syscheck | /var/ossec/etc/shared/syscheck.conf |
File integrity monitoring | |
| Active response | /var/ossec/etc/shared/active-response.conf |
Active response scripts | |
| Logs | /var/ossec/logs/ |
Wazuh log files | |
| Queue | /var/ossec/queue/ |
Internal queues | |
| Indexer config | /etc/wazuh-indexer/opensearch.yml |
Wazuh indexer configuration | |
| Dashboard config | /etc/wazuh-dashboard/opensearch_dashboards.yml |
Dashboard configuration | |
| API config | /var/ossec/api/configuration/api.yaml |
Wazuh API configuration |
<!-- /var/ossec/etc/ossec.conf -->
<ossec_config>
<!-- Global settings -->
<global>
<jsonout_output>yes</jsonout_output>
<alerts_log>yes</alerts_log>
<logall>no</logall>
<logall_json>no</logall_json>
<email_notification>yes</email_notification>
<smtp_server>smtp.example.com</smtp_server>
<email_from>wazuh@example.com</email_from>
<email_to>admin@example.com</email_to>
<email_maxperhour>12</email_maxperhour>
<email_log_source>alerts.log</email_log_source>
<agents_disconnection_time>10m</agents_disconnection_time>
<agents_disconnection_alert_time>0</agents_disconnection_alert_time>
</global>
<!-- Alerts configuration -->
<alerts>
<log_alert_level>3</log_alert_level>
<email_alert_level>7</email_alert_level>
<email_alerts_maxperhour>12</email_alerts_maxperhour>
<email_log_source>alerts.log</email_log_source>
</alerts>
<!-- Remote connection settings -->
<remote>
<connection>secure</connection>
<port>1514</port>
<protocol>tcp</protocol>
<queue_size>131072</queue_size>
<ipv6>no</ipv6>
</remote>
<!-- Syscheck (File Integrity Monitoring) -->
<syscheck>
<disabled>no</disabled>
<frequency>43200</frequency>
<scan_on_start>yes</scan_on_start>
<!-- Directories to monitor -->
<directories check_all="yes" realtime="yes" report_changes="yes" whodata="yes">/etc,/usr/bin,/usr/sbin</directories>
<directories check_all="yes" realtime="yes" report_changes="yes">/bin,/sbin</directories>
<directories check_all="yes" realtime="yes">/boot</directories>
<!-- Skip directories -->
<skip_nfs>yes</skip_nfs>
<skip_dev>yes</skip_dev>
<skip_proc>yes</skip_proc>
<skip_sys>yes</skip_sys>
<!-- Process priority -->
<process_priority>10</process_priority>
<!-- Max EPS -->
<max_eps>50</max_eps>
<!-- Synchronization -->
<synchronization>
<enabled>yes</enabled>
<interval>5m</interval>
<max_interval>1h</max_interval>
<max_eps>10</max_eps>
</synchronization>
</syscheck>
<!-- Rootcheck -->
<rootcheck>
<disabled>no</disabled>
<check_files>yes</check_files>
<check_trojans>yes</check_trojans>
<check_dev>yes</check_dev>
<check_sys>yes</check_sys>
<check_pids>yes</check_pids>
<check_ports>yes</check_ports>
<check_if>yes</check_if>
<frequency>43200</frequency>
<rootkit_files>/var/ossec/etc/rootcheck/rootkit_files.txt</rootkit_files>
<rootkit_trojans>/var/ossec/etc/rootcheck/rootkit_trojans.txt</rootkit_trojans>
<skip_nfs>yes</skip_nfs>
</rootcheck>
<!-- Log analysis -->
<localfile>
<log_format>syslog</log_format>
<location>/var/log/syslog</location>
</localfile>
<localfile>
<log_format>syslog</log_format>
<location>/var/log/auth.log</location>
</localfile>
<localfile>
<log_format>syslog</log_format>
<location>/var/log/dpkg.log</location>
</localfile>
<localfile>
<log_format>command</log_format>
<command>df -P</command>
<frequency>360</frequency>
</localfile>
<localfile>
<log_format>full_command</log_format>
<command>netstat -tulpn | sed 's/\([[:alnum:]]\+\)\ \+[[:digit:]]\+\ \+[[:digit:]]\+\ \+\(.*\):\([[:digit:]]*\)\ \+\([0-9.*:]*\)\ \+\([[:alnum:]-]*\)\ \+\([[:digit:]]*\/[[:alnum:]-]*\).*/\1 \2 == \3 == \4 \5 process: \6/' | sort -k 4 -g | sed 's/ == /:/g' | sed 1,2d</command>
<alias>netstat listening ports</alias>
<frequency>360</frequency>
</localfile>
<!-- Vulnerability detection -->
<vulnerability-detection>
<enabled>yes</enabled>
<index-status>yes</index-status>
<feed-update-interval>60m</feed-update-interval>
</vulnerability-detection>
<!-- Indexer connection -->
<indexer>
<enabled>yes</enabled>
<hosts>
<host>https://wazuh-indexer:9200</host>
</hosts>
<ssl>
<certificate_authorities>
<ca>/etc/filebeat/certs/root-ca.pem</ca>
</certificate_authorities>
<certificate>/etc/filebeat/certs/filebeat.pem</certificate>
<key>/etc/filebeat/certs/filebeat-key.pem</key>
</ssl>
</indexer>
<!-- Cluster configuration -->
<cluster>
<name>wazuh_cluster</name>
<node_name>node01</node_name>
<node_type>master</node_type>
<key>cluster_secret_key_here</key>
<port>1516</port>
<bind_addr>0.0.0.0</bind_addr>
<nodes>
<node>NODE_IP</node>
</nodes>
<hidden>no</hidden>
<disabled>no</disabled>
</cluster>
<!-- Active response -->
<active-response>
<disabled>no</disabled>
<ca_store>/var/ossec/etc/wpk_root.pem</ca_store>
<ca_verification>yes</ca_verification>
</active-response>
<!-- Logging -->
<logging>
<log_format>plain</log_format>
</logging>
</ossec_config>
<!-- /var/ossec/etc/ossec.conf (Agent) -->
<ossec_config>
<!-- Client settings -->
<client>
<server>
<address>wazuh-manager.example.com</address>
<port>1514</port>
<protocol>tcp</protocol>
</server>
<config-profile>centos, centos7</config-profile>
<notify_time>10</notify_time>
<time-reconnect>60</time-reconnect>
<auto_restart>yes</auto_restart>
<crypto_method>aes</crypto_method>
</client>
<!-- Client buffer -->
<client_buffer>
<queue_size>5000</queue_size>
<events_per_second>500</events_per_second>
</client_buffer>
<!-- Vulnerability detection -->
<vulnerability-detection>
<enabled>yes</enabled>
<index-status>yes</index-status>
</vulnerability-detection>
<!-- File integrity monitoring -->
<syscheck>
<disabled>no</disabled>
<frequency>43200</frequency>
<scan_on_start>yes</scan_on_start>
<directories check_all="yes" realtime="yes" report_changes="yes">/etc,/usr/bin,/usr/sbin</directories>
<directories check_all="yes" realtime="yes">/bin,/sbin</directories>
<skip_nfs>yes</skip_nfs>
<skip_dev>yes</skip_dev>
<skip_proc>yes</skip_proc>
<skip_sys>yes</skip_sys>
<process_priority>10</process_priority>
<max_eps>50</max_eps>
</syscheck>
<!-- Rootcheck -->
<rootcheck>
<disabled>no</disabled>
<check_files>yes</check_files>
<check_trojans>yes</check_trojans>
<check_dev>yes</check_dev>
<check_sys>yes</check_sys>
<check_pids>yes</check_pids>
<check_ports>yes</check_ports>
<check_if>yes</check_if>
<frequency>43200</frequency>
</rootcheck>
<!-- Log collection -->
<localfile>
<log_format>syslog</log_format>
<location>/var/log/syslog</location>
</localfile>
<localfile>
<log_format>syslog</log_format>
<location>/var/log/auth.log</location>
</localfile>
<localfile>
<log_format>syslog</log_format>
<location>/var/log/secure</location>
</localfile>
<localfile>
<log_format>apache</log_format>
<location>/var/log/apache2/error.log</location>
</localfile>
<localfile>
<log_format>apache</log_format>
<location>/var/log/apache2/access.log</location>
</localfile>
<localfile>
<log_format>mysql_log</log_format>
<location>/var/log/mysql/error.log</location>
</localfile>
<!-- Active response -->
<active-response>
<disabled>no</disabled>
<ca_store>/var/ossec/etc/wpk_root.pem</ca_store>
</active-response>
<!-- Logging -->
<logging>
<log_format>plain</log_format>
</logging>
</ossec_config>
# /var/ossec/etc/internal_options.conf
# Analysis daemon
analysisd.debug=0
analysisd.event_format=3
# Syscheck
syscheck.debug=0
syscheck.sleep=2
syscheck.sleep_after=15
syscheck.default_max_eps=50
# Rootcheck
rootcheck.debug=0
# Logcollector
logcollector.debug=0
logcollector.max_lines=1000
logcollector.max_files=256
logcollector.loop_timeout=500
logcollector.open_attempts=8
logcollector.remote_commands=0
logcollector.sock_fail_time=300
# Remoted
remoted.debug=0
remoted.recv_timeout=1
remoted.comp_average_printout=199
remoted.verify_msg_id=0
remoted.pass_empty_keyfile=0
remoted.rids_closing_time=600
# Monitord
monitord.rotate_log=1
monitord.day_wait=10
monitord.min_day_wait=3
monitord.compress=0
monitord.sign_log=0
monitord.integrity_check=0
monitord.integrity_global=1
# Wazuh-db
wazuh_db.debug=0
wazuh_db.commit_interval=10
wazuh_db.commit_interval_max=500
# Cluster
cluster.debug=0
cluster.interval=5
cluster.tcp_keepalive=1
cluster.tcp_user_timeout=0
# Indexer
indexer.debug=0
indexer.timeout=60
# /var/ossec/api/configuration/api.yaml
# API host and port
host: 0.0.0.0
port: 55000
# Use HTTPS
https:
enabled: yes
key: "/var/ossec/api/configuration/ssl/server.key"
cert: "/var/ossec/api/configuration/ssl/server.crt"
use_ca: false
ca: "/var/ossec/api/configuration/ssl/ca.crt"
ssl_protocol: TLSv1.2
ssl_ciphers: "ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256"
# Logging
logs:
level: "info"
format: "plain"
path: "/var/ossec/logs/api.log"
# Authentication
auth:
auth_token_exp_timeout: 900
rbac_mode: "white"
# CORS
cors:
enabled: no
source_route: "*"
expose_headers: "*"
allow_headers: "*"
allow_credentials: no
# Cache
cache:
enabled: yes
time: 0.750
# Access
access:
max_login_attempts: 50
block_time: 300
max_request_per_minute: 300
# Upload limits
upload_max_size: 10485760
# Experimental features
experimental_features: no
<!-- /var/ossec/etc/rules/local_rules.xml -->
<group name="local,syslog,sshd,">
<!-- Custom SSH brute force rule -->
<rule id="100001" level="5">
<if_sid>5716</if_sid>
<srcip>OFFENDER_IP</srcip>
<description>SSHD: brute force attacking from $(srcip).</description>
<group>authentication_failed,pci_dss_10.2.4,pci_dss_10.2.5,</group>
</rule>
<!-- Custom SSH successful login after failures -->
<rule id="100002" level="10">
<if_sid>5715</if_sid>
<same_srcip />
<description>SSHD: Successful login after multiple failures from $(srcip).</description>
<group>authentication_success,pci_dss_10.2.4,</group>
</rule>
<!-- Custom web attack detection -->
<rule id="100003" level="12">
<if_sid>31100</if_sid>
<match>union|select|insert|update|delete|drop|exec|script</match>
<description>Web attack: SQL injection or XSS attempt detected.</description>
<group>web,attack,pci_dss_6.5,</group>
</rule>
<!-- Custom sudo abuse -->
<rule id="100004" level="10">
<if_sid>5603</if_sid>
<user>non-root-user</user>
<description>Sudo executed by non-privileged user $(user).</description>
<group>privilege_escalation,pci_dss_10.2.2,</group>
</rule>
</group>
<!-- /var/ossec/etc/decoders/local_decoder.xml -->
<decoder name="custom-app">
<prematch>^CustomApp:</prematch>
</decoder>
<decoder name="custom-app">
<regex>^CustomApp: \[(\w+)\] (.+)</regex>
<order>level,message</order>
</decoder>
<decoder name="custom-webapp">
<prematch>^webapp:</prematch>
</decoder>
<decoder name="custom-webapp">
<regex>^webapp: (\S+) - (\S+) - (\d+) - "(.+)"</regex>
<order>user,action,status,request</order>
</decoder>
<!-- /var/ossec/etc/shared/active-response.conf -->
<active-response>
<!-- Block IP on firewall -->
<command>
<name>firewall-drop</name>
<executable>firewall-drop.sh</executable>
<timeout_allowed>yes</timeout_allowed>
</command>
<command>
<name>host-deny</name>
<executable>host-deny.sh</executable>
<timeout_allowed>yes</timeout_allowed>
</command>
<command>
<name>restart-wazuh</name>
<executable>restart-wazuh.sh</executable>
</command>
<command>
<name>disable-account</name>
<executable>disable-account.sh</executable>
<timeout_allowed>yes</timeout_allowed>
</command>
<!-- Active response rules -->
<active-response>
<command>firewall-drop</command>
<location>local</location>
<rules_id>100001</rules_id>
<timeout>600</timeout>
</active-response>
<active-response>
<command>firewall-drop</command>
<location>local</location>
<rules_id>5712</rules_id>
<timeout>600</timeout>
</active-response>
</active-response>
#!/bin/bash
# /var/ossec/active-response/bin/firewall-drop.sh
# Firewall drop script
# Args: action type ip
ACTION=$1
TYPE=$2
IP=$3
if [ "$ACTION" = "add" ]; then
iptables -I INPUT -s "$IP" -j DROP
echo "$(date) - Blocked IP: $IP" >> /var/ossec/logs/active-responses.log
elif [ "$ACTION" = "delete" ]; then
iptables -D INPUT -s "$IP" -j DROP
echo "$(date) - Unblocked IP: $IP" >> /var/ossec/logs/active-responses.log
fi
<!-- Email configuration in ossec.conf -->
<global>
<email_notification>yes</email_notification>
<smtp_server>smtp.example.com</smtp_server>
<email_from>wazuh@example.com</email_from>
<email_to>admin@example.com</email_to>
<email_to>security-team@example.com</email_to>
<email_maxperhour>12</email_maxperhour>
</global>
<alerts>
<email_alert_level>7</email_alert_level>
</alerts>
<!-- Group-based email alerts -->
<email_alerts>
<email_alert>
<email_to>dba-team@example.com</email_to>
<group>database</group>
<level>7</level>
</email_alert>
<email_alert>
<email_to>web-team@example.com</email_to>
<group>web,attack</group>
<level>10</level>
</email_alert>
<email_alert>
<email_to>security@example.com</email_to>
<group>authentication_failed,privilege_escalation</group>
<level>8</level>
</email_alert>
</email_alerts>
#!/bin/bash
# /var/ossec/active-response/bin/slack-alert.sh
# Slack alert script
WEBHOOK_URL="https://hooks.slack.com/services/XXX/YYY/ZZZ"
CHANNEL="#security-alerts"
USERNAME="Wazuh"
ICON=":warning:"
# Read alert from stdin
ALERT=$(cat)
# Parse alert data
RULE_ID=$(echo "$ALERT" | grep -oP '"rule":{"id":\K\d+')
RULE_DESC=$(echo "$ALERT" | grep -oP '"rule":{"description":"\K[^"]+')
SRC_IP=$(echo "$ALERT" | grep -oP '"srcip":"\K[^"]+')
AGENT_NAME=$(echo "$ALERT" | grep -oP '"agent":{"name":"\K[^"]+')
TIMESTAMP=$(echo "$ALERT" | grep -oP '"timestamp":"\K[^"]+')
# Create payload
PAYLOAD=$(cat <<EOF
{
"channel": "$CHANNEL",
"username": "$USERNAME",
"icon_emoji": "$ICON",
"attachments": [
{
"color": "danger",
"title": "Wazuh Security Alert",
"fields": [
{"title": "Rule ID", "value": "$RULE_ID", "short": true},
{"title": "Description", "value": "$RULE_DESC", "short": false},
{"title": "Source IP", "value": "$SRC_IP", "short": true},
{"title": "Agent", "value": "$AGENT_NAME", "short": true},
{"title": "Timestamp", "value": "$TIMESTAMP", "short": true}
]
}
]
}
EOF
)
curl -X POST -H 'Content-type: application/json' --data "$PAYLOAD" "$WEBHOOK_URL"
# Validate manager configuration
sudo /var/ossec/bin/wazuh-logtest
# Test specific log against rules
echo "Failed password for root from 192.168.1.100 port 22 ssh2" | sudo /var/ossec/bin/wazuh-logtest
# Validate XML syntax
sudo /var/ossec/bin/wazuh-analysisd -t
# Check cluster status
sudo /var/ossec/bin/cluster_control -l
# Verify agent connection
sudo /var/ossec/bin/agent_control -l
# Restart Wazuh manager
sudo systemctl restart wazuh-manager
# Restart Wazuh indexer
sudo systemctl restart wazuh-indexer
# Restart Wazuh dashboard
sudo systemctl restart wazuh-dashboard
# Check service status
sudo systemctl status wazuh-manager
sudo systemctl status wazuh-indexer
sudo systemctl status wazuh-dashboard
# View logs
sudo tail -f /var/ossec/logs/ossec.log
sudo tail -f /var/ossec/logs/alerts/alerts.log
sudo tail -f /var/ossec/logs/cluster.log
# Register agent using manager
sudo /var/ossec/bin/manage_agents
# Register agent remotely
sudo /var/ossec/bin/agent-auth -m wazuh-manager.example.com -A agent-name
# List registered agents
sudo /var/ossec/bin/agent_control -l
# Extract agent key
sudo /var/ossec/bin/agent_control -k 001
# Remove agent
sudo /var/ossec/bin/agent_control -R 001
# Check manager status
sudo /var/ossec/bin/wazuh-control status
# Check cluster status
sudo /var/ossec/bin/cluster_control -l
# List connected agents
sudo /var/ossec/bin/agent_control -l
# Check agent details
sudo /var/ossec/bin/agent_control -i 001
# Check agent status on agent
sudo /var/ossec/bin/wazuh-control status
# Verify connection to manager
sudo tail -f /var/ossec/logs/ossec.log
# Force agent reconnect
sudo /var/ossec/bin/wazuh-control restart
# View recent alerts
sudo tail -100 /var/ossec/logs/alerts/alerts.json
# Search for specific alerts
sudo grep "SSH" /var/ossec/logs/alerts/alerts.log
# Check alert statistics
sudo /var/ossec/bin/wazuh-logtest -v
# Test API connection
curl -k -u admin:password https://localhost:55000/security/user/authenticate
# Get token and list agents
TOKEN=$(curl -k -u admin:password -X GET "https://localhost:55000/security/user/authenticate" | jq -r .data.token)
curl -k -H "Authorization: Bearer $TOKEN" https://localhost:55000/agents
# Check cluster status via API
curl -k -H "Authorization: Bearer $TOKEN" https://localhost:55000/cluster/status
Squeezing every bit of performance from your Wazuh installation? Our experts help with:
Optimize your setup: office@linux-server-admin.com | Contact Us