Tuesday, March 18, 2014

Send sms from Nagios/Icinga through Kannel

Sending notifications from nagios via sms through kannel is not as trivial as it looks first.
Some basics related to this topic:
  1. Nagios accepts only an "one-liner" command to send notifications (command_line parameter of command object). Note that ; means comment here.
  2. Kannel has a web interface which expects the text to be sent urlencoded
  3. curl is a very nice tool to connect to http interfaces, but it is too smart in this case. It means that it has a very useful argument --data-urlencode which URLencodes the text given to this parameter preceeding an "&".
    That "&" causes problem. Kannel expets the message in "text=messagetobesent" format in the url, but data-urlencode encodes "text=" to "text%3D" which kannel does not understand.
So I endedd up with a simple wrapper script, which does the URLencoding only where it is needed.

#!/bin/bash
# ZsZs 2014

trap cleanup EXIT

cleanup() {
  rm -F $TMP 2>/dev/null
}

MSISDN=$1
MSG="$2"

TMP=$(mktemp)
printf '%b' "$MSG" >$TMP
MSGU=$( perl -p -e 's/([^A-Za-z0-9])/sprintf("%%%02X", ord($1))/seg' $TMP )
curl -G -s "http://localhost:13131/cgi-bin/sendsms?username=KANNELUSER&password=KANNELPW&validity=60&to=$MSISDN&text=$MSGU"

Nagios configuration should look like this:

define command{
        command_name    notify-host-by-sms
        command_line    /usr/local/bin/smssend $CONTACTPAGER$ 'Host: $HOSTNAME$\nState: $HOSTSTATE$\nInfo: $HOSTOUTPUT$\nTime: $LONGDATETIME$'
        }

define command{
        command_name    notify-service-by-sms
        command_line    /usr/local/bin/smssend $CONTACTPAGER$ 'Service: $SERVICEDESC$\nHost: $HOSTNAME$\nState: $SERVICESTATE$\nInfo: $SERVICEOUTPUT$\nTime: $LONGDATETIME$'
        } 

Tuesday, March 5, 2013

IP alias on CentOS6:"SIOCADDRT: No such process"

I just added an ip alias in my CentOS box by creating ifcfg-eth0:0 file with following content:
DEVICE=eth0:0
IPADDR=192.168.111.77
NETMASK=255.255.255.0
NETWORK=192.168.111.0
ONBOOT=yes
But after restarting network service I got following output:
Shutting down interface eth0:                [ OK ]
Shutting down loopback interface:            [ OK ]
Bringing up loobback interface:              [ OK ]
Bringing up interface eth0:  SIOCADDRT: No such process
                                             [ OK ]
The root cause is that the ifup procedure would like to add the default route to this alias, but the gatewa address is missing.
To get rid of this mistic message just give the gateway address to config by addiing following line in the alias interface config file:
GATEWAY="192.168.111.254"
Or of you do not need/have default gateway simply add:
GATEWAY=""
If you have a lot of aliases on a parent interface then you can add following line in parent interface config (ifcfg-eth0 in my case)
NO_ALIASROUTING=yes
After that the network restarted without the strange message.
Hope this helps somebody.

Saturday, February 23, 2013

Debricking Seagate Dockstar

Somehow I managed to brick my Dockstar. It was so simple like the first sentence :) The debricking process was quite long due to lack of experience and tools. Tools required:
- A buspirate card (I have a v3.6)
- openocd with buspirate support
- An USB2serial converter (3.3V version!) . Tip:  search "CP2102 usb serial" on Ebay. You'll get tons for a few bucks.
1. Upgrade your BusPirate 3.x to at least 6.0RC fw version to have an openocd capable firmware on your buspirate.
2. Connect the ingredients according to this schematic. My "setup":

3. Download boot image and make a symlink to it:
# wget http://jeff.doozan.com/debian/uboot/files/uboot/uboot.mtd0.dockstar.jeff-2010-10-23.kwb
# ln -s uboot.mtd0.dockstar.jeff-2010-10-23.kwb uboot.kwb
4. Download docstar.cfg and change the start of the config from
# I'm using a wiggler compatible cable
source [find interface/buspirate.cfg]
source [find target/feroceon.cfg]
jtag_khz 500
jtag_nsrst_delay 500
to
interface buspirate
source [find target/feroceon.cfg]
buspirate_port /dev/ttyUSB0
buspirate_speed fast
buspirate_vreg 0
reset_config srst_only
adapter_khz 500
5. Connect Buspirate'c USB port to your USB port and start openocd on Terminal #1:
# openocd -f ./dockstar.cfg
Open On-Chip Debugger 0.7.0-dev-00079-g08ddb19 (2012-12-02-23:14)
Licensed under GNU GPL v2
For bug reports, read
        http://openocd.sourceforge.net/doc/doxygen/bugs.html
