diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..6a9b375 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +*.backup +*.orig diff --git a/README.md b/README.md index ed6551d..27576fd 100644 --- a/README.md +++ b/README.md @@ -4,14 +4,14 @@ This is a pfSense active template for Zabbix, based on Standard Agent and a php This is forked from https://github.com/rbicelli/pfsense-zabbix-template for FWS needs -Tested with pfSense 2.4.x, Zabbix 4.0, Zabbix 5.0 +Tested with pfSense 2.5.x, Zabbix 4.0, Zabbix 5.0, Zabbix 6.0 ## What it does **Template pfSense Active** - Network interface Discovery and Monitoring with User Assigned Names - - Gateway Discovery and Monitoring (Gateway Status/RTT) + - Gateway Discovery and Monitoring (Gateway Status/RTT) - OpenVPN Server Discovery and Monitoring (Server Status/Tunnel Status) - OpenVPN Clients Discovery and Monitoring (Client Status/Tunnel Status) - CARP Monitoring (Global CARP State) @@ -28,21 +28,35 @@ Tested with pfSense 2.4.x, Zabbix 4.0, Zabbix 5.0 - Discovery of IPsec Site-to-Site tunnels - Monitoring tunnel status (Phase 1 and Phase 2) + +**Template pfSense Active: Speedtest** + + - Discovery of WAN Interfaces + - Perform speed tests and collect metrics ## Configuration First copy the file pfsense_zbx.php to your pfsense box (e.g. to /root/scripts). -For example, from pfSense shell: +From **Diagnostics/Command Prompt** input this one-liner: ```bash +<<<<<<< HEAD mkdir /root/zabbix curl -o /root/zabbix/pfsense_zbx.php https://git.fws.fr/fws/pfsense-zabbix/raw/branch/master/pfsense_zbx.php +======= +curl --create-dirs -o /root/scripts/pfsense_zbx.php https://raw.githubusercontent.com/rbicelli/pfsense-zabbix-template/master/pfsense_zbx.php +>>>>>>> upstream/master ``` -Then install package "Zabbix Agent 4" on your pfSense Box +Then, setup the system version cronjob with: +```bash +/usr/local/bin/php /root/scripts/pfsense_zbx.php sysversion_cron +``` + +Then install package "Zabbix Agent 5" (or "Zabbix Agent 6") on your pfSense Box In Advanced Features-> User Parameters @@ -56,7 +70,11 @@ UserParameter=pfsense.discovery[*],/usr/local/bin/sudo /usr/local/bin/php /root/ UserParameter=pfsense.value[*],/usr/local/bin/sudo /usr/local/bin/php /root/zabbix/pfsense_zbx.php $1 $2 $3 ``` +<<<<<<< HEAD _You need to allow zabbix user to exec /usr/local/bin/sudo /usr/local/bin/php /root/zabbix* without password with sudo_ +======= +_Please note that **AllowRoot=1** option is required in order to correctly execute OpenVPN checks and others._ +>>>>>>> upstream/master Also increase the **Timeout** value at least to **5**, otherwise some checks will fail. @@ -72,6 +90,46 @@ Possible values are: This is useful when monitoring services which could stay stopped on CARP Backup Member. + +## Setup Speedtest + +For running speedtests on WAN interfaces you have to install the speedtest package. + +From **Diagnostics/Command Prompt** input this commands: + +```bash +pkg update && pkg install -y py38-speedtest-cli +``` + +Speedtest python package could be broken at the moment, so you could need an extra step, *only if manually executing speedtest results in an error*: download the latest version from package author's github repo. + +```bash +curl -Lo /usr/local/lib/python3.8/site-packages/speedtest.py https://raw.githubusercontent.com/sivel/speedtest-cli/master/speedtest.py +``` + +For testing if speedtest is installed properly you can try it: + +```bash +/usr/local/bin/speedtest +``` + +Then, setup the cronjob with: + +```bash +/url/local/bin/php /root/scripts/pfsense_zbx.php speedtest_cron +``` + +Remember that you will need to install the package on *every* pfSense upgrade. + +Speedtest template creates a cron job and check for entry everytime Zabbix requests its items. If you want to uninstall the cron jobs simply run, from **Diagnostics/Command Prompt**: + +```bash +/url/local/bin/php /root/scripts/pfsense_zbx.php cron_cleanup +``` + +**NOTE**: When used in multiple gateways scenario, speedtest results are OK only with default gateway. This is a known behavior that must be fixed upstream. + + ## Credits [Keenton Zabbix Template](https://github.com/keentonsas/zabbix-template-pfsense) for Zabbix Agent freeBSD part. diff --git a/pfsense_zbx.php b/pfsense_zbx.php index 459d0c0..0677567 100644 --- a/pfsense_zbx.php +++ b/pfsense_zbx.php @@ -1,12 +1,18 @@ This program is licensed under Apache 2.0 License */ +//Some Useful defines + +define('SPEEDTEST_INTERVAL', 8); //Speedtest Interval (in hours) +define('CRON_TIME_LIMIT', 300); // Time limit in seconds of speedtest and sysinfo +define('DEFAULT_TIME_LIMIT', 30); // Time limit in seconds otherwise + require_once('globals.inc'); require_once('functions.inc'); require_once('config.inc'); @@ -26,7 +32,6 @@ require_once('pkg-utils.inc'); //For DHCP - //Testing function, for template creating purpose function pfz_test(){ $line = "-------------------\n"; @@ -90,40 +95,139 @@ function pfz_test(){ // Interface Discovery // Improved performance -function pfz_interface_discovery() { +function pfz_interface_discovery($is_wan=false,$is_cron=false) { $ifdescrs = get_configured_interface_with_descr(true); $ifaces = get_interface_arr(); $ifcs=array(); - - $json_string = '['; - + $if_ret=array(); + + $json_string = '{"data":['; + foreach ($ifdescrs as $ifname => $ifdescr){ $ifinfo = get_interface_info($ifname); $ifinfo["description"] = $ifdescr; - $ifcs[$ifname] = $ifinfo; - } + $ifcs[$ifname] = $ifinfo; + } foreach ($ifaces as $hwif) { - $json_string .= '{"{#IFNAME}":"' . $hwif . '"'; - + $ifdescr = $hwif; + $has_gw = false; + $is_vpn = false; + $has_public_ip = false; + foreach($ifcs as $ifc=>$ifinfo){ if ($ifinfo["hwif"] == $hwif){ $ifdescr = $ifinfo["description"]; + if (array_key_exists("gateway",$ifinfo)) $has_gw=true; + // Issue #81 - https://stackoverflow.com/a/13818647/15093007 + if (filter_var($ifinfo["ipaddr"], FILTER_VALIDATE_IP, FILTER_FLAG_IPV4 | FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE)) $has_public_ip=true; + if (strpos($ifinfo["if"],"ovpn")!==false) $is_vpn=true; break; } } - - $json_string .= ',"{#IFDESCR}":"' . $ifdescr . '"'; - $json_string .= '},'; + + if ( ($is_wan==false) || (($is_wan==true) && (($has_gw==true) || ($has_public_ip==true)) && ($is_vpn==false)) ) { + $if_ret[]=$hwif; + $json_string .= '{"{#IFNAME}":"' . $hwif . '"'; + $json_string .= ',"{#IFDESCR}":"' . $ifdescr . '"'; + $json_string .= '},'; + } + } $json_string = rtrim($json_string,","); $json_string .= "]"; + if ($is_cron) return $if_ret; + echo $json_string; } +//Interface Speedtest +function pfz_interface_speedtest_value($ifname, $value){ + $tvalue = explode(".", $value); + + if (count($tvalue)>1) { + $value = $tvalue[0]; + $subvalue = $tvalue[1]; + } + + //If the interface has a gateway is considered WAN, so let's do the speedtest + $filename = "/tmp/speedtest-$ifname"; + + if (file_exists($filename)) { + $speedtest_data = json_decode(file_get_contents($filename), true) ?? []; + + if (array_key_exists($value, $speedtest_data)) { + if ($subvalue == false) + echo $speedtest_data[$value]; + else + echo $speedtest_data[$value][$subvalue]; + } + } + +} + +// This is supposed to run via cron job +function pfz_speedtest_cron(){ + require_once("services.inc"); + $ifdescrs = get_configured_interface_with_descr(true); + $ifaces = get_interface_arr(); + $pf_interface_name=''; + $subvalue=false; + + $ifcs = pfz_interface_discovery(true, true); + + foreach ($ifcs as $ifname) { + foreach ($ifdescrs as $ifn => $ifd){ + $ifinfo = get_interface_info($ifn); + if($ifinfo['hwif']==$ifname) { + $pf_interface_name = $ifn; + break; + } + } + pfz_speedtest_exec($ifname, $ifinfo['ipaddr']); + } +} + +//installs a cron job for speedtests +function pfz_speedtest_cron_install($enable=true){ + //Install Cron Job + $command = "/usr/local/bin/php " . __FILE__ . " speedtest_cron"; + install_cron_job($command, $enable, $minute = "*/15", "*", "*", "*", "*", "root", true); +} + + +// 2023-02-26: +// Fixed issue #127 +function pfz_speedtest_exec ($ifname, $ipaddr){ + + $filename = "/tmp/speedtest-$ifname"; + $filetemp = "$filename.tmp"; + $filerun = "/tmp/speedtest-run"; + + // Issue #82 + // Sleep random delay in order to avoid problem when 2 pfSense on the same Internet line + sleep (rand ( 1, 90)); + + if ( (time()-filemtime($filename) > SPEEDTEST_INTERVAL * 3600) || (file_exists($filename)==false) ) { + // file is older than SPEEDTEST_INTERVAL + if ( (time()-filemtime($filerun) > 180 ) ) @unlink($filerun); + + if (file_exists($filerun)==false) { + touch($filerun); + $st_command = "/usr/local/bin/speedtest --secure --source $ipaddr --json > $filetemp"; + exec ($st_command); + rename($filetemp,$filename); + @unlink($filerun); + } + } + + return true; +} + + // OpenVPN Server Discovery function pfz_openvpn_get_all_servers(){ $servers = openvpn_get_active_servers(); @@ -161,7 +265,7 @@ function pfz_openvpn_servervalue($server_id,$valuekey){ $value = $server[$valuekey]; if ($valuekey=="status") { if ( ($server['mode']=="server_user") || ($server['mode']=="server_tls_user") || ($server['mode']=="server_tls") ){ - if ($value=="") $value="server_user_listening"; + if ($value=="") $value="server_user_listening"; } else if ($server['mode']=="p2p_tls"){ // For p2p_tls, ensure we have one client, and return up if it's the case if ($value=="") @@ -202,16 +306,19 @@ function pfz_openvpn_server_userdiscovery(){ $json_string = '['; foreach ($servers as $server){ - if ( ($server['mode']=='server_user') || ($server['mode']=='server_tls_user') ) { - if (is_array($server['conns'])) { + if ( ($server['mode']=='server_user') || ($server['mode']=='server_tls_user') || ($server['mode']=='server_tls') ) { + if (is_array($server['conns'])) { $name = trim(preg_replace('/\w{3}(\d)?\:\d{4,5}/i', '', $server['name'])); - + foreach($server['conns'] as $conn) { - $json_string .= '{"{#SERVERID}":"' . $server['vpnid'] . '"'; - $json_string .= ',"{#SERVERNAME}":"' . $name . '"'; - $json_string .= ',"{#UNIQUEID}":"' . $server['vpnid'] . '+' . $conn['common_name'] . '"'; - $json_string .= ',"{#USERID}":"' . $conn['common_name'] . '"'; - $json_string .= '},'; + + $common_name = pfz_replacespecialchars($conn['common_name']); + + $json_string .= '{"{#SERVERID}":"' . $server['vpnid'] . '"'; + $json_string .= ',"{#SERVERNAME}":"' . $name . '"'; + $json_string .= ',"{#UNIQUEID}":"' . $server['vpnid'] . '+' . $common_name . '"'; + $json_string .= ',"{#USERID}":"' . $conn['common_name'] . '"'; + $json_string .= '},'; } } } @@ -226,6 +333,7 @@ function pfz_openvpn_server_userdiscovery(){ // Get OpenVPN User Connected Value function pfz_openvpn_server_uservalue($unique_id, $valuekey, $default=""){ + $unique_id = pfz_replacespecialchars($unique_id,true); $atpos=strpos($unique_id,'+'); $server_id = substr($unique_id,0,$atpos); $user_id = substr($unique_id,$atpos+1); @@ -262,6 +370,20 @@ function pfz_openvpn_clientdiscovery() { echo $json_string; } +function pfz_replacespecialchars($inputstr,$reverse=false){ + $specialchars = ",',\",`,*,?,[,],{,},~,$,!,&,;,(,),<,>,|,#,@,0x0a"; + $specialchars = explode(",",$specialchars); + $resultstr = $inputstr; + + for ($n=0;$n"none") + $value = $gws[$gw]["substatus"]; + $value = pfz_valuemap("gateway.status", $value); - echo $value; + } + echo $value; } } @@ -441,8 +570,7 @@ function pfz_ipsec_discovery_ph1(){ } - -function pfz_ipsec_ph1($ikeid,$valuekey){ +function pfz_ipsec_ph1($ikeid,$valuekey){ // Get Value from IPsec Phase 1 Configuration // If Getting "disabled" value only check item presence in config array @@ -538,28 +666,45 @@ function pfz_ipsec_status($ikeid,$reqid=-1,$valuekey='state'){ require_once("ipsec.inc"); global $config; init_config_arr(array('ipsec', 'phase1')); + $a_phase1 = &$config['ipsec']['phase1']; + $conmap = array(); + foreach ($a_phase1 as $ph1ent) { + if (function_exists('get_ipsecifnum')) { + if (get_ipsecifnum($ph1ent['ikeid'], 0)) { + $cname = "con" . get_ipsecifnum($ph1ent['ikeid'], 0); + } else { + $cname = "con{$ph1ent['ikeid']}00000"; + } + } else{ + $cname = ipsec_conid($ph1ent); + } + + $conmap[$cname] = $ph1ent['ikeid']; + } + $status = ipsec_list_sa(); $ipsecconnected = array(); - + $carp_status = pfz_carp_status(false); - - //Phase-Status match borrowed from status_ipsec.php - if (is_array($status)) { + + //Phase-Status match borrowed from status_ipsec.php + if (is_array($status)) { foreach ($status as $l_ikeid=>$ikesa) { - - if(isset($ikesa['con-id'])){ + + if (isset($ikesa['con-id'])) { $con_id = substr($ikesa['con-id'], 3); - }else{ - $con_id = filter_var($l_ikeid, FILTER_SANITIZE_NUMBER_INT); + } else { + $con_id = filter_var($ikeid, FILTER_SANITIZE_NUMBER_INT); } + $con_name = "con" . $con_id; if ($ikesa['version'] == 1) { - $ph1idx = substr($con_id, 0, strrpos(substr($con_id, 0, -1), '00')); + $ph1idx = $conmap[$con_name]; $ipsecconnected[$ph1idx] = $ph1idx; } else { if (!ipsec_ikeid_used($con_id)) { // probably a v2 with split connection then - $ph1idx = substr($con_id, 0, strrpos(substr($con_id, 0, -1), '00')); + $ph1idx = $conmap[$con_name]; $ipsecconnected[$ph1idx] = $ph1idx; } else { $ipsecconnected[$con_id] = $ph1idx = $con_id; @@ -570,7 +715,7 @@ function pfz_ipsec_status($ikeid,$reqid=-1,$valuekey='state'){ // Asking for Phase2 Status Value foreach ($ikesa['child-sas'] as $childsas) { if ($childsas['reqid']==$reqid) { - if ($childsas['state'] == 'REKEYED') { + if (strtolower($childsas['state']) == 'rekeyed') { //if state is rekeyed go on $tmp_value = $childsas[$valuekey]; } else { @@ -587,20 +732,56 @@ function pfz_ipsec_status($ikeid,$reqid=-1,$valuekey='state'){ } } } + switch($valuekey) { case 'state': $value = pfz_valuemap('ipsec.state', strtolower($tmp_value)); - if ($carp_status != 0) - $value = $value + (10 * ($carp_status-1)); + if ($carp_status!=0) $value = $value + (10 * ($carp_status-1)); break; default: $value = $tmp_value; break; } -// print_r($ikesa); + return $value; } +// Temperature sensors Discovery +function pfz_temperature_sensors_discovery(){ + + + $json_string = '{"data":['; + $sensors = []; + exec("sysctl -a | grep temperature | cut -d ':' -f 1", $sensors, $code); + if ($code != 0) { + echo ""; + return; + } else { + foreach ($sensors as $sensor) { + $json_string .= '{"{#SENSORID}":"' . $sensor . '"'; + $json_string .= '},'; + } + } + + $json_string = rtrim($json_string,","); + $json_string .= "]}"; + + echo $json_string; + +} + +// Temperature sensor get value +function pfz_get_temperature($sensorid){ + + exec("sysctl '$sensorid' | cut -d ':' -f 2", $value, $code); + if ($code != 0 or count($value)!=1) { + echo ""; + return; + } else { + echo trim($value[0]); + } + +} function pfz_carp_status($echo = true){ @@ -652,6 +833,182 @@ function pfz_carp_status($echo = true){ } +// DHCP Checks (copy of status_dhcp_leases.php, waiting for pfsense 2.5) +function pfz_remove_duplicate($array, $field) { + foreach ($array as $sub) { + $cmp[] = $sub[$field]; + } + $unique = array_unique(array_reverse($cmp, true)); + foreach ($unique as $k => $rien) { + $new[] = $array[$k]; + } + return $new; +} + +// Get DHCP Arrays (copied from status_dhcp_leases.php, waiting for pfsense 2.5, in order to use system_get_dhcpleases();) +function pfz_dhcp_get($valuekey) { + + require_once("config.inc"); + + $leasesfile = "{$g['dhcpd_chroot_path']}/var/db/dhcpd.leases"; + + $awk = "/usr/bin/awk"; + /* this pattern sticks comments into a single array item */ + $cleanpattern = "'{ gsub(\"#.*\", \"\");} { gsub(\";\", \"\"); print;}'"; + /* We then split the leases file by } */ + $splitpattern = "'BEGIN { RS=\"}\";} {for (i=1; i<=NF; i++) printf \"%s \", \$i; printf \"}\\n\";}'"; + + /* stuff the leases file in a proper format into a array by line */ + @exec("/bin/cat {$leasesfile} 2>/dev/null| {$awk} {$cleanpattern} | {$awk} {$splitpattern}", $leases_content); + $leases_count = count($leases_content); + @exec("/usr/sbin/arp -an", $rawdata); + + $leases = []; + $pools = []; + + $i = 0; + $l = 0; + $p = 0; + + foreach ($leases_content as $lease) { + /* split the line by space */ + $data = explode(" ", $lease); + /* walk the fields */ + $f = 0; + $fcount = count($data); + /* with less than 20 fields there is nothing useful */ + if ($fcount < 20) { + $i++; + continue; + } + while ($f < $fcount) { + switch ($data[$f]) { + case "failover": + $pools[$p]['name'] = trim($data[$f+2], '"'); + $pools[$p]['name'] = "{$pools[$p]['name']} (" . convert_friendly_interface_to_friendly_descr(substr($pools[$p]['name'], 5)) . ")"; + $pools[$p]['mystate'] = $data[$f+7]; + $pools[$p]['peerstate'] = $data[$f+14]; + $pools[$p]['mydate'] = $data[$f+10]; + $pools[$p]['mydate'] .= " " . $data[$f+11]; + $pools[$p]['peerdate'] = $data[$f+17]; + $pools[$p]['peerdate'] .= " " . $data[$f+18]; + $p++; + $i++; + continue 3; + case "lease": + $leases[$l]['ip'] = $data[$f+1]; + $leases[$l]['type'] = $dynamic_string; + $f = $f+2; + break; + case "starts": + $leases[$l]['start'] = $data[$f+2]; + $leases[$l]['start'] .= " " . $data[$f+3]; + $f = $f+3; + break; + case "ends": + if ($data[$f+1] == "never") { + // Quote from dhcpd.leases(5) man page: + // If a lease will never expire, date is never instead of an actual date. + $leases[$l]['end'] = gettext("Never"); + $f = $f+1; + } else { + $leases[$l]['end'] = $data[$f+2]; + $leases[$l]['end'] .= " " . $data[$f+3]; + $f = $f+3; + } + break; + case "tstp": + $f = $f+3; + break; + case "tsfp": + $f = $f+3; + break; + case "atsfp": + $f = $f+3; + break; + case "cltt": + $f = $f+3; + break; + case "binding": + switch ($data[$f+2]) { + case "active": + $leases[$l]['act'] = $active_string; + break; + case "free": + $leases[$l]['act'] = $expired_string; + $leases[$l]['online'] = $offline_string; + break; + case "backup": + $leases[$l]['act'] = $reserved_string; + $leases[$l]['online'] = $offline_string; + break; + } + $f = $f+1; + break; + case "next": + /* skip the next binding statement */ + $f = $f+3; + break; + case "rewind": + /* skip the rewind binding statement */ + $f = $f+3; + break; + case "hardware": + $leases[$l]['mac'] = $data[$f+2]; + /* check if it's online and the lease is active */ + if (in_array($leases[$l]['ip'], $arpdata_ip)) { + $leases[$l]['online'] = $online_string; + } else { + $leases[$l]['online'] = $offline_string; + } + $f = $f+2; + break; + case "client-hostname": + if ($data[$f+1] <> "") { + $leases[$l]['hostname'] = preg_replace('/"/', '', $data[$f+1]); + } else { + $hostname = gethostbyaddr($leases[$l]['ip']); + if ($hostname <> "") { + $leases[$l]['hostname'] = $hostname; + } + } + $f = $f+1; + break; + case "uid": + $f = $f+1; + break; + } + $f++; + } + $l++; + $i++; + /* slowly chisel away at the source array */ + array_shift($leases_content); + } + /* remove duplicate items by mac address */ + if (count($leases) > 0) { + $leases = pfz_remove_duplicate($leases, "ip"); + } + + if (count($pools) > 0) { + $pools = pfz_remove_duplicate($pools, "name"); + asort($pools); + } + + switch ($valuekey){ + case "pools": + return $pools; + break; + case "failover": + return $failover; + break; + case "leases": + default: + return $leases; + } + +} + function pfz_dhcpfailover_discovery(){ //System functions regarding DHCP Leases will be available in the upcoming release of pfSense, so let's wait require_once("system.inc"); @@ -671,6 +1028,29 @@ function pfz_dhcpfailover_discovery(){ echo $json_string; } +function pfz_dhcp_check_failover(){ + // Check DHCP Failover Status + // Returns number of failover pools which state is not normal or + // different than peer state + $failover = pfz_dhcp_get("failover"); + $ret = 0; + foreach ($failover as $f){ + if ( ($f["mystate"]!="normal") || ($f["mystate"]!=$f["peerstate"])) { + $ret++; + } + } + return $ret; +} + +function pfz_dhcp($section, $valuekey=""){ + switch ($section){ + case "failover": + echo pfz_dhcp_check_failover(); + break; + default: + } +} + //Packages function pfz_packages_uptodate(){ require_once("pkg-utils.inc"); @@ -687,40 +1067,152 @@ function pfz_packages_uptodate(){ return $ret; } + +function pfz_sysversion_cron_install($enable=true){ + //Install Cron Job + $command = "/usr/local/bin/php " . __FILE__ . " systemcheck_cron"; + install_cron_job($command, $enable, $minute = "0", "9,21", "*", "*", "*", "root", true); +} + +// System information takes a long time to get on slower systems. +// So it is saved via a cronjob. +function pfz_sysversion_cron (){ + $filename = "/tmp/sysversion.json"; + $upToDate = pfz_packages_uptodate(); + $sysVersion = get_system_pkg_version(); + $sysVersion["packages_update"] = $upToDate; + $sysVersionJson = json_encode($sysVersion); + if (file_exists($filename)) { + if ((time()-filemtime($filename) > CRON_TIME_LIMIT ) ) { + @unlink($filename); + } + } + if (file_exists($filename)==false) { + touch($filename); + file_put_contents($filename, $sysVersionJson); + } + return true; +} + //System Information function pfz_get_system_value($section){ + $filename = "/tmp/sysversion.json"; + if(file_exists($filename)) { + $sysVersion = json_decode(file_get_contents($filename), true); + } else { + if($section == "new_version_available") { + echo "0"; + } else { + echo "error: cronjob not installed. Run \"php pfsense_zbx.php sysversion_cron\""; + } + } switch ($section){ case "version": - echo( get_system_pkg_version()['version']); + echo( $sysVersion['version']); break; case "installed_version": - echo( get_system_pkg_version()['installed_version']); + echo($sysVersion['installed_version']); break; case "new_version_available": - $pkgver = get_system_pkg_version(); - if ($pkgver['version']==$pkgver['installed_version']) + if ($sysVersion['version']==$sysVersion['installed_version']) echo "0"; else echo "1"; break; case "packages_update": - echo pfz_packages_uptodate(); + echo $sysVersion["packages_update"]; break; } } +//S.M.A.R.T Status +// Taken from /usr/local/www/widgets/widgets/smart_status.widget.php +function pfz_get_smart_status(){ + + $devs = get_smart_drive_list(); + $status = 0; + foreach ($devs as $dev) { ## for each found drive do + $smartdrive_is_displayed = true; + $dev_ident = exec("diskinfo -v /dev/$dev | grep ident | awk '{print $1}'"); ## get identifier from drive + $dev_state = trim(exec("smartctl -H /dev/$dev | awk -F: '/^SMART overall-health self-assessment test result/ {print $2;exit} +/^SMART Health Status/ {print $2;exit}'")); ## get SMART state from drive + switch ($dev_state) { + case "PASSED": + case "OK": + //OK + $status=0; + break; + case "": + //Unknown + $status=2; + return $status; + break; + default: + //Error + $status=1; + return $status; + break; + } + } + + echo $status; +} + +// Certificats validity date +function pfz_get_cert_date($valuekey){ + global $config; + + // Contains a list of refs that were revoked and should not be considered + $revoked_cert_refs = []; + foreach ($config["crl"] as $crl) { + foreach ($crl["cert"] as $revoked_cert) { + $revoked_cert_refs[] = $revoked_cert["refid"]; + } + } + + $value = 0; + foreach (array("cert", "ca") as $cert_type) { + switch ($valuekey){ + case "validFrom.max": + foreach ($config[$cert_type] as $cert) { + if ( ! in_array($cert['refid'], $revoked_cert_refs) ) { + $certinfo = openssl_x509_parse(base64_decode($cert["crt"])); + if ($value == 0 or $value < $certinfo['validFrom_time_t']) $value = $certinfo['validFrom_time_t']; + } + } + break; + case "validTo.min": + foreach ($config[$cert_type] as $cert) { + if ( ! in_array($cert['refid'], $revoked_cert_refs) ) { + $certinfo = openssl_x509_parse(base64_decode($cert["crt"])); + if ($value == 0 or $value > $certinfo['validTo_time_t']) $value = $certinfo['validTo_time_t']; + } + } + break; + } + } + echo $value; +} + +// File is present +function pfz_file_exists($filename) { + if (file_exists($filename)) + echo "1"; + else + echo "0"; +} // Value mappings // Each value map is represented by an associative array function pfz_valuemap($valuename, $value, $default="0"){ - - switch ($valuename){ + switch ($valuename){ case "openvpn.server.status": $valuemap = array( "down" => "0", "up" => "1", + "connected (success)" => "1", "none" => "2", "reconnecting; ping-restart" => "3", "waiting" => "4", @@ -730,6 +1222,7 @@ function pfz_valuemap($valuename, $value, $default="0"){ case "openvpn.client.status": $valuemap = array( "up" => "1", + "connected (success)" => "1", "down" => "0", "none" => "0", "reconnecting; ping-restart" => "2"); @@ -746,6 +1239,7 @@ function pfz_valuemap($valuename, $value, $default="0"){ case "gateway.status": $valuemap = array( + "online" => "0", "none" => "0", "loss" => "1", "highdelay" => "2", @@ -797,9 +1291,11 @@ function pfz_valuemap($valuename, $value, $default="0"){ } - if (array_key_exists($value, $valuemap)) - return $valuemap[$value]; - + if (is_array($valuemap)) { + $value = strtolower($value); + if (array_key_exists($value, $valuemap)) + return $valuemap[$value]; + } return $default; } @@ -809,6 +1305,9 @@ function pfz_discovery($section){ case "gw": pfz_gw_discovery(); break; + case "wan": + pfz_interface_discovery(true); + break; case "openvpn_server": pfz_openvpn_serverdiscovery(); break; @@ -833,11 +1332,23 @@ function pfz_discovery($section){ case "dhcpfailover": pfz_dhcpfailover_discovery(); break; - } + case "temperature_sensors": + pfz_temperature_sensors_discovery(); + break; + } } //Main Code -switch (strtolower($argv[1])){ +$mainArgument = strtolower($argv[1]); +if(substr($mainArgument, -4, 4) == "cron") { + // A longer time limit for cron tasks. + set_time_limit(CRON_TIME_LIMIT); +} else { + // Set a timeout to prevent a blocked call from stopping all future calls. + set_time_limit(DEFAULT_TIME_LIMIT); +} + +switch ($mainArgument){ case "discovery": pfz_discovery($argv[2]); break; @@ -847,6 +1358,10 @@ switch (strtolower($argv[1])){ case "gw_status": pfz_gw_rawstatus(); break; + case "if_speedtest_value": + pfz_speedtest_cron_install(); + pfz_interface_speedtest_value($argv[2],$argv[3]); + break; case "openvpn_servervalue": pfz_openvpn_servervalue($argv[2],$argv[3]); break; @@ -868,6 +1383,10 @@ switch (strtolower($argv[1])){ case "if_name": pfz_get_if_name($argv[2]); break; + case "sysversion_cron": + pfz_sysversion_cron_install(); + pfz_sysversion_cron(); + break; case "system": pfz_get_system_value($argv[2]); break; @@ -877,6 +1396,29 @@ switch (strtolower($argv[1])){ case "ipsec_ph2": pfz_ipsec_ph2($argv[2],$argv[3]); break; + case "dhcp": + pfz_dhcp($argv[2],$argv[3]); + break; + case "file_exists": + pfz_file_exists($argv[2]); + break; + case "speedtest_cron": + pfz_speedtest_cron_install(); + pfz_speedtest_cron(); + break; + case "cron_cleanup": + pfz_speedtest_cron_install(false); + pfz_sysversion_cron_install(false); + break; + case "smart_status": + pfz_get_smart_status(); + break; + case "cert_date": + pfz_get_cert_date($argv[2]); + break; + case "temperature": + pfz_get_temperature($argv[2]); + break; default: pfz_test(); } diff --git a/pfsense_zbx_rc.php b/pfsense_zbx_rc.php new file mode 100644 index 0000000..9e6d246 --- /dev/null +++ b/pfsense_zbx_rc.php @@ -0,0 +1,1571 @@ + + * This program is licensed under Apache 2.0 License + */ + +namespace RBicelli\Pfz; + +use Closure; +use Exception; +use ReflectionClass; +use ReflectionMethod; + +require_once("config.inc"); +require_once("functions.inc"); +require_once("globals.inc"); +require_once("interfaces.inc"); +require_once("ipsec.inc"); +require_once("openvpn.inc"); +require_once("pkg-utils.inc"); +require_once("service-utils.inc"); +require_once("services.inc"); +require_once("system.inc"); +require_once("util.inc"); + +define("COMMAND_HANDLERS", build_method_lookup(Command::class)); +define("DISCOVERY_SECTION_HANDLERS", build_method_lookup(Discovery::class)); +define("SERVICES_VALUE_HANDLERS", build_method_lookup(Service::class)); + +define("TEXT_ACTIVE", gettext("active")); +define("TEXT_DYNAMIC", gettext("dynamic")); +define("TEXT_EXPIRED", gettext("expired")); +define("TEXT_NEVER", gettext("Never")); +define("TEXT_OFFLINE", gettext("offline")); +define("TEXT_ONLINE", gettext("online")); +define("TEXT_RESERVED", gettext("reserved")); + +const SPEED_TEST_INTERVAL_HOURS = 8; +const SPEED_TEST_INTERVAL_SECONDS = SPEED_TEST_INTERVAL_HOURS * 3600; +const SPEED_TEST_RANDOM_DELAY_MIN_SECONDS = 1; +const SPEED_TEST_RANDOM_DELAY_MAX_SECONDS = 90; + +const FALLBACK_VALUE = 0; + +const LINE = "-------------------\n"; + +const VALUE_MAPPINGS = [ + "openvpn.server.status" => [ + "down" => 0, + "up" => 1, + "none" => 2, + "reconnecting; ping-restart" => 3, + "waiting" => 4, + "server_user_listening" => 5], + "openvpn.client.status" => [ + "connected" => 1, + "up" => 1, + "down" => 0, + "none" => 0, + "reconnecting; ping-restart" => 2], + "openvpn.server.mode" => [ + "p2p_tls" => 1, + "p2p_shared_key" => 2, + "server_tls" => 3, + "server_user" => 4, + "server_tls_user" => 5], + "gateway.status" => [ + "online" => 0, + "none" => 0, + "loss" => 1, + "highdelay" => 2, + "highloss" => 3, + "force_down" => 4, + "down" => 5], + "ipsec.iketype" => [ + "auto" => 0, + "ikev1" => 1, + "ikev2" => 2], + "ipsec.mode" => [ + "main" => 0, + "aggressive" => 1], + "ipsec.protocol" => [ + "both" => 0, + "inet" => 1, + "inet6" => 2], + "ipsec_ph2.mode" => [ + "transport" => 0, + "tunnel" => 1, + "tunnel6" => 2], + "ipsec_ph2.protocol" => [ + "esp" => 1, + "ah" => 2], + "ipsec.state" => [ + "established" => 1, + "connecting" => 2, + "installed" => 1, + "rekeyed" => 2]]; + +const CERT_VK_TO_FIELD = [ + "validFrom.max" => "validFrom_time_t", + "validTo.min" => "validTo_time_t", +]; + +const SMART_DEV_PASSED = "PASSED"; +const SMART_DEV_OK = "OK"; +const SMART_DEV_UNKNOWN = ""; + +const SMART_OK = 0; +const SMART_UNKNOWN = 2; +const SMART_ERROR = 1; + +const SMART_DEV_STATUS = [ + SMART_DEV_PASSED => SMART_OK, + SMART_DEV_OK => SMART_OK, + SMART_DEV_UNKNOWN => SMART_UNKNOWN +]; + +const CARP_INCONSISTENT = "INCONSISTENT"; +const CARP_MASTER = "MASTER"; + +const CARP_STATUS_DISABLED = 0; +const CARP_STATUS_OK = 1; +const CARP_STATUS_UNKNOWN = 2; +const CARP_STATUS_INCONSISTENT = 3; +const CARP_STATUS_PROBLEM = 4; + +const CARP_RES = [ + CARP_INCONSISTENT => CARP_STATUS_INCONSISTENT, + CARP_MASTER => CARP_STATUS_OK +]; + +// Abstract undefined symbols and globals from code +class PfEnv +{ + public static function cfg() + { + global $config; + + return $config; + } + + public static function g($key) + { + global $g; + + return $g[$key]; + } + + private static function call_pfsense_method_with_same_name_and_arguments() + { + $caller_function_name = debug_backtrace()[1]["function"]; + + return call_user_func_array($caller_function_name, ...func_get_args()); + } + + public static function convert_friendly_interface_to_friendly_descr() + { + return self::call_pfsense_method_with_same_name_and_arguments(func_get_args()); + } + + public static function get_carp_status() + { + return self::call_pfsense_method_with_same_name_and_arguments(func_get_args()); + } + + public static function get_carp_interface_status() + { + return self::call_pfsense_method_with_same_name_and_arguments(func_get_args()); + } + + public static function get_configured_interface_list() + { + return self::call_pfsense_method_with_same_name_and_arguments(func_get_args()); + } + + public static function get_configured_interface_with_descr() + { + return self::call_pfsense_method_with_same_name_and_arguments(func_get_args()); + } + + public static function get_interface_arr() + { + return self::call_pfsense_method_with_same_name_and_arguments(func_get_args()); + } + + public static function get_interface_info() + { + return self::call_pfsense_method_with_same_name_and_arguments(func_get_args()); + } + + public static function get_service_status() + { + return self::call_pfsense_method_with_same_name_and_arguments(func_get_args()); + } + + public static function get_services() + { + return self::call_pfsense_method_with_same_name_and_arguments(func_get_args()) ?: []; + } + + public static function get_smart_drive_list() + { + return self::call_pfsense_method_with_same_name_and_arguments(func_get_args()) ?: []; + } + + public static function get_ipsecifnum() + { + return self::call_pfsense_method_with_same_name_and_arguments(func_get_args()); + } + + public static function ipsec_conid() + { + return self::call_pfsense_method_with_same_name_and_arguments(func_get_args()); + } + + public static function get_pkg_info() + { + return self::call_pfsense_method_with_same_name_and_arguments(func_get_args()); + } + + public static function get_single_sysctl() + { + return self::call_pfsense_method_with_same_name_and_arguments(func_get_args()); + } + + public static function get_system_pkg_version() + { + return self::call_pfsense_method_with_same_name_and_arguments(func_get_args()); + } + + public static function init_config_arr() + { + return self::call_pfsense_method_with_same_name_and_arguments(func_get_args()); + } + + public static function install_cron_job() + { + return self::call_pfsense_method_with_same_name_and_arguments(func_get_args()); + } + + public static function ipsec_ikeid_used() + { + return self::call_pfsense_method_with_same_name_and_arguments(func_get_args()); + } + + public static function ipsec_list_sa() + { + return self::call_pfsense_method_with_same_name_and_arguments(func_get_args()) ?: []; + } + + public static function is_service_enabled() + { + return self::call_pfsense_method_with_same_name_and_arguments(func_get_args()); + } + + public static function openvpn_get_active_clients() + { + return self::call_pfsense_method_with_same_name_and_arguments(func_get_args()) ?: []; + } + + public static function openvpn_get_active_servers() + { + return self::call_pfsense_method_with_same_name_and_arguments(func_get_args()) ?: []; + } + + public static function return_gateways_status() + { + return self::call_pfsense_method_with_same_name_and_arguments(func_get_args()); + } + + public static function system_get_dhcpleases() + { + return self::call_pfsense_method_with_same_name_and_arguments(func_get_args()); + } +} + +class Util +{ + public static function array_first(Closure $match, array $haystack) + { + foreach ($haystack as $needle) { + if ($match($needle)) { + return $needle; + } + } + + return null; + } + + public static function array_flatten(array $multi_dimensional_array): array + { + return array_merge(...$multi_dimensional_array) ?: []; + } + + public static function b2int(bool $b): int + { + return (int)$b; + } + + public static function result($result, bool $echo_result = true) + { + if ($echo_result) { + echo $result; + } + + return $result; + } + + public static function space_to_underscore($value) + { + return str_replace(" ", "__", $value); + } + + public static function underscore_to_space($value) + { + return str_replace("__", " ", $value); + } +} + +class NetworkInterface +{ + public static function retrieve_wan_interfaces(): array + { + $interfaces = []; + + foreach (PfEnv::get_configured_interface_with_descr(true) as $if_name => $description) { + $interfaces[] = array_merge( + PfEnv::get_interface_info($if_name), + ["description" => $description], + ); + } + + return array_filter($interfaces, function ($iface_info_ext) { + $has_gw = array_key_exists("gateway", $iface_info_ext); + // Issue #81 - https://stackoverflow.com/a/13818647/15093007 + $has_public_ip = + filter_var( + $iface_info_ext["ipaddr"], + FILTER_VALIDATE_IP, + FILTER_FLAG_IPV4 | FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE); + $is_vpn = strpos($iface_info_ext["if"], "ovpn") !== false; + + return ($has_gw || $has_public_ip) && !$is_vpn; + }); + } +} + +class Shell +{ + const ARP = "/usr/sbin/arp"; + const AWK = "/usr/bin/awk"; + const CAT = "/bin/cat"; + const SMART_CTL = "/usr/local/sbin/smartctl"; + const SPEED_TEST = "/usr/local/bin/speedtest"; + + public static function run_speed_test(string $source_ip_address, string $output_file_path) + { + $tmp_file_path = tempnam(sys_get_temp_dir(), "speedtest."); + + exec(implode(" ", [self::SPEED_TEST, "--source", $source_ip_address, "--json", ">", $tmp_file_path])); + + rename($tmp_file_path, $output_file_path); + } + + public static function read_smart_status(string $device_name): string + { + return trim(exec( + implode(" ", + [ + self::SMART_CTL, "-H", "/dev/$device_name", "|", + self::AWK, "-F:", "'/^SMART overall-health self-assessment test result/ {print $2;exit} / + ^SMART Health Status/ {print $2;exit}'"]))); + } + + public static function read_dhcpd_records(string $leases_file_path): array + { + // Remove all content up to the first lease record + $clean_pattern = "'/lease.*{\$/,0'"; + + // Split file into records by '}' + $split_pattern = "'BEGIN { RS=ORS=\"}\" } { gsub(\"\\n\", \"\"); print; printf \"\\n\"}'"; + + // Stuff the leases file in a proper format into an array by line + exec( + implode(" ", + [ + self::CAT, $leases_file_path, "2>/dev/null", "|", + self::AWK, $clean_pattern, "|", + self::AWK, $split_pattern]), $raw_lease_records); + + return array_filter($raw_lease_records, fn($r) => preg_match("/^lease.*|^failover.*/", $r)); + } + + public static function read_arp_ips(): array + { + exec(implode(" ", [ + self::ARP, "-an", "|", + self::AWK, "'{ gsub(/[()]/,\"\") } {print $2}'"]), $arp_data); + + return $arp_data; + } +} + +class Service +{ + public static function enabled(array $service, $name, $short_name): int + { + return Util::b2int(PfEnv::is_service_enabled($short_name)); + } + + public static function name(array $service, string $name): string + { + return $name; + } + + public static function status(array $service): int + { + $status = PfEnv::get_service_status($service); + + if (!empty($status)) { + return $status; + } + + return FALLBACK_VALUE; + } + + public static function run_on_carp_slave(array $service, $name, $short_name, $carpcfr, $stopped_on_carp_slave): int + { + return Util::b2int(in_array($carpcfr, $stopped_on_carp_slave)); + } +} + +class Discovery +{ + public static function gw() + { + $gateway_discoveries = []; + foreach (PfEnv::return_gateways_status(true) as $gateway) { + $gateway_discoveries[] = ["{#GATEWAY}" => $gateway["name"]]; + } + + self::print_json($gateway_discoveries); + } + + public static function wan() + { + self::discover_interface(true); + } + + private static function sanitize_server_name(string $raw_name): string + { + return trim(preg_replace('/\w{3}(\d)?\:\d{4,5}/i', '', $raw_name)); + } + + public static function temperature_sensors() + { + $json_string = '{"data":['; + $sensors = []; + exec("sysctl -a | grep temperature | cut -d ':' -f 1", $sensors, $code); + if ($code != 0) { + echo ""; + return; + } else { + foreach ($sensors as $sensor) { + $json_string .= '{"{#SENSORID}":"' . $sensor . '"'; + $json_string .= '},'; + } + } + + $json_string = rtrim($json_string, ","); + $json_string .= "]}"; + + echo $json_string; + } + + public static function openvpn_server() + { + $active_openvpn_server_discoveries = []; + foreach (OpenVpn::get_active_servers() as $server) { + $active_openvpn_server_discoveries[] = [ + "{#SERVER}" => $server["vpnid"], + "{#NAME}" => self::sanitize_name($server["name"]), + ]; + } + + self::print_json($active_openvpn_server_discoveries); + } + + public static function openvpn_server_user() + { + $servers_with_relevant_mode = + array_filter( + OpenVpn::get_active_servers(), + fn($server) => in_array($server["mode"], ["server_user", "server_tls_user", "server_tls"])); + + $servers_with_conns = array_filter( + $servers_with_relevant_mode, + fn($server) => is_array($server["conns"])); + + $server_discoveries = []; + foreach ($servers_with_conns as $server) { + $server_discoveries[] = self::map_server($server); + } + + self::print_json(Util::array_flatten($server_discoveries)); + } + + public static function openvpn_client() + { + $client_discoveries = []; + foreach (PfEnv::openvpn_get_active_clients() as $client) { + $client_discoveries[] = [ + "{#CLIENT}" => $client["vpnid"], + "{#NAME}" => self::sanitize_name($client["name"]), + ]; + } + + self::print_json($client_discoveries); + } + + public static function services() + { + $named_services = array_filter(PfEnv::get_services(), fn($service) => !empty($service["name"])); + + $service_discoveries = []; + foreach ($named_services as $service) { + $maybe_id = Util::array_first(fn($key) => in_array($key, ["id", "zone"]), array_keys($service)); + + $id = ""; + if (!is_null($maybe_id)) { + $id = $service[$maybe_id]; + } + + $service_discoveries[] = [ + "{#SERVICE}" => sprintf("%s%s", Util::space_to_underscore($service["name"]), $id), + "{#DESCRIPTION}" => $service["description"], + ]; + } + + self::print_json($service_discoveries); + } + + public static function interfaces() + { + self::discover_interface(); + } + + public static function ipsec_ph1() + { + PfEnv::init_config_arr(array("ipsec", "phase1")); + + $config = PfEnv::cfg(); + + $ipsec_ph1_discoveries = []; + foreach ($config["ipsec"]["phase1"] as $data) { + $ipsec_ph1_discoveries[] = [ + "{#IKEID}" => $data["ikeid"], + "{#NAME}" => $data["descr"], + ]; + } + + self::print_json($ipsec_ph1_discoveries); + } + + public static function ipsec_ph2() + { + PfEnv::init_config_arr(array("ipsec", "phase2")); + + $config = PfEnv::cfg(); + + $ipsec_ph2_discoveries = []; + foreach ($config["ipsec"]["phase2"] as $data) { + $ipsec_ph2_discoveries[] = [ + "{#IKEID}" => $data["ikeid"], + "{#NAME}" => $data["descr"], + "{#UNIQID}" => $data["uniqid"], + "{#REQID}" => $data["reqid"], + "{#EXTID}" => sprintf("%s.%s", $data["ikeid"], $data["reqid"]), + ]; + } + + self::print_json($ipsec_ph2_discoveries); + } + + public static function dhcpfailover() + { + // System public static functions regarding DHCP Leases will be available in the upcoming release of pfSense, so let's wait + $leases = PfEnv::system_get_dhcpleases(); + + $dhcp_failover_discoveries = []; + foreach ($leases["failover"] as $data) { + $dhcp_failover_discoveries[] = [ + "{#FAILOVER_GROUP}" => Util::space_to_underscore($data["name"]), + ]; + } + + self::print_json($dhcp_failover_discoveries); + } + + private static function print_json(array $json) + { + echo json_encode([ + "data" => $json + ]); + } + + private static function sanitize_name(string $raw_name): string + { + return trim(preg_replace("/\w{3}(\d)?:\d{4,5}/i", "", $raw_name)); + } + + private static function map_conn(string $server_name, string $vpn_id, array $conn): array + { + return [ + "{#SERVERID}" => $vpn_id, + "{#SERVERNAME}" => $server_name, + "{#UNIQUEID}" => sprintf("%s+%s", $vpn_id, $conn["common_name"]), + "{#USERID}" => $conn["common_name"], + ]; + } + + private static function map_conns(string $server_name, string $vpn_id, array $conns): array + { + $conn_discoveries = []; + foreach ($conns as $conn) { + $conn_discoveries[] = self::map_conn($server_name, $vpn_id, $conn); + + } + + return $conn_discoveries; + } + + private static function map_server(array $server): array + { + return self::map_conns( + self::sanitize_name($server["name"]), + $server["vpnid"], + $server["conns"]); + } + + private static function discover_interface($is_wan = false) + { + if (!$is_wan) { + self::print_json([]); + return; + } + + $wan_interface_discoveries = []; + foreach (NetworkInterface::retrieve_wan_interfaces() as $hwif) { + $wan_interface_discoveries[] = [ + "{#IFNAME}" => $hwif["hwif"], + "{#IFDESCR}" => $hwif["description"], + ]; + } + + self::print_json($wan_interface_discoveries); + } +} + +class SpeedTest +{ + public static function interface_value($if_name, $value) + { + list($tv0, $tv1) = explode(".", $value); + + $filename = self::if_filename($if_name); + if (!file_exists($filename)) { + return Util::result(""); + } + + $speed_test_data = json_decode(file_get_contents($filename), true) ?? []; + if (!array_key_exists($value, $speed_test_data)) { + return Util::result(""); + } + + if (empty($tv1)) { + return Util::result($speed_test_data[$tv0]); + } + + return Util::result($speed_test_data[$tv0][$tv1]); + } + + public static function cron_install($enable = true) + { + PfEnv::install_cron_job( + implode(" ", ["/usr/local/bin/php", __FILE__, "speedtest_cron"]), + $enable, + "*/15", "*", "*", "*", "*", + "root", + true); + } + + public static function run($if_name, $ip_address) + { + $output_file_path = self::if_filename($if_name); + + $is_output_file_older_than_interval = + !file_exists($output_file_path) || + (time() - filemtime($output_file_path) > SPEED_TEST_INTERVAL_SECONDS); + if (!$is_output_file_older_than_interval) { + return; + } + + self::run_exclusively(function () use ($ip_address, $output_file_path) { + // Issue #82 + // Sleep random delay in order to avoid problem when 2 pfSense on the same Internet line + sleep(rand(SPEED_TEST_RANDOM_DELAY_MIN_SECONDS, SPEED_TEST_RANDOM_DELAY_MAX_SECONDS)); + + Shell::run_speed_test($ip_address, $output_file_path); + }); + } + + private static function run_exclusively(Closure $fn) + { + $fp = fopen(implode("", [sys_get_temp_dir(), "pfz-speedtest.lock"]), "w"); + + $is_other_test_currently_running = !flock($fp, LOCK_EX | LOCK_NB); + if ($is_other_test_currently_running) { + fclose($fp); + return; + } + + $fn(); + + flock($fp, LOCK_UN); + + fclose($fp); + } + + private static function if_filename($if_name): string + { + return implode(DIRECTORY_SEPARATOR, [sys_get_temp_dir(), "speedtest-$if_name"]); + } +} + +class OpenVpn +{ + public static function get_active_servers(): array + { + $servers = PfEnv::openvpn_get_active_servers(); + $sk_servers = PfEnv::openvpn_get_active_servers("p2p"); + + return array_merge($servers, $sk_servers); + } +} + +class Command +{ + private const BINDING_STATES = [ + "active" => [ + "act" => TEXT_ACTIVE, + ], + "free" => [ + "act" => TEXT_EXPIRED, + "online" => TEXT_OFFLINE, + ], + "backup" => [ + "act" => TEXT_RESERVED, + "online" => TEXT_OFFLINE, + ], + ]; + + public static function discovery($section) + { + $is_known_section = in_array(strtolower($section), DISCOVERY_SECTION_HANDLERS); + if (!$is_known_section) { + return; + } + + Discovery::{$section}(); + } + + public static function gw_value($gw, $value_key) + { + $gws = PfEnv::return_gateways_status(true); + if (!array_key_exists($gw, $gws)) { + return Util::result(""); + } + + $gw_data = $gws[$gw]; + + $value = $gw_data[$value_key]; + if ($value_key != "status") { + return Util::result($value); + } + + $substatus = $gw_data["substatus"]; + $has_relevant_substatus = $substatus != "none"; // Issue #70: Gateway Forced Down + + return Util::result(self::get_value_mapping( + "gateway.status", + $has_relevant_substatus ? $substatus : $value)); + } + + public static function gw_status() + { + $gw_statuses = []; + foreach (PfEnv::return_gateways_status(true) as $gw) { + $gw_statuses[] = sprintf("%s.%s", $gw["name"], $gw["status"]); + } + + return Util::result(implode(",", $gw_statuses)); + } + + public static function if_speedtest_value($if_name, $value) + { + SpeedTest::cron_install(); + SpeedTest::interface_value($if_name, $value); + } + + public static function openvpn_servervalue(int $server_id, $value_key) + { + $maybe_server = Util::array_first(fn($s) => $s["vpnid"] == $server_id, OpenVpn::get_active_servers()); + if (empty($maybe_server)) { + return Util::result(FALLBACK_VALUE); + } + + $server_value = self::get_server_value($maybe_server, $value_key); + + if ($value_key == "conns") { + return Util::result(is_array($server_value) ? count($server_value) : FALLBACK_VALUE); + } + + if (in_array($value_key, ["status", "mode"])) { + return Util::result(self::get_value_mapping("openvpn.server.status", $server_value)); + } + + return Util::result($server_value); + } + + public static function openvpn_server_uservalue($unique_id, $value_key) + { + return self::get_openvpn_server_uservalue_($unique_id, $value_key); + } + + public static function openvpn_server_uservalue_numeric($unique_id, $value_key) + { + return self::get_openvpn_server_uservalue_($unique_id, $value_key, FALLBACK_VALUE); + } + + public static function openvpn_clientvalue($client_id, $value_key, $fallback_value = FALLBACK_VALUE) + { + $maybe_client = Util::array_first( + fn($client) => $client["vpnid"] == $client_id, + PfEnv::openvpn_get_active_clients()); + if (empty($maybe_client)) { + return Util::result($fallback_value); + } + + $value = ($value_key == "status") ? + self::sanitize_openvpn_clientvalue_status($maybe_client) : + $maybe_client[$value_key]; + + if ($value == "") { + return Util::result($fallback_value); + } + + return Util::result($value); + } + + public static function service_value(string $name, string $value) + { + $sanitized_name = Util::underscore_to_space($name); + + // List of service which are stopped on CARP Slave. + // For now this is the best way I found for filtering out the triggers + // Waiting for a way in Zabbix to use Global Regexp in triggers with items discovery + $stopped_on_carp_slave = array("haproxy", "radvd", "openvpn.", "openvpn", "avahi"); + + $maybe_service = Util::array_first(function ($service) use ($sanitized_name) { + foreach (["id", "zone"] as $key) { + if (array_key_exists($key, $service)) { + return sprintf("%s%s", $service["name"], $service[$key]) == $sanitized_name; + } + } + + return $service["name"] == $sanitized_name; + }, PfEnv::get_services()); + + if (empty($maybe_service)) { + return Util::result(FALLBACK_VALUE); + } + + $short_name = $maybe_service["name"]; + $carp_cfr = "$short_name."; + + $is_known_service_value = in_array($value, SERVICES_VALUE_HANDLERS); + if (!$is_known_service_value) { + return Util::result($maybe_service[$value]); + } + + return Util::result( + Service::{$value}( + $maybe_service, + $sanitized_name, + $short_name, + $carp_cfr, + $stopped_on_carp_slave)); + } + + public static function temperature($sensorid) + { + exec("sysctl '$sensorid' | cut -d ':' -f 2", $value, $code); + if ($code != 0 or count($value) != 1) { + echo ""; + return; + } + + echo trim($value[0]); + } + + public static function carp_status(): int + { + return Util::result(self::get_carp_status()); + } + + // System Information + public static function system($section) + { + if ($section === "packages_update") { + return Util::result(self::get_outdated_packages()); + } + + $system_pkg_version = PfEnv::get_system_pkg_version(); + if ($section === "new_version_available") { + return Util::result( + Util::b2int($system_pkg_version["version"] != $system_pkg_version["installed_version"])); + } + + $is_known_section = array_key_exists($section, $system_pkg_version); + + if ($is_known_section) { + return Util::result($$system_pkg_version[$section]); + } + + return Util::result(""); + } + + public static function ipsec_ph1($ike_id, $value_key) + { + // Get Value from IPsec Phase 1 Configuration + // If Getting "disabled" value only check item presence in config array + $config = PfEnv::cfg(); + PfEnv::init_config_arr(["ipsec", "phase1"]); + $a_phase2 = $config["ipsec"]["phase1"] ?: []; + + if ($value_key == "status") { + return Util::result(Command::get_ipsec_status($ike_id)); + } + + if ($value_key == "disabled") { + return Util::result(FALLBACK_VALUE); + } + + $maybe_ike_match = Util::array_first(fn($d) => $d["ikeid"] == $ike_id, $a_phase2); + if (empty($maybe_ike_match)) { + return Util::result(FALLBACK_VALUE); + } + + if (!array_key_exists($value_key, $maybe_ike_match)) { + return Util::result(FALLBACK_VALUE); + } + + return Util::result(self::get_value_mapping("ipsec.$value_key", $maybe_ike_match[$value_key])); + } + + public static function ipsec_ph2($uniqid, $value_key) + { + $config = PfEnv::cfg(); + PfEnv::init_config_arr(array("ipsec", "phase2")); + $a_phase2 = $config["ipsec"]["phase2"] ?: []; + + $valuecfr = explode(".", $value_key); + + $value = FALLBACK_VALUE; + if ($valuecfr[0] == "status") { + $ids = explode(".", $uniqid); + $status_key = (isset($valuecfr[1])) ? $valuecfr[1] : "state"; + $value = self::get_ipsec_status($ids[0], $ids[1], $status_key); + } + + $maybe_data = Util::array_first(fn($data) => $data["uniqid"] == $uniqid, $a_phase2); + if (is_null($maybe_data) || !array_key_exists($value_key, $maybe_data)) { + return Util::result($value); + } + + if ($value_key != "disabled") { + return Util::result(self::get_value_mapping("ipsec_ph2." . $value_key, $maybe_data[$value_key])); + } + + return Util::result(1); + } + + public static function dhcp($section) + { + if ($section === "failover") { + return Util::result(self::check_dhcp_failover()); + + } + + return Util::result(self::check_dhcp_offline_leases()); + } + + // File is present + public static function file_exists($filename) + { + return Util::result(Util::b2int(file_exists($filename))); + } + + public static function speedtest_cron() + { + foreach (NetworkInterface::retrieve_wan_interfaces() as $if_info) { + SpeedTest::run($if_info["hwif"], $if_info["ipaddr"]); + } + } + + public static function cron_cleanup() + { + SpeedTest::cron_install(false); + } + + // S.M.A.R.T Status + // Taken from /usr/local/www/widgets/widgets/smart_status.widget.php + public static function smart_status() + { + $dev_states = []; + foreach (PfEnv::get_smart_drive_list() as $device_name) { + $dev_states[] = Shell::read_smart_status($device_name); + } + + $smart_states = []; + foreach ($dev_states as $dev_state) { + $smart_states[] = array_key_exists($dev_state, SMART_DEV_STATUS) ? + SMART_DEV_STATUS[$dev_state] : + SMART_ERROR; + } + + $maybe_not_ok = Util::array_first(function ($smart_state) { + return $smart_state != SMART_OK; + }, $smart_states); + + return Util::result($maybe_not_ok ?: SMART_OK); + } + + public static function cert_date($value_key) + { + if (!array_key_exists($value_key, CERT_VK_TO_FIELD)) { + return Util::result(FALLBACK_VALUE); + } + + $field = CERT_VK_TO_FIELD[$value_key]; + $config = PfEnv::cfg(); + + $certs_and_cas = []; + foreach (["cert", "ca"] as $cert_type) { + $certs_and_cas[] = $config[$cert_type] ?: []; + } + $all_certs = Util::array_flatten($certs_and_cas); + + return Util::result(array_reduce($all_certs, function ($value, $certificate) use ($field) { + $cert_info = openssl_x509_parse(base64_decode($certificate["crt"])); + + if ($value == 0 || $value < $cert_info[$field]) { + return $cert_info[$field]; + } + + return $value; + }, FALLBACK_VALUE)); + } + + // Testing function, for template creating purpose + public static function test() + { + $config = PfEnv::cfg(); + + echo "OPENVPN Servers:\n"; + print_r(OpenVpn::get_active_servers()); + echo LINE; + + echo "OPENVPN Clients:\n"; + print_r(PfEnv::openvpn_get_active_clients()); + echo LINE; + + $ifdescrs = PfEnv::get_configured_interface_with_descr(true); + $ifaces = []; + foreach ($ifdescrs as $ifdescr => $ifname) { + $ifaces[$ifname] = PfEnv::get_interface_info($ifdescr); + } + echo "Network Interfaces:\n"; + print_r($ifaces); + print_r(PfEnv::get_interface_arr()); + print_r(PfEnv::get_configured_interface_list()); + echo LINE; + + echo "Services: \n"; + print_r(PfEnv::get_services()); + echo LINE; + + echo "IPsec: \n"; + PfEnv::init_config_arr(array("ipsec", "phase1")); + PfEnv::init_config_arr(array("ipsec", "phase2")); + echo "IPsec Status: \n"; + print_r(PfEnv::ipsec_list_sa()); + + echo "IPsec Config Phase 1: \n"; + print_r($config["ipsec"]["phase1"]); + + echo "IPsec Config Phase 2: \n"; + print_r($config["ipsec"]["phase2"]); + + echo LINE; + + echo "Packages: \n"; + print_r(PfEnv::get_pkg_info("all", false, true)); + } + + private static function sanitize_openvpn_clientvalue_status($client_data) + { + $is_pre_version_22_05 = in_array($client_data["status"], array_keys(VALUE_MAPPINGS["openvpn.client.status"])); + + $raw_value = $is_pre_version_22_05 ? + $client_data["status"] : $client_data["state"]; + + return self::get_value_mapping("openvpn.client.status", $raw_value); + } + + private static function get_carp_status(): int + { + $is_carp_enabled = PfEnv::get_carp_status() != 0; + if (!$is_carp_enabled) { + return CARP_STATUS_DISABLED; + } + + $is_carp_demotion_status_ok = PfEnv::get_single_sysctl("net.inet.carp.demotion") == 0; + if (!$is_carp_demotion_status_ok) { + return CARP_STATUS_PROBLEM; + } + + $config = PfEnv::cfg(); + + $just_carps = array_filter($config["virtualip"]["vip"], fn($virtual_ip) => $virtual_ip["mode"] != "carp"); + $status_str = array_reduce($just_carps, function ($status, $carp) { + $if_status = PfEnv::get_carp_interface_status("_vip{$carp["uniqid"]}"); + + $state_differs_from_previous_interface = ($status != $if_status) && (!empty($if_status)); + if (!$state_differs_from_previous_interface) { + return $status; + } + + if ($status != "") { + return CARP_INCONSISTENT; + } + + return $if_status; + }, ""); + + $is_known_carp_status = array_key_exists($status_str, CARP_RES); + + return $is_known_carp_status ? CARP_RES[$status_str] : CARP_STATUS_UNKNOWN; + } + + private static function get_openvpn_server_uservalue_($unique_id, $value_key, $default = "") + { + list($server_id, $user_id) = explode("+", $unique_id); + + $servers = OpenVpn::get_active_servers(); + + $maybe_server = Util::array_first(fn($server) => $server["vpnid"] == $server_id, $servers); + if (!$maybe_server) { + return $default; + } + + $maybe_conn = Util::array_first(fn($conn) => ($conn["common_name"] == $user_id), $maybe_server["conns"] ?: []); + + return $maybe_conn[$value_key] ?: $default; + } + + private static function get_server_value($maybe_server, $value_key) + { + if (empty($maybe_server)) { + return null; + } + + $raw_value = $maybe_server[$value_key]; + if (in_array($maybe_server["mode"], ["server_user", "server_tls_user", "server_tls"])) { + return $raw_value == "" ? "server_user_listening" : $raw_value; + } + + // For p2p_tls, ensure we have one client, and return up if it's the case + if ($maybe_server["mode"] == "p2p_tls" && $raw_value == "") { + $has_at_least_one_connection = + is_array($maybe_server["conns"]) && count($maybe_server["conns"]) > 0; + + return $has_at_least_one_connection ? "up" : "down"; + } + + return $raw_value; + } + + private static function get_ipsec_status($ike_id, $req_id = -1, $value_key = "state") + { + PfEnv::init_config_arr(array("ipsec", "phase1")); + + $process_result = function ($vk, $r) { + if ($vk != "state") { + return $r; + } + + $v = self::get_value_mapping("ipsec.state", strtolower($r[$vk])); + + $carp_status = self::get_carp_status(); + + if ($carp_status != 0) { + return $v + (10 * ($carp_status - 1)); + } + + return $v; + }; + + $ipsec_list_sa = PfEnv::ipsec_list_sa(); + if (!is_array($ipsec_list_sa)) { + return 0; + } + + $config = PfEnv::cfg(); + + $connection_map = array_reduce($config["ipsec"]["phase1"], function ($p, $ph1ent) { + $ike_id = $ph1ent["ikeid"]; + + if (function_exists('get_ipsecifnum')) { + $id_name = (PfEnv::get_ipsecifnum($ike_id, 0)); + + $cname = $id_name ? "con$id_name" : "con{$ike_id}00000"; + } else { + $cname = PfEnv::ipsec_conid($ph1ent); + } + + return array_merge( + $p, + [$cname => $ike_id], + ); + }, []); + + + // Phase-Status match borrowed from status_ipsec.php + $maybe_ike_sa = Util::array_first(function ($ike_sa) use ($ike_id, $connection_map) { + $con_id = isset($ike_sa["con-id"]) ? + substr($ike_sa["con-id"], 3) : + filter_var($ike_id, FILTER_SANITIZE_NUMBER_INT); + + $con_name = "con$con_id"; + + $is_version_1 = $ike_sa["version"] == 1; + $is_split_connection = !$is_version_1 && !PfEnv::ipsec_ikeid_used($con_id); + + $ph1idx = ($is_version_1 || $is_split_connection) ? $connection_map[$con_name] : $con_id; + + return $ph1idx == $ike_id; + }, $ipsec_list_sa); + + if (!$maybe_ike_sa) { + return 0; + } + + if ($req_id == -1) { + return $process_result($value_key, $maybe_ike_sa); + } + + $just_matching_child_sas = + array_filter($maybe_ike_sa["child-sas"], fn($child_sa) => ($child_sa["reqid"] == $req_id)); + + if (count($just_matching_child_sas) === 0) { + return 0; + } + + $result = NULL; + + // Asking for Phase2 Status Value + foreach ($just_matching_child_sas as $child_sa) { + $result = $child_sa; + + // If state is rekeyed go on + if (strtolower($child_sa["state"]) == "rekeyed") { + break; + } + } + + return $process_result($value_key, $result); + } + + private static function remove_duplicates(array $haystack, $field): array + { + return array_values(array_reduce($haystack, fn($lookup_table, $item) => array_merge( + $lookup_table, [$item[$field] => $item] + ), [])); + } + + private static function parse_raw_record(string $raw_lease_data): array + { + $raw_lease_data_lines = []; + foreach (explode(";", $raw_lease_data) as $raw_line) { + $raw_lease_data_lines[] = trim($raw_line); + } + + $lease_data_lines = array_filter($raw_lease_data_lines); + + return array_reduce( + $lease_data_lines, + function ($p, $lease_data_line) { + list($k, $v) = array_pad(explode(" ", $lease_data_line, 2), 2, true); + + return array_merge($p, [$k => $v]); + }, + []); + } + + private static function parse_failover_record(array $data): array + { + $sanitized_data = []; + foreach ($data as $line) { + $sanitized_data[] = trim($line); + } + + list($name, $raw_lease_data) = $sanitized_data; + + return [ + "type" => "failover", + "data" => array_merge( + ["name" => $name], + self::parse_raw_record($raw_lease_data))]; + } + + private static function parse_lease_record(array $data): array + { + $sanitized_data = []; + foreach ($data as $line) { + $sanitized_data[] = trim($line); + } + + list($lease_address, $raw_lease_data) = $sanitized_data; + + return [ + "type" => "lease", + "data" => array_merge( + ["ip" => $lease_address], + self::parse_raw_record($raw_lease_data))]; + } + + private static function parse_dhcp_record(string $record): ?array + { + $is_lease_record = preg_match("/^lease\s+(.*)\s+{(.+)}$/", $record, $lease_record_match); + $is_failover_record = preg_match("/^failover.*\"(.*)\"\s+state\s+{(.+)}$/", $record, $failover_record_match); + + $is_known_record_type = $is_lease_record || $is_failover_record; + if (!$is_known_record_type) { + return null; + } + + if ($is_lease_record) { + return self::parse_lease_record(array_slice($lease_record_match, 1)); + } + + return self::parse_failover_record(array_slice($failover_record_match, 1)); + } + + private static function read_dhcp_records_from_file(string $leases_file_path): array + { + $dhcp_records = []; + foreach (Shell::read_dhcpd_records($leases_file_path) as $raw_dhcp_record) { + $dhcp_records[] = self::parse_dhcp_record($raw_dhcp_record); + + } + + return $dhcp_records; + } + + private static function binding_to_state($binding): array + { + $is_known_binding = array_key_exists($binding, self::BINDING_STATES); + if (!$is_known_binding) { + return [ + "act" => "", + ]; + } + + return self::BINDING_STATES[$binding]; + } + + private static function raw_lease_record_to_lease(array $raw_lease_record, array $arpdata_ip): array + { + $data = $raw_lease_record["data"]; + + $ip = $data["ip"]; + $maybe_client_hostname = + array_key_exists("client-hostname", $data) ? + str_replace("\"", "", $data["client-hostname"]) : + null; + + list(, $binding) = explode(" ", $data["binding"]); + list(, $mac) = explode(" ", $data["hardware"]); + list(, $start_date, $start_time) = explode(" ", $data["starts"]); + + $hostname = + !empty($maybe_client_hostname) ? + preg_replace('/"/', "", $maybe_client_hostname) : + gethostbyaddr($data["ip"]); + + $online = in_array($data["ip"], $arpdata_ip) ? TEXT_ONLINE : TEXT_OFFLINE; + + $binding_state = self::binding_to_state($binding); + + $start = implode(" ", [$start_date, $start_time]); + list(, $end_date, $end_time) = array_pad(explode(" ", $data["ends"]), 3, null); + + $end = ($end_date == "never") ? TEXT_NEVER : implode(" ", [$end_date, $end_time]); + + return array_merge(compact("end", "hostname", "ip", "mac", "online", "start"), $binding_state); + } + + private static function raw_failover_record_to_pool(array $raw_failover_record): array + { + $data = $raw_failover_record["data"]; + + $n0 = $data["name"]; + + $friendly_description = PfEnv::convert_friendly_interface_to_friendly_descr(substr($n0, 5)); + $name = "$n0 ($friendly_description)"; + + list($my_state_str, $my_time_str) = explode(" at ", $data["my"]); + list($partner_state_str, $partner_time_str) = explode(" at ", $data["partner"]); + + list(, $mystate) = explode(" ", $my_state_str); + list(, $peerstate) = explode(" ", $partner_state_str); + list(, $my_date, $my_time) = explode(" ", $my_time_str); + list(, $partner_date, $partner_time) = explode(" ", $partner_time_str); + + $mydate = implode(" ", [$my_date, $my_time]); + $peerdate = implode(" ", [$partner_date, $partner_time]); + + return compact("name", "mystate", "peerstate", "mydate", "peerdate"); + } + + // Get DHCP Arrays (copied from status_dhcp_leases.php, waiting for pfsense 2.5, in order to use system_get_dhcpleases();) + private static function get_dhcp($value_key): array + { + $leases_file = implode( + DIRECTORY_SEPARATOR, + [PfEnv::g("dhcpd_chroot_path"), "var", "db", "dhcpd.leases"]); + + $dhcp_records = self::read_dhcp_records_from_file($leases_file); + + $failover = []; + if ($value_key === "failover") { + return $failover; + } + + if ($value_key === "pools") { + $failover_records = array_filter($dhcp_records, fn($r) => $r["type"] == "failover"); + + $pools = []; + foreach ($failover_records as $failover_record) { + $pools[] = self::raw_failover_record_to_pool($failover_record); + } + + return self::remove_duplicates($pools, "name"); + } + + $arp_ips = Shell::read_arp_ips(); + + $leases = []; + foreach (array_filter($dhcp_records, fn($r) => $r["type"] == "lease") as $lease_record) { + $leases[] = self::raw_lease_record_to_lease($lease_record, $arp_ips); + } + + return self::remove_duplicates($leases, "mac"); + } + + private static function check_dhcp_offline_leases(): int + { + return count(array_filter( + self::get_dhcp("leases"), + fn($f) => $f["online"] != TEXT_ONLINE)); + } + + private static function check_dhcp_failover(): int + { + // Check DHCP Failover Status + // Returns number of failover pools which state is not normal or + // different from peer state + $failover_pools = self::get_dhcp("pools"); + + return count(array_filter( + $failover_pools, + fn($f) => ($f["mystate"] != "normal") || ($f["mystate"] != $f["peerstate"]))); + } + + private static function get_outdated_packages(): int + { + return count(array_filter( + PfEnv::get_pkg_info("all", false, true), + fn($p) => $p["version"] != $p["installed_version"])); + } + + // Value mappings + // Each value map is represented by an associative array + private static function get_value_mapping($value_name, $value) + { + $is_known_value_name = array_key_exists($value_name, VALUE_MAPPINGS); + if (!$is_known_value_name) { + return FALLBACK_VALUE; + } + + $value_mapping = VALUE_MAPPINGS[$value_name]; + if (!is_array($value_mapping)) { + return FALLBACK_VALUE; + } + + $sanitized_value = strtolower($value); + $is_value_with_known_mapping = array_key_exists($sanitized_value, $value_mapping); + + if ($is_value_with_known_mapping) { + return $value_mapping[$sanitized_value]; + } + + return FALLBACK_VALUE; + } +} + +function build_method_lookup(string $clazz): array +{ + try { + $reflector = new ReflectionClass($clazz); + + $all_methods = $reflector->getMethods(); + + $commands = array_filter($all_methods, fn($method) => $method->isStatic() && $method->isPublic()); + + $available_methods = []; + foreach ($commands as $method) { + $available_methods[] = $method->getName(); + } + + return $available_methods; + } catch (Exception $e) { + return []; + } +} + +function main($arguments) +{ + $command = strtolower($arguments[1]); + $parameters = array_slice($arguments, 2); + + if ($command == "help") { + print_r(COMMAND_HANDLERS); + exit; + } + + $is_known_command = in_array($command, COMMAND_HANDLERS); + if (!$is_known_command) { + Command::test(); + exit; + } + + Command::{$command}(...$parameters); +} + +main($argv); diff --git a/template_pfsense_active.xml b/zabbix4/template_pfsense_active.xml similarity index 98% rename from template_pfsense_active.xml rename to zabbix4/template_pfsense_active.xml index 036fd30..7b8638a 100644 --- a/template_pfsense_active.xml +++ b/zabbix4/template_pfsense_active.xml @@ -1,7 +1,7 @@ 4.0 - 2021-01-18T15:00:52Z + 2021-07-04T19:16:51Z Templates/Network Devices @@ -21,9 +21,6 @@ https://github.com/rbicelli/pfsense-zabbix-template - - CARP - CPU @@ -33,6 +30,9 @@ https://github.com/rbicelli/pfsense-zabbix-template Gateways + + HA + Memory @@ -271,7 +271,7 @@ https://github.com/rbicelli/pfsense-zabbix-template 0 - CARP + HA @@ -745,7 +745,7 @@ https://github.com/rbicelli/pfsense-zabbix-template 0 - CARP + HA @@ -774,6 +774,65 @@ https://github.com/rbicelli/pfsense-zabbix-template 0 + + DHCP Failover Pool Problems + 7 + + + pfsense.value[dhcp,failover] + 120s + 90d + 365d + 0 + 3 + + + + + 0 + 0 + + 0 + + + + 0 + + + + + + This value indicates, in a HA scenario, if DHCP failover pool partners are out of sync. + 0 + + + HA + + + + + + + 3s + + + + 200 + 1 + 0 + + + 0 + 0 + 0 + 0 + + + + 0 + 0 + + Gateway Status Raw 7 @@ -2466,7 +2525,7 @@ https://github.com/rbicelli/pfsense-zabbix-template - quantité de mémoire en cours d'utilisation par les processus + Memory used by processes 0 @@ -2645,7 +2704,7 @@ https://github.com/rbicelli/pfsense-zabbix-template - quantité de mémoire utilisée pour mettre des données en cache + amount of memory used to cache data 0 @@ -2704,7 +2763,7 @@ https://github.com/rbicelli/pfsense-zabbix-template - quantité de mémoire complètement libre et prête a être utilisée directement. + amount of memory completely free and ready to be used directly. 0 @@ -2763,7 +2822,7 @@ https://github.com/rbicelli/pfsense-zabbix-template - quantité de mémoire qui contient des données qui ne sont plus utilisées (peut être directement libéré si besoin) + amount of memory that contains data that is no longer used (can be directly freed if needed) 0 @@ -3065,7 +3124,7 @@ https://github.com/rbicelli/pfsense-zabbix-template - quantité de mémoire utilisée par le kernel, ne peut être ni déchargée en swap, ni compressée. + amount of memory used by the kernel, can neither be unloaded in swap, nor compressed. 0 @@ -4420,14 +4479,21 @@ https://github.com/rbicelli/pfsense-zabbix-template 0 - + + + {#SERVICE} + @pfSense service names for discovery + 8 + A + + 30d Service {#DESCRIPTION} enabled on CARP Slave - 0 + 7 pfsense.value[service_value,{#SERVICE},run_on_carp_slave] @@ -4489,7 +4555,7 @@ https://github.com/rbicelli/pfsense-zabbix-template Service {#DESCRIPTION} Status - 0 + 7 pfsense.value[service_value,{#SERVICE},status] @@ -5254,6 +5320,22 @@ or + + {Template pfSense Active:pfsense.value[carp_status].last()}>2 + 0 + + DHCP Failover Problems on {HOST.NAME} + 0 + + https://docs.netgate.com/pfsense/en/latest/troubleshooting/ha-dhcp-failover.html + 0 + 4 + One or more DHCP Pools are experiencing failover problems. This could potentially cause other problems in yourr network. + 0 + 0 + + + {Template pfSense Active:system.uname.diff(0)}>0 0 @@ -5392,7 +5474,7 @@ or 0 1 - Notify of new version of packages are available + New version of packages are available 0 0 diff --git a/template_pfsense_active_ipsec.xml b/zabbix4/template_pfsense_active_ipsec.xml similarity index 80% rename from template_pfsense_active_ipsec.xml rename to zabbix4/template_pfsense_active_ipsec.xml index 30721a1..8ebeafe 100644 --- a/template_pfsense_active_ipsec.xml +++ b/zabbix4/template_pfsense_active_ipsec.xml @@ -1,7 +1,7 @@ 4.0 - 2021-01-18T15:02:45Z + 2021-01-18T21:30:16Z Templates/Network Devices @@ -504,188 +504,6 @@ https://github.com/rbicelli/pfsense-zabbix-template 30d Discovery of IPsec Phase 2 - - IPsec Tunnel {#IKEID}.{#REQID} {#NAME} Phase 2 Byte Received - 7 - - - pfsense.value[ipsec_ph2,{#EXTID},status.bytes-in] - 60s - 90d - 365d - 0 - 3 - - b - - - 0 - 0 - - 0 - - - - 0 - - - - - - IPsec Tunnel Phase 2 Protocol - 0 - - - IPsec - - - - - - - 3s - - - - 200 - 1 - 0 - - - 0 - 0 - 0 - 0 - - - - 0 - 0 - - - - - IPsec Tunnel {#IKEID}.{#REQID} {#NAME} Phase 2 Byte Sent - 7 - - - pfsense.value[ipsec_ph2,{#EXTID},status.bytes-out] - 60s - 90d - 365d - 0 - 3 - - b - - - 0 - 0 - - 0 - - - - 0 - - - - - - IPsec Tunnel Phase 2 Protocol - 0 - - - IPsec - - - - - - - 3s - - - - 200 - 1 - 0 - - - 0 - 0 - 0 - 0 - - - - 0 - 0 - - - - - IPsec Tunnel {#IKEID}.{#REQID} {#NAME} Phase 2 Status - 7 - - - pfsense.value[ipsec_ph2,{#EXTID},status] - 60s - 90d - 365d - 0 - 3 - - - - - 0 - 0 - - 0 - - - - 0 - - - - - - IPsec Tunnel Phase 2 Protocol - 0 - - - IPsec - - - - pfSense IPsec Phase 2 Status - - - - - 3s - - - - 200 - 1 - 0 - - - 0 - 0 - 0 - 0 - - - - 0 - 0 - - - IPsec Tunnel {#IKEID}.{#REQID} {#NAME} Phase 2 Enabled 7 @@ -1025,27 +843,6 @@ https://github.com/rbicelli/pfsense-zabbix-template - - pfSense IPsec Phase 2 Status - - - 0 - Down - - - 1 - Installed - - - 2 - Rekeyed - - - 10 - Down on CARP Secondary - - - pfSense IPsec Protocol diff --git a/template_pfsense_active_ovpn_user.xml b/zabbix4/template_pfsense_active_ovpn_user.xml similarity index 100% rename from template_pfsense_active_ovpn_user.xml rename to zabbix4/template_pfsense_active_ovpn_user.xml diff --git a/zabbix4/template_pfsense_active_speedtest.xml b/zabbix4/template_pfsense_active_speedtest.xml new file mode 100644 index 0000000..41335bd --- /dev/null +++ b/zabbix4/template_pfsense_active_speedtest.xml @@ -0,0 +1,332 @@ + + + 4.0 + 2021-07-05T15:51:20Z + + + Templates/Network Devices + + + + + + diff --git a/zabbix5/template_pfsense_active.xml b/zabbix5/template_pfsense_active.xml new file mode 100644 index 0000000..3568b05 --- /dev/null +++ b/zabbix5/template_pfsense_active.xml @@ -0,0 +1,2150 @@ + + + 5.0 + 2021-07-12T10:35:24Z + + + Templates/Network Devices + + + + + + + + {Template pfSense Active:pfsense.expected_carp_status.last()}<>0 and {Template pfSense Active:pfsense.value[carp_status].last()}<>{$EXPECTED_CARP_STATUS} + CARP Status not Expected on {HOST.NAME} + HIGH + pfSense CARP is not in the state Expected. This means that a failover could be in process. + + + ({Template pfSense Active:pfsense.value[system,version].last()}<>{Template pfSense Active:pfsense.value[system,installed_version].last()})=1 + New Version Available on {HOST.NAME} + INFO + Noify of new version of pfsense available + + + + + Active Connections + NO + FIXED + ITEM + + Template pfSense Active + pfsense.states.max + + + + GRADIENT_LINE + FF2C27 + + Template pfSense Active + pfsense.states.current + + + + + + Active Connections (pie) + 600 + 340 + 0 + NO + NO + PIE + + + 5B5B5B + GRAPH_SUM + + Template pfSense Active + pfsense.states.max + + + + 1 + GRADIENT_LINE + FF2C27 + + Template pfSense Active + pfsense.states.current + + + + + + CPU jumps + + + GRADIENT_LINE + 009900 + + Template pfSense Active + system.cpu.switches + + + + 1 + GRADIENT_LINE + 000099 + + Template pfSense Active + system.cpu.intr + + + + + + CPU load + STACKED + FIXED + + + FFA619 + + Template pfSense Active + system.cpu.load[percpu,avg1] + + + + 1 + E86E30 + + Template pfSense Active + system.cpu.load[percpu,avg5] + + + + 2 + FF2F26 + + Template pfSense Active + system.cpu.load[percpu,avg15] + + + + + + CPU utilization (Line) + NO + FIXED + FIXED + + + GRADIENT_LINE + FFE819 + + Template pfSense Active + system.cpu.util[,interrupt] + + + + 1 + GRADIENT_LINE + E85D17 + + Template pfSense Active + system.cpu.util[,nice] + + + + 2 + GRADIENT_LINE + DF26FF + + Template pfSense Active + system.cpu.util[,system] + + + + 3 + GRADIENT_LINE + 1775E8 + + Template pfSense Active + system.cpu.util[,user] + + + + 4 + 03D933 + + Template pfSense Active + system.cpu.util[,idle] + + + + + + Memory Available details (pie) + 600 + 340 + 0 + NO + NO + PIE + + + 003300 + GRAPH_SUM + + Template pfSense Active + vm.memory.size[available] + + + + 1 + 005500 + + Template pfSense Active + vm.memory.size[free] + + + + 2 + 007700 + + Template pfSense Active + vm.memory.size[cached] + + + + 3 + 009900 + + Template pfSense Active + vm.memory.size[inactive] + + + + + + Memory usage + NO + STACKED + FIXED + ITEM + + Template pfSense Active + vm.memory.size[total] + + + + 00EE00 + + Template pfSense Active + vm.memory.size[wired] + + + + 1 + 00CC00 + + Template pfSense Active + vm.memory.size[active] + + + + 2 + 007700 + + Template pfSense Active + vm.memory.size[inactive] + + + + 3 + 005500 + + Template pfSense Active + vm.memory.size[cached] + + + + 4 + 003300 + + Template pfSense Active + vm.memory.size[free] + + + + + + Memory Usage simple (pie) + 600 + 340 + 0 + NO + NO + PIE + + + 003300 + + Template pfSense Active + vm.memory.size[available] + + + + 1 + 00DD00 + + Template pfSense Active + kt.mem.used + + + + + + Network Memory Buffer + NO + STACKED + FIXED + ITEM + + Template pfSense Active + pfsense.mbuf.max + + + + B26E16 + + Template pfSense Active + pfsense.mbuf.current + + + + 1 + FFCE8E + + Template pfSense Active + pfsense.mbuf.cache + + + + + + Network Memory Buffer (pie) + 600 + 340 + 0 + NO + NO + PIE + + + 5B5B5B + GRAPH_SUM + + Template pfSense Active + pfsense.mbuf.max + + + + 1 + FFCE8E + + Template pfSense Active + pfsense.mbuf.cache + + + + 2 + B26E16 + + Template pfSense Active + pfsense.mbuf.current + + + + + + Swap usage + 600 + 340 + 0 + NO + NO + PIE + YES + + + 5B5B5B + GRAPH_SUM + + Template pfSense Active + system.swap.size[,total] + + + + 1 + FFFF33 + + Template pfSense Active + system.swap.size[,used] + + + + + + + + Generic YesNo + + + 0 + No + + + 1 + Yes + + + + + pfSense CARP Status + + + 0 + Disabled + + + 1 + Master + + + 2 + Backup + + + 3 + Inconsistent + + + 4 + Problem + + + + + pfSense Gateway Status + + + 0 + Up + + + 1 + Packet Loss + + + 2 + High Delay + + + 3 + High Packet Loss + + + 4 + Forced Down + + + 5 + Down + + + + + pfSense OpenVPN Interface Status + + + 0 + Down + + + 1 + Up + + + 2 + None + + + 3 + Reconnecting + + + 4 + Waiting + + + 5 + Up/Listening + + + + + pfSense OpenVPN Mode + + + 1 + Peer to Peer (SSL/TLS) + + + 2 + P2P Shared Key + + + 3 + Remote Access (SSL/TLS) + + + 4 + Remote Access (User Auth) + + + 5 + Remote Access 8SSL/TLS + User Auth) + + + + + Service state + + + 0 + Down + + + 1 + Up + + + + + diff --git a/zabbix5/template_pfsense_active_ipsec.xml b/zabbix5/template_pfsense_active_ipsec.xml new file mode 100644 index 0000000..094d9da --- /dev/null +++ b/zabbix5/template_pfsense_active_ipsec.xml @@ -0,0 +1,301 @@ + + + 5.0 + 2021-07-12T10:36:28Z + + + Templates/Network Devices + + + + + + + + pfSense IPsec Enabled + + + 0 + Yes + + + 1 + No + + + + + pfSense IPsec IKE Type + + + 0 + Auto + + + 1 + IKE v1 + + + 2 + IKE v2 + + + + + pfSense IPsec Phase 1 Status + + + 0 + Down + + + 1 + Established + + + 2 + Connecting + + + 10 + Down on CARP Secondary + + + + + pfSense IPsec Phase 2 Protocol + + + 1 + ESP + + + 2 + AH + + + + + pfSense IPsec Protocol + + + 0 + Dual Stack (IPv4 & IPv6) + + + 1 + IPv4 + + + 2 + IPv6 + + + + + pfSense IPsec Tunnel Mode + + + 0 + Main + + + 1 + Aggressive + + + + + diff --git a/zabbix5/template_pfsense_active_ovpn_user.xml b/zabbix5/template_pfsense_active_ovpn_user.xml new file mode 100644 index 0000000..cc07a0f --- /dev/null +++ b/zabbix5/template_pfsense_active_ovpn_user.xml @@ -0,0 +1,168 @@ + + + 5.0 + 2021-07-12T10:37:03Z + + + Templates/Network Devices + + + + + + diff --git a/zabbix5/template_pfsense_active_speedtest.xml b/zabbix5/template_pfsense_active_speedtest.xml new file mode 100644 index 0000000..ae135c2 --- /dev/null +++ b/zabbix5/template_pfsense_active_speedtest.xml @@ -0,0 +1,119 @@ + + + 5.0 + 2021-07-12T10:37:45Z + + + Templates/Network Devices + + + + + + diff --git a/zabbix6/pfsense_active.yaml b/zabbix6/pfsense_active.yaml new file mode 100644 index 0000000..69ff082 --- /dev/null +++ b/zabbix6/pfsense_active.yaml @@ -0,0 +1,1809 @@ +zabbix_export: + version: '6.0' + date: '2023-02-26T16:18:59Z' + groups: + - + uuid: 4918b88734c54bd094cff7585b5d71fc + name: 'Templates/Network Devices' + templates: + - + uuid: 7a0b3294155c4454bd5df455f7a827b6 + template: 'Template pfSense Active' + name: 'pfsense Active' + description: | + Active template for pfsense, requires pfsense_zbx.php installed to pfSense Box. + Version 1.0.2 + + https://github.com/rbicelli/pfsense-zabbix-template + groups: + - + name: 'Templates/Network Devices' + items: + - + uuid: fe0bfdabfd494c859bae516980bb412c + name: 'Maximum number of opened files' + type: ZABBIX_ACTIVE + key: kernel.maxfiles + delay: '3600' + history: 27d + description: 'It could be increased by using sysctrl utility or modifying file /etc/sysctl.conf.' + tags: + - + tag: Application + value: OS + triggers: + - + uuid: d081e34519d4449ca9379b74ef276141 + expression: 'last(/Template pfSense Active/kernel.maxfiles)<1024' + name: 'Configured max number of opened files is too low on {HOST.NAME}' + priority: INFO + - + uuid: d9b8395c028b43fd8a2c2b667165747e + name: 'Maximum number of processes' + type: ZABBIX_ACTIVE + key: kernel.maxproc + delay: '3600' + history: 27d + description: 'It could be increased by using sysctrl utility or modifying file /etc/sysctl.conf.' + tags: + - + tag: Application + value: OS + triggers: + - + uuid: 9854402b6a474f05af721835dc464338 + expression: 'last(/Template pfSense Active/kernel.maxproc)<256' + name: 'Configured max number of processes is too low on {HOST.NAME}' + priority: INFO + - + uuid: 906d29a9443d4e3d8ae58d6db61ffebd + name: 'Used memory (calc)' + type: CALCULATED + key: kt.mem.used + delay: '60' + history: 28d + units: B + params: 'last(//vm.memory.size[total]) - last(//vm.memory.size[available])' + tags: + - + tag: Application + value: Memory + - + uuid: a233016d2e664687a480052812297879 + name: 'Expected CARP Status' + type: CALCULATED + key: pfsense.expected_carp_status + delay: 600s + params: '{$EXPECTED_CARP_STATUS}' + description: 'Expected CARP Status' + valuemap: + name: 'pfSense CARP Status' + tags: + - + tag: Application + value: CARP + - + uuid: dd3d8f993d3e468197500b09da067b20 + name: 'MBUF Cache' + type: ZABBIX_ACTIVE + key: pfsense.mbuf.cache + delay: '60' + history: 27d + tags: + - + tag: Application + value: 'Network Limits' + - + uuid: f184df5af3104ac9b1e28ae7dbc6f6af + name: 'MBUF Current' + type: ZABBIX_ACTIVE + key: pfsense.mbuf.current + delay: '60' + history: 27d + tags: + - + tag: Application + value: 'Network Limits' + - + uuid: cf70cf5e8b294e359a7bce7b64cc2f88 + name: 'MBUF Max' + type: ZABBIX_ACTIVE + key: pfsense.mbuf.max + delay: '600' + history: 27d + tags: + - + tag: Application + value: 'Network Limits' + - + uuid: 154c27479d50479b9824e8253ac687fa + name: 'MBUF Total Used (percent)' + type: CALCULATED + key: pfsense.mbuf.ptotal + delay: '60' + history: 28d + value_type: FLOAT + units: '%' + params: '((last(//pfsense.mbuf.current) + last(//pfsense.mbuf.cache)) * 100) / last(//pfsense.mbuf.max)' + tags: + - + tag: Application + value: 'Network Limits' + triggers: + - + uuid: 4453b627d68b4c44b5a909426fd06784 + expression: 'last(/Template pfSense Active/pfsense.mbuf.ptotal)>80' + name: 'MBUF used at 80%' + priority: WARNING + - + uuid: 5bfdf44122ee4a16b97909f1071256a5 + expression: 'last(/Template pfSense Active/pfsense.mbuf.ptotal)>90' + name: 'MBUF used at 90%' + priority: HIGH + - + uuid: a61781a790734d71a512e592fec87b84 + name: 'States Table Current' + type: ZABBIX_ACTIVE + key: pfsense.states.current + delay: '60' + history: 27d + tags: + - + tag: Application + value: 'Network Limits' + - + uuid: 022009a762ee4ec8bc4988a57b0d1412 + name: 'States Table Max' + type: ZABBIX_ACTIVE + key: pfsense.states.max + delay: '600' + history: 27d + tags: + - + tag: Application + value: 'Network Limits' + - + uuid: 6d0f8d81fd3d46b39e9bbccacb2aaf4c + name: 'States Table Current (percent)' + type: CALCULATED + key: pfsense.states.pused + delay: '60' + history: 28d + value_type: FLOAT + units: '%' + params: '(last(//pfsense.states.current) * 100) / last(//pfsense.states.max)' + tags: + - + tag: Application + value: 'Network Limits' + triggers: + - + uuid: 1a7faf6d80ca4a408987de1f039e4dba + expression: 'last(/Template pfSense Active/pfsense.states.pused)>80' + name: 'State Table used at 80%' + priority: WARNING + - + uuid: dbd147c6b43144dc9541939fbb9c8eef + expression: 'last(/Template pfSense Active/pfsense.states.pused)>90' + name: 'State Table used at 90%' + priority: HIGH + - + uuid: cc7fd0d7da504c71b0da3fcc36133510 + name: 'CARP Status' + type: ZABBIX_ACTIVE + key: 'pfsense.value[carp_status]' + delay: '60' + description: 'pfSense CARP Status' + valuemap: + name: 'pfSense CARP Status' + tags: + - + tag: Application + value: CARP + triggers: + - + uuid: 43391e9ed3134e689b0b09b1d124178b + expression: 'last(/Template pfSense Active/pfsense.value[carp_status])>2' + name: 'CARP Problems on {HOST.NAME}' + priority: HIGH + description: 'CARP Problems' + - + uuid: a0ad30cea628413987919bd9bc8e229f + expression: 'avg(/Template pfSense Active/pfsense.value[carp_status],#3)>2' + name: 'DHCP Failover Problems on {HOST.NAME}' + url: 'https://docs.netgate.com/pfsense/en/latest/troubleshooting/ha-dhcp-failover.html' + priority: HIGH + description: 'One or more DHCP Pools are experiencing failover problems. This could potentially cause other problems in yourr network.' + - + uuid: 3c38af8aef59489d93224ab03319e997 + name: 'DHCP Failover Pool Problems' + key: 'pfsense.value[dhcp,failover]' + delay: 120s + description: 'This value indicates, in a HA scenario, if DHCP failover pool partners are out of sync.' + tags: + - + tag: Application + value: HA + - + uuid: 12399afd70014ce7bf96f6283c946bc2 + name: 'Gateway Status Raw' + type: ZABBIX_ACTIVE + key: 'pfsense.value[gw_status]' + delay: 60s + trends: '0' + value_type: TEXT + description: 'Gateway Status Raw' + tags: + - + tag: Application + value: Gateways + triggers: + - + uuid: 44df9b029fe64ef1b70aa6142d38d105 + expression: '(last(/Template pfSense Active/pfsense.value[gw_status],#1)<>last(/Template pfSense Active/pfsense.value[gw_status],#2))>0' + recovery_mode: RECOVERY_EXPRESSION + recovery_expression: '(last(/Template pfSense Active/pfsense.value[gw_status],#1)<>last(/Template pfSense Active/pfsense.value[gw_status],#2))=0' + name: 'pfSense Gateway Status Changed on {HOST.NAME}' + priority: AVERAGE + description: 'Gateway Status Change, for use with an acion Script (e.g. update DNS record)' + manual_close: 'YES' + - + uuid: 856991c40aa043dfa6075468add93f7d + name: 'SMART Status' + key: 'pfsense.value[smart_status]' + delay: 1800s + description: 'pfSense SMART Status' + tags: + - + tag: Application + value: System + triggers: + - + uuid: 523e16493b534fb7ad9def66fef6f286 + expression: 'avg(/Template pfSense Active/pfsense.value[smart_status],#3)=1' + name: 'SMART Errors on {HOST.NAME}' + priority: HIGH + description: 'pfSense has detected SMART Problems on one or more drives.' + - + uuid: 5820137593604e63869cd3bf009a3dbf + name: 'pfSense Installed Version' + type: ZABBIX_ACTIVE + key: 'pfsense.value[system,installed_version]' + delay: 1d + trends: '0' + value_type: TEXT + tags: + - + tag: Application + value: System + - + uuid: 36a0a399f1ad4ca3aea3e52c1dfe0de1 + name: 'New Version of pfSense Available' + type: ZABBIX_ACTIVE + key: 'pfsense.value[system,new_version_available]' + delay: 1d + valuemap: + name: 'Generic YesNo' + tags: + - + tag: Application + value: System + triggers: + - + uuid: ac1745d4a3d24445a9c53e294a3aba0a + expression: 'last(/Template pfSense Active/pfsense.value[system,new_version_available])=1' + name: 'New Version of pfSense Available on {HOST.NAME}' + priority: INFO + description: 'A new version of pfSense is available for update.' + manual_close: 'YES' + - + uuid: 47855133ddb6495280fdcf8b52fc38f9 + name: 'Packages Needing Update' + type: ZABBIX_ACTIVE + key: 'pfsense.value[system,packages_update]' + delay: 1d + description: 'Number of packages needing update.' + tags: + - + tag: Application + value: System + triggers: + - + uuid: aa627e1f209741c0a7490665fd15c4bc + expression: 'last(/Template pfSense Active/pfsense.value[system,packages_update])>0' + name: 'Packages Update Available on {HOST.NAME}' + priority: INFO + description: 'Notify of new version of packages are available' + - + uuid: d801429fd147415396b61f5f6c47af27 + name: 'pfSense Available Version' + type: ZABBIX_ACTIVE + key: 'pfsense.value[system,version]' + delay: 1d + trends: '0' + value_type: TEXT + tags: + - + tag: Application + value: System + - + uuid: 65a633fa48e64fa7b3e56e2e1294a396 + name: 'Number of running processes' + type: ZABBIX_ACTIVE + key: 'proc.num[,,run]' + delay: '60' + history: 27d + description: 'Number of processes in running state.' + tags: + - + tag: Application + value: Processes + triggers: + - + uuid: 8e87c7171e4e43d5b4ee51922fb634ff + expression: 'avg(/Template pfSense Active/proc.num[,,run],5m)>30' + name: 'Too many processes running on {HOST.NAME}' + priority: WARNING + - + uuid: 5ac8f03d4fa74700ad96d139acfe6baf + name: 'Number of processes' + type: ZABBIX_ACTIVE + key: 'proc.num[]' + delay: '60' + history: 27d + description: 'Total number of processes in any state.' + tags: + - + tag: Application + value: Processes + triggers: + - + uuid: 8237ec2c23b6449298ff7d9327f93b2d + expression: 'avg(/Template pfSense Active/proc.num[],5m)>300' + name: 'Too many processes on {HOST.NAME}' + priority: WARNING + - + uuid: b8c1f4bac1834aee87f0bda3a546f98a + name: 'Host boot time' + type: ZABBIX_ACTIVE + key: system.boottime + delay: '600' + history: 27d + units: unixtime + tags: + - + tag: Application + value: OS + - + uuid: d4823bbc8d9849e0bb36e5418168fe06 + name: 'Interrupts per second' + type: ZABBIX_ACTIVE + key: system.cpu.intr + delay: '60' + history: 27d + units: ips + preprocessing: + - + type: CHANGE_PER_SECOND + parameters: + - '' + tags: + - + tag: Application + value: CPU + - + uuid: ff36a3e91fd44e7981874e8e363069df + name: 'Processor load (1min/core)' + type: ZABBIX_ACTIVE + key: 'system.cpu.load[percpu,avg1]' + delay: '60' + history: 27d + value_type: FLOAT + description: 'The processor load is calculated as system CPU load divided by number of CPU cores.' + tags: + - + tag: Application + value: CPU + triggers: + - + uuid: b9bdc3be79eb40f0be33931a5c6f5378 + expression: 'avg(/Template pfSense Active/system.cpu.load[percpu,avg1],5m)>5' + name: 'Processor load is too high on {HOST.NAME}' + priority: WARNING + - + uuid: 6ac7d111b73d4150aaead8f470ff41ba + name: 'Processor load (5min/core)' + type: ZABBIX_ACTIVE + key: 'system.cpu.load[percpu,avg5]' + delay: '60' + history: 27d + value_type: FLOAT + description: 'The processor load is calculated as system CPU load divided by number of CPU cores.' + tags: + - + tag: Application + value: CPU + - + uuid: d244b629aaf74fa1af608332df014df4 + name: 'Processor load (15min/core)' + type: ZABBIX_ACTIVE + key: 'system.cpu.load[percpu,avg15]' + delay: '60' + history: 27d + value_type: FLOAT + description: 'The processor load is calculated as system CPU load divided by number of CPU cores.' + tags: + - + tag: Application + value: CPU + - + uuid: d450e0b3d0b441f191d7f7e5faab4f38 + name: 'Context switches per second' + type: ZABBIX_ACTIVE + key: system.cpu.switches + delay: '60' + history: 27d + units: sps + preprocessing: + - + type: CHANGE_PER_SECOND + parameters: + - '' + tags: + - + tag: Application + value: CPU + - + uuid: 8bc963352bef46e5a92763b9c866d0a7 + name: 'CPU $2 time' + type: ZABBIX_ACTIVE + key: 'system.cpu.util[,idle]' + delay: '60' + history: 27d + value_type: FLOAT + units: '%' + description: 'The time the CPU has spent doing nothing.' + tags: + - + tag: Application + value: CPU + - + uuid: f2f60c68e4604f55b0a437542507fd86 + name: 'CPU $2 time' + type: ZABBIX_ACTIVE + key: 'system.cpu.util[,interrupt]' + delay: '60' + history: 27d + value_type: FLOAT + units: '%' + description: 'The amount of time the CPU has been servicing hardware interrupts.' + tags: + - + tag: Application + value: CPU + - + uuid: b81c545ae21b417b85b62ce115e1dd8e + name: 'CPU $2 time' + type: ZABBIX_ACTIVE + key: 'system.cpu.util[,nice]' + delay: '60' + history: 27d + value_type: FLOAT + units: '%' + description: 'The time the CPU has spent running users'' processes that have been niced.' + tags: + - + tag: Application + value: CPU + - + uuid: e0ddfcc0ffe34a60a575cdae1f1d8a98 + name: 'CPU $2 time' + type: ZABBIX_ACTIVE + key: 'system.cpu.util[,system]' + delay: '60' + history: 27d + value_type: FLOAT + units: '%' + description: 'The time the CPU has spent running the kernel and its processes.' + tags: + - + tag: Application + value: CPU + - + uuid: b99746ff4914473f9c2d3e39dfb9d6fc + name: 'CPU $2 time' + type: ZABBIX_ACTIVE + key: 'system.cpu.util[,user]' + delay: '60' + history: 27d + value_type: FLOAT + units: '%' + description: 'The time the CPU has spent running users'' processes that are not niced.' + tags: + - + tag: Application + value: CPU + - + uuid: b2797942c3404742a068e2c5f90a796f + name: 'Host name' + type: ZABBIX_ACTIVE + key: system.hostname + delay: '3600' + history: 27d + trends: '0' + value_type: CHAR + description: 'System host name.' + inventory_link: NAME + tags: + - + tag: Application + value: OS + triggers: + - + uuid: ef84b7baa0564b50a8ad6537ec8c81b9 + expression: '(last(/Template pfSense Active/system.hostname,#1)<>last(/Template pfSense Active/system.hostname,#2))>0' + name: 'Hostname was changed on {HOST.NAME}' + priority: INFO + - + uuid: def69b566341465f971635459ecf3a93 + name: 'Host local time' + type: ZABBIX_ACTIVE + key: system.localtime + delay: '60' + history: 27d + units: unixtime + tags: + - + tag: Application + value: OS + - + uuid: 9370c5052d564338b74bbd3d38847d35 + name: 'Free swap space' + type: ZABBIX_ACTIVE + key: 'system.swap.size[,free]' + delay: '60' + history: 27d + units: B + tags: + - + tag: Application + value: Memory + - + uuid: 709cac33a5384f85b62fd3ff1b35d173 + name: 'Free swap space in %' + type: ZABBIX_ACTIVE + key: 'system.swap.size[,pfree]' + delay: '60' + history: 27d + value_type: FLOAT + units: '%' + tags: + - + tag: Application + value: Memory + triggers: + - + uuid: 7ad93b922ed8416495109bf6eb14bdf4 + expression: 'last(/Template pfSense Active/system.swap.size[,pfree])<50' + name: 'Lack of free swap space on {HOST.NAME}' + priority: WARNING + description: 'It probably means that the systems requires more physical memory.' + - + uuid: b902dc19ad4e48e0bfc8bf90773f7f64 + name: 'Total swap space' + type: ZABBIX_ACTIVE + key: 'system.swap.size[,total]' + delay: '3600' + history: 27d + units: B + tags: + - + tag: Application + value: Memory + - + uuid: b4516badf0ab41cba862482a3c9ebf37 + name: 'Used swap space' + type: ZABBIX_ACTIVE + key: 'system.swap.size[,used]' + delay: '60' + history: 27d + units: B + tags: + - + tag: Application + value: Memory + - + uuid: 4266ddd2f44546e4b4856c7edfe5c37e + name: 'System information' + type: ZABBIX_ACTIVE + key: system.uname + delay: '3600' + history: 27d + trends: '0' + value_type: CHAR + description: 'The information as normally returned by ''uname -a''.' + inventory_link: OS + tags: + - + tag: Application + value: OS + triggers: + - + uuid: 299fcdc70a8c4b3aa1b187f05eebf983 + expression: '(last(/Template pfSense Active/system.uname,#1)<>last(/Template pfSense Active/system.uname,#2))>0' + name: 'Host information was changed on {HOST.NAME}' + priority: INFO + - + uuid: adde548d1da74e72ba7d25d30515cf31 + name: 'System uptime' + type: ZABBIX_ACTIVE + key: system.uptime + delay: '600' + history: 27d + units: uptime + tags: + - + tag: Application + value: OS + triggers: + - + uuid: 982e988c84bb43d197b157b9d85f5d46 + expression: 'change(/Template pfSense Active/system.uptime)<0' + name: '{HOST.NAME} has just been restarted' + priority: INFO + - + uuid: c0543949d4004092a1c0446b5615b5e8 + name: 'Number of logged in users' + type: ZABBIX_ACTIVE + key: system.users.num + delay: '60' + history: 27d + description: 'Number of users who are currently logged in.' + tags: + - + tag: Application + value: OS + - + uuid: bbaf67d0ca854704b1d13ba08f4108fe + name: 'Checksum of $1' + type: ZABBIX_ACTIVE + key: 'vfs.file.cksum[/etc/passwd]' + delay: '3600' + history: 27d + tags: + - + tag: Application + value: OS + triggers: + - + uuid: 703ce0e80d0b45009d714413a3c336b4 + expression: '(last(/Template pfSense Active/vfs.file.cksum[/etc/passwd],#1)<>last(/Template pfSense Active/vfs.file.cksum[/etc/passwd],#2))>0' + name: '/etc/passwd has been changed on {HOST.NAME}' + priority: WARNING + - + uuid: a6d63cd84a314056bd638e25c5f0308b + name: 'Active memory' + type: ZABBIX_ACTIVE + key: 'vm.memory.size[active]' + delay: '60' + history: 28d + units: B + description: 'quantité de mémoire en cours d''utilisation par les processus' + tags: + - + tag: Application + value: Memory + - + uuid: 092eb762e52a45db9aa27a167b517dfa + name: 'Available memory' + type: ZABBIX_ACTIVE + key: 'vm.memory.size[available]' + delay: '60' + history: 27d + units: B + description: 'Available memory is defined as free+cached+buffers memory.' + tags: + - + tag: Application + value: Memory + triggers: + - + uuid: 8146acaf455344c39add5460c7d48186 + expression: 'last(/Template pfSense Active/vm.memory.size[available])<20M' + name: 'Lack of available memory on server {HOST.NAME}' + priority: AVERAGE + - + uuid: 75329478c6da472894fc3afd9bc4ff78 + name: 'Buffered memory' + type: ZABBIX_ACTIVE + key: 'vm.memory.size[buffers]' + delay: '60' + history: 28d + status: DISABLED + units: B + description: | + Cache d'entrées des IO disque. + + (Item désactivé car buggé) + tags: + - + tag: Application + value: Memory + - + uuid: 112b875916c74b418e33964e4134d88a + name: 'Cached memory' + type: ZABBIX_ACTIVE + key: 'vm.memory.size[cached]' + delay: '60' + history: 28d + units: B + description: 'quantité de mémoire utilisée pour mettre des données en cache' + tags: + - + tag: Application + value: Memory + - + uuid: d403943f72ef41c6ac893d55f56991cc + name: 'Free memory' + type: ZABBIX_ACTIVE + key: 'vm.memory.size[free]' + delay: '60' + history: 28d + units: B + description: 'quantité de mémoire complètement libre et prête a être utilisée directement.' + tags: + - + tag: Application + value: Memory + - + uuid: 6299a6e55f394ed8bb888443c6cf9c12 + name: 'Inactive memory' + type: ZABBIX_ACTIVE + key: 'vm.memory.size[inactive]' + delay: '60' + history: 28d + units: B + description: 'quantité de mémoire qui contient des données qui ne sont plus utilisées (peut être directement libéré si besoin)' + tags: + - + tag: Application + value: Memory + - + uuid: 2600308db79349a2884b3e44099fe486 + name: 'Available memory (percent)' + type: ZABBIX_ACTIVE + key: 'vm.memory.size[pavailable]' + delay: '60' + history: 28d + value_type: FLOAT + units: '%' + description: 'Available memory is defined as free+cached+buffers memory.' + preprocessing: + - + type: MULTIPLIER + parameters: + - '1' + tags: + - + tag: Application + value: Memory + - + uuid: 1f4b1470af3f408aa08001620ff0ec5d + name: 'Shared memory' + type: ZABBIX_ACTIVE + key: 'vm.memory.size[shared]' + delay: '60' + history: 28d + status: DISABLED + units: B + description: | + quantité de mémoire partagée entre plusieurs processus + + (Item désactivé car non utilisé) + tags: + - + tag: Application + value: Memory + - + uuid: 69bec6035e964582832732239f8c07a4 + name: 'Total memory' + type: ZABBIX_ACTIVE + key: 'vm.memory.size[total]' + delay: '3600' + history: 27d + units: B + description: 'quantité de mémoire totale' + tags: + - + tag: Application + value: Memory + - + uuid: 3214f881ee01414cb1d824671ae0074b + name: 'Used memory' + type: ZABBIX_ACTIVE + key: 'vm.memory.size[used]' + delay: '60' + history: 28d + status: DISABLED + units: B + description: 'Item désactivé car non utilisé' + tags: + - + tag: Application + value: Memory + - + uuid: 79a6075f223d442199accef75762f8b4 + name: 'Wired memory' + type: ZABBIX_ACTIVE + key: 'vm.memory.size[wired]' + delay: '60' + history: 28d + units: B + description: 'quantité de mémoire utilisée par le kernel, ne peut être ni déchargée en swap, ni compressée.' + tags: + - + tag: Application + value: Memory + discovery_rules: + - + uuid: 4db6be9bdf7b4876a13f9b936cdd3321 + name: 'Gateways Discovery' + type: ZABBIX_ACTIVE + key: 'pfsense.discovery[gw]' + delay: 300s + description: 'Gateway Discovery' + item_prototypes: + - + uuid: db89e0dd738148e19c52f08bbc7723f7 + name: 'Gateway {#GATEWAY} RTT' + type: ZABBIX_ACTIVE + key: 'pfsense.value[gw_value,{#GATEWAY},delay]' + delay: 60s + value_type: FLOAT + units: ms + preprocessing: + - + type: RTRIM + parameters: + - ms + tags: + - + tag: Application + value: Gateways + - + uuid: ba759ceb73f949108fddbc4029cfc9f2 + name: 'Gateway {#GATEWAY} Packet Loss' + type: ZABBIX_ACTIVE + key: 'pfsense.value[gw_value,{#GATEWAY},loss]' + delay: 60s + units: '%' + preprocessing: + - + type: RTRIM + parameters: + - '%' + tags: + - + tag: Application + value: Gateways + - + uuid: 7522dfc8c6724534a8fd4efc4bbf87f8 + name: 'Gateway {#GATEWAY} Status' + type: ZABBIX_ACTIVE + key: 'pfsense.value[gw_value,{#GATEWAY},status]' + delay: 60s + description: 'Status of Gateway' + valuemap: + name: 'pfSense Gateway Status' + tags: + - + tag: Application + value: Gateways + trigger_prototypes: + - + uuid: 2523755541f242d190825ae67f8039fb + expression: 'avg(/Template pfSense Active/pfsense.value[gw_value,{#GATEWAY},status],#3)=5' + name: 'Gateway {#GATEWAY} is down' + priority: DISASTER + description: 'Gateway is Down' + - + uuid: 4c306732349b4cfe8e66d7656bc0d397 + expression: 'avg(/Template pfSense Active/pfsense.value[gw_value,{#GATEWAY},status],#3)=4' + name: 'Gateway {#GATEWAY} is forced down' + priority: INFO + description: 'Gateway is forced down by system administrator' + - + uuid: faaa981f96444c90accf769c5d1949a7 + expression: 'avg(/Template pfSense Active/pfsense.value[gw_value,{#GATEWAY},status],#3)=2' + name: 'High Delay on gateway {#GATEWAY}' + priority: WARNING + description: 'Gateway is lagging' + - + uuid: a89a7d0dbd87432fa13ee7e4d15a4bdf + expression: 'avg(/Template pfSense Active/pfsense.value[gw_value,{#GATEWAY},status],#3)=3' + name: 'High packet Loss on {#GATEWAY}' + priority: HIGH + description: 'High Packet Loss on Gateway' + - + uuid: f5e9d80e672042aeb609f9ad82a019e4 + expression: 'avg(/Template pfSense Active/pfsense.value[gw_value,{#GATEWAY},status],#3)=1' + name: 'Packet Loss on {#GATEWAY}' + priority: WARNING + description: 'Packet loss on Gateway' + - + uuid: c6c8376ac666461a91df53eacdaf5f8b + name: 'Gateway {#GATEWAY} RTT Std Deviation' + type: ZABBIX_ACTIVE + key: 'pfsense.value[gw_value,{#GATEWAY},stddev]' + delay: 60s + value_type: FLOAT + units: ms + preprocessing: + - + type: RTRIM + parameters: + - ms + tags: + - + tag: Application + value: Gateways + graph_prototypes: + - + uuid: 25f10d4fe86549e893bf8ebb8de8f39c + name: 'Gateway {#GATEWAY} Availability' + graph_items: + - + color: 199C0D + calc_fnc: ALL + item: + host: 'Template pfSense Active' + key: 'pfsense.value[gw_value,{#GATEWAY},delay]' + - + sortorder: '1' + color: FF5722 + calc_fnc: ALL + item: + host: 'Template pfSense Active' + key: 'pfsense.value[gw_value,{#GATEWAY},loss]' + - + uuid: 05c556c8a8c24703a06be8d2b6a7a082 + name: 'Gateway {#GATEWAY} Status' + yaxismax: '5' + ymin_type_1: FIXED + ymax_type_1: FIXED + graph_items: + - + color: 199C0D + calc_fnc: ALL + item: + host: 'Template pfSense Active' + key: 'pfsense.value[gw_value,{#GATEWAY},status]' + - + uuid: baa842b8e5bf40b3bfbeb4d3b6507d08 + name: 'Network interface discovery' + type: ZABBIX_ACTIVE + key: 'pfsense.discovery[interfaces]' + delay: 3600s + filter: + conditions: + - + macro: '{#IFNAME}' + value: '@Network interfaces for discovery' + formulaid: A + lifetime: 7d + description: 'Discovery of network interfaces as defined in global regular expression "Network interfaces for discovery".' + item_prototypes: + - + uuid: 71301cd82a0749b4abed0feb58061a37 + name: 'Incoming Errors on {#IFDESCR}' + type: ZABBIX_ACTIVE + key: 'net.if.in[{#IFNAME},errors]' + delay: '60' + history: 7d + preprocessing: + - + type: CHANGE_PER_SECOND + parameters: + - '' + tags: + - + tag: Application + value: 'Network interfaces' + - + uuid: cbadb376e2924e438a81f068fd8553ef + name: 'Incoming network traffic on {#IFDESCR}' + type: ZABBIX_ACTIVE + key: 'net.if.in[{#IFNAME}]' + delay: '60' + history: 7d + units: bps + preprocessing: + - + type: CHANGE_PER_SECOND + parameters: + - '' + - + type: MULTIPLIER + parameters: + - '8' + tags: + - + tag: Application + value: 'Network interfaces' + - + uuid: a885e855bdda4eeda877a91ac30bbcb1 + name: 'Outgoing errors on {#IFDESCR}' + type: ZABBIX_ACTIVE + key: 'net.if.out[{#IFNAME},errors]' + delay: '60' + history: 7d + preprocessing: + - + type: CHANGE_PER_SECOND + parameters: + - '' + tags: + - + tag: Application + value: 'Network interfaces' + - + uuid: 74c6ae5e88bb4be49a23f82c50a957ac + name: 'Outgoing network traffic on {#IFDESCR}' + type: ZABBIX_ACTIVE + key: 'net.if.out[{#IFNAME}]' + delay: '60' + history: 7d + units: bps + preprocessing: + - + type: CHANGE_PER_SECOND + parameters: + - '' + - + type: MULTIPLIER + parameters: + - '8' + tags: + - + tag: Application + value: 'Network interfaces' + graph_prototypes: + - + uuid: adcaff7d4cdf4dbb8df4a5c1069a9fff + name: 'Network traffic on {#IFDESCR}' + show_triggers: 'NO' + show_legend: 'NO' + ymin_type_1: FIXED + graph_items: + - + drawtype: GRADIENT_LINE + color: '29E900' + item: + host: 'Template pfSense Active' + key: 'net.if.in[{#IFNAME}]' + - + sortorder: '1' + drawtype: GRADIENT_LINE + color: FD0000 + item: + host: 'Template pfSense Active' + key: 'net.if.out[{#IFNAME}]' + - + uuid: 111d1d4374084b4d94bd930dfa16e216 + name: 'OpenVPN Client Discovery' + type: ZABBIX_ACTIVE + key: 'pfsense.discovery[openvpn_client]' + delay: 300s + description: 'OpenVPN Client Discovery' + item_prototypes: + - + uuid: 15e5067016824fc7963ae22df7a675ea + name: 'OpenVPN Client {#NAME} Tunnel Status' + type: ZABBIX_ACTIVE + key: 'pfsense.value[openvpn_clientvalue,{#CLIENT},status]' + delay: 60s + valuemap: + name: 'pfSense OpenVPN Interface Status' + tags: + - + tag: Application + value: 'OpenVPN Client' + trigger_prototypes: + - + uuid: 33ac9b529a1f485394bca3b7a04d113f + expression: 'avg(/Template pfSense Active/pfsense.value[openvpn_clientvalue,{#CLIENT},status],#3)=0' + name: 'OpenVPN Client {#NAME} Tunnel is Down' + priority: HIGH + description: 'OpenVPN Tunnel Down' + - + uuid: 9afe1fad6b6a4ec88ae81969a57c6107 + name: 'OpenVPN Server Discovery' + type: ZABBIX_ACTIVE + key: 'pfsense.discovery[openvpn_server]' + delay: 300s + item_prototypes: + - + uuid: 0a6ee94cefe8457eb56ef832d8734790 + name: 'OpenVPN Server {#NAME} Clients Connected' + type: ZABBIX_ACTIVE + key: 'pfsense.value[openvpn_servervalue,{#SERVER},conns]' + delay: 60s + tags: + - + tag: Application + value: 'OpenVPN Server' + - + uuid: d3cadc40e5d74acf8e0549e9d28771ea + name: 'OpenVPN Server {#NAME} Mode' + type: ZABBIX_ACTIVE + key: 'pfsense.value[openvpn_servervalue,{#SERVER},mode]' + delay: 300s + valuemap: + name: 'pfSense OpenVPN Mode' + tags: + - + tag: Application + value: 'OpenVPN Server' + - + uuid: c2187f680f92432d9dc3b1609b1f7fa7 + name: 'OpenVPN Server {#NAME} Port' + type: ZABBIX_ACTIVE + key: 'pfsense.value[openvpn_servervalue,{#SERVER},port]' + delay: 300s + tags: + - + tag: Application + value: 'OpenVPN Server' + - + uuid: be75ce1d23fa48cf80d8ba7ab181ad12 + name: 'OpenVPN Server {#NAME} Tunnel Status' + type: ZABBIX_ACTIVE + key: 'pfsense.value[openvpn_servervalue,{#SERVER},status]' + delay: 60s + valuemap: + name: 'pfSense OpenVPN Interface Status' + tags: + - + tag: Application + value: 'OpenVPN Server' + trigger_prototypes: + - + uuid: ea2851d79a11460fa467f3c02038dcf9 + expression: 'avg(/Template pfSense Active/pfsense.expected_carp_status,#3)<>2 and last(/Template pfSense Active/pfsense.value[openvpn_servervalue,{#SERVER},status],#3)=0' + name: 'OpenVPN Server {#NAME} is Down' + priority: HIGH + description: 'OpenVPN Tunnel is Down' + - + uuid: f99425c237ad457b8c17ac6e87fb26fc + name: 'Services Discovery' + type: ZABBIX_ACTIVE + key: 'pfsense.discovery[services]' + delay: 300s + item_prototypes: + - + uuid: 072e3f3d659c4414adb7054e268383e9 + name: 'Service {#DESCRIPTION} enabled on CARP Slave' + key: 'pfsense.value[service_value,{#SERVICE},run_on_carp_slave]' + delay: 600s + valuemap: + name: 'Generic YesNo' + tags: + - + tag: Application + value: Services + - + uuid: a082002e7599481b8b58ad2d5e1d4e43 + name: 'Service {#DESCRIPTION} Status' + key: 'pfsense.value[service_value,{#SERVICE},status]' + delay: 60s + valuemap: + name: 'Service state' + tags: + - + tag: Application + value: Services + trigger_prototypes: + - + uuid: f9f34f0546b24f30b098254d052507f1 + expression: | + avg(/Template pfSense Active/pfsense.value[service_value,{#SERVICE},status],#3)=0 and ( + + (last(/Template pfSense Active/pfsense.value[service_value,{#SERVICE},run_on_carp_slave])=1 and + avg(/Template pfSense Active/pfsense.value[carp_status],#3)=2) + + or + + ( last(/Template pfSense Active/pfsense.value[carp_status])=1) + + or + + (last(/Template pfSense Active/pfsense.value[carp_status])=0) + ) + name: 'Service {#DESCRIPTION} is not running' + priority: HIGH + description: 'Service is not running' + - + uuid: 06f42546705d4a7b89178d8f024f4a03 + name: 'Mounted filesystem discovery' + type: ZABBIX_ACTIVE + key: vfs.fs.discovery + delay: '3600' + filter: + conditions: + - + macro: '{#FSTYPE}' + value: '@File systems for discovery' + formulaid: A + lifetime: 7d + description: 'Discovery of file systems of different types as defined in global regular expression "File systems for discovery".' + item_prototypes: + - + uuid: 96acea60f88b42cb8fbc9c7d47881d26 + name: 'Free inodes on {#FSNAME} (percentage)' + type: ZABBIX_ACTIVE + key: 'vfs.fs.inode[{#FSNAME},pfree]' + delay: '60' + history: 7d + value_type: FLOAT + units: '%' + tags: + - + tag: Application + value: Filesystems + trigger_prototypes: + - + uuid: 1ea81cdc56fd483d82f187d209cff516 + expression: 'last(/Template pfSense Active/vfs.fs.inode[{#FSNAME},pfree])<20' + name: 'Free inodes is less than 20% on volume {#FSNAME}' + priority: WARNING + - + uuid: ff42876417ee4d6b9a69341f69c3cb5c + name: 'Free disk space on {#FSNAME}' + type: ZABBIX_ACTIVE + key: 'vfs.fs.size[{#FSNAME},free]' + delay: '60' + history: 7d + units: B + tags: + - + tag: Application + value: Filesystems + - + uuid: 04c24f47f7ea4ed68416b0b465fc7de5 + name: 'Free disk space on {#FSNAME} (percentage)' + type: ZABBIX_ACTIVE + key: 'vfs.fs.size[{#FSNAME},pfree]' + delay: '60' + history: 7d + value_type: FLOAT + units: '%' + tags: + - + tag: Application + value: Filesystems + trigger_prototypes: + - + uuid: 41119ea7e7924b95ba5e148277745f3c + expression: 'last(/Template pfSense Active/vfs.fs.size[{#FSNAME},pfree])<20' + name: 'Free disk space is less than 20% on volume {#FSNAME}' + priority: WARNING + - + uuid: 6466404aa20a40bb95ccadc0662f7eeb + name: 'Total disk space on {#FSNAME}' + type: ZABBIX_ACTIVE + key: 'vfs.fs.size[{#FSNAME},total]' + delay: '3600' + history: 7d + units: B + tags: + - + tag: Application + value: Filesystems + - + uuid: bcd151df26344c1580b68a88b80a919e + name: 'Used disk space on {#FSNAME}' + type: ZABBIX_ACTIVE + key: 'vfs.fs.size[{#FSNAME},used]' + delay: '60' + history: 7d + units: B + tags: + - + tag: Application + value: Filesystems + graph_prototypes: + - + uuid: e0fcad45031446ee81562fa2c5a19740 + name: 'Disk space usage {#FSNAME}' + width: '600' + height: '340' + yaxismax: '0' + show_work_period: 'NO' + show_triggers: 'NO' + type: PIE + show_3d: 'YES' + graph_items: + - + color: CC0000 + type: GRAPH_SUM + item: + host: 'Template pfSense Active' + key: 'vfs.fs.size[{#FSNAME},total]' + - + sortorder: '1' + color: 5B5B5B + item: + host: 'Template pfSense Active' + key: 'vfs.fs.size[{#FSNAME},free]' + - + sortorder: '2' + color: AEEE00 + item: + host: 'Template pfSense Active' + key: 'vfs.fs.size[{#FSNAME},used]' + macros: + - + macro: '{$CARP_SERVICES_STOPPED}' + value: ^(haproxy|openvpn)$ + - + macro: '{$CARP_SLAVE_SERVICES:"haproxy"}' + value: '0' + - + macro: '{$CARP_SLAVE_SERVICES:"openvpn"}' + value: '0' + - + macro: '{$EXPECTED_CARP_STATUS}' + value: '0' + dashboards: + - + uuid: a88c02addc374f83ade5063845b7a828 + name: 'System performance' + pages: + - + widgets: + - + type: GRAPH_CLASSIC + width: '12' + height: '7' + fields: + - + type: GRAPH + name: graphid + value: + host: 'Template pfSense Active' + name: 'Active Connections (pie)' + - + type: GRAPH_CLASSIC + x: '12' + width: '12' + height: '7' + fields: + - + type: GRAPH + name: graphid + value: + host: 'Template pfSense Active' + name: 'Network Memory Buffer (pie)' + - + type: GRAPH_CLASSIC + 'y': '7' + width: '12' + height: '7' + fields: + - + type: GRAPH + name: graphid + value: + host: 'Template pfSense Active' + name: 'CPU load' + - + type: GRAPH_CLASSIC + x: '12' + 'y': '7' + width: '12' + height: '7' + fields: + - + type: GRAPH + name: graphid + value: + host: 'Template pfSense Active' + name: 'Memory Usage simple (pie)' + valuemaps: + - + uuid: c1dcf6e418b94f07bf15ca15844d3eb3 + name: 'Generic YesNo' + mappings: + - + value: '0' + newvalue: 'No' + - + value: '1' + newvalue: 'Yes' + - + uuid: cc85f86bc6974aaca6cf474d69d404fa + name: 'pfSense CARP Status' + mappings: + - + value: '0' + newvalue: Disabled + - + value: '1' + newvalue: Master + - + value: '2' + newvalue: Backup + - + value: '3' + newvalue: Inconsistent + - + value: '4' + newvalue: Problem + - + uuid: e5ef9028f13144a994c65b1b0fd866ee + name: 'pfSense Gateway Status' + mappings: + - + value: '0' + newvalue: Up + - + value: '1' + newvalue: 'Packet Loss' + - + value: '2' + newvalue: 'High Delay' + - + value: '3' + newvalue: 'High Packet Loss' + - + value: '4' + newvalue: 'Forced Down' + - + value: '5' + newvalue: Down + - + uuid: 0230121a072c459582593d9d70686f6e + name: 'pfSense OpenVPN Interface Status' + mappings: + - + value: '0' + newvalue: Down + - + value: '1' + newvalue: Up + - + value: '2' + newvalue: None + - + value: '3' + newvalue: Reconnecting + - + value: '4' + newvalue: Waiting + - + value: '5' + newvalue: Up/Listening + - + uuid: e394e9e9642e4999aaeb4bae2f67e612 + name: 'pfSense OpenVPN Mode' + mappings: + - + value: '1' + newvalue: 'Peer to Peer (SSL/TLS)' + - + value: '2' + newvalue: 'P2P Shared Key' + - + value: '3' + newvalue: 'Remote Access (SSL/TLS)' + - + value: '4' + newvalue: 'Remote Access (User Auth)' + - + value: '5' + newvalue: 'Remote Access 8SSL/TLS + User Auth)' + - + uuid: 8e060d1f44054f2499c649a299dd6f42 + name: 'Service state' + mappings: + - + value: '0' + newvalue: Down + - + value: '1' + newvalue: Up + triggers: + - + uuid: ba26b37d090c439faf2ed71f0e8b2be3 + expression: 'last(/Template pfSense Active/pfsense.expected_carp_status)<>0 and last(/Template pfSense Active/pfsense.value[carp_status])<>{$EXPECTED_CARP_STATUS}' + name: 'CARP Status not Expected on {HOST.NAME}' + priority: HIGH + description: 'pfSense CARP is not in the state Expected. This means that a failover could be in process.' + graphs: + - + uuid: 499d867c58974a8e914b0423bdbf3d01 + name: 'Active Connections' + show_triggers: 'NO' + ymin_type_1: FIXED + ymax_type_1: ITEM + ymax_item_1: + host: 'Template pfSense Active' + key: pfsense.states.max + graph_items: + - + drawtype: GRADIENT_LINE + color: FF2C27 + item: + host: 'Template pfSense Active' + key: pfsense.states.current + - + uuid: 6cd23b5084844a2481beb5c34f1e603a + name: 'Active Connections (pie)' + width: '600' + height: '340' + yaxismax: '0' + show_work_period: 'NO' + show_triggers: 'NO' + type: PIE + graph_items: + - + color: 5B5B5B + type: GRAPH_SUM + item: + host: 'Template pfSense Active' + key: pfsense.states.max + - + sortorder: '1' + drawtype: GRADIENT_LINE + color: FF2C27 + item: + host: 'Template pfSense Active' + key: pfsense.states.current + - + uuid: 15db8adacf6e4b35ba5a6b36b2ddef1f + name: 'CPU jumps' + graph_items: + - + drawtype: GRADIENT_LINE + color: '009900' + item: + host: 'Template pfSense Active' + key: system.cpu.switches + - + sortorder: '1' + drawtype: GRADIENT_LINE + color: '000099' + item: + host: 'Template pfSense Active' + key: system.cpu.intr + - + uuid: c515614caf3445e6b28858907b1d1713 + name: 'CPU load' + type: STACKED + ymin_type_1: FIXED + graph_items: + - + color: FFA619 + item: + host: 'Template pfSense Active' + key: 'system.cpu.load[percpu,avg1]' + - + sortorder: '1' + color: E86E30 + item: + host: 'Template pfSense Active' + key: 'system.cpu.load[percpu,avg5]' + - + sortorder: '2' + color: FF2F26 + item: + host: 'Template pfSense Active' + key: 'system.cpu.load[percpu,avg15]' + - + uuid: aa694daef9004553952ec7cf3fa153b1 + name: 'CPU utilization (Line)' + show_triggers: 'NO' + ymin_type_1: FIXED + ymax_type_1: FIXED + graph_items: + - + drawtype: GRADIENT_LINE + color: FFE819 + item: + host: 'Template pfSense Active' + key: 'system.cpu.util[,interrupt]' + - + sortorder: '1' + drawtype: GRADIENT_LINE + color: E85D17 + item: + host: 'Template pfSense Active' + key: 'system.cpu.util[,nice]' + - + sortorder: '2' + drawtype: GRADIENT_LINE + color: DF26FF + item: + host: 'Template pfSense Active' + key: 'system.cpu.util[,system]' + - + sortorder: '3' + drawtype: GRADIENT_LINE + color: '1775E8' + item: + host: 'Template pfSense Active' + key: 'system.cpu.util[,user]' + - + sortorder: '4' + color: 03D933 + item: + host: 'Template pfSense Active' + key: 'system.cpu.util[,idle]' + - + uuid: 61378e27951a4882b1f88d041922ad16 + name: 'Memory Available details (pie)' + width: '600' + height: '340' + yaxismax: '0' + show_work_period: 'NO' + show_triggers: 'NO' + type: PIE + graph_items: + - + color: '003300' + type: GRAPH_SUM + item: + host: 'Template pfSense Active' + key: 'vm.memory.size[available]' + - + sortorder: '1' + color: '005500' + item: + host: 'Template pfSense Active' + key: 'vm.memory.size[free]' + - + sortorder: '2' + color: '007700' + item: + host: 'Template pfSense Active' + key: 'vm.memory.size[cached]' + - + sortorder: '3' + color: '009900' + item: + host: 'Template pfSense Active' + key: 'vm.memory.size[inactive]' + - + uuid: 625d8fc33a5d410ab2229dd2e8e99762 + name: 'Memory usage' + show_triggers: 'NO' + type: STACKED + ymin_type_1: FIXED + ymax_type_1: ITEM + ymax_item_1: + host: 'Template pfSense Active' + key: 'vm.memory.size[total]' + graph_items: + - + color: 00EE00 + item: + host: 'Template pfSense Active' + key: 'vm.memory.size[wired]' + - + sortorder: '1' + color: 00CC00 + item: + host: 'Template pfSense Active' + key: 'vm.memory.size[active]' + - + sortorder: '2' + color: '007700' + item: + host: 'Template pfSense Active' + key: 'vm.memory.size[inactive]' + - + sortorder: '3' + color: '005500' + item: + host: 'Template pfSense Active' + key: 'vm.memory.size[cached]' + - + sortorder: '4' + color: '003300' + item: + host: 'Template pfSense Active' + key: 'vm.memory.size[free]' + - + uuid: eeb86545b71145949b241b7d89b3a79b + name: 'Memory Usage simple (pie)' + width: '600' + height: '340' + yaxismax: '0' + show_work_period: 'NO' + show_triggers: 'NO' + type: PIE + graph_items: + - + color: '003300' + item: + host: 'Template pfSense Active' + key: 'vm.memory.size[available]' + - + sortorder: '1' + color: 00DD00 + item: + host: 'Template pfSense Active' + key: kt.mem.used + - + uuid: ab954e447cb14b10bb902e7c43a6d31a + name: 'Network Memory Buffer' + show_triggers: 'NO' + type: STACKED + ymin_type_1: FIXED + ymax_type_1: ITEM + ymax_item_1: + host: 'Template pfSense Active' + key: pfsense.mbuf.max + graph_items: + - + color: B26E16 + item: + host: 'Template pfSense Active' + key: pfsense.mbuf.current + - + sortorder: '1' + color: FFCE8E + item: + host: 'Template pfSense Active' + key: pfsense.mbuf.cache + - + uuid: eab355b1ef2f450a938441c913b7631a + name: 'Network Memory Buffer (pie)' + width: '600' + height: '340' + yaxismax: '0' + show_work_period: 'NO' + show_triggers: 'NO' + type: PIE + graph_items: + - + color: 5B5B5B + type: GRAPH_SUM + item: + host: 'Template pfSense Active' + key: pfsense.mbuf.max + - + sortorder: '1' + color: FFCE8E + item: + host: 'Template pfSense Active' + key: pfsense.mbuf.cache + - + sortorder: '2' + color: B26E16 + item: + host: 'Template pfSense Active' + key: pfsense.mbuf.current + - + uuid: 9522838e31244b6e88a9a020bdd07602 + name: 'Swap usage' + width: '600' + height: '340' + yaxismax: '0' + show_work_period: 'NO' + show_triggers: 'NO' + type: PIE + show_3d: 'YES' + graph_items: + - + color: 5B5B5B + type: GRAPH_SUM + item: + host: 'Template pfSense Active' + key: 'system.swap.size[,total]' + - + sortorder: '1' + color: FFFF33 + item: + host: 'Template pfSense Active' + key: 'system.swap.size[,used]' diff --git a/zabbix6/pfsense_active_ipsec.yaml b/zabbix6/pfsense_active_ipsec.yaml new file mode 100644 index 0000000..fff4dd8 --- /dev/null +++ b/zabbix6/pfsense_active_ipsec.yaml @@ -0,0 +1,247 @@ +zabbix_export: + version: '6.0' + date: '2023-02-26T13:19:29Z' + groups: + - + uuid: 4918b88734c54bd094cff7585b5d71fc + name: 'Templates/Network Devices' + templates: + - + uuid: 7b956a3e6aa1464781b38a854872a1c6 + template: 'Template pfSense Active IPsec' + name: 'pfSense Active: IPsec' + description: | + Extension for pfSense Active Template. + Monitor IPsec VPN. + + Requires pfsense_zbx.php installed to pfSense Box. + Version 1.0.2 + + https://github.com/rbicelli/pfsense-zabbix-template + groups: + - + name: 'Templates/Network Devices' + discovery_rules: + - + uuid: e7526169245d49a6aa6afbcacaa02b18 + name: 'IPsec Phase 1 Discovery' + type: ZABBIX_ACTIVE + key: 'pfsense.discovery[ipsec_ph1]' + delay: 1200s + description: 'Discovery of IPsec Phase 1' + item_prototypes: + - + uuid: 04d6b1d0a32949bfa96cf503f60b6c53 + name: 'IPsec Tunnel {#IKEID} {#NAME} Tunnel Enabled' + type: ZABBIX_ACTIVE + key: 'pfsense.value[ipsec_ph1,{#IKEID},disabled]' + delay: 120s + description: 'IPsec Phase 1 Tunnel Mode' + valuemap: + name: 'pfSense IPsec Enabled' + tags: + - + tag: Application + value: IPsec + - + uuid: 810da7b475df4d738c702f373771092e + name: 'IPsec Tunnel {#IKEID} {#NAME} IKE Type' + type: ZABBIX_ACTIVE + key: 'pfsense.value[ipsec_ph1,{#IKEID},iketype]' + delay: 600s + description: 'IPsec Phase 1 IKE Type' + valuemap: + name: 'pfSense IPsec IKE Type' + tags: + - + tag: Application + value: IPsec + - + uuid: 47b54bc4a08e464b839bcfd5106ec5a9 + name: 'IPsec Tunnel {#IKEID} {#NAME} Tunnel Mode' + type: ZABBIX_ACTIVE + key: 'pfsense.value[ipsec_ph1,{#IKEID},mode]' + delay: 600s + description: 'IPsec Phase 1 Tunnel Mode' + valuemap: + name: 'pfSense IPsec Tunnel Mode' + tags: + - + tag: Application + value: IPsec + - + uuid: a404f5d20988445d8777758b95b02076 + name: 'IPsec Tunnel {#IKEID} {#NAME} Protocol' + type: ZABBIX_ACTIVE + key: 'pfsense.value[ipsec_ph1,{#IKEID},protocol]' + delay: 600s + description: 'IPsec Phase 1 Protocol' + valuemap: + name: 'pfSense IPsec Protocol' + tags: + - + tag: Application + value: IPsec + - + uuid: ce0d2464361e41018fdd1831db1ec4b3 + name: 'IPsec Tunnel {#IKEID} {#NAME} Remote Gateway' + type: ZABBIX_ACTIVE + key: 'pfsense.value[ipsec_ph1,{#IKEID},remote-gateway]' + delay: 600s + trends: '0' + value_type: TEXT + description: 'IPsec Phase 1 Remote Gateway' + tags: + - + tag: Application + value: IPsec + - + uuid: 34d7e2395d8b43ec9c0267664be27881 + name: 'IPsec Tunnel {#IKEID} {#NAME} Phase 1 Status' + type: ZABBIX_ACTIVE + key: 'pfsense.value[ipsec_ph1,{#IKEID},status]' + delay: 60s + description: 'IPsec Phase 1 Tunnel Mode' + valuemap: + name: 'pfSense IPsec Phase 1 Status' + tags: + - + tag: Application + value: IPsec + trigger_prototypes: + - + uuid: d675635e19aa4cd7a7202e983cbe4ce6 + expression: 'last(/Template pfSense Active IPsec/pfsense.value[ipsec_ph1,{#IKEID},disabled])=0 and last(/Template pfSense Active IPsec/pfsense.value[ipsec_ph1,{#IKEID},status])<>1 and last(/Template pfSense Active IPsec/pfsense.value[ipsec_ph1,{#IKEID},status])<10' + name: 'IPsec Tunnel {#IKEID} ({#NAME}) Not Connected' + priority: HIGH + description: 'IPsec Phase 1 is not connected.' + - + uuid: fa934077cae64a049e68e2130e5e1e84 + name: 'IPsec Phase 2 Discovery' + type: ZABBIX_ACTIVE + key: 'pfsense.discovery[ipsec_ph2]' + delay: 1200s + description: 'Discovery of IPsec Phase 2' + item_prototypes: + - + uuid: 1857b124103c4f08b5ed962259fcbe06 + name: 'IPsec Tunnel {#IKEID}.{#REQID} {#NAME} Phase 2 Enabled' + type: ZABBIX_ACTIVE + key: 'pfsense.value[ipsec_ph2,{#UNIQID},disabled]' + delay: 120s + description: 'IPsec Tunnel Phase 2 Protocol' + valuemap: + name: 'pfSense IPsec Enabled' + tags: + - + tag: Application + value: IPsec + - + uuid: 3ac7d6d1be034a3db8afad18791b43aa + name: 'IPsec Tunnel {#IKEID}.{#REQID} {#NAME} Phase 2 Life Time' + type: ZABBIX_ACTIVE + key: 'pfsense.value[ipsec_ph2,{#UNIQID},lifetime]' + delay: 600s + units: s + description: 'IPsec Tunnel Phase 2 Life Time' + tags: + - + tag: Application + value: IPsec + - + uuid: dfbae3fe2bcd45f3ac38c6ea0df5d250 + name: 'IPsec Tunnel {#IKEID}.{#REQID} {#NAME} Phase 2 Mode' + type: ZABBIX_ACTIVE + key: 'pfsense.value[ipsec_ph2,{#UNIQID},mode]' + delay: 600s + description: 'IPsec Tunnel Phase 2 Mode' + tags: + - + tag: Application + value: IPsec + - + uuid: 794565a046ff447ca8ad3a7597ee52f5 + name: 'IPsec Tunnel {#IKEID}.{#REQID} {#NAME} Phase 2 Protocol' + type: ZABBIX_ACTIVE + key: 'pfsense.value[ipsec_ph2,{#UNIQID},protocol]' + delay: 600s + description: 'IPsec Tunnel Phase 2 Protocol' + valuemap: + name: 'pfSense IPsec Phase 2 Protocol' + tags: + - + tag: Application + value: IPsec + valuemaps: + - + uuid: fb66440f3f454b36ae5c5d7b015529a1 + name: 'pfSense IPsec Enabled' + mappings: + - + value: '0' + newvalue: 'Yes' + - + value: '1' + newvalue: 'No' + - + uuid: 7077365285f14733a55edd9ade5fdfcb + name: 'pfSense IPsec IKE Type' + mappings: + - + value: '0' + newvalue: Auto + - + value: '1' + newvalue: 'IKE v1' + - + value: '2' + newvalue: 'IKE v2' + - + uuid: a7a80f8152804c6f882898ca7378c403 + name: 'pfSense IPsec Phase 1 Status' + mappings: + - + value: '0' + newvalue: Down + - + value: '1' + newvalue: Established + - + value: '2' + newvalue: Connecting + - + value: '10' + newvalue: 'Down on CARP Secondary' + - + uuid: 55e4705203cf4b5996dcd6e10cd508b9 + name: 'pfSense IPsec Phase 2 Protocol' + mappings: + - + value: '1' + newvalue: ESP + - + value: '2' + newvalue: AH + - + uuid: b72cdb06faec4f9492913ba820677370 + name: 'pfSense IPsec Protocol' + mappings: + - + value: '0' + newvalue: 'Dual Stack (IPv4 & IPv6)' + - + value: '1' + newvalue: IPv4 + - + value: '2' + newvalue: IPv6 + - + uuid: 864f6d2be4c544cf8fe38b9a619363b5 + name: 'pfSense IPsec Tunnel Mode' + mappings: + - + value: '0' + newvalue: Main + - + value: '1' + newvalue: Aggressive diff --git a/zabbix6/pfsense_active_openvpn_userauth.yaml b/zabbix6/pfsense_active_openvpn_userauth.yaml new file mode 100644 index 0000000..687f5ff --- /dev/null +++ b/zabbix6/pfsense_active_openvpn_userauth.yaml @@ -0,0 +1,147 @@ +zabbix_export: + version: '6.0' + date: '2023-02-26T13:19:53Z' + groups: + - + uuid: 4918b88734c54bd094cff7585b5d71fc + name: 'Templates/Network Devices' + templates: + - + uuid: 6a1ef5e767cc4aba85c0d1712972eeb2 + template: 'Template pfSense Active OpenVPN Server User Auth' + name: 'pfSense Active: OpenVPN Server User Auth' + description: | + Extension for pfSense Active Template. + Monitor client Connections of OpenVPN Server. + + Requires pfsense_zbx.php installed to pfSense Box. + Version 1.0.2 + + https://github.com/rbicelli/pfsense-zabbix-template + groups: + - + name: 'Templates/Network Devices' + discovery_rules: + - + uuid: bae30f6a683e407aa9eeafbf9edb9179 + name: 'OpenVPN User Auth Connected Clients Discovery' + type: ZABBIX_ACTIVE + key: 'pfsense.discovery[openvpn_server_user]' + delay: 60s + description: 'Discovery of clients connected to OpenVPN Server in User Auth Mode' + item_prototypes: + - + uuid: 272166157ee4456b887e7df305167c2d + name: 'OpenVPN Server {#SERVERNAME}, Client {#USERID}: Bytes Received' + type: ZABBIX_ACTIVE + key: 'pfsense.value[openvpn_server_uservalue,{#UNIQUEID},bytes_recv]' + delay: 60s + trends: '0' + units: bytes + description: 'Client Bytes Received' + tags: + - + tag: Application + value: 'OpenVPN Server Clients' + - + uuid: 1acfb6c10d4d4a8d97281f37e757d3bf + name: 'OpenVPN Server {#SERVERNAME}, Client {#USERID}: Bytes Sent' + type: ZABBIX_ACTIVE + key: 'pfsense.value[openvpn_server_uservalue,{#UNIQUEID},bytes_sent]' + delay: 60s + trends: '0' + units: bytes + description: 'Client Bytes Sent' + tags: + - + tag: Application + value: 'OpenVPN Server Clients' + - + uuid: 5f779a0e03b84be19030766d6fcffd92 + name: 'OpenVPN Server {#SERVERNAME}, Client {#USERID}: Connection Time' + type: ZABBIX_ACTIVE + key: 'pfsense.value[openvpn_server_uservalue,{#UNIQUEID},connect_time_unix]' + delay: 60s + trends: '0' + units: unixtime + description: 'Client Connect Time' + tags: + - + tag: Application + value: 'OpenVPN Server Clients' + - + uuid: 40b0a64862a44a99a33581b916ad6467 + name: 'OpenVPN Server {#SERVERNAME}, Client {#USERID}: Remote Host' + type: ZABBIX_ACTIVE + key: 'pfsense.value[openvpn_server_uservalue,{#UNIQUEID},remote_host]' + delay: 60s + trends: '0' + value_type: TEXT + description: 'Remote Host' + tags: + - + tag: Application + value: 'OpenVPN Server Clients' + - + uuid: 8e1b6f2d8397483d8a2768babd93a1a7 + name: 'OpenVPN Server {#SERVERNAME}, Client {#USERID}: User Name' + type: ZABBIX_ACTIVE + key: 'pfsense.value[openvpn_server_uservalue,{#UNIQUEID},user_name]' + delay: 60s + trends: '0' + value_type: TEXT + description: 'Client User Name' + tags: + - + tag: Application + value: 'OpenVPN Server Clients' + - + uuid: 0329f5bf3fb94bdaa30c0e412bc337f8 + name: 'OpenVPN Server {#SERVERNAME}, Client {#USERID}: Virtual IP Address (IPv6)' + type: ZABBIX_ACTIVE + key: 'pfsense.value[openvpn_server_uservalue,{#UNIQUEID},virtual_addr6]' + delay: 60s + trends: '0' + value_type: TEXT + description: 'IPv6 Address assigned from OpenVPN Server' + tags: + - + tag: Application + value: 'OpenVPN Server Clients' + - + uuid: 1c21ccdd3bf14aa3b8b65986b5317f6a + name: 'OpenVPN Server {#SERVERNAME}, Client {#USERID}: Virtual IP Address' + type: ZABBIX_ACTIVE + key: 'pfsense.value[openvpn_server_uservalue,{#UNIQUEID},virtual_addr]' + delay: 60s + trends: '0' + value_type: TEXT + description: 'IP Address assigned from OpenVPN Server' + tags: + - + tag: Application + value: 'OpenVPN Server Clients' + - + uuid: 15192106b2164e0e9df447ba330007db + name: 'OpenVPN Server {#SERVERNAME}, Client {#USERID}: Client ID' + type: ZABBIX_ACTIVE + key: 'pfsense.value[openvpn_server_uservalue_numeric,{#UNIQUEID},client_id]' + delay: 60s + trends: '0' + description: 'Client ID' + tags: + - + tag: Application + value: 'OpenVPN Server Clients' + - + uuid: de719e75d02440fe96c987bd5ddcb367 + name: 'OpenVPN Server {#SERVERNAME}, Client {#USERID}: Peer ID' + type: ZABBIX_ACTIVE + key: 'pfsense.value[openvpn_server_uservalue_numeric,{#UNIQUEID},peer_id]' + delay: 60s + trends: '0' + description: 'Peer ID' + tags: + - + tag: Application + value: 'OpenVPN Server Clients' diff --git a/zabbix6/pfsense_active_speedtest.yaml b/zabbix6/pfsense_active_speedtest.yaml new file mode 100644 index 0000000..4f1c07b --- /dev/null +++ b/zabbix6/pfsense_active_speedtest.yaml @@ -0,0 +1,97 @@ +zabbix_export: + version: '6.0' + date: '2023-02-26T13:20:29Z' + groups: + - + uuid: 4918b88734c54bd094cff7585b5d71fc + name: 'Templates/Network Devices' + templates: + - + uuid: 1c7cba22540d4c10a5ee14c2b25223ca + template: 'pfSense Active Speedtest' + name: 'pfSense Active: Speedtest' + description: | + Extension for pfSense Active Template. + Executes Speedtests on WAN Interfaces. + + Requires pfsense_zbx.php installed to pfSense Box. + Version 1.0.5 + + https://github.com/rbicelli/pfsense-zabbix-template + groups: + - + name: 'Templates/Network Devices' + discovery_rules: + - + uuid: 40288914aa9742adb93120c367263690 + name: 'WAN Interfaces' + type: ZABBIX_ACTIVE + key: 'pfsense.discovery[wan]' + delay: 300s + description: 'Discover WAN Interfaces' + item_prototypes: + - + uuid: a79d28cf3f3b4981b59f571117e64d24 + name: 'Speedtest Download on {#IFDESCR}' + type: ZABBIX_ACTIVE + key: 'pfsense.value[if_speedtest_value,{#IFNAME},download]' + delay: 3600s + value_type: FLOAT + units: bps + description: 'Download speed determined by Ookla Speedtest package' + tags: + - + tag: Application + value: 'Network interfaces' + - + uuid: 52b640fcdf484b538f85bf32d2afbcf3 + name: 'Speedtest Ping on {#IFDESCR}' + type: ZABBIX_ACTIVE + key: 'pfsense.value[if_speedtest_value,{#IFNAME},ping]' + delay: 3600s + value_type: FLOAT + units: ms + description: 'Ping determined by Ookla Speedtest package' + tags: + - + tag: Application + value: 'Network interfaces' + - + uuid: 4bd063f24e554832b59bfa2231d53bf1 + name: 'Speedtest Upload on {#IFDESCR}' + type: ZABBIX_ACTIVE + key: 'pfsense.value[if_speedtest_value,{#IFNAME},upload]' + delay: 3600s + value_type: FLOAT + units: bps + description: 'Ping determined by Ookla Speedtest package' + tags: + - + tag: Application + value: 'Network interfaces' + graph_prototypes: + - + uuid: 74cdea0b8136495496bb90593bd78a59 + name: 'Speedtest metrics on {#IFDESCR}' + graph_items: + - + sortorder: '1' + color: 199C0D + calc_fnc: ALL + item: + host: 'pfSense Active Speedtest' + key: 'pfsense.value[if_speedtest_value,{#IFNAME},download]' + - + sortorder: '2' + color: FFFF00 + calc_fnc: ALL + item: + host: 'pfSense Active Speedtest' + key: 'pfsense.value[if_speedtest_value,{#IFNAME},upload]' + - + sortorder: '3' + color: 0040FF + calc_fnc: ALL + item: + host: 'pfSense Active Speedtest' + key: 'pfsense.value[if_speedtest_value,{#IFNAME},ping]'