Plugin de Centreon/Nagios para la API de Pi-hole

Este mañana he descubierto que Pihole tiene una pequeña API que se puede llamar desde el endpoint: admin/api.php? así que he decido crear un pequeño plugin que se pueda usar tanto en Centreon como en Nagios . Lo que conseguiremos con este plugin es mantener un histórico y graficar datos en nuestro Centreon como:

  • Numero consultas DNS al dia
  • Numero y porcentaje de anuncios bloqueados
  • Numero de clientes usando Pihole como DNS
  • Numero consultas clasificadas por IPv4, IPv6, PTR, SRV, etc…

La API es bastante limitada así que no he podido sacarle mucho mas. A continuación os dejo unos gráficos extraídos de mi Dashboard en el Centreon que tengo en mi Raspberry corriendo sobre un contenedor de Docker.

Query Types
DNS Queries
Numero de hosts
ADS blocked

El plugin es el que dejo aquí a continuación, pero como siempre digo, lo mas probable es que lo vaya actualizando, así que si lo queréis lo tendréis en mi GitHub actualizado.

#!/bin/bash
# Nagios plugin to work with Pihole API
########### By @deividgdt ###########
plugin_version="1.3"
#####################################

function info() {
	case "$1" in
		token)
			echo "[i] The file ${api_token_file} does not exist or it's empty."
			echo "[i] You can get your token from the value WEBPASSWORD in the file /etc/pihole/setupVars.conf"
			echo "[i] Just put in the file ${api_token_file} and that's it."
			echo ""
			echo "[i] Example:"
			echo "	centreon-engine@centreon # touch ${api_token_file}"
			echo "	centreon-engine@centreon # echo 'PASTE_YOUR_TOKEN_HERE' >> ${api_token_file}"
			exit 1;
		;;
		usage)
			echo "[i] Usage $0 -h pihole_ipaddress -s [ clients || queries || ads ] || -i || -q"
			echo ""
			echo "[i] -s (summary)"
			echo "	- clients: Number of clients using Pihole as their DNS server"
			echo "	- queries: Number of DNS queries"
			echo "	- ads: Number and percentage of ads blocked."
			echo ""
			echo "[i] -i (information)"
			echo "	- show the version of the plugin"
			echo "[i] -q"
			echo "	- queries by type AAAA, A, SOA, TXT, PTR, ANY, SRV, IPV4, IPV6"
		;;
		version)
			echo "[v] plugin by @deividgdt https://github.com/deividgdt - version: ${plugin_version}"
		;;
	esac
}

function apiCall() {
	local obj=$1
	local token=$2
	
	pihole_api_tempfile="/usr/lib/nagios/plugins/pihole_api.tmp"
	
	case $obj in 
		"summary")
			pihole_api_output=$(curl http://${pihole_ipadd}/admin/api.php?${obj} 2> /dev/null | sed 's/","/\n/g ; s/"//g' > ${pihole_api_tempfile})
		;;
		"getQueryTypes")
			pihole_api_output=$(curl "http://${pihole_ipadd}/admin/api.php?${obj}&auth=${token}" 2> /dev/null | sed "s,),,g ; s,(,,g ; s/,\"/\n/g ; s/\"//g" > ${pihole_api_tempfile})
		;;
	esac
}

function getApiToken() {
	# Default token file location
	api_token_file="/usr/lib/nagios/plugins/apihole.token"
	
	# If the file does not exist
	if [ ! -f ${api_token_file} ]; then
		info token
	else
		export api_token=$(cat ${api_token_file})
		# If the the api_token var is NULL because the file is empty (?)
		if [ -z ${api_token} ]; then 
			echo "[e] Token is NULL"; 
			info token 
		fi
	fi
}

function functSummary() {
	apiCall "summary"
	# The summary option passed
	case "${summary_opt}" in
		clients)	
			unique_clients=$(cat ${pihole_api_tempfile} | grep unique_clients | cut -f2 -d":")
			echo "THERE ARE ${unique_clients} HOSTS UP|Total=${unique_clients}"
		;;
		queries)	
			dns_queries_today=$(cat ${pihole_api_tempfile} | grep dns_queries_today | cut -f2 -d":")
			echo "DNS QUERIES TODAY ${dns_queries_today}|Total=${dns_queries_today}"
		;;
		ads)		
			ads_percentage_today=$(cat ${pihole_api_tempfile} | grep ads_percentage_today | cut -f2 -d":")
			ads_blocked_today=$(cat ${pihole_api_tempfile} | grep ads_blocked_today | cut -f2 -d":")
			echo "ADS BLOCKED TODAY ${ads_blocked_today} , PERCENTAGE = ${ads_percentage_today} %|Total=${ads_blocked_today} Percentage=${ads_percentage_today}%"
		;;
		
		*)
			echo "Incorrect arugment > ${summary_opt} < for the option -s";
			info "usage"
			exit 1;
		;;
	esac
}