Warn : Adapter driver 'buspirate' did not declare which transports it allows; assuming legacy JTAG-only
Info : only one transport option; autoselect 'jtag'
trst_and_srst separate srst_gates_jtag trst_push_pull srst_open_drain
adapter_nsrst_delay: 200
jtag_ntrst_delay: 200
srst_only separate srst_gates_jtag srst_open_drain
adapter speed: 500 kHz
Warn : use 'feroceon.cpu' as target identifier, not '0'
dockstar_reset_cpu
Info : Buspirate switched to FAST mode
Info : Buspirate Interface ready!
Info : Want to set speed to 500kHz, but not implemented yet
Error: Translation from jtag_speed to khz not implemented
Info : adapter-specific clock speed value 500
Info : JTAG tap: feroceon.cpu tap/device found: 0x20a023d3 (mfg: 0x1e9, part: 0x0a02, ver: 0x2)
Info : Embedded ICE version 0
Info : feroceon.cpu: hardware has 1 breakpoint/watchpoint unit
You can minimize this terminal because you do not need to watch this
6. Open Terminal #2 and connect to openocd:
# telnet localhost 4444
Trying ::1...
telnet: connect to address ::1: Connection refused
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
Connection closed by foreign host.
[root@centos6 ~]# telnet localhost 4444
Trying ::1...
telnet: connect to address ::1: Connection refused
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
Open On-Chip Debugger
>
7. On Terminal #2 issue following commands:
> init
> soft_reset_halt
requesting target halt and executing a soft reset
target state: halted
target halted in ARM state due to debug-request, current mode: Supervisor
cpsr: 0x000000d3 pc: 0x00000000
MMU: disabled, D-Cache: disabled, I-Cache: disabled
> dockstar_init
> load_image uboot.kwb 0x800000
524288 bytes written at address 0x00800000
downloaded 524288 bytes in 108.139221s (4.735 KiB/s)
Update: The trick was to issue "soft_reset_halt" instead of "halt". There are a few guides which operates with halt command and immediate press reset button. With "soft_reset_halt" no need to be lucky with reset button. You don't have to press it.
Halt command lead my Dockstar to "target halted in Thumb state", which wasn't enough to access the NAND.
8. Check NAND on Terminal #2:
> nand probe 0
NAND flash device 'NAND 256MiB 3.3V 8-bit (Micron)' found
> nand list
#0: NAND 256MiB 3.3V 8-bit (Micron) pagesize: 2048, buswidth: 8,
        blocksize: 131072, blocks: 2048
> nand check_bad_blocks 0
checked NAND flash device for bad blocks, use "nand info" command to list blocks
9. Open Terminal #3 and connect it to Dockstar's serial port via USB2Serial adapter
10. On Terminal #2 issue following connmmand and be prepared co switch to Termianl #3 within 3 seconds and press a key to stop boot process.
> resume 0x800200
11. Switch to Termnal #3 and press a key to stop boot process:
U-Boot 2010.09 (Oct 23 2010 - 11:49:22)
Marvell-Dockstar/Pogoplug by Jeff Doozan

SoC:   Kirkwood 88F6281_A0
DRAM:  128 MiB
NAND:  256 MiB
*** Warning - bad CRC or NAND, using default environment

In:    serial
Out:   serial
Err:   serial
Net:   egiga0
88E1116 Initialized on egiga0
Hit any key to stop autoboot:  0
Marvell>>
12. Write uBoot into NAND on Terminal #3:
Marvell>> nand erase

NAND erase: device 0 whole chip
Erasing at 0xffe0000 -- 100% complete.
OK
Marvell>> nand write.e 0x800000 0x0 0x80000

NAND write: device 0 offset 0x0, size 0x80000
 524288 bytes written: OK
