pfSense – Scripte für Icinga2 Monitoring

Icinga2 Check -  Öffentliche WAN IP Adresse der pfSense gleich der im DNS vom DynDNS Anbieter

Wenn man an seinem eigenen DSL Anschluss mit Zwangstrennung einen Dienst betreibt, der vom Internet aus erreichbar sein soll, ist es hilfreich zu wissen, ob die beim DynDNS Anbieter hinterlegten IP Adressen mit der des WAN Interfaces vom Router übereinstimmen.

Voraussetzung für das Monitoring ist Icinga2 und eine pfSense mit aktivierten SNMP, oder besser wie in diesem Fall SNMPv3. In der Paketverwaltung von pfSense kann man das Paket net-snmp für SNMPv3 nachinstallieren. Weitere Voraussetzung ist das Paket snmp auf dem Icinga2 Server, welches für den Befehl snmpwalk notwendig ist.

Die Scripte laufen auf einem Ubuntu Server. Bei einer anderen Linux Distribution sind eventuell weitere Anpassungen notwendig.

IPv4 Check

Für IPv4 ist die Überwachung noch recht einfach, da man die Adresse direkt per SNMP auslesen kann. Die markierten Stellen müssen an die eigenen Gegebenheiten angepasst werden. Auf dem Icinga2 Server folgenden Script anlegen:

sudo vi /usr/lib/nagios/plugins/check_ip_dns
#!/bin/bash
# Version 1.2
# Icinga Plugin
# WAN IPv4 Adresse der pfSense auslesen und mit der im DNS hinterlegten IPv4 Adresse vergleichen.

SNMPHost='IP SNMP Server' # IP-Adresse der pfSense
Username='user' # SNMPv3 User - pfSense SNMPv3 Konfiguration
Passwort='geheim' # SNMPv3 Passwort - pfSense SNMPv3 Konfiguration
Encryption='secret' # SNMPv3 Pre-Shared-Key (Passphrase) - pfSense SNMPv3 Konfiguration
Domain='example.com' # eigene Domain die überwacht werden soll
DNSHost='IP DNS Server' # DNS Server, z.B. IP-Adresse der pfSense oder Google DNS Server 8.8.8.8

OIDGateway='iso.3.6.1.2.1.4.21.1.7.0.0.0.0'  # Object Identifer: Provider IPv4 Gateway Adresse
OID='iso.3.6.1.2.1.4.21.1.7.'                # Object Identifer: öffentliche IPv4 Adresse der pfSense

# SNMPv3: öffentliche IPv4 Adresse der pfSense ermitteln
# Provider IPv4 Gateway Adresse
IPGateway=$(/usr/bin/snmpwalk $SNMPHost -v3 -l authPriv -u $Username -A $Passwort -a SHA -X $Encryption -x AES $OIDGateway | awk '{print $4}')
# Öffentliche IPv4 Adresse der pfSense: Object Identifer + Provider IPv4 Gateway Adresse 
IP=$(/usr/bin/snmpwalk $SNMPHost -v3 -l authPriv -u $Username -A $Passwort -a SHA -X $Encryption -x AES $OID$IPGateway | awk '{print $4}')

# IPv4 Adresse im öffentlichen DNS mit Icinga Plugin check_dig ermitteln
DIG=$(/usr/lib/nagios/plugins/check_dig -H $DNSHost -T A -l $Domain | awk '{print $12}' | sed 's#).*##')

# Überprüfen ob eine gültige IPv4 Adresse im öffentlichen DNS existiert
echo "$DIG" | grep -q -E '^([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}|[0-9a-e:]{1,39})$'
if [ "$?" != "0" ]
  then 
    echo "WARNING - No IPv4 DNS address for $Domain"
    exit 1

  else

# Überprüfen ob eine gültige öffentliche IPv4 Adresse am WAN Interface existiert
echo "$IP" | grep -q -E '^([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}|[0-9a-e:]{1,39})$'

  if [ "$?" != "0" ]
    then
      echo CRITICAL - No Public IPv4 address on the WAN interface!
      exit 2
    else

# Überprüfen ob die per SNMP ausgelesene Router IPv4 Adresse gleich der im öffentlichen DNS ist
    if [ $IP == $DIG ]
      then
        echo "($IP) OK - Public IPv4 address is equal to DynDNS address ($DIG)"
        exit 0
      else
        echo "($IP) CRITICAL - Public IPv4 address is not equal to DynDNS address! ($DIG)"
        exit 2
    fi
  fi
fi

Anschließend noch die korrekte Berechtigung setzen und den Script für einen Funktionstest auf der Konsole ausführen.

sudo chmod 755 /usr/lib/nagios/plugins/check_ip_dns

$ /usr/lib/nagios/plugins/check_ip_dns

In der commands.conf auf dem Icinga2 Server folgenden Eintrag hinzufügen:

sudo vi /etc/icinga2/conf.d/commands.conf
object CheckCommand "check_ip_dns" {
    import "plugin-check-command"
    command = [PluginDir + "/check_ip_dns" ]
}

