SwordArMor

Monitoring des sessions BGP de bird via NRPE

Présentation

Toujours pour l’association grifon, j’ai eu besoin d’écrire un script afin de pouvoir remonter l’état de nos session BGP dans notre monitoring, c’est à dire un icinga2. Comme icinga est un fork de nagios, ça devrait marcher avec tous les outils de monitoring compatibles avec nagios.

Installation

La procédure d’installation a été réalisée sous FreeBSD, mais le script fonctionne aussi sous Linux, il suffit d’adapter les chemins

Récupération du script

Pour commencer, copiez le script si dessous dans le dossier contenant tous les plugins nagios sous le nom check_bgp. Vous devez donc obtenir un truc du genre /usr/local/libexec/nagios/check_bgp ou /usr/lib/nagios/plugins/check_bgp en fonction de votre OS.

Ensuite, rendez-le exécutable avec un petit chmod +x.

Configuration de sudo

Les plugins nagios tournent avec les droits de l’utilisateur nagios mais les droits sur le socket de bird sont très souvent limités à root. Il faut donc soit modifier les droits, soit utiliser sudo sans mot de passe. Voici une ligne de configuration sudo pour permettre à nagios d’exécuter birdc et birdc6 : nagios ALL=(ALL) NOPASSWD: /usr/local/sbin/birdc, /usr/local/sbin/birdc6.

Configuration de nrpe

Si nrpe n’est pas installé, installez-le avec pkg install nrpe-ssl. La configuration se fait dans /usr/local/etc/nrpe.cfg.
Il faut ajouter l’IP de la machine de monitoring dans allowed_hosts. Il est possible d’en mettre plusieurs séparée par des virgules. Par exemple : allowed_hosts=127.0.0.1, 2001:67c:1740:9032::229, 193.200.42.229.
Il faut ensuite ajouter les sessions que nous allons monitorées. Il faut obligatoirement utiliser -4 ou -6 pour préciser si on monitore une session IPv4 ou IPv6 ainsi que -p $protocol. L’option -s permet d’utiliser sudo pour avoir accès au socket de bird, elle n’est pas obligatoire. Par exemple, pour les sessions entre mon serveur et les routeurs de grifon s’appelle « bgp_alarig » aussi bien en IPv4 qu’en IPv6, je vais donc utiliser ces arguments :

command[check_bgp_ipv4_alarig]=/usr/local/libexec/nagios/check_bgp -4 -s -p bgp_alarig
command[check_bgp_ipv6_alarig]=/usr/local/libexec/nagios/check_bgp -6 -s -p bgp_alarig

Configuration de icinga2

Enfin, on va dire à icinga d’aller utiliser les commandes que l’on vient de créer :

object Service "nrpe-bgp-ipv4-alarig" {
  import "generic-service"

  host_name = "budic.grifon.fr"
  check_command = "nrpe"
  vars.nrpe_command = "check_bgp_ipv4_alarig"
  vars.sla = "24x7"
}

object Service "nrpe-bgp-ipv6-alarig" {
  import "generic-service"

  host_name = "budic.grifon.fr"
  check_command = "nrpe"
  vars.nrpe_command = "check_bgp_ipv6_alarig"
  vars.sla = "24x7"
}

On recharge les confs, et normalement on a un beau check qui vient de s’ajouter.

Code

Et voici le script à utiliser :

#!/bin/sh

# Copyright 2017 alarig <alarig@grifon.fr>
#
# BSD-3-Clause licence
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
#
# 2. Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
#
# 3. Neither the name of the copyright holder nor the names of its contributors
# may be used to endorse or promote products derived from this software without
# specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.

# For debuggin purpose, uncomment the next line and `tail -F` the file.
#exec 2> /tmp/check_bgp.log

usage() {
        printf "Usage:\n"
        printf "check_bgp [-4|-6] -p session\n"
        printf "Must be run with user account able to use birdc/birdc6 or use"
        printf "-s to use birdc with sudo.\n"
}

args=$(getopt 46hsp: $*)

if [ $? -ne 0 ]; then
        usage
        exit 3
fi
set -- $args

while :; do
        case "$1" in
                -h)
                        usage
                        exit 0
                        shift
                        ;;
                -4)
                        VERSION="IPv4"
                        shift
                        ;;
                -6)
                        VERSION="IPv6"
                        shift
                        ;;
                -s)
                        SUDO='sudo'
                        shift
                        ;;
                -p)
                        SESSION="$2"
                        shift; shift
                        ;;
                --)
                        shift; break
                        ;;
        esac
done

# path expansion for birdc and sudo of FreeBSD
PATH="$PATH:/usr/local/sbin/:/usr/local/bin/"

if [ "${VERSION}" = "IPv4" ]; then
        birdc="${SUDO} birdc -r"
elif [ "${VERSION}" = "IPv6" ]; then
        birdc="${SUDO} birdc6 -r"
else
        printf "CRITICAL: Invalid IP version, use -4 for IPv4 and -6 for IPv6\n"
        exit 2
fi

if [ -z ${SESSION} ]; then
        printf "CRITICAL: No session name supplied, use -p \$session.\n"
        exit 2
fi

STATE="$($birdc show protocol ${SESSION} | awk -v session=${SESSION} '$0 ~ session { print $6 }')"

# Session states: https://gitlab.labs.nic.cz/labs/bird/blob/master/proto/bgp/bgp.c#L1465
# Plugin return codes: https://nagios-plugins.org/doc/guidelines.html#AEN78

case ${STATE} in
        Established)
                printf "OK: ${SESSION} is ${STATE}\n"
                exit 0
                ;;
        OpenSent | OpenConfirm)
                printf "WARNING: ${SESSION} is in ${STATE} state\n"
                exit 1
                ;;
        Idle | Connect | Active)
                printf "CRITICAL: ${SESSION} is in ${STATE} state\n"
                exit 2
                ;;
        *)
                printf "Unknown state: ${STATE}\n"
                exit 3
                ;;
esac