Marvell>> reset
resetting ...
You are Done!
+1 Extra steps to write rescue image to NAND
Download rescue images and put them to a local TFTP server:
http://jeff.doozan.com/debian/rescue/uImage-mtd1.img
http://jeff.doozan.com/debian/rescue/rootfs-mtd2.img
On Terminal #3 stop the boot process and issue following commands:
Marvell>> setenv ipaddr 192.168.A.B
Marvell>> setenv serverip 192.168.A.C
Marvell>> setenv ethaddr 00:10:75:XX:XX:XX
Marvell>> saveenv
Saving Environment to NAND...
Erasing Nand...
Erasing at 0xc0000 -- 100% complete.
Writing to Nand... done
Marvell>> ping 192.168.A.C
Using egiga0 device
host 192.168.A.C is alive
Marvell>> nand erase 0x100000 0x400000

NAND erase: device 0 offset 0x100000, size 0x400000
Erasing at 0x4e0000 -- 100% complete.
OK
Marvell>> tftp 0x800000 uImage-mtd1.img
Using egiga0 device
TFTP from server 192.168.248.254; our IP address is 192.168.248.199
Filename 'uImage-mtd1.img'.
Load address: 0x800000
Loading: #################################################################
         #################################################################
         #################################################################
         ########################################################
done
Bytes transferred = 3670016 (380000 hex)
Marvell>> nand write.e 0x800000 0x100000 0x380000

NAND write: device 0 offset 0x100000, size 0x380000
 3670016 bytes written: OK
Marvell>> tftp 0x1000000 rootfs-mtd2.img
Using egiga0 device
TFTP from server 192.168.248.254; our IP address is 192.168.248.199
Filename 'rootfs-mtd2.img'.
Load address: 0x1000000
Loading: #################################################################
         #################################################################
         #################################################################
         #################################################################
         #################################################################
         #################################################################
         #################################################################
         #################################################################
         #################################################################
         #################################################################
         #################################################################
         #################################################################
         #################################################################
         #################################################################
         #################################################################
         #################################################################
         #################################################################
         #################################################################
         #################################################################
         #################################################################
         #################################################################
         #################################################################
         #################################################################
         #################################################################
         #################################################################
         #################################################################
         #################################################################
         #################################################################
         #################################################################
         #################################################################
         ########################
done
Bytes transferred = 28966912 (1ba0000 hex)
Marvell>> setenv rescue_set_bootargs 'setenv bootargs console=$console ubi.mtd=2 root=ubi0:rootfs ro rootfstype=ubifs $mtdparts $rescue_custom_params'
Marvell>> setenv rescue_bootcmd 'if test $rescue_installed -eq 1; then run rescue_set_bootargs; nand read.e 0x800000 0x100000 0x400000; bootm 0x800000; else run pogo_bootcmd; fi'
Marvell>> setenv bootcmd 'run bootcmd_usb; usb stop; run rescue_bootcmd; reset'
Marvell>> saveenv
Saving Environment to NAND...
Erasing Nand...
Erasing at 0xc0000 -- 100% complete.
Writing to Nand... done
Marvell>> run rescue_bootcmd

NAND read: device 0 offset 0x100000, size 0x400000
 4194304 bytes read: OK
## Booting kernel from Legacy Image at 00800000 ...
   Image Name:   Linux-2.6.32.18-dockstar
   Image Type:   ARM Linux Kernel Image (uncompressed)
   Data Size:    3236180 Bytes = 3.1 MiB
   Load Address: 00008000
   Entry Point:  00008000
   Verifying Checksum ... OK
   Loading Kernel Image ... OK
OK

Starting kernel ...