In dem jeweiligen Service Template muss noch folgendes Objekt hinzugefügt werden:

object Service "Router IPv4-Adresse = DynDNS IPv4-Adresse" {
    import "generic-service"
    host_name = "router"
    check_command = "check_ip_dns"
    vars.sla = "24x7"
}

Der Eintrag router ist nur ein Beispiel und muss durch den Host ersetzt werden, für dem der Icinga2 Check angezeigt werden soll.

Icinga2 Service neu starten.

sudo systemctl restart icinga2.service

Historie

    • Version 1.2 - Ermittlung der öffentlichen IPv4-Adresse optimiert.
    • Version 1.1 - Bug zur Ermittlung der öffentlichen IPv4-Adresse beseitigt.

IPv6 Check

Der Script für IPv6 ist etwas aufwendiger. Die per SNMP aus dem pfSense Router ausgelesene Adresse liegt in Dezimalform vor und muss anschließend in Hexadezimal umgewandelt werden. Danach ist noch eine Anpassung des IPv6 Format an die verschiedenen Schreibweisen notwendig. Die markierten Stellen müssen an die eigenen Gegebenheiten angepasst werden.

sudo vi /usr/lib/nagios/plugins/check_ipv6_dns
#!/bin/bash
# Icinga Plugin
# pfSense WAN IPv6 Adresse auslesen und mit DNS IPv6 Adresse vergleichen.

SNMPHost='IP SNMP Server' # IP-Adresse der pfSense
Username='user' # SNMPv3 User - pfSense SNMPv3 Konfiguration
Passwort='geheim' # SNMPv3 Passwort - pfSense SNMPv3 Konfiguration
Encryption='secret' # SNMPv3 Pre-Shared-Key - pfSense SNMPv3 Konfiguration
Domain='example.com' # eigene Domain die überwacht werden soll
DNSHost='IP DNS Server' # DNS Server, z.B. Google DNS Server 8.8.8.8 oder pfSense IP-Adresse

OID='iso.3.6.1.2.1.4.34.1.6.2.16.32' # Object Identifer, zum Auslesen der aktuellen öffentlichen IPv6 Adresse (dezimal) am WAN Interface

# IPv6 Adresse DNS
DIG=$(/usr/lib/nagios/plugins/check_dig -H $DNSHost -T AAAA -l $Domain | awk '{print $12}' | sed 's#).*##')

# SNMPv3 IPv6 Dezimal
SNMPDez=$(/usr/bin/snmpwalk $SNMPHost -v3 -l authPriv -u $Username -A $Passwort -a SHA -X $Encryption -x AES $OID | tail -fn1 | awk '{ print $1 }' | cut -c29- | tr -s '.' ' ')

# Umwandlung der per SNMP ausgelesenen Router WAN IPv6 Adresse von Dezimal in Hexadezimal
# Dxx -> Dezimal
# Hxx -> Hexadezimal

# SNMP 1. Dezimalzahl -> Hex
                   D01=$(echo $SNMPDez | awk '{ print $1 }')
                   HX01=$(printf "%x\n" $D01)
                    if [ "$HX01" = 0 ]
                      then
                                 echo führende Nullen werden weggelassen > /dev/null 2>&1
                      else
                                 H01=$HX01
                    fi

# SNMP 2. Dezimalzahl -> Hex, zweistellig
                    D02=$(echo $SNMPDez | awk '{ print $2 }')
                    H02=$(printf "%02x\n" $D02)

# : #######################################################################

# SNMP 3. Dezimalzahl -> Hex
                    D03=$(echo $SNMPDez | awk '{ print $3 }')
                    HX03=$(printf "%x\n" $D03)
                    if [ "$HX03" = 0 ]
                      then
                                 echo führende Nullen werden weggelassen > /dev/null 2>&1
                      else
                                 H03=$HX03
                    fi

# SNMP 4. Dezimalzahl -> Hex, zweistellig
                    D04=$(echo $SNMPDez | awk '{ print $4 }')
                    H04=$(printf "%02x\n" $D04)

# : ######################################################################

# SNMP 5. Dezimalzahl -> Hex
                     D05=$(echo $SNMPDez | awk '{ print $5 }')
                     HX05=$(printf "%x\n" $D05)
                     if [ "$HX05" = 0 ]
                       then
                                 echo führende Nullen werden weggelassen > /dev/null 2>&1
                       else
                                 H05=$HX05
                     fi

# SNMP 6. Dezimalzahl -> Hex, zweistellig
                     D06=$(echo $SNMPDez | awk '{ print $6 }')
                     H06=$(printf "%02x\n" $D06)

# : ######################################################################

# SNMP 7. Dezimalzahl -> Hex
                    D07=$(echo $SNMPDez | awk '{ print $7 }')
                    HX07=$(printf "%x\n" $D07)
                     if [ "$HX07" = 0 ]
                       then
                                 echo führende Nullen werden weggelassen > /dev/null 2>&1
                       else
                                 H07=$HX07
                     fi

