SELinux: Integration with Zabbix and Other Tools

What awaits us?

In this article, we’ll take a detailed look at the fundamentals of SELinux, its proper integration with Zabbix, and how to effectively create custom SELinux policies to address common issues. We’ll also demonstrate how to monitor SELinux directly in Zabbix, which will help you enhance your system security and simplify day-to-day administration.

This guide is intended for RPM-based distributions (RHEL, CentOS, Rocky Linux, AlmaLinux, Fedora, …).

What is SELinux and how does it work?

SELinux (Security-Enhanced Linux) is a Linux security module that implements Mandatory Access Control (MAC). Unlike standard Discretionary Access Control (DAC), where users define permissions for their own files, MAC enforces security policies managed by the administrator, restricting the actions of programs and users based on clearly defined rules.

SELinux operates in three modes:

  • Enforcing – policies are enforced, and access is actively blocked when rules are violated.
  • Permissive – SELinux is active but does not block access; it only logs policy violations.
  • Disabled – SELinux is completely turned off.

You can check the status of SELinux using the command:

sestatus

Example output:

SELinux status:                 enabled
SELinuxfs mount:                /sys/fs/selinux
SELinux root directory:         /etc/selinux
Loaded policy name:             targeted
Current mode:                   enforcing
Mode from config file:          enforcing
Policy MLS status:              enabled
Policy deny_unknown status:     allowed
Max kernel policy version:      33
  • enabled – SELinux is active.
  • enforcing – The policy is being enforced.
  • targeted – The standard targeted policy is in use.

Zabbix package zabbix-selinux-policy

The zabbix-selinux-policy package contains specific SELinux rules required for smooth operation of the Zabbix server, proxy, and agent, without the need to disable SELinux. The package is available in the official Zabbix repository.

Package installation:

dnf install zabbix-selinux-policy

Temporary SELinux deactivation

If you need to quickly disable SELinux, use:

setenforce 0
  • 0 means switching to Permissive mode (everything is allowed, violations are only logged).
  • 1 means switching back to Enforcing mode (violations are both blocked and logged).

The change is valid only until the system is restarted. Check the current mode with:

getenforce

Permanent SELinux deactivation

To permanently disable SELinux, edit /etc/selinux/config:

nano /etc/selinux/config

Change:

SELINUX=enforcing

to:

SELINUX=disabled

Reboot the system:

reboot

Re-enabling SELinux and relabeling

To re-enable SELinux, it is recommended to first set the mode to permissive, verify that the policies are functioning correctly, and only then switch to enforcing mode. First, set:

SELINUX=permissive

Then set the relabel:

touch /.autorelabel
reboot

Create the .autorelabel file directly in /. This process will apply the correct SELinux contexts during the next reboot. A file’s context refers to metadata that determines which SELinux rules apply to it. If relabeling does not occur, files (such as /etc/passwd) may have incorrect or missing contexts, which can lead to issues like being unable to log in.

After verifying that permissive mode works as expected, you can switch to enforcing. First, update the configuration in /etc/selinux/config:

SELINUX=enforcing

This change will take effect after the system is restarted. To apply the change immediately without rebooting, use the command:

setenforce 1

Creating custom SELinux policies

If SELinux blocks an operation of the zabbix_server application, you can identify it from the auditd logs:

grep AVC /var/log/audit/audit.log | grep zabbix_server

Example log entry:

type=AVC msg=audit(1743521737.355:209): avc: denied { name_bind } for pid=1620 comm="zabbix_server" src=10055 scontext=system_u:system_r:zabbix_t:s0 tcontext=system_u:object_r:unreserved_port_t:s0 tclass=tcp_socket permissive=0

This error indicates that SELinux is preventing the Zabbix server from using port 10055. To create a rule that allows this action, install the audit2allow tool:

dnf install policycoreutils policycoreutils-python-utils -y

Create a policy for the Zabbix server

Run the command:

grep zabbix_server /var/log/audit/audit.log | audit2allow -m zabbix_server_policy > zabbix_server_policy.te