Uncompressing Linux............................................................................................................................................................................................................. done, booting the kernel.
[    0.000000] Initializing cgroup subsys cpuset
[    0.000000] Initializing cgroup subsys cpu
[    0.000000] Linux version 2.6.32.18-dockstar (root@stfu.tcbnet) (gcc version 4.3.5 (Buildroot 2010.08) ) #1 Thu Feb 17 03:09:57 EST 2011
[    0.000000] CPU: Feroceon 88FR131 [56251311] revision 1 (ARMv5TE), cr=00053977
[    0.000000] CPU: VIVT data cache, VIVT instruction cache
[    0.000000] Machine: Marvell SheevaPlug Reference Board
[    0.000000] Memory policy: ECC disabled, Data cache writeback
[    0.000000] Built 1 zonelists in Zone order, mobility grouping on.  Total pages: 32512
[    0.000000] Kernel command line: console=ttyS0,115200 ubi.mtd=2 root=ubi0:rootfs ro rootfstype=ubifs mtdparts=orion_nand:1M(u-boot),4M(uImage),32M(rootfs),-(data)
[    0.000000] PID hash table entries: 512 (order: -1, 2048 bytes)
[    0.000000] Dentry cache hash table entries: 16384 (order: 4, 65536 bytes)
[    0.000000] Inode-cache hash table entries: 8192 (order: 3, 32768 bytes)
[    0.000000] Memory: 128MB = 128MB total
[    0.000000] Memory: 122836KB available (5968K code, 708K data, 128K init, 0K highmem)
[    0.000000] SLUB: Genslabs=11, HWalign=32, Order=0-3, MinObjects=0, CPUs=1, Nodes=1
[    0.000000] Hierarchical RCU implementation.
[    0.000000] NR_IRQS:114
[    0.000000] Console: colour dummy device 80x30
[    0.000123] Calibrating delay loop... 1192.75 BogoMIPS (lpj=5963776)
[    0.240079] Security Framework initialized
[    0.240098] SELinux:  Disabled at boot.
[    0.240118] Mount-cache hash table entries: 512
[    0.240368] Initializing cgroup subsys ns
[    0.240381] Initializing cgroup subsys cpuacct
[    0.240390] Initializing cgroup subsys devices
[    0.240399] Initializing cgroup subsys freezer
[    0.240406] Initializing cgroup subsys net_cls
[    0.240438] CPU: Testing write buffer coherency: ok
[    0.240988] devtmpfs: initialized
[    0.242412] regulator: core version 0.5
[    0.242586] NET: Registered protocol family 16
[    0.242971] Kirkwood: MV88F6281-A0, TCLK=200000000.
[    0.242983] Feroceon L2: Cache support initialised.
[    0.246010] bio: create slab  at 0
[    0.246292] vgaarb: loaded
[    0.246568] SCSI subsystem initialized
[    0.246822] usbcore: registered new interface driver usbfs
[    0.246888] usbcore: registered new interface driver hub
[    0.246977] usbcore: registered new device driver usb
[    0.247423] Switching to clocksource orion_clocksource
[    0.252761] NET: Registered protocol family 2
[    0.253024] IP route cache hash table entries: 1024 (order: 0, 4096 bytes)
[    0.253840] TCP established hash table entries: 4096 (order: 3, 32768 bytes)
[    0.253939] TCP bind hash table entries: 4096 (order: 2, 16384 bytes)
[    0.253992] TCP: Hash tables configured (established 4096 bind 4096)
[    0.254001] TCP reno registered

Thursday, February 7, 2013

Backup multiple pfSense 2.x

Recently I've installed some pfSense firewalls and looked around how to backup their config.
I found this on pfsense.org, but I improved the idea because I would like to:
  • backup more than one firewall without changing the script
  • push something useful about config change to syslog
  • properly log out and do not leave the admin session alive
  • retain previous config files if something strange happens :)
I wrote pfsensecfgarch.sh:
#!/bin/bash
# Download the actual config.xml from pfSense firewall and archive it, if it has changed
# Read config file in following format
# host=host1;username;password
# host=host2;username;password
#
# ZsZs 2013

cfgfile=pfsensecfgarch.cfg
backupdirpfx=config
tmpdir=tmp

