From Segfault
Jump to navigation Jump to search


For Debian (non-free) or Ubuntu (multiverse):

sudo apt-get install mrtg snmp libsnmp-base snmp-mibs-downloader

Note: the snmp-mibs-downloader[1] package will download missing MIBs which cannot be distributed by Debian due to licensing issues.

The Debian mrtg package will install a cronjob to periodically run and generate our statistics. However, there's no need to have the cronjob run as root and we're going to change that:

$ cat /etc/cron.d/mrtg 
*/5 *   * * *   www-data if [ -x /usr/bin/mrtg -a -r /etc/mrtg.cfg ]; \
                then env LANG=C /usr/bin/mrtg /etc/mrtg.cfg >> /var/log/mrtg/mrtg.log; fi

$ sudo mkdir -p /var/www/mrtg/{images,logs}
$ sudo chown -cR www-data:www-data /var/lock/mrtg/ /var/log/mrtg/ /var/lib/mrtg/ /var/www/mrtg
$ sudo chmod -c 0700 /var/lock/mrtg/ /var/log/mrtg/ /var/lib/mrtg/ /var/www/mrtg

If Nagios needs to query those logfiles later on:

sudo setfacl -m g:nagios:rx /var/www{,/mrtg}


We installed the MIB files but loading MIBs is disabled in Debian:

$ cat /etc/snmp/snmp.conf 
# As the snmp packages come without MIB files due to license reasons, loading
# of MIBs is disabled by default. If you added the MIBs you can reenable
# loading them by commenting out the following line.
mibs :

So yeah: comment out that line :-)

If we're querying ourselves, we will need an SNMP server too:

sudo apt-get install snmpd                         # Debian, Ubuntu
sudo dnf install net-snmp                          # Fedora

Debian's default /etc/snmp/snmpd.conf is pretty restrictive[2], so let's make sure the rocommunity is configured correctly:

agentAddress  udp:

view          systemonly  included   .
view          systemonly  included   .

rocommunity   public  localhost                            # Full access from the local host
# rocommunity public  default    -V systemonly             # Default access to basic system info

sysLocation    MX
sysContact     Admin <admin@localhost>
sysServices    72                                          # Value of the sysServices.0 object

# proc  mountd                                             # At least one mountd process
# proc  ntalkd    4                                        # No more than 4 ntalkd processes, 0 is OK too
# proc  sendmail 10 1                                      # At least one sendmail process, but no more than 10

# disk       /     10000                                   # At least 10 MB free required on root disk
# disk       /var  5%                                      # At least 5% free on /var
# includeAllDisks  10%                                     # At least 10% free on all other disks
# load   12 10 5                                           # Unacceptable load averages (1min, 5min, 15min)

# Disable the trap destinations[3]
# trapsink     localhost public                            # send SNMPv1 traps
# trap2sink    localhost public                            # send SNMPv2c traps
# informsink   localhost public                            # send SNMPv2c INFORMs

Another example, which actually allows access from a (trusted) network:

# Map the community name "public" into a "security name"
com2sec  local       localhost         public
com2sec  thisnetwork      public

# Map the security name into a group name:
# >      name   sec.model
group    TNRW   v1         local
group    TNRW   v2c        local
# group  TNRW   usm        local

group    TNRO   v1         thisnetwork
group    TNRO   v2c        thisnetwork
# group  TNRO   usm        thisnetwork

# Create a view
# >      name          incl/excl  subtree                mask
view     systemview    included   .
view     systemview    included   .
view     all           included   .1                       80

# Grant access
# >      group context sec.model sec.level prefix read   write  notif
access   TNRO  ""      any       noauth    exact  all    none   none
access   TNRW  ""      any       noauth    exact  all    all    none

syslocation MX
syscontact  Admin <root@proxy>
dontLogTCPWrappersConnects yes

Restart snmpd and we should be good to go.

$ snmpwalk -v1 -c public localhost | wc -l

$ snmpwalk -v2c -c public router
SNMPv2-MIB::sysDescr.0 = STRING: Linux router.local
SNMPv2-MIB::sysObjectID.0 = OID: NET-SNMP-MIB::netSnmpAgentOIDs.255
DISMAN-EVENT-MIB::sysUpTimeInstance = Timeticks: (963073) 2:40:30.73
SNMPv2-MIB::sysContact.0 = STRING: Admin <root@router>
SNMPv2-MIB::sysName.0 = STRING: router.local


  • snmpd tries to access /proc/diskstats and /proc/partitions, so we need to make sure that the snmp user has access to those files:
chgrp snmp /proc/{diskstats,partitions} && chmod 0440 /proc/{diskstats,partitions}
  • When accessed over the network, we have to configure the tcpwrapper to allow snmpd.
  • To suppress those error on subcontainer 'ia_addr' insert (-1) warnings[4][5][6], we can change the loglevel of snmpd[7][8]
SNMPDOPTS='-LS6d -Lf /dev/null -u snmp -g snmp [...]


mrtg will call snmpget to gather statistics, e.g.:

$ snmpget -v2c -c public localhost ifInOctets.1
IF-MIB::ifInOctets.1 = Counter32: 17479

After getting statistics, the rateup program will be used to generate log entries and update the traffic graphs.

For mrtg to work, an mrtg.conf is needed. Some examples:


We can use cfgmaker to generate a basic configuration file:

$ cfgmaker --ifref=name --zero-speed=100000000 --no-down public@router
WorkDir:                /var/www/mrtg
Options[_]:             growright, bits

Target[router_wlan0]:   wlan0:public@router
MaxBytes[router_wlan0]: 12500000
Title[router_wlan0]:    Traffic Analysis for wlan0 -- router
PageTop[router_wlan0]:  <h1>Traffic Analysis for wlan0 -- router</h1>


An example mrtg.cfg:

HtmlDir:                /var/www/mrtg/html
ImageDir:               /var/www/mrtg/images
LogDir:                 /var/www/mrtg/logs
IconDir:                /mrtg/icons
WriteExpires:           no                              # No .meta files

Options[_]:             growright,noborder,pngdate,printrouter
TimeStrFmt[_]:          %Y-%m-%d %H:%M %Z
Title[^]:               Traffic Analysis for

Title[router_eth0]:     router
PageTop[router_eth0]:   <h1>router eth0</h1>
Target[router_eth0]:    ifInOctets.3&ifOutOctets.3:public@router
MaxBytes[router_eth0]:  10000000

Title[box_eth0]:        box_eth0
Target[box_eth0]:       \eth0:public@box:
MaxBytes[box_eth0]:     12500000
PageTop[box_eth0]:      <h1>box_eth0</h1>

Once the mrtg.cfg file is in place, we can use indexmaker to generate an index.html file:

indexmaker --autoprefix --show=week --perhost --title MRTG  \
   --headeradd='<meta http-equiv="refresh" content="60;" />' --output /var/www/mrtg/index.html /etc/mrtg.cfg

Because we're querying localhost as well, let's replace its name in the HTML output with the real host name:

sed 's/Localhost/machine/g' -i /var/www/mrtg/index.html

Remove graph spikes

According to How to remove spikes from your MRTG graphs[9], this is how it's done:

mkdir -p old/
mv *.log old/
for i in `ls *.log`; do
   awk '!(NF==5 && ($4+$5) > 1000000)' old/$i > $i