Skip to content

Commit

Permalink
Merge pull request #293 from RobinR1/ipfire
Browse files Browse the repository at this point in the history
Add template for monitoring IPFire
  • Loading branch information
oscar120584 authored Nov 6, 2023
2 parents 7d42e28 + 9e43ca7 commit 2ad8b15
Show file tree
Hide file tree
Showing 10 changed files with 3,326 additions and 0 deletions.
76 changes: 76 additions & 0 deletions Network_Appliances/template_ipfire/6.0/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
# IPFire by Zabbix Agent Active

## Description

This template monitors an [IPFire](https://www.ipfire.org/) [appliance](https://www.lightningwirelabs.com/products/ipfire/appliances) or [instance](https://www.ipfire.org/download)

## Overview

For Zabbix version: 6.0

Supports monitoring of:
- IPFire general stats (Number of current DHCPd clients)
- IPFire services (default IPFire services and possible Addon services)
- Pakfire status (Installed version, Available update(s))
- Network stats (Line quality, Open Connections, Firewall hits)
- OpenVPN clients and stats (OpenVPN client discovery, OpenVPN client properties, Traffic stats)

Use in conjunction with a default Template OS Linux-template for CPU/Memory/Storage monitoring of the IPFire appliance/instance.

This template was created for:

- IPFire 2.27 - Core update 179

**Warning**: This template will *NOT* work on earlier versions of IPFire due to changes to the Zabbix Agent addon.

## Author

Robin Roevens

## Setup

- Install and configure [IPFire addon `zabbix_agentd`](https://wiki.ipfire.org/addons/zabbix_agentd) using Pakfire
- Make sure the IPFire builtin specific userparameters are enabled in `/etc/zabbix_agentd/zabbix_agentd.conf` (which should be by default)
- Copy `template_ipfire_services.conf` into the folder with Zabbix agent configuration (`/etc/zabbix_agentd/zabbix_agentd.d/` on IPFire)
- Copy `ipfire_services.pl` into the folder with Zabbix agent scripts (`/etc/zabbix_agentd/scripts/` on IPFire) and make it executable for user `root`.
- Unless you have your own custom sudoers config for zabbix; Copy `zabbix_agentd_user` into the folder with sudoers configuration (`/etc/sudoers.d`) to allow Zabbix agent to run `ipfire_services.pl` as root user.
Otherwise, make sure the contents of `zabbix_agentd_user` from this template are added to your custom `/etc/sudoers.d/zabbix_agentd_user` file.
- Restart Zabbix agent.

## Zabbix configuration

No specific Zabbix configuration is required

### Macros used
|Name|Description|Default|
|----|-----------|-------|
|{$IPFIRE.CONN.MAX.WARN} |<p>Max percentage of max open connections used before triggering warning</p>|`95` |
|{$IPFIRE.CONN.MAX.RESOLVE} |<p>Percentage of max open connections used before resolving trigger</p>|`85` |
|{$IPFIRE.FW_CHAIN.MATCHES} |<p>Only discover firewall chains matching this regex</p>|`^.*$` |
|{$IPFIRE.FW_CHAIN.NOT_MATCHES} |<p>Do not discover firewall chains matching this regex</p>|`CHANGE_IF_NEEDED` |
|{$IPFIRE.SERVICE.TRIGGER} |<p>Whether Zabbix needs to trigger when an IPFire service is down. This variable can be used with context to exclude specific services.</p>|`1` |
|{$IPFIRE.SERVICENAME.MATCHES} |<p>All services matching this regex will be discovered</p>|`^.*$` |
|{$IPFIRE.SERVICENAME.NOT_MATCHES} |<p>Services matching this regex will not be discovered</p>|`CHANGE_IF_NEEDED` |
|{$IPFIRE.OVPN.COMMONNAME.MATCHES} |<p>OpenVPN clients with common name matching this regex will be discovered</p>|`^.*$` |
|{$IPFIRE.OVPN.COMMONNAME.NOTMATCHES} |<p>OpenVPN clients with common name matching this regex will not be discovered</p>|`CHANGE_IF_NEEDED` |
|{$IPFIRE.OVPN.STATE.MATCHES} |<p>OpenVPN clients with a state (on/off) matching this regex will be discovered.</p>|`on` |

#### Notes about $IPFIRE.SERVICE.TRIGGER
This template does not 'detect' if you have manually disabled a service in IPFire, so by default it will alarm you when any service is down. This is done on purpose so that you will also be notified if a service is unintentionly disabled.

To disable the trigger for a specific service (because it is disabled or you just don't want notifications about that service) add a host macro `{$IPFIRE.SERVICE.TRIGGER:"<service>"}` to the IPFire host and set it to `0`.

For example to disable the OpenVPN service trigger add `{$IPFIRE.SERVICE.TRIGGER:"openvpn"}` to the host. Check the discovered IPFire service item-keys for the correct service-name of each service.

Or you could opt to use the variables `{$IPFIRE.SERVICENAME.MATCHES}` and/or `{$IPFIRE.SERVICENAME.NOT_MATCHES}` to filter out services
you don't want to be monitored at all.

## Credits

[Alexander Koch](https://community.ipfire.org/t/looking-for-the-zabbix-agent-template/1459/2) for the app Pakfire template.

[IPFire Team](https://www.ipfire.org) for the IPFire distro and for accepting my contributions to allow easier/better monitoring using Zabbix Agent.

## Feedback

Please report any issues with the template at https://github.com/RobinR1/zbx-template-ipfire/issues
Original file line number Diff line number Diff line change
@@ -0,0 +1,232 @@
#!/usr/bin/perl
###############################################################################
# ipfire_services.pl - Retrieves available IPFire services information and
# return this as a JSON array suitable for easy processing
# by Zabbix server
#
# Author: robin.roevens (at) disroot.org
# Version: 2.0
#
# Based on: services.cgi by IPFire Team
# Copyright (C) 2007-2021 IPFire Team <[email protected]>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
###############################################################################

use strict;

# enable only the following on debugging purpose
# use warnings;

# Load pakfire "library"
require "/opt/pakfire/lib/functions.pl";

# Maps a nice printable name to the changing part of the pid file, which
# is also the name of the program
my %servicenames = (
'DHCP Server' => 'dhcpd',
'Web Server' => 'httpd',
'CRON Server' => 'fcron',
'DNS Proxy Server' => 'unbound',
'Logging Server' => 'syslogd',
'Kernel Logging Server' => 'klogd',
'NTP Server' => 'ntpd',
'Secure Shell Server' => 'sshd',
'VPN' => 'charon',
'Web Proxy' => 'squid',
'Intrusion Detection System' => 'suricata',
'OpenVPN' => 'openvpn'
);

# Hash to overwrite the process name of a process if it differs from the launch command.
my %overwrite_exename_hash = (
"suricata" => "Suricata-Main"
);

my $first = 1;

print "[";

# Built-in services
my $key = '';
foreach $key (sort keys %servicenames){
print "," if not $first;
$first = 0;

print "{";
print "\"service\":\"$key\",";

my $shortname = $servicenames{$key};
print &servicestats($shortname);

print "}";
}

# Generate list of installed addon pak's
my %paklist = &Pakfire::dblist("installed");

foreach my $pak (keys %paklist) {
my %metadata = &Pakfire::getmetadata($pak, "installed");

# If addon contains services
if ("$metadata{'Services'}") {
foreach my $service (split(/ /, "$metadata{'Services'}")) {
print ",";
print "{";

print "\"service\":\"Addon: $metadata{'Name'}\",";
print "\"servicename\":\"$service\",";

my $onboot = isautorun($service);
print "\"onboot\":$onboot,";

print &addonservicestats($service);

print "}";
}
}
}

print "]";

sub servicestats {
my $cmd = $_[0];
my $status = "\"servicename\":\"$cmd\",\"state\":\"0\"";
my $pid = '';
my $testcmd = '';
my $exename;
my $memory;


$cmd =~ /(^[a-z]+)/;

# Check if the exename needs to be overwritten.
# This happens if the expected process name string
# differs from the real one. This may happened if
# a service uses multiple processes or threads.
if (exists($overwrite_exename_hash{$cmd})) {
# Grab the string which will be reported by
# the process from the corresponding hash.
$exename = $overwrite_exename_hash{$1};
} else {
# Directly expect the launched command as
# process name.
$exename = $1;
}

if (open(FILE, "/var/run/${cmd}.pid")){
$pid = <FILE>; chomp $pid;
close FILE;
if (open(FILE, "/proc/${pid}/status")){
while (<FILE>){
if (/^Name:\W+(.*)/) {
$testcmd = $1;
}
}
close FILE;
}
if (open(FILE, "/proc/${pid}/status")) {
while (<FILE>) {
my ($key, $val) = split(":", $_, 2);
if ($key eq 'VmRSS') {
$val =~ /\s*([0-9]*)\s+kB/;
# Convert kB to B
$memory = $1*1024;
last;
}
}
close(FILE);
}
if ($testcmd =~ /$exename/){
$status = "\"servicename\":\"$cmd\",\"state\":1,\"pid\":$pid,\"memory\":$memory";
}
}
return $status;
}

sub isautorun {
my $cmd = $_[0];

# Init directory.
my $initdir = "/etc/rc.d/rc3.d/";

return &find_init("$cmd", "$initdir") ? 1 : 0;
}

sub find_init {
my ($cmd, $dir) = @_;

# Open given init directory.
opendir (INITDIR, "$dir") || die "Cannot opendir $dir: $!";

# Read-in init files from directory.
my @inits = readdir(INITDIR);

# Close directory handle.
closedir(INITDIR);

# Loop through the directory.
foreach my $init (@inits) {
# Check if the current processed file belongs to the given command.
if ($init =~ /S\d+\d+$cmd\z/) {
# Found, return "1" - True.
return "1";
}
}

# Nothing found, return nothing.
return;
}

sub addonservicestats {
my $cmd = $_[0];
my $status = "0";
my $pid = '';
my $testcmd = '';
my $exename;
my @memory = (0);

$testcmd = `/usr/local/bin/addonctrl $cmd status 2>/dev/null`;

if ( $testcmd =~ /is\ running/ && $testcmd !~ /is\ not\ running/){
$status = "\"state\":1";

$testcmd =~ s/.* //gi;
$testcmd =~ s/[a-z_]//gi;
$testcmd =~ s/\[[0-1]\;[0-9]+//gi;
$testcmd =~ s/[\(\)\.]//gi;
$testcmd =~ s/ //gi;
$testcmd =~ s///gi;

my @pid = split(/\s/,$testcmd);
$status .=",\"pid\":\"$pid[0]\"";

my $memory = 0;

foreach (@pid){
chomp($_);
if (open(FILE, "/proc/$_/statm")){
my $temp = <FILE>;
@memory = split(/ /,$temp);
}
$memory+=$memory[0];
}
$memory*=1024;
$status .=",\"memory\":$memory";
}else{
$status = "\"state\":0";
}
return $status;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Include file for sudoers file
#
# This is needed for some userparameters to be able to execute commands that only run as root (using sudo)
# e.g. /usr/bin/openssl or /usr/sbin/smartctl
#
# USE AT YOU'RE OWN RISK. USING THIS WRONG CAN RESULT IN A SECURITY BREACH!
#
# Some hints:
# - It is strongly recommended to edit this file only using the visudo -f <filename> command. If you mess up this file,
# you might end up locking yourself out of your system!
# - Append the full path incl. parameters to each command, using "," as separator.
# - Only add commands you really need. Zabbix should not have more rights than it has to.
#

zabbix ALL=(ALL) NOPASSWD: /etc/zabbix_agentd/scripts/ipfire_services.pl
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
### Parameter for monitoring IPFire services
UserParameter=ipfire.services,sudo /etc/zabbix_agentd/scripts/ipfire_services.pl
Loading

0 comments on commit 2ad8b15

Please sign in to comment.