[ -d $tmpdir ] || mkdir -p $tmpdir
scr=${0##*/}
loginf() { logger -t "$scr" -p "info" "$@"; }
logerr() { logger -t "$scr" -p "error" "$@"; }
cleanup() { /bin/rm $curlerr 2>/dev/null; /bin/rm $cookiefile 2>/dev/null; }

[[ ! -f $cfgfile ]] && { logerr "Missing config file: $cfgfile"; exit 1; }
for cfgline in $(egrep "^host=" $cfgfile | cut -d= -f 2-)
do
  echo $cfgline | while IFS=';' read -r host user passwd rest
  do
    [ ! -z "$rest" ] && { echo "Invalid line in $cfgfile: $(grep "$cfgline" $cfgfile)"; exit 1; }
    # Login and store sessionid in cookie file
    cookiefile=$(mktemp)
    curlerr=$(mktemp)
    curl -s -S --data-ascii "login=Login&usernamefld=$user&passwordfld=$passwd" -k https://$host/diag_backup.php -o /dev/null -c $cookiefile 2>$curlerr \
      || { logerr "[$host]: login: $(cat $curlerr)"; cleanup; exit 1; }
    backupdir=$backupdirpfx/$host
    [ -d $backupdir ] || mkdir -p $backupdir
    # Download actual config
    curl -s -S --data-ascii 'Submit=download&donotbackuprrd=yes' -k https://$host/diag_backup.php -o $backupdir/config.xml.tmp -b $cookiefile 2>$curlerr \
      || { logerr "[$host]: download: $(cat $curlerr)"; cleanup; exit 1; }
    # Logout
    curl -s -S -k "https://$host/index.php?logout" -o /dev/null -b $cookiefile 2>$curlerr \
      || { logerr "[$host]: logout: $(cat $curlerr)"; cleanup; exit 1; }
    if [ "$?" == "0" ]; then
      # Check for change
      diff $backupdir/config.xml.tmp $backupdir/config.xml.latest 2>/dev/null >/dev/null
      # Archive previous config if the new one is different
      if [ "$?" != "0" ]; then
        if [ -f $backupdir/config.xml.latest ]; then
          mv $backupdir/config.xml.latest $backupdir/config.xml.$(date "+%Y%m%d-%H%M%S") 2>/dev/null
          mv $backupdir/config.xml.tmp $backupdir/config.xml.latest 2>/dev/null
        else
          mv $backupdir/config.xml.tmp $backupdir/config.xml.latest 2>/dev/null
        fi
        loginf "[$host]: updated"
      fi
      /bin/rm $backupdir/config.xml.tmp 2>/dev/null
    fi
    cleanup
  done
done 
This script should be run from cron approximately every hour.
Comments welcome!

Wednesday, December 12, 2012

Dovecot -> MySQL SElinux issue on CentOS6

I set up a postfix, dovecot, mysql, postfixadmin combo on SElinux enabled CentOS6, but I was keep getting following error in mail.log:

dovecot: dict: Error: mysql: Connect failed to localhost (mail): Can't connect to local MySQL server through socket '/var/lib/mysql/mysql.sock' (13) - waiting for 1 seconds before retry

The problem is that Selinux prevents dovecot connecting to mysql socket. I was unable to find simple solution by setting some setsebol parameter, so I went through the audit.log with audit2allow.

Solution:
Create dovecot2mysql.te file under /etc/selinux:
cat > /etc/selinux/dovecot2mysql.te
module dovecot2mysqldb 1.0.0;

require {
    type dovecot_t;
    type dovecot_deliver_t;
    type var_t;
    type mysqld_db_t;
    type mysqld_t;
    type mysqld_var_run_t;
    type usr_t;
    class file { rename read create write getattr link unlink open };
    class dir search;
    class unix_stream_socket connectto;
    class sock_file write;
    class file { read getattr open };
}


allow dovecot_deliver_t var_t:file { rename read create write getattr link unlink open };
allow dovecot_t mysqld_db_t:dir search;
allow dovecot_t mysqld_t:unix_stream_socket connectto;
allow dovecot_t mysqld_var_run_t:sock_file write;
allow dovecot_t usr_t:file { read getattr open };


cat >/etc/selinux/sel.sh <<EOF
name=\${1%%.*}
echo "\$name"
checkmodule -M -m -o \$name.mod \$name.te \
  && semodule_package -o \$name.pp -m \$name.mod \
  && /usr/sbin/semodule -i \$name.pp
EOF

chmod 700 /etc/selinux/sel.sh
/etc/selinux/sel.sh /etc/selinux/dovecot2mysql.te

Tuesday, November 20, 2012

djndns on CentOS6

I use DJB's dns package for a long time and I am satisfied with it. Recently I started migrating it to a CentOS6 machine.
My new requirements were following:
  • run services from init script
  • collect log messages by syslog-ng
  • have config files under /etc
There are a few guides on the net but they use DJB's svscan service to start-stop djb services and they use multilog as log collector.
There is my guide to achieve my requirements:
Install prerequisites (build environment):
yum install gcc make

Build daemontools

cd /usr/local/src
wget http://cr.yp.to/daemontools/daemontools-0.76.tar.gz
tar xvfz daemontools-0.76.tar.gz
cd admin/daemontools-0.76
sed -i '/gcc/ s|$| -include /usr/include/errno.h|' src/conf-cc
package/compile
for i in $(cat package/commands); do cp command/$i /usr/local/bin/$i; done

Build ucspi-tcp

cd /usr/local/src
wget http://cr.yp.to/ucspi-tcp/ucspi-tcp-0.88.tar.gz
tar xvfz ucspi-tcp-0.88.tar.gz
cd ucspi-tcp-0.88
sed -i '/gcc/ s|$| -include /usr/include/errno.h|' conf-cc
make
make setup check

Build djbdns

cd /usr/local/src
wget http://cr.yp.to/djbdns/djbdns-1.05.tar.gz
tar xvfz djbdns-1.05.tar.gz
cd djbdns-1.05
sed -i '/gcc/ s|$| -include /usr/include/errno.h|' conf-cc
make
make setup check
UPDATE:

Add /usr/local/bin to your PATH:

sed -i '/PATH=/ s|$|:/usr/local/bin|' /root/.bash_profile
Re-login or simply add to bash session:
export PATH=$PATH:/usr/local/bin

dnscache

Create dnscache users
groupadd -g 200 djbdns
useradd --no-create-home -s /bin/false -u 201 -g 200 dnscache
useradd --no-create-home -s /bin/false -u 202 -g 200 dnslog
Setup dnscache
dnscache-conf dnscache dnslog /etc/dnscache 192.168.233.254
Specify client's address range
touch /etc/dnscache/root/ip/192.168.233
Create init script
cat >/etc/init.d/dnscache <<EOF
#!/bin/bash
#
# dnscache      DNS cache server
#
# chkconfig: 345 11 89
# Provides: dnscache
# Required-Start: \$network
# Required-Stop: \$network
# Short-Description: start and stop dnscache
# Description: Dan Bernstein (DJB) dns cache server
# ZsZs
 
# Source function library.
. /etc/rc.d/init.d/functions
 
prog=dnscache
progdir=/usr/local/bin
 
# pull in sysconfig settings
[ -f /etc/sysconfig/dnscache ] && . /etc/sysconfig/dnscache
 
start(){
    echo -n \$"Starting \$prog: "
    pid=\$(pidof \$progdir/\$prog)
    if [[ "\$pid" == "" ]]; then
        # Read up dnscache environment files and export them
        for env in \$(cd \$dnscachedir/env/; ls -1); do envs="\$envs \$env=\$(cat \$dnscachedir/env/\$env)"; done
        export \$envs
        \$progdir/envuidgid dnscache \$progdir/softlimit -o250 -d "\$DATALIMIT" \
          \$progdir/\$prog 2>&1 | (\$progdir/setuidgid dnslog /usr/bin/logger -p local4.info -t \$prog) &
        if [[ "\$?" == "0" ]]
        then
            success
            echo
        else
            failure \$"\$prog start"
            echo
            exit 1
        fi
    else
        failure \$"\$prog start"
        echo
        exit 1
    fi
}
 
stop(){
    pid=\$(pidof \$progdir/\$prog)
    if [[ "\$pid" == "" ]]
    then
        echo -n "Stopping  \$prog: "
        failure \$"\$prog not running."
        echo
    else
        echo -n "Stopping \$prog: "
        kill \$pid && success || failure \$"\$prog stop"
        echo
    fi
}
 
# See how we were called.
case "\$1" in
    start)
        start
        ;;
    stop)
        stop
        ;;
    restart)
        stop
        sleep 1
        start
        ;;
    *)
        echo "Usage: \$prog {start|stop|restart}"
        exit 1
