Installing a Wazuh Cluster with Load Balancing

WAZUH

Cluster Installation with Load Balancing

Wazuh is an open-source security platform that provides unified threat detection, file integrity monitoring, and compliance management across diverse environments. In this blog post, I’ll show how I installed and configured a Wazuh cluster with load balancing using Nginx. This will build the foundation of future blog posts where I go more in-depth.

CLUSTER

Components

Wazuh Manager : the core component that collects and analyzes data from the Wazuh Agents. It applies security rules, detects anomalies, and generates alerts. In a cluster setup, the Wazuh Managers work together to ensure high availability and data consistency.

Wazuh Indexer (OpenSearch/Elasticsearch) : All alerts, logs, and security events processed by the Wazuh Manager are stored in the Wazuh Indexer. This component provides powerful indexing and search capabilities, making it easy to analyze large volumes of security data in real-time.

Wazuh Dashboard : The Wazuh Dashboard is the web interface you use to monitor your environment, visualize alerts, and manage the Wazuh configuration. It centralizes data from the Wazuh Indexer, allowing you to investigate potential threats and policy violations quickly.

Nginx : Nginx can be used in front of Wazuh components to distribute incoming requests across multiple servers. This not only helps balance the load but also ensures uninterrupted service if one of the servers becomes unavailable. By leveraging Nginx, you can achieve a more scalable and resilient Wazuh deployment.

‣ Prerequisites

• Hypervisor

• 6 Virtual Machines

‣ My Setup

HYPERVISOR Proxmox
  • Dell PowerEdge R720
  • Intel Xeon E5-2680 v2 @ 2.80GHz
  • 256GB RAM
  • 7TB Storage
VIRTUAL MACHINES Ubuntu 22.04
  • 2 Cores
  • 2 - 4GB RAM
  • 50 - 80GB Storage
SERVERS IP Addresses
  • Nginx : 10.33.99.20
  • Wazuh-DSH1 : 10.33.99.21
  • Wazuh-IDX1 : 10.33.99.22
  • Wazuh-SVR1 : 10.33.99.23
  • Wazuh-IDX2 : 10.33.99.24
  • Wazuh-SVR2 : 10.33.99.25

INDEXERS

‣ Installation

The way I setup my cluster is I had servers for each service (dashboard, indexers, servers/managers). Then in the 2nd part of this blog I added another server for Nginx to setup load balancing.

• CERTIFICATES •

You can create the certificates on any of the servers, I created them on wazuh-dsh1, and then transferred them to the other servers. The following shows how I did that.

First, I downloaded the Wazuh certificates tool.

				
					curl -sO https://packages.wazuh.com/4.10/wazuh-certs-tool.sh
				
			
  • curl – Used for transferring data.
  • -s – Tells curl to operate in silent mode.
  • -o – Tells curl to save the downloaded file with the same name as it appears in the URL.

Then downloaded the Wazuh configuration file.

				
					curl -sO https://packages.wazuh.com/4.10/config.yml
				
			

I then edited the config.yml file.

				
					sudo nano ./config.yml
				
			

I then entered the server names and IP addresses. These names and IP addresses will be used for the certificates and throughout the whole setup, so be sure everything is correct.

				
					nodes:
  # Wazuh indexer nodes
  indexer:
    - name: wazuh-idx1
      ip: "10.33.99.22"
    - name: wazuh-idx2
      ip: "10.33.99.24"

  # Wazuh server nodes
  # If there is more than one Wazuh server
  # node, each one must have a node_type
  server:
    - name: wazuh-svr1
      ip: "10.33.99.23"
      node_type: master
    - name: wazuh-svr2
      ip: "10.33.99.25"
      node_type: worker

  # Wazuh dashboard nodes
  dashboard:
    - name: wazuh-dsh1
      ip: "10.33.99.21"
				
			

Then executed the certificate generation script.

				
					bash ./wazuh-certs-tool.sh -A
				
			

I then compressed the certificates, so that I can then transfer them to the other servers.

				
					tar -cvf ./wazuh-certificates.tar -C ./wazuh-certificates/ .
				
			

Note

You should have a .pem and a .key for each server (e.g. wazuh-dsh1.pem, wazuh-dsh1-key.pem, wazuh-svr1.pm, wazuh-server1-key.pem, etc.), as well as:
– admin-key.pem
– admin.pem
– root-ca.key
– root-ca.pem

I then transferred the tar file to the other servers.

				
					scp -r wazuh-certificates.tar <USER_NAME>@<IP_ADDRESS>:<DESTINATION_DIRECTORY>
				
			
  • <USER_NAME> – The destination server’s username.
  • <IP_ADDRESS> – The destination server’s IP address.
  • <DISTINATION_DIRECTORY> – The destination server’s working directory. E.g. /home/nesto/

