Zabbix, SNMP traps mapped to the right host

In my opinion Zabbix is a really good NMS, but it’s lacking on SNMP traps handling.

Traps can be received using Net-SNMP suite and snmptrap.sh, a script released within the misc directory of Zabbix.

This is how it works: snmptrapd starts listening on port UDP 162, receives traps and sends them to a handler, which runs the script and pass trap information to its standard input. Finally, the script runs zabbix_sender to send information to the Zabbix server. On Zabbix, you can setup a fake Host with an Item of type “ZABBIX Trapper”: in the original script, both host and item’s key are referenced as snmptraps.

It works! The problem is that, whatever the sender is, trap data is always binded to one host: snmptraps.

zabbix_sender, used to send traps information to the server, can’t translate IP address to hostname:

# ./zabbix_sender -h

ZABBIX send v1.6.2 (16 January 2009)

usage: zabbix_sender [-Vhv] {[-zpsI] -ko | [-zpI] -i } [-c ]
Options:

[cut]

-s --host <Hostname> Specify host name.
Host IP address and DNS name will not work.

[cut]

So, we need to translate the sender’s IP address to its Zabbix hostname, in order to runs zabbix_sender with the right -s option value.

I make a very simple script to build an { IP / Zabbix hostname } file, using mysql client:

DST="/home/zabbix/zabbix-1.6.2/misc/snmptrap/zabbixhosts"
mysql --batch --silent -e "SELECT CONCAT( '[', IP, ']', Host )
FROM zabbix.hosts WHERE IP <> '' AND IP <> '0.0.0.0'" > $DST

Running this script every 30 minutes I have a file containing pairs of IP/HostName such these:

[192.168.0.1]MYWEBSERVER
[192.168.0.2]MYMAILSERVER

With few changes to the original script I can send traps to the right Zabbix host, grabbing the hostname from the mySql dump (zabbixhosts):

# CONFIGURATION

ZABBIX_SERVER="127.0.0.1";
ZABBIX_PORT="10051";

# path to zabbix_sender
ZABBIX_SENDER="/home/zabbix/zabbix-1.6.2/src/zabbix_sender/zabbix_sender";

# path to zabbixhosts, containing IP/hostname pairs
ZABBIX_HOSTSFILE="/home/zabbix/zabbix-1.6.2/misc/snmptrap/zabbixhosts"

# item key used to grab snmp data
KEY="snmptrap";

# used if the script can't find the hostname
DEFAULTHOST="Default_Trapper";

# END OF CONFIGURATION

read hostname
read ip
read uptime
read oid
read var1
read var2
read var3

oid=`echo $oid|cut -f2 -d' '`

# get hostname from the mySql dump
ZABBIX_HOST=`grep "[$hostname]" $ZABBIX_HOSTSFILE`

if [ $? -eq 0 ]; then
        hostname=`echo "$ZABBIX_HOST" | cut -f2 -d]`
else
        hostname="$DEFAULTHOST"
fi

str="$oid $var1 $var2 $var3"

result=`$ZABBIX_SENDER -z $ZABBIX_SERVER -p $ZABBIX_PORT
-s $hostname -k $KEY -o "$str"`

With this script you need an Item with type=”ZABBIX Trapper” and key=”snmptrap” for each host you want trap handling. You can also create a template and attach it to hosts you want to monitor.
You can create triggers based on snmp trap content as you want.

I use crontab to update the IP-to-hostname file two times each hour.

The following two tabs change content below.
Italian, born in 1980, I started working in the IT/telecommunications industry in the late '90s; I'm now a system and network engineer with a deep knowledge of the global Internet and its core architectures, and a strong focus on network automation.

Latest posts by Pier Carlo Chiodi (see all)