esac
 
exit 0
EOF
Create dnscache config file
echo "dnscachedir=/etc/dnscache" >/etc/sysconfig/dnscache
Start dnscache service
chmod 755 /etc/init.d/dnscache
service dnscache start
chkconfig dnscache on

tinydns

Create tinydns users
useradd --no-create-home -s /bin/false -u 203 -g 200 tinydns
useradd --no-create-home -s /bin/false -u 204 -g 200 tinylog
Install tinydns
tinydns-conf tinydns tinylog /etc/tinydns your.pub.lic.ip
cd /etc/tinydns/root
Create example domain Add SOA record
./add-ns example.hu 123.123.123.123
Add host
./add-host garfield.examle.hu 123.123.123.124
Add MX record
./add-mx examle.hu 123.123.123.123
Add alias
./add-alias www.example.hu 123.123.123.123
Make data.cdb
make
Create init script
cat >/etc/init.d/tinydns <<EOF
#!/bin/bash
#
# tinydns      Authoritative DNS server
#
# chkconfig: 345 11 89
# Provides: tinydns
# Required-Start: \$network
# Required-Stop: \$network
# Short-Description: start and stop tinydns
# Description: Dan Bernstein (DJB) authoritative dns server
# ZsZs
 
# Source function library.
. /etc/rc.d/init.d/functions
 