What each part does:

  • grep zabbix_server /var/log/audit/audit.log: Filters audit logs to show only entries related to the Zabbix server.
  • audit2allow -m zabbix_server_policy: Analyzes the input and generates a proposed SELinux policy module.

Example content of the zabbix_server_policy.te file:

module zabbix_server_policy 1.0;

require {
	type krb5_keytab_t;
	type unreserved_port_t;
	type zabbix_t;
	class dir search;
	class tcp_socket name_bind;
}

#============= zabbix_t ==============
allow zabbix_t krb5_keytab_t:dir search;

#!!!! This avc can be allowed using the boolean 'nis_enable

This file contains rules that allow the Zabbix server to:

  • Use specific ports (e.g. unreserved ports),
  • Search directories containing Kerberos key files (krb5_keytab_t).

module zabbix_server_policy 1.0;
→ Module name and version.

require { ... }
→ The module requires access to the following:

  • krb5_keytab_t → Kerberos key files (e.g. /etc/krb5.keytab)
  • unreserved_port_t → standard (unreserved) network ports
  • zabbix_t → Zabbix server process
  • dir search → allows directory traversal
  • tcp_socket name_bind → allows binding to a TCP port

allow zabbix_t krb5_keytab_t:dir search;
→ Zabbix is allowed to access the directory containing the Kerberos key.

#!!!! This avc can be allowed using the boolean 'nis_enable'
→ Comment: a similar permission could be granted by enabling the boolean nis_enable.

Security note:
This example also highlights a potential drawback of automatically generating rules using audit2allow.
It’s possible that, along with the necessary permissions, unwanted access—such as to Kerberos key files—may also be granted.
Therefore, it is crucial to carefully review and edit the output of audit2allow before compiling and applying the policy.

Next, compile and apply the rule:

checkmodule -M -m -o zabbix_server_policy.mod zabbix_server_policy.te
semodule_package -o zabbix_server_policy.pp -m zabbix_server_policy.mod
semodule -i zabbix_server_policy.pp
  • checkmodule -M -m: Compiles the .te file into a .mod module file.
  • semodule_package: Converts the .mod file into a .pp policy package.
  • semodule -i: Installs the generated policy package into the SELinux system.

Verifying policy application:

semodule -l | grep zabbix_server_policy

The output should show the installed zabbix_server_policy, confirming that the policy has been successfully applied to the SELinux system.

To list SELinux policies, for example those related to Zabbix, use:

semodule -l | grep zabbix

This command displays all currently installed SELinux modules that contain “zabbix” in their name.

zabbix
zabbix_server_policy

If you want to see what rules are included in a specific SELinux module (e.g. zabbix_server_policy), you can use the following approach:

mkdir -p /tmp/policyview && \
cd /tmp/policyview && \
semodule --extract zabbix_server_policy && \
strings zabbix_server_policy.pp

Extending an existing SELinux policy with a new rule

If you later need to add another rule to an existing policy, edit the existing .te file (e.g. by adding another allow rule), then repeat the full process of compiling and applying the policy:

checkmodule -M -m -o zabbix_server_policy.mod zabbix_server_policy.te
semodule_package -o zabbix_server_policy.pp -m zabbix_server_policy.mod
semodule -i zabbix_server_policy.pp

SELinux automatically updates the existing policy with new rules without requiring the original policy to be removed.

grep zabbix_server /var/log/audit/audit.log | audit2allow -m zabbix_server_policy > zabbix_server_policy.te

How do I remove a custom SELinux policy?

Use the semodule command:

semodule -r zabbix_server_policy

Monitoring SELinux AVC denials using Zabbix

To monitor SELinux, we first need permission to read the relevant log file. A secure approach is to redirect its contents to a separate file created specifically for this purpose and accessible by the Zabbix agent—rather than modifying permissions on the original system log files, thereby maintaining the system’s security standards.

AVC denial messages in the log look like this:

type=AVC msg=audit(1744268323.007:2345954): avc: denied { search } for pid=2102180 comm="zabbix_server" name="krb5" ...