Example:

				
					scp -r wazuh-certificates.tar root@10.33.99.22:/home/nesto/
				
			

Note

I used root for the transfers. So on all the other servers, I temporarily enabled SSH for ‘root.’

I first edited the config file.

				
					sudo nano /etc/ssh/sshd_config
				
			

I found the following line and uncommented it, and add yes.

				
					PermitRootLogin yes
				
			

I saved the file and then restarted SSH.

				
					sudo systemctl restart ssh
				
			

• WAZUH-IDX1 •

I did the following setup the same for both indexer servers.

First, I installed some necessary packages.

				
					apt-get install debconf adduser procps
				
			
  • debconf – A utility used to handle the configuration of other packages during installation.
  • adduser – A script that simplifies the process of adding users to the system.
  • procps – A package that contains utilities that provide system information (e.g. ps, top, vmstat).

I also installed the following 2 packages that enhance security and reliability of package management.

				
					apt-get install gnupg apt-transport-https
				
			
  • gnupg – This allows for encrypting and signing data and communications.
  • apt-transport-https – This allows the APT package manager to retrieve packages from repositories security using HTTPS.

I then installed the Wazuh GPG key.

				
					curl -s https://packages.wazuh.com/key/GPG-KEY-WAZUH | gpg --no-default-keyring --keyring gnupg-ring:/usr/share/keyrings/wazuh.gpg --import && chmod 644 /usr/share/keyrings/wazuh.gpg
				
			

Then added the repository.

				
					echo "deb [signed-by=/usr/share/keyrings/wazuh.gpg] https://packages.wazuh.com/4.x/apt/ stable main" | tee -a /etc/apt/sources.list.d/wazuh.list
				
			

Then updated the package information.

				
					apt-get update
				
			

Next, I installed the Wazuh indexer package.

				
					apt-get -y install wazuh-indexer
				
			

I edited the opensearch.yml file.

				
					sudo nano /etc/wazuh-indexer/opensearch.yml
				
			

And made a few changes to the opensearch.yml file.

				
					network.host: "10.33.99.22"
node.name: "wazuh-idx1"
cluster.initial_master_nodes:
- "wazuh-idx1"
- "wazuh-idx2"
cluster.name: "wazuh-cluster"
discovery.seed_hosts:
  - "10.33.99.22"
  - "10.33.99.24"
node.max_local_storage_nodes: "10"
path.data: /var/lib/wazuh-indexer
path.logs: /var/log/wazuh-indexer
...
plugins.security.nodes_dn:
- "CN=wazuh-idx1,OU=Wazuh,O=Wazuh,L=California,C=US"
- "CN=wazuh-idx2,OU=Wazuh,O=Wazuh,L=California,C=US"
...
				
			
  • network.host – I put the IP address of wazuh-idx1.
  • node.name – The name of the server.
  • cluster.initial_master_nodes – I put the names of both indexer servers.
  • cluster.name – I named is wazuh-cluster.
  • discovery.seed_hosts – I put the IP addresses of both indexer servers.
  • node.max_local_storage_nodes – The default is 3, I changed it to 10.
  • plugins.security.nodes – I put the name of the indexer servers.

I then made an environment variable for the server’s name, to make copying files easier.

				
					NODE_NAME=wazuh-idx1
				
			

I made the following directory for the certificates.

				
					mkdir /etc/wazuh-indexer/certs
				
			

Note

For the following commands I changed to root .

				
					sudo -s
				
			

First I extracted the contents of the tar to /etc/wazuh-indexer/certs/

				
					tar -xf ./wazuh-certificates.tar -C /etc/wazuh-indexer/certs/ ./$NODE_NAME.pem ./$NODE_NAME-key.pem ./admin.pem ./admin-key.pem ./root-ca.pem
				
			

Then I moved and renamed the indexer certificates.

				
					mv -n /etc/wazuh-indexer/certs/$NODE_NAME.pem /etc/wazuh-indexer/certs/indexer.pem
mv -n /etc/wazuh-indexer/certs/$NODE_NAME-key.pem /etc/wazuh-indexer/certs/indexer-key.pem
				
			

Next I changed directory and file permissions.

				
					chmod 500 /etc/wazuh-indexer/certs