prog=tinydns
progdir=/usr/local/bin
 
# pull in sysconfig settings
[ -f /etc/sysconfig/tinydns ] && . /etc/sysconfig/tinydns
 
start(){
    echo -n \$"Starting \$prog: "
    pid=\$(pidof \$progdir/\$prog)
    if [[ "\$pid" == "" ]]; then
        # Read up tinydns environment files and export them
        for env in \$(cd \$tinydnsdir/env/; ls -1); do envs="\$envs \$env=\$(cat \$tinydnsdir/env/\$env)"; done
        export \$envs
        \$progdir/envuidgid tinydns \$progdir/softlimit -d300000 \$progdir/\$prog 2>&1 | \
          (\$progdir/setuidgid tinylog /usr/bin/logger -p local4.info -t \$prog) &
        if [[ "\$?" == "0" ]]
        then
            success
            echo
        else
            failure \$"\$prog start"
            echo
            exit 1
        fi
    else
        failure \$"\$prog start"
        echo
        exit 1
    fi
}
 
stop(){
    pid=\$(pidof \$progdir/\$prog)
    if [[ "\$pid" == "" ]]
    then
        echo -n "Stopping  \$prog: "
        failure \$"\$prog not running."
        echo
    else
        echo -n "Stopping \$prog: "
        kill \$pid && success || failure \$"\$prog stop"
        echo
    fi
}
 
# See how we were called.
case "\$1" in
    start)
        start
        ;;
    stop)
        stop
        ;;
    restart)
        stop
        sleep 1
        start
        ;;
    *)
        echo "Usage: \$prog {start|stop|restart}"
        exit 1
esac
 
exit 0
EOF
Create tinydns config file
echo "tinydnsdir=/etc/tinydns" >/etc/sysconfig/tinydns
Start tinydns service
chmod 755 /etc/sysconfig/tinydns
service tinydns start
chkconfig tinydns on
Test dns server: ask it for some type of records
dnsq soa example.hu 123.123.123.123
dnsq a example.hu 123.123.123.123

axfrdns

Create axfrdns user
useradd --no-create-home -s /bin/false -u 205 -g 200 axfrlog
Install axfrdns
axfrdns-conf axfrdns axfrlog /etc/axfrdns /etc/tinydns 123.123.123.123
Allow a cleint to tranfser zone
cd /etc/axfrdns
cat >>tcp <<EOF
123.123.123.123:allow,AXFR="example.hu"
EOF
make
Create init script
cat >/etc/init.d/axfrdns <<-EOF
#!/bin/bash
#
# axfrdns      DNS zone transfer server
#
# chkconfig: 345 11 89
# Provides: axfrdns
# Required-Start: \$network
# Required-Stop: \$network
# Short-Description: start and stop axfrdns
# Description: Dan Bernstein (DJB) dns zone transfer server
# ZsZs
 
# Source function library.
. /etc/rc.d/init.d/functions
 
prog=axfrdns
progdir=/usr/local/bin
 
# pull in sysconfig settings
[ -f /etc/sysconfig/axfrdns ] && . /etc/sysconfig/axfrdns
 
start(){
    echo -n \$"Starting \$prog: "
    pid=\$(pidof \$progdir/tcpserver \$progdir/\$prog)
    if [[ "\$pid" == "" ]]; then
        # Read up axfrdns environment files and export them
        for env in \$(cd \$axfrdnsdir/env/; ls -1); do envs="\$envs \$env=\$(cat \$axfrdnsdir/env/\$env)"; done
        export \$envs
        \$progdir/envuidgid axfrlog \$progdir/softlimit -d300000 \$progdir/tcpserver -vDRHl0 -x \$axfrdnsdir/tcp.cdb -- "\$IP" 53 \
          \$progdir/\$prog 2>&1 | (\$progdir/setuidgid axfrlog /usr/bin/logger -p local4.info -t \$prog) &
        if [[ "\$?" == "0" ]]
        then
            success
            echo
        else
            failure \$"\$prog start"
            echo
            exit 1
        fi
    else
        failure \$"\$prog start"
        echo
        exit 1
    fi
}
 
stop(){
    pid=\$(pidof \$progdir/tcpserver \$progdir/\$prog)
    if [[ "\$pid" == "" ]]
    then
        echo -n "Stopping  \$prog: "
        failure \$"\$prog not running."
        echo
    else
        echo -n "Stopping \$prog: "
        kill \$pid && success || failure \$"\$prog stop"
        echo
    fi
}
 