12 Comments

  1. monolithic says:

    Hello there and thank you for this post! I am having an issue with this regarding the hostname.

    I have manually created the zabbixhosts file and for some reason the hostname always comes back with the IP address instead of the hostname. I’ve grepped the file manually and it always gives me the correct hostname, however from the snmptrap.sh script i have added an entry to echo the hostname to a log file so i can see what is going on and it only reads back the IP address. Can you offer any help at all. I’m running it on Solaris 10. THanks a bunch!

    • pierky says:

      Hi, so zabbixhosts contains lines such these:

      [10.0.0.1]HOST1
      [10.0.0.2]HOST2

      Is it right?

      Have you tried to add echo entries to snmptrap.sh to log $hostname, $ip and $ZABBIX_HOST? Maybe with more infos you could understand what appens…

  2. monolithic says:

    Thank you for the quick response,

    Yes
    the zabbixhosts file contains the following:
    [192.168.2.5]switch1
    [192.168.2.202]esx1-ilo

    I’m doing some echos now, i will see what i come back with, thank you for the very fast reply, i’ve been working on this for 3 weeks and it’s the last piece to monitor my environment! Thank you again, I appreciate any help at all, will let you know what i come back with

  3. monolithic says:

    This line: if [ $? -eq 0 ]; then
    hostname=`echo “$ZABBIX_HOST” | cut -f2 -d]`
    else
    hostname=”$DEFAULTHOST”
    fi

    is where it seems to be hanging.

    I have ZABBIX_HOST=`grep $hostname $ZABBIX_HOSTSFILE`

    And if I echo $ZABBIX_HOST i get this
    [192.168.2.202]esx1-ilo

    Which is good, i believe it’s failing on the if statement because when I echo the $hostname it comes back with the IP address.

    Do you have any tips on what i can do with the if statement? because i don’t think it’s doing anything at all

  4. pierky says:

    I suggest you to use square brackets in the grep:

    ZABBIX_HOST=`grep “[$hostname]” $ZABBIX_HOSTSFILE`

    Without them if you have 10.0.0.1 you match both 10.0.0.1 and 10.0.0.100 an so on…

    You can add an echo line before the “if” to dump the “$?” value.
    Be aware, after the “echo $? > /tmp/mylog” the $? in the if will be the exit code of the echo command!

  5. monolithic says:

    Here is what I did to resolve the problem:

    read hostname
    read ip
    read uptime
    read oid
    read var1
    read var2
    read var3

    oid=`echo $oid|cut -f2 -d’ ‘`

    ZABBIX_HOST=`grep $hostname $ZABBIX_HOSTSFILE`
    if [ $ZABBIX_HOST != 0 ]; then
    hostname=`echo “$ZABBIX_HOST” | cut -f2 -d]`
    else
    hostname=”$DEFAULTHOST”
    fi

    str=”$oid $var1 $var2 $var3″

    echo ” ” > /tmp/snmptrapzabbix.log
    echo $FINDER “FINDER” >> /tmp/snmptrapzabbix.log
    echo $ZABBIX_HOST “ZABBIX HOST” >> /tmp/snmptrapzabbix.log
    echo $ZABBIX_SERVER “ZABBIX_SERVER” >> /tmp/snmptrapzabbix.log
    echo $hostname “HOSTNAME” >> /tmp/snmptrapzabbix.log
    echo $KEY “KEY” >> /tmp/snmptrapzabbix.log
    echo $str >> /tmp/snmptrapzabbix.log
    result=`$ZABBIX_SENDER -z $ZABBIX_SERVER -p $ZABBIX_PORT -s $hostname -k $KEY -o
    “$str”`

    The above seems to work well. Now my only issue is that I want to manipulate one host, for instance, one snmp trap is coming from one host but i would like it to be linked to a different host.

    Basically our firewall logs to an log server and then from there it gets sent an SNMP Trap to zabbix which it is now picking up. However it is corresponding to the log server host and not the firewall. Is there any command that I can grep for in the $str that i can force the hostname to change to ‘firewall’? I tried every derivation of this :
    FINDER=`grep “192.168.2.1” [$str]` (2.1 is the firewall)
    if [ $FINDER != 0 ]; then
    hostname=”firewall”
    fi

    But the hostname still remains as the log server hostname.

    Thank you soo much for all your help, if you have any idea of what I can do to force the hostname to change with a specific string inside the $str variable please please please let me know!!!!! THANK YOU AGAIN!!

    • pierky says:

      Thank you for the solution!

      What’s the SNMP trap format? Does it contain the original sender’s information?

      If so, you could understand the trap format and extract the original sender IP address, and then lookup the $ZABBIX_HOSTSFILE file again to obtain its Zabbix hostname.

  6. synec! says:

    zabbix_hostname.sh

    #!/bin/sh
    mysql --batch --silent -e "SELECT CONCAT( '[', IP, ']', Host ) FROM zabbix.hosts WHERE IP '' AND IP '0.0.0.0' AND STATUS = '0' ORDER BY IP, Host ASC" > /tmp/zabbix_hostname

    zabbix_trapkey.sh

    #!/bin/sh
    mysql --batch --silent -e "SELECT CONCAT( '[', snmp_oid, ']', key_ ) FROM zabbix.items WHERE type = '2' AND snmp_community = 'ZBX_TRAP' GROUP BY snmp_oid" > /tmp/zabbix_trapkey

    Item add
    1. select type: SNMP v1 or SNMP v2 or SNMP v3
    2. input snmp_community and key and so on
    3. change type: zabbix trapper
    4. click save button

  7. synec! says:

    zabbix_trapper.sh

    #!/bin/bash

    # START OF CONFIGURATION
    # used if the script can't find the hostname
    DEFAULTHOST="Default_Trapper";

    ZBX_SERVER="127.0.0.1";
    ZBX_PORT="10051";

    # path to zabbix_sender
    ZBX_SENDER="/usr/local/bin/zabbix_sender";

    # path to zabbix_hostname, containing IP/hostname pairs
    ZBX_HOSTSFILE="/tmp/zabbix_hostname"

    # path to zabbix_trapkey, containing snmp_oid/zabbix_key pairs
    ZBX_KEYFILE="/tmp/zabbix_trapkey"

    # END OF CONFIGURATION

    read in_hostname
    read in_ip
    read in_uptime
    read in_oid
    read in_var1
    read in_var2
    read in_var3

    ip=`echo $in_ip|cut -f2 -d[|cut -f1 -d]`
    oid=`echo $in_oid|cut -f2 -d=|cut -f2 -d' '`
    var1=`echo $in_var1|cut -f2 -d'"'`
    #edit oid and var1 - for your snmp trap message format

    # get hostname from the mySql dump
    ZBX_HOST=`grep $ip $ZBX_HOSTSFILE|tr 'n' ' '`

    if [ -z "$ZBX_HOST" ]; then
    hostname="$ip"
    else
    hostname=`echo "$ZBX_HOST"|cut -f2 -d]|cut -f1 -d' '`
    fi

    # get zabbix_key from the mySql dump
    ZBX_KEY=`grep $oid $ZBX_KEYFILE`

    if [ -z "$ZBX_KEY" ]; then
    key="snmptrap"
    else
    key=`echo "$ZBX_KEY"|cut -f2 -d]`
    fi

    str="$oid $var1 $var2 $var3"

    result_trap=`$ZBX_SENDER -z $ZBX_SERVER -p $ZBX_PORT -s $hostname -k $key -o "$str"`

    echo "----------------------------------------------------" > /tmp/zabbix_trapper.log
    echo `date` >> /tmp/zabbix_trapper.log
    echo "IN_HOSTNAME:" $in_hostname >> /tmp/zabbix_trapper.log
    echo "IN_IP:" $in_ip >> /tmp/zabbix_trapper.log
    echo "IN_UPTIME:" $in_uptime >> /tmp/zabbix_trapper.log
    echo "IN_OID:" $in_oid >> /tmp/zabbix_trapper.log
    echo "IN_VAR1:" $in_var1 >> /tmp/zabbix_trapper.log
    echo "IN_VAR2:" $in_var2 >> /tmp/zabbix_trapper.log
    echo "IN_VAR3:" $in_var3 >> /tmp/zabbix_trapper.log
    echo "FINDER:" $FINDER >> /tmp/zabbix_trapper.log
    echo "ZABBIX SERVER:" $ZBX_SERVER >> /tmp/zabbix_trapper.log
    echo "ZABBIX HOST:" $ZBX_HOST >> /tmp/zabbix_trapper.log
    echo "HOSTNAME:" $hostname >> /tmp/zabbix_trapper.log
    echo "IP :" $ip >> /tmp/zabbix_trapper.log
    echo "KEY:" $key >> /tmp/zabbix_trapper.log
    echo "STR:" $str >> /tmp/zabbix_trapper.log
    echo "RESULT TRAP:" $result_trap >> /tmp/zabbix_trapper.log

    Old ‘zabbix trap handler script’ have problem that same ip address hosts.
    (ex)
    /tmp/zabbix_hostname
    [127.0.0.1]Zabbix
    [127.0.0.1]Test

    Error grep $ip ZBX_Hostfile

  8. Jorge says:

    hello.i´m currently working with a Dell DRAC5 and im having problem defining Triggers for the Traps i receive. I cannot know the format of the traps because i cannot simulate then. How can i know the traps format?

  9. mathews joseph says:

    inorder add snmp devices or hosts in zabbix server
    1.we have configure snmptraps in zabbix server also make some tweak set up in zabbix tool
    2.please let what are the stepa reqiured in hosts side or how to enaable each in zabbix?

    • mathews joseph says:

      in order to add snmp devices or hosts in zabbix server
      1.we have configure snmptraps in zabbix server also make some tweak set up in zabbix tool
      2.please let me know what are the steps required in hosts side or how to enable each in zabbix?

Leave a Reply