chmod 400 /etc/wazuh-indexer/certs/*
				
			

I then changed ownership of the directory and all its contents to the user wazuh-indexer.

				
					chown -R wazuh-indexer:wazuh-indexer /etc/wazuh-indexer/certs
				
			

Then reloaded the system configuration files.

				
					systemctl daemon-reload
				
			

Then made the wazuh-indexer start on boot.

				
					systemctl enable wazuh-indexer
				
			

Finally, started the wazuh-indexer.

				
					systemctl start wazuh-indexer
				
			

• WAZUH-IDX2 •

I repeated the same steps for the second indexer server.

• CLUSTER INITIALIZATION •

To initialize the cluster, I ran the following on idx1, but you can do it on any of the indexer servers.

				
					/usr/share/wazuh-indexer/bin/indexer-security-init.sh
				
			

To test if everything is running correctly, I ran the following.

				
					curl -k -u admin:admin https://<WAZUH_INDEXER_IP_ADRESS>:9200
				
			
  • <WAZUH_INDEXER_IP_ADDRESS> – I tested both IP addresses.

SERVERS

‣ Installation

• WAZUH-SVR1 •

The following will be done to both svr1 and svr2. 

I first installed some necessary packages.

				
					apt-get install gnupg apt-transport-https
				
			

then installed the Wazuh GPG key.

				
					curl -s https://packages.wazuh.com/key/GPG-KEY-WAZUH | gpg --no-default-keyring --keyring gnupg-ring:/usr/share/keyrings/wazuh.gpg --import && chmod 644 /usr/share/keyrings/wazuh.gpg
				
			

Then added the repository.

				
					echo "deb [signed-by=/usr/share/keyrings/wazuh.gpg] https://packages.wazuh.com/4.x/apt/ stable main" | tee -a /etc/apt/sources.list.d/wazuh.list
				
			

Then updated the packages.

				
					apt-get update
				
			

Next, I installed the Wazuh manager.

				
					apt-get -y install wazuh-manager
				
			

I also installed Filebeat, necessary for log shipping.

				
					apt-get -y install filebeat
				
			

Then downloaded the preconfigured Filebeat configuration file.

				
					curl -so /etc/filebeat/filebeat.yml https://packages.wazuh.com/4.10/tpl/wazuh/filebeat/filebeat.yml
				
			

I then edited the yml file.

				
					sudo nano /etc/filebeat/filebeat.yml
				
			

I added the following IP addresses.

				
					# Wazuh - Filebeat configuration file
 output.elasticsearch:
 hosts: ["10.33.99.22:9200", "10.33.99.24:9200"]
 protocol: https
 username: ${username}
 password: ${password}
...
				
			
  • hosts – I added the 2 IP addresses for wazuh-idx1, and wazuh-idx2.

I then created a keystore to securely store authentication credentials for Filebeat.

				
					filebeat keystore create
				
			

I added the default username and password admin:admin to the keystore.

				
					echo admin | filebeat keystore add username --stdin --force
echo admin | filebeat keystore add password --stdin --force
				
			

I downloaded the alerts template for the Wazuh indexer.

				
					curl -so /etc/filebeat/wazuh-template.json https://raw.githubusercontent.com/wazuh/wazuh/v4.10.0/extensions/elasticsearch/7.x/wazuh-template.json
chmod go+r /etc/filebeat/wazuh-template.json
				
			
  • go+r – Sets the permissions so that “group” and “others” have read access to the file.
    • g – Refers to the group.
    • o – Refers to others.
    • +r – Adds read permission.

Then installed the Wazuh module for Filebeat.

				
					curl -s https://packages.wazuh.com/4.x/filebeat/wazuh-filebeat-0.4.tar.gz | tar -xvz -C /usr/share/filebeat/module
				
			

Now to deploy the certificates. Which will be done exactly like it was done on the indexer servers, but with name changes.

I made an environment variable for the server.

				
					NODE_NAME=wazuh-svr1
				
			

Then created a directory for the certificates.

				
					mkdir /etc/filebeat/certs
				
			

This time I extracted the contents to /etc/filebeat/certs/

				
					tar -xf ./wazuh-certificates.tar -C /etc/filebeat/certs/ ./$NODE_NAME.pem ./$NODE_NAME-key.pem ./root-ca.pem
				
			

Then moved and renamed the filebeat certificates.

				
					mv -n /etc/filebeat/certs/$NODE_NAME.pem /etc/filebeat/certs/filebeat.pem
mv -n /etc/filebeat/certs/$NODE_NAME-key.pem /etc/filebeat/certs/filebeat-key.pem
				
			

Next I changed the directory and file permissions.

				
					chmod 500 /etc/filebeat/certs
chmod 400 /etc/filebeat/certs/*
				
			

Now to configure the Wazuh indexer connection.

I saved the Wazuh indexer username and password into the Wazuh manager keystore, using the wazuh-keystore tool. I used admin:admin for now and will change it later on.

				
					echo 'admin' | /var/ossec/bin/wazuh-keystore -f indexer -k username
echo 'admin' | /var/ossec/bin/wazuh-keystore -f indexer -k password
				
			

I then edited the ossec.conf file.

				
					sudo nano /var/ossec/etc/ossec.conf
				
			

I made the following changes.

				
					<indexer>
  <enabled>yes</enabled>
  <hosts>
    <host>https://10.33.99.22:9200</host>
    <host>https://10.33.99.24: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>
				
			
  • host – I added both indexer server IP addresses.

Like before with the Wazuh indexer, I reloaded the system daemon configuration, enabled wazuh-manager to start on boot, and then start the service.

				
					systemctl daemon-reload
systemctl enable wazuh-manager
systemctl start wazuh-manager
				
			

Then checked to make sure it started with no problems.

				
					systemctl status wazuh-manager
				
			

I did the same for Filebeat.

				
					systemctl daemon-reload
systemctl enable filebeat
systemctl start filebeat
				
			

As well as tested it.

				
					filebeat test output
				
			

• WAZUH-SVR2 •

I repeated the same steps for the second server.

• CLUSTER INITIALIZATION •

After both servers are setup, I chose wazuh-svr1 as the master node, and wazuh-sv2 as the worker node.

First, I’ll need to create a key, and this will be used on both wazuh-svr1, and wazuh-sv2.

				
					openssl rand -hex 16
				
			

On wazuh-svr1 I edited the ossec.conf file.

				
					sudo nano /var/ossec/etc/ossec.conf
				
			

Then scroll to the very bottom for the <cluster> section.

				
					<cluster>
  <name>wazuh</name>
  <node_name>wazuh-svr1</node_name>
  <node_type>master</node_type>
  <key>c98b62a9b6169ac5f67dae55ae4a9088</key>
  <port>1516</port>
  <bind_addr>0.0.0.0</bind_addr>
  <nodes>
    <node>10.33.99.23</node>
  </nodes>
  <hidden>no</hidden>
  <disabled>no</disabled>
</cluster>
				
			
  • <node_name> – I named it after the master server which is wazuh-svr1.
  • <key> – I pasted the key I created with openssl.
  • <node> – I put the IP address of wazuh-svr1.
  • <disabled> – I changed it from ‘yes’ to ‘no’.

Then restarted the wazuh-manager.

				
					systemctl restart wazuh-manager
				
			

On wazuh-svr2 I edited the ossec.conf as well.

				
					sudo nano /var/ossec/etc/ossec.conf
				
			

Once again I scrolled to the bottom and made some changes.

				
					<cluster>
    <name>wazuh</name>
    <node_name>wazuh-svr2</node_name>
    <node_type>worker</node_type>
    <key>c98b62a9b6169ac5f67dae55ae4a9088</key>
    <port>1516</port>
    <bind_addr>0.0.0.0</bind_addr>
    <nodes>
        <node>10.33.99.23</node>
    </nodes>
    <hidden>no</hidden>
    <disabled>no</disabled>
</cluster>
				
			
  • <node_name> – I named it after the worker server which is wazuh-svr2.
  • <key> – I pasted the same key I created with openssl for the master node.
  • <node> – I put the IP address of wazuh-svr1.
  • <disabled> – I changed it from ‘yes’ to ‘no’.

Then restarted the wazuh-manager.

				
					systemctl restart wazuh-manager
				
			

To verify everything is connected and working, I ran the following. You can do it on either server.

				
					/var/ossec/bin/cluster_control -l
				
			

DASHBOARD

‣ Installation

I only have 1 dashboard, which will be used to access the webui.

First, I installed some necessary packages.

				
					apt-get install debhelper tar curl libcap2-bin
				
			

Like before, I installed the following packages.

				
					apt-get install gnupg apt-transport-https
				
			

Installed the Wazuh GPG key.

				
					curl -s https://packages.wazuh.com/key/GPG-KEY-WAZUH | gpg --no-default-keyring --keyring gnupg-ring:/usr/share/keyrings/wazuh.gpg --import && chmod 644 /usr/share/keyrings/wazuh.gpg
				
			

Added the repository.

				
					echo "deb [signed-by=/usr/share/keyrings/wazuh.gpg] https://packages.wazuh.com/4.x/apt/ stable main" | tee -a /etc/apt/sources.list.d/wazuh.list
				
			

Then updated the package information.

				
					apt-get update
				
			

Next, I installed the Wazuh dashboard.

				
					apt-get -y install wazuh-dashboard
				
			

I then needed to edit the yml file.

				
					sudo nano /etc/wazuh-dashboard/opensearch_dashboards.yml
				
			

I then needed to edit the yml file.

				
					server.host: 10.33.99.21
   server.port: 443
   opensearch.hosts: ["https://10.33.99.22:9200", "https://10.33.99.24:9200"]
   opensearch.ssl.verificationMode: certificate
				
			
  • server.host – The IP address of the dashboard server.
  • opensearch.hosts – The IP addresses of the indexer servers.

Now to deploy the certificates.

Same concept as before, but I won’t go into much detail.

				
					NODE_NAME=wazuh-dsh1
mkdir /etc/wazuh-dashboard/certs
tar -xf ./wazuh-certificates.tar -C /etc/wazuh-dashboard/certs/ ./$NODE_NAME.pem ./$NODE_NAME-key.pem ./root-ca.pem
mv -n /etc/wazuh-dashboard/certs/$NODE_NAME.pem /etc/wazuh-dashboard/certs/dashboard.pem
mv -n /etc/wazuh-dashboard/certs/$NODE_NAME-key.pem /etc/wazuh-dashboard/certs/dashboard-key.pem
chmod 500 /etc/wazuh-dashboard/certs
chmod 400 /etc/wazuh-dashboard/certs/*
chown -R wazuh-dashboard:wazuh-dashboard /etc/wazuh-dashboard/certs
				
			

Then enabled and started the Wazuh dashboard service.

				
					systemctl daemon-reload
systemctl enable wazuh-dashboard
systemctl start wazuh-dashboard
				
			

Finally I needed to edit the wazuh.yml file.

				
					sudo nano /usr/share/wazuh-dashboard/data/wazuh/config/wazuh.yml
				
			

Note

During my setup, the file did not exist, so I created it.

I changed the URL to point to the IP address of wazuh-svr1.

				
					hosts:
   - default:
      url: https://10.33.99.23
      port: 55000
      username: wazuh-wui
      password: wazuh-wui
      run_as: false
				
			

Then went to the IP address of my wazuh-dsh1 server.

Then logged in with admin:admin.

All the checks cleared, so I was taken to the default homepage.

LOAD BALANCER

‣ Installation

• Nginx •

For the load balancer, I utilized Nginx.

First, I installed required packages.

				
					sudo apt install curl gnupg2 ca-certificates lsb-release ubuntu-keyring
				
			

Then imported an official Nginx signing key, so that apt can verify the package’s authenticity.

				
					curl https://nginx.org/keys/nginx_signing.key | gpg --dearmor \
    | sudo tee /usr/share/keyrings/nginx-archive-keyring.gpg >/dev/null
				
			

I then setup the apt repository for stable Ngin packages.

				
					echo "deb [signed-by=/usr/share/keyrings/nginx-archive-keyring.gpg] \
http://nginx.org/packages/ubuntu `lsb_release -cs` nginx" \
    | sudo tee /etc/apt/sources.list.d/nginx.list
				
			

I then updated the packages, and installed Nginx.

				
					sudo apt update
sudo apt install nginx
				
			

I then edited the nginx.conf file.

				
					sudo nano /etc/nginx/nginx.conf
				
			

I made the following changes and saved the file.

				
					stream {
   upstream master {
       server 10.33.99.23:1515;
   }
   upstream mycluster {
   hash $remote_addr consistent;
       server 10.33.99.23:1514;
       server 10.33.99.25:1514
   }
   server {
       listen 1515;
       proxy_pass master;
   }
   server {
       listen 1514;
       proxy_pass mycluster;
   }
}
				
			
  • upstream master – The IP address of wazuh-svr1.
  • upstream mycluster – IP addresses for wazuh-svr1 and wazuh-svr2.

I verified there are no syntax errors

				
					nginx -t
				
			

Then finally reloaded the Nginx service.

				
					nginx -s reload
				
			

WAZUH AGENT

‣ Installation

I tested the load balancer by installing the Wazuh agent on my Windows 11 desktop.

I downloaded the installer from the following link.

				
					https://documentation.wazuh.com/current/installation-guide/wazuh-agent/wazuh-agent-package-windows.html
				
			

I opened PowerShell and navigated to the directory where I downloaded the msi. Then ran the following command.

				
					.\wazuh-agent-4.10.0-1.msi /q WAZUH_MANAGER="10.33.99.20"
				
			
  • WAZUH_MANAGER – I entered the IP address of my load balancer.

I then verified it worked by logging into Wazuh.

WHAT'S NEXT

In the upcoming blog posts I’ll show I integrated Suricata, TheHive with Cortex, VirusTotal, Shuffle, and more.

×

Table of Contents