# See how we were called.
case "\$1" in
    start)
        start
        ;;
    stop)
        stop
        ;;
    restart)
        stop
        sleep 1
        start
        ;;
    *)
        echo "Usage: \$prog {start|stop|restart}"
        exit 1
esac
 
exit 0
EOF
Create axfrdns config file
echo "axfrdnsdir=/etc/axfrdns" >/etc/sysconfig/axfrdns
Start axfrdns service
chmod 755 /etc/init.d/axfrdns
service axfrdns start
chkconfig axfrdns on
Test axfrdns server
tcpclient 123.123.123.123 53 axfr-get example.hu aa aa.tmp
cat aa
#1352995218 auto axfr-get
Zexample.hu:0.ns.example.hu.:hostmaster.example.hu.:1352995218:16384:2048:1048576:2560:2560
&example.hu::0.ns.example.hu.:259200
+0.ns.example.hu:123.123.123.123:259200
+garfield.example.hu:123.123.123.123:86400
@example.hu::a.mx.example.hu.:0:86400
+a.mx.example.hu:123.123.123.123:86400
+www.example.hu:123.123.123.123:86400

syslog-ng

Relevant lines of syslog-ng.conf to collect logs in sepatare log files:
destination df_djb { file("/var/log/$YEAR/$MONTH/$DAY/djb_$PROGRAM.$YEAR$MONTH$DAY.log" ); };
filter f_djb { facility(local4); };
log { source(s_sys); filter(f_djb); destination(df_djb); };

Thanks to http://www.koelzer.us/~thomas/postfix-CentOS6.html

Comments are welcome!

Saturday, October 20, 2012

Ratelimit callbacks suppressed


Recently I hardened some RHEL6 based machines.
During this hardening process - among the others - I did the following:
- disdabled ipv6 by "options ipv6 disable=1" in /etc/modprobe.d/hardening.conf
- added some more audit rules according to NSA guide
- stopped auditd therefore audit log events are redirected to kernel log
- filtered audit logs by following filter to separate audilt.log:
filter f_audit { match(' audit\(' value("MESSAGE")); };

After this hardening there were staerted appearing "__ratelimit: XX callbacks suppressed" messages regularly in kernel log, like following:

Oct 18 01:00:01 test1 kernel: __ratelimit: 4 callbacks suppressed
Oct 18 01:01:01 test1 kernel: __ratelimit: 192 callbacks suppressed
Oct 18 01:05:07 test1 kernel: __ratelimit: 188 callbacks suppressed

It didn't cause any problem but after a while I've started investigating (thx Cipo) what can cause this strange behaviour.

The root cause of this problem is a bit complex. Let's see them:
- disabling ipv6 module caused that some programs would like to insert it
- I've set an audit rule which logs any module instertion attempts: "-w /sbin/modprobe -p x -k modules"
- there are kernel.printk_ratelimit* kernel parameters
# cat /proc/sys/kernel/printk_ratelimit
5
# cat /proc/sys/kernel/printk_ratelimit_burst
10
This means that there is a 10 msgs/5 seconds limit in kernel logging. Exceeding this limit messages will be dropped AND "__ratelimit NumberOfDroppedMessages: callbacks suppressed" messages will be written to the kernel log.

To put the pieces of the picture together:
- my script runs curl 20 times
- curl tried to insert ipv6 module by modprobe
- modprobe tries were logged by audit (5 lines/ modprobe)
- too much audit log in short time exceeded the ratelimit


My solution:
- re-enable ipv6 by commenting  "options ipv6 disable=1" line in /etc/modprobe.d/hardening.conf
- prevent use of ipv6 calls by appending following line to /etc/sysctl.conf:
net.ipv6.conf.all.disable_ipv6 = 1 
(Thanks to Daniel Walsh)

These resulted that:
- ipv6 module is already inserted, so programs do not want to insert it
- ipv6 remained pseudo-disabled

After finishing this I've continued getting ratelimit messaged but not regularly.
I've  find out that Midnight Commander deletes a few temporary files and changes permissions of its config files after exiting. This process resulted more than 150 lines within one second in audit log...
My solution is that I've appended following line to the /etc/sysctl.conf file:
kernel.printk_ratelimit = 30
kernel.printk_ratelimit_burst = 200
This means that kernel accepts 200 messages/30 sec

Comments are welcome.