# SNMP 8. Dezimalzahl -> Hex, zweistellig
                     D08=$(echo $SNMPDez | awk '{ print $8 }')
                     H08=$(printf "%02x\n" $D08)

# : ######################################################################

# SNMP 9. Dezimalzahl -> Hex
                     D09=$(echo $SNMPDez | awk '{ print $9 }')
                     HX09=$(printf "%x\n" $D09)
                     if [ "$HX09" = 0 ]
                       then
                                 echo führende Nullen werden weggelassen > /dev/null 2>&1
                       else
                                 H09=$HX09
                     fi

# SNMP 10. Dezimalzahl -> Hex, zweistellig
                     D10=$(echo $SNMPDez | awk '{ print $10 }')
                     H10=$(printf "%02x\n" $D10)

# : ######################################################################

# SNMP 11. Dezimalzahl -> Hex
                      D11=$(echo $SNMPDez | awk '{ print $11 }')
                      HX11=$(printf "%x\n" $D11)
                      if [ "$HX11" = 0 ]
                        then
                                  echo führende Nullen werden weggelassen > /dev/null 2>&1
                        else
                                  H11=$HX11
                      fi

# SNMP 12. Dezimalzahl -> Hex, zweistellig
                      D12=$(echo $SNMPDez | awk '{ print $12 }')
                      H12=$(printf "%02x\n" $D12)

# : ######################################################################

# SNMP 13. Dezimalzahl -> Hex
                      D13=$(echo $SNMPDez | awk '{ print $13 }')
                      HX13=$(printf "%x\n" $D13)
                      if [ "$HX13" = 0 ]
                        then
                                  echo führende Nullen werden weggelassen > /dev/null 2>&1
                        else
                                  H13=$HX13
                      fi

# SNMP 14. Dezimalzahl -> Hex, zweistellig
                      D14=$(echo $SNMPDez | awk '{ print $14 }')
                      H14=$(printf "%02x\n" $D14)

# : ######################################################################

# SNMP 15. Dezimalzahl -> Hex
                      D15=$(echo $SNMPDez | awk '{ print $15 }')
                      HX15=$(printf "%x\n" $D15)
                      if [ "$HX15" = 0 ]
                        then
                                  echo führende Nullen werden weggelassen > /dev/null 2>&1
                        else
                                  H15=$HX15
                      fi

# SNMP 16. Dezimalzahl -> Hex, zweistellig
                      D16=$(echo $SNMPDez | awk '{ print $16 }')
                      H16=$(printf "%02x\n" $D16)

# IPv6 Adresse SNMP Router
IPv6=$(echo $H01$H02:$H03$H04:$H05$H06:$H07$H08:$H09$H10:$H11$H12:$H13$H14:$H15$H16)

# Überprüfen ob eine gültige öffentliche IPv6 Adresse im DNS existiert
echo "$DIG" | egrep '2001|2002|2003|240|260|261|262|280|2a0|2b0|2c0' > /dev/null 2>&1;

if [ "$?" != "0" ]
    then
           echo "WARNING - No IPv6 DNS address for $Domain"
           exit 1

    else

# Überprüfen ob eine gültige öffentliche IPv6 Adresse am WAN Interface existiert
echo "$IPv6" | egrep '2001|2002|2003|240|260|261|262|280|2a0|2b0|2c0' > /dev/null 2>&1;

  if [ "$?" != "0" ]
    then
          echo "CRITICAL - No public IPv6 address on the WAN interface!"
          exit 2

    else

# Vergleich ob die per SNMP ausgelesene Router IPv6 Adresse gleich der DNS IPv6 Adresse ist
        if [ $IPv6 = $DIG ]
           then
                  echo "($IPv6) OK - Public IPv6 address is equal to DynDNS address ($DIG)"
                  exit 0
           else
                  echo "($IPv6) CRITICAL - Public IPv6 address is not equal to DynDNS address! ($DIG)"
       			  exit 2
        fi
  fi
fi

Anschließend noch die korrekte Berechtigung setzen und den Script für einen Funktionstest auf der Konsole ausführen.

sudo chmod 755 /usr/lib/nagios/plugins/check_ipv6_dns

$ /usr/lib/nagios/plugins/check_ipv6_dns

In der commands.conf auf dem Icinga2 Server folgenden Eintrag hinzufügen:

sudo vi /etc/icinga2/conf.d/commands.conf
object CheckCommand "check_ipv6_dns" {
    import "plugin-check-command"
    command = [PluginDir + "/check_ipv6_dns" ]
}

In dem jeweiligen Service Template muss noch folgendes Objekt hinzugefügt werden:

object Service "Router IPv6-Adresse = DynDNS IPv6-Adresse" {
    import "generic-service"
    host_name = "router"
    check_command = "check_ipv6_dns"
    vars.sla = "24x7"
}

Der Eintrag router ist nur ein Beispiel und muss durch den Host ersetzt werden, für dem der Icinga2 Check angezeigt werden soll.

Icinga2 Service neu starten.

sudo systemctl restart icinga2.service