function functGetQueryTypes() {
	# This function requires a token
	getApiToken
	
	# Calling the api
	apiCall "getQueryTypes" "${api_token}"
	
	# Local vars for query types
	local ipv4=$(cat ${pihole_api_tempfile} | grep -io "ipv4:.*" | cut -f2 -d":")
	local ipv6=$(cat ${pihole_api_tempfile} | grep -io "ipv6:.*" | cut -f2 -d":")
	local any=$(cat ${pihole_api_tempfile} | grep -io "any:.*" | cut -f2 -d":")
	local srv=$(cat ${pihole_api_tempfile} | grep -io "srv:.*" | cut -f2 -d":")
	local soa=$(cat ${pihole_api_tempfile} | grep -io "soa:.*" | cut -f2 -d":")
	local ptr=$(cat ${pihole_api_tempfile} | grep -io "ptr:.*" | cut -f2 -d":")
	local txt=$(cat ${pihole_api_tempfile} | grep -io "txt:.*" | sed 's,},,g' | cut -f2 -d":")
	
	echo "NUMBER OF QUERIES BY TYPE IPV4=${ipv4} , IPV6=${ipv6} , ANY=${any} , SRV=${srv} , SOA=${soa} , PTR=${ptr} , TXT=${txt}|IPV4=${ipv4} IPV6=${ipv6} ANY=${any} SRV=${srv} SOA=${soa} PTR=${ptr} TXT=${txt}"
	
}

if [ $# -eq 0 ]; then
	info "usage"
	exit 1;
fi

# The options passed by the user
while getopts "h:s:iq" opt; do
	case "$opt" in
		h ) 
			pihole_ipadd=$OPTARG						;;
		s ) 
			summary_selected="y"
			summary_opt=$OPTARG							;;
		q ) 
			query_type_selected="y" 					;;
		i ) 
			info "version"
			exit 0										;;
		\?) 
			echo "[e] Invalid option. -$OPTARG" 
			exit 1										;;
	esac
done

# The values passed by the user
if [ -z ${pihole_ipadd} ]; then 
	echo "[i] Please enter the Pihole IP address as follow: -h pihole_ipaddress"; 
	exit 1;
else
	if [[ "${summary_selected}" == "y" ]]; then
		# Calling the summary function
		functSummary
		exit 1;
	elif [[ "${query_type_selected}" == "y" ]]; then
		# Calling the Query Types funct
		functGetQueryTypes
	else
		info "usage"
	fi
	
	# Just delete the temp file
	rm -f ${pihole_api_tempfile}
fi

USO

Para usar el plugin es tan simple como ubicarlo en /usr/lib/nagios/plugins o en la ruta que tengáis todos vuestros plugins, en mi caso es esta. Desde aquí lo podremos llamar con Centreon o Nagios.

La sintaxis de uso es la siguiente:

./check_pihole_api -h pihole_ipaddress ( -s [ clients || queries || ads ] || -i || -q )
-h (hosts)
   - La dirección IP del hosts donde este instalado Pi-hole

-s (summary)
    - clients: Numero de clientes usando Pihole como DNS
    - queries: Numero de consultas DNS
    - ads: Numero y porcentaje de anuncios bloqueados

-i (information)
    - Muestra la version del plugin
-q
    - consulta por tipo AAAA, A, SOA, TXT, PTR, ANY, SRV, IPV4, IPV6

A continuación algunos ejemplos de uso en mi Pihole

Tened en cuenta que los valores que se extraen de la API son los mismo que se pueden observar en el Dashboard de Pi-hole:

Pi-hole Dashboard

UPDATE 14/04/2020

He añadido una nueva función al script que extrae los hosts en la red que más consultas DNS han realizado en las ultimas 24 h y que como veis a continuación podéis graficarlo:

TOP number of queries by host

Para obtener estos datos con el plugin hay que ejecutarlo con el parámetro: -t

./check_pihole_api -h $PIHOLE_IPADDRESS -t
TOP NUMBER OF QUERIES BY HOST portatil1.pihome=5678 movil1.pihome=4442 movil2.pihome=3556 portatil2.pihome=2280 samsungtv.pihome=1942| portatil1.pihome=5678 movil1.pihome=4442 movil2.pihome=3556 portatil2.pihome=2280 samsungtv.pihome=1942

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión /  Cambiar )

Google photo

Estás comentando usando tu cuenta de Google. Cerrar sesión /  Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión /  Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión /  Cambiar )

Conectando a %s