These messages are logged in the audit log:
/var/log/audit/audit.log
We will specifically monitor these messages.

First, create a script that continuously monitors audit.log and filters out only AVC messages:

nano /usr/local/bin/selinux-denial-logger.sh

Script content:

#!/bin/bash

tail --follow=name /var/log/audit/audit.log | grep --line-buffered -E "avc:\s+denied" >> /var/log/selinux_denials.log

Then set executable permissions for the script:

chmod +x /usr/local/bin/selinux-denial-logger.sh

Automatically start the script using systemd

To ensure the created script runs automatically after system reboot and continues running in the background, you need to create a corresponding systemd service.
Create a new systemd service using the command:

nano /etc/systemd/system/selinux-denial-logger.service

Content of the systemd service file:

[Unit]
Description=SELinux AVC Denial Logger by initMAX s.r.o.
After=auditd.service

[Service]
Type=simple
ExecStart=/usr/local/bin/selinux-denial-logger.sh
Restart=always
RestartSec=5

[Install]
WantedBy=multi-user.target

Enable and start the newly created service:

systemctl daemon-reload 
systemctl enable selinux-denial-logger.service --now

Check that the service is running without issues:

systemctl status selinux-denial-logger.service

Log rotation setup using logrotate

To ensure that the log file does not grow too large, it is recommended to use the logrotate tool for regular rotation.
Create a log rotation configuration using the command:

nano /etc/logrotate.d/selinux_denials

Content of the logrotate configuration:

/var/log/selinux_denials.log {
    weekly
    rotate 4
    missingok
    notifempty
    compress
    delaycompress
    create 0644 root root
    sharedscripts
    postrotate
        systemctl restart selinux-denial-logger.service > /dev/null 2>&1 || true
    endscript
}

This configuration ensures weekly log rotation, retains 4 weeks of history, compresses the logs, and restarts the service after each rotation to ensure logging continues to the correct file.

Template Import and Requirements

To monitor SELinux using Zabbix, we have prepared a custom SELinux template that can be easily imported into your Zabbix server.

Requirements

  • Zabbix version: 7.0 or higher
  • Zabbix agent: it is recommended to use Zabbix Agent 2 (required for systemd.unit.info and easier integration)
  • Zabbix agent: to use log* keys, the agent must run in active mode (active checks)
  • System with SELinux: e.g. RHEL, AlmaLinux, CentOS Stream, Fedora, etc.
  • Agent: must have access to the following files (usually allowed by default):
    • /sys/fs/selinux/enforce
    • /etc/selinux/config
    • /var/log/selinux_denials.log – file generated by the external script (see above)

The template can be downloaded from our repository here: https://git.initmax.cz/initMAX-Public/zabbix-templates/-/tree/production/free/SELinux_by_Zabbix_Agent_2

Template Import

In the Zabbix frontend, go to Data collection → Templates.

Click on Import.

Select the file template_SELinux_by_Zabbix_Agent_2.yaml from our repository and confirm the import.

After importing, link the template to a host with active communication enabled—this is required for processing logs using log[*].

You can verify the configuration by going to Monitoring → Latest data for the corresponding host.

When a denial is detected, Zabbix creates a problem event. The event is automatically closed if no further denials occur within 30 minutes.

This time interval can be adjusted using the user macro {$TRIGGER.CLOSE.TIME}, either directly in the template or individually on the host level.

Each problem record includes the PID, process name (Comm), and object type (Class) in the title, making it easy to identify at a glance.

Tags such as comm, class, pid, and source are also attached to the event, allowing for efficient filtering, notification routing, and display in organized dashboards.

The image below shows how SELinux events appear in the “Monitoring → Problems” section.

Recommendation: SELinux is an important part of system security and it is generally not recommended to disable it. The zabbix-selinux-policy package resolves most common issues with Zabbix, but non-standard operations (such as custom ports or access to non-standard files) must be handled by the administrator using custom policies, as described above. We recommend investing time in understanding how SELinux works so you can manage security policies effectively.

×Shopping Cart

Your cart is empty.