drut default route manager

Drut --Default RoUTe manager-- is a simple script that manages default routes.



I use Drut in systems that need Internet connectivity in LANs with multiple Routers routing through different uplinks. Drut is not a replacement for VRRP and VRRP is not a replacement for Drut, the same goes for tables ... blah ... blah ... it is easier to read what it does ...



#!/bin/bash 
#g0 2014 , http://ipduh.com/contact
#drut.sh , Default RoUTe manager

#Default Gateways
MYGWS=("10.21.241.120" "10.21.241.121" "10.21.241.122" "10.21.241.123")
#IP addresses to ping
PONG=("8.8.8.8" "8.8.4.4")

PING_COUNT=3
FAIL=0
ALTGW=0
SET_GW=`route -n |grep "^0.0.0" |awk '{print $2}'`

for PIP in ${!PONG[*]};do
 if ! ping -c ${PING_COUNT} ${PONG[$PIP]} 1>/dev/null 2>/dev/null; then
  FAIL=`expr ${FAIL} + 1`
 fi
done

if [ ${FAIL} -eq 0 ]; then
 exit 0
else
 for GW in ${!MYGWS[*]}; do
  if [ " ${MYGWS[$GW]}" != "${SET_GW}" ]; then
   FAIL=0
   route add default gw ${MYGWS[$GW]}
   route del -net 0/0 gw ${SET_GW}
   
    for PIP in ${!PONG[*]};do
           if ! ping -c ${PING_COUNT} ${PONG[$PIP]} 1>/dev/null 2>/dev/null; then
                   FAIL=`expr ${FAIL} + 1`
           fi
    done

    [ ${FAIL} -eq 0 ] && exit 0
  fi
 done
 
 exit 3
fi









Drut --Default RoUTe manager

raspberry pi set keyboard to a US keyboard and get rid off the british keyboard and the # madness



Install locales and set default locale with
$ sudo -s
# raspi-config


To set the keyboard layout to "us" in /etc/default/keyboard
$ cat /etc/default/keyboard 
# KEYBOARD CONFIGURATION FILE

# Consult the keyboard(5) manual page.

XKBMODEL="pc105"
XKBLAYOUT="gb"
XKBVARIANT=""
XKBOPTIONS=""

BACKSPACE="guess"



do it ... save a copy of the original keybord in keyboard.0 and reboot the system
# cd /etc/default/
# perl -i.0 -p -e 's/gb/us/g;' ./keyboard
# shutdown -r now




Raspberry Pi set keyboard layout to US

raspberrypi get rid off GUI



Notes on getting rid of the desktop environment on raspbian --the arm debian optimized for raspberry pi put together by the raspberry pi foundation.



Set boot on CLI
$ sudo -s
# raspi-config
Choose 3)
3 Enable Boot to Desktop/Scratch Choose whether to boot into a desktop environment, Scratch, or the command-line


Check file system usage
# df
Filesystem     1K-blocks    Used Available Use% Mounted on
rootfs           3731208 2085704   1448600  60% /
/dev/root        3731208 2085704   1448600  60% /
devtmpfs          215824       0    215824   0% /dev
tmpfs              44820     200     44620   1% /run
tmpfs               5120       0      5120   0% /run/lock
tmpfs              89620       0     89620   0% /run/shm
/dev/mmcblk0p1     57288   19064     38224  34% /boot


Purge everyging that depends on-requires X --the following packgages
ii  libx11-6:armhf                        2:1.5.0-1+deb7u1+wheezy                armhf        X11 client-side library
ii  libx11-data                           2:1.5.0-1+deb7u1+wheezy                all          X11 client-side library
ii  libx11-xcb1:armhf                     2:1.5.0-1+deb7u1+wheezy                armhf        Xlib/XCB interface library


with
# apt-get remove --auto-remove --purge libx11*


Check filesystem usage again
# df 
Filesystem     1K-blocks    Used Available Use% Mounted on
rootfs           3731208 1011460   2522844  29% /
/dev/root        3731208 1011460   2522844  29% /
devtmpfs          215824       0    215824   0% /dev
tmpfs              44820     200     44620   1% /run
tmpfs               5120       0      5120   0% /run/lock
tmpfs              89620       0     89620   0% /run/shm
/dev/mmcblk0p1     57288   19064     38224  34% /boot



# df -h
Filesystem      Size  Used Avail Use% Mounted on
rootfs          3.6G  988M  2.5G  29% /
/dev/root       3.6G  988M  2.5G  29% /
devtmpfs        211M     0  211M   0% /dev
tmpfs            44M  200K   44M   1% /run
tmpfs           5.0M     0  5.0M   0% /run/lock
tmpfs            88M     0   88M   0% /run/shm
/dev/mmcblk0p1   56M   19M   38M  34% /boot


that 's over one GiB in savings , 1/4 of the SD in this pi!



remove the desktop environment from raspberry pi raspbian

qemu kvm Debian Jessie

Notes on setting up qemu-kvm on Debian Jessie

The system
# cat /etc/debian_version /etc/issue
8.4
Debian GNU/Linux 8 \n \l
# uname -r
3.16.0-4-amd64
# grep "model\ name" /proc/cpuinfo -m1
model name  : Intel(R) Core(TM) i7-4790 CPU @ 3.60GHz
# egrep "vmx|svm" /proc/cpuinfo -c
8


Install the following debian packages
qemu-kvm - QEMU Full virtualization on x86 hardware
libvirt-bin - programs for the libvirt library
virtinst - Programs to create and clone virtual machines
bridge-utils - Utilities for configuring the Linux Ethernet bridge


# apt-get update
# apt-get install qemu-kvm libvirt-bin virtinst bridge-utils


Example interfaces file
# cat /etc/network/interfaces

source /etc/network/interfaces.d/*

auto lo
iface lo inet loopback

auto eth0
iface eth0 inet manual

auto br0
iface br0 inet static
    address 192.168.1.93
    netmask 255.255.255.0
    gateway 192.168.1.1

    bridge_ports eth0
    bridge_stp off    #disable spanning tree
    bridge_waitport 0 #no delay before a port becomes available
    bridge_fd 0       #no forwarding delay
    bridge_hello 2    #Use hello packets to communicate information about the topology throughout the entire Bridged Local Area Network.



Restart network
# /etc/init.d/networking restart


Check bridge
# brctl show
bridge name bridge id       STP enabled interfaces
br0     8000.f832e4a45ec2   no      eth0


Create a guest VM
# virt-install \
--connect qemu:///system \
-n eratosthenes \
--memory=4056,maxmemory=8112 \
--vcpus=1,maxvcpus=2 \
--disk path=/home/vm/eratosthenes/eratosthenes.qcow2,size=20 \
--cdrom=/home/vm/debian-8.4.0-amd64-netinst.iso \
--graphics vnc --noautoconsole \
--os-type linux \
--network=bridge=br0 \
--hvm



virt-install options used
qemu:///system
  For creating KVM and QEMU guests to be run by the system libvirtd
  instance.  This is the default mode that virt-manager uses, and
  what most KVM users want.


-n NAME, --name=NAME
  Name of the new guest virtual machine instance. This must be unique
  amongst all guests known to the hypervisor on the connection,
  including those not currently active. To re-define an existing guest,
  use the virsh(1) tool to shut it down ('virsh shutdown') & delete
  ('virsh undefine') it prior to running "virt-install".

--memory=MEM[,OPT1=VAL][...]
  Memory to allocate for the guest, in megabytes. Sub options are
  available, like 'maxmemory' and 'hugepages'. This deprecates the
  -r/--ram option.


--vcpus=VCPUS[,maxvcpus=MAX][,sockets=#][,cores=#][,threads=#][,cpuset=CPUSET]
  Number of virtual cpus to configure for the guest. If 'maxvcpus' is
  specified, the guest will be able to hotplug up to MAX vcpus while
  the guest is running, but will startup with VCPUS.

  CPU topology can additionally be specified with sockets, cores, and
  threads.  If values are omitted, the rest will be autofilled
  preferring sockets over cores over threads.

  'cpuset' sets which physical cpus the guest can use. "CPUSET" is a
  comma separated list of numbers, which can also be specified in
  ranges or cpus to exclude. Example:

      0,2,3,5     : Use processors 0,2,3 and 5
      1-5,^3,8    : Use processors 1,2,4,5 and 8

  If the value 'auto' is passed, virt-install attempts to automatically
  determine an optimal cpu pinning using NUMA data, if available.

  Use --vcpus=? to see a list of all available sub options. Complete
  details at
  


--disk=DISKOPTS
  Specifies media to use as storage for the guest, with various
  options. The general format of a disk string is

      --disk opt1=val1,opt2=val2,...

  The simplest invocation to create a new 10G disk image and associated
  disk device:

      --disk size=10

  virt-install will generate a path name, and place it in the default
  image location for the hypervisor. To specify media, the command can
  either be:

      --disk /some/storage/path[,opt1=val1]...

  or explicitly specify one of the following arguments:

  path
      A path to some storage media to use, existing or not. Existing
      media can be a file or block device.

      Specifying a non-existent path implies attempting to create the
      new storage, and will require specifying a 'size' value. Even for
      remote hosts, virt-install will try to use libvirt storage APIs
      to automatically create the given path.


--cdrom=CDROM
  File or device use as a virtual CD-ROM device for fully virtualized
  guests.  It can be path to an ISO image, or to a CDROM device. It can
  also be a URL from which to fetch/access a minimal boot ISO image.
  The URLs take the same format as described for the "--location"
  argument. If a cdrom has been specified via the "--disk" option, and
  neither "--cdrom" nor any other install option is specified, the
  "--disk" cdrom is used as the install media.


--noautoconsole
  Don't automatically try to connect to the guest console. The default
  behaviour is to launch virt-viewer(1) to display the graphical
  console, or to run the "virsh" "console" command to display the text
  console. Use of this parameter will disable this behaviour.


-w NETWORK, --network=NETWORK,opt1=val1,opt2=val2,...
  Connect the guest to the host network. The value for "NETWORK" can
  take one of 4 formats:

  bridge=BRIDGE
      Connect to a bridge device in the host called "BRIDGE". Use this
      option if the host has static networking config & the guest
      requires full outbound and inbound connectivity  to/from the LAN.
      Also use this if live migration will be used with this guest.







Install kvm-vnc-list
# git clone https://github.com/ipduh/kvm-vnc-list.git
# mv kvm-vnc-list/kvm-vnc-list /usr/sbin/
# rm -r kvm-vnc-list




kvm jessie

RouterOS gheto Load Balancer

GLBer is a program that creates the configuration for a Mikrotik RouterOS Load Balancer.

The confiuration is suitable for a router with many uplinks that serves many end users
eg: a workplace with many adsl lines

glber.sh takes as input the names of the point-to-point named interfaces and creates the RouterOS configuration commands and a RouterOS script that runs every 10 minutes.

glber.sh
#!/bin/bash
#Creates the configuration commands and a RouterOS script used to put together a Ghetto Load BalanER --GLBer
#GLBer balances traffic among n named interfaces 
#GLBer NATs and masquerades 
#GLBer watches if the interfaces have Internet Access every 10 minutes and adjusts
#g0 2014 , there is a post about GLBer at http://alog.ipduh.com

GATEWAYS="${1}"
ECMP=""
MIKAR=""
GW_COUNT=0

for GW in ${GATEWAYS}; do
 ((GW_COUNT+=1))
done

echo "glber.sh:hola , I will create the configuration for ${GW_COUNT} named interfaces" 

POS=0
for GW in ${GATEWAYS}; do
 ((POS+=1))

 if [ ${POS} -eq ${GW_COUNT} ] 
 then
  ECMP+="${GW}"
  MIKAR+="\"${GW}\""
 else
  ECMP+="${GW},"
  MIKAR+="\"${GW}\";"
 fi 
done

echo ""
echo "###commands###"
echo ""

echo "/ip route"
echo "add dst-address=0.0.0.0/0 gateway=$ECMP check-gateway=ping comment=lbercur ;"

echo "/ip firewall nat"
for GW in ${GATEWAYS}; do
 echo "add chain=srcnat out-interface=${GW} action=masquerade comment=GLBer_${GW}_nat ;"
done

echo "/ip firewall mangle"
for GW in ${GATEWAYS}; do
 echo "add chain=input in-interface=${GW} action=mark-connection new-connection-mark=${GW}_c comment=GLBer_mangle ;"
 echo "add chain=output connection-mark=${GW}_c action=mark-routing new-routing-mark=to_${GW} comment=GLBer_mangle ;"
done

echo "/ip route"
for GW in ${GATEWAYS}; do
 echo "add dst-address=0.0.0.0/0 gateway=${GW} routing-mark=to_${GW} comment=GLBER ;"
done 

echo ""
echo "###script###"
echo "###add the following script to the router 'script-repository' and name it glber###"
echo ""

read -r -d '' SCR <<- 'SCRIPTT'
:local goodgates " "
:local gcount 0
:local coma ""
:local lbercur "lbercur"
:local lbertmp "lbertmp"
:local pong "8.8.8.8"

:foreach g in=$gateways do={
:if ( $gcount > 0 ) do={ :set coma (",") }
:if ([/ping $pong interface="$g" count=3] = 0) do={  }  else={ 
:set $goodgates ( "$goodgates" . "$coma" . "$g" ) ;
:set gcount ($gcount+1) 
}
};

/ip route set [find comment=$lbercur] distance=2  
/ip route add dst-address=0.0.0.0/0 gateway=$goodgates check-gateway=ping comment="$lbertmp"
/ip route remove [find comment=$lbercur] 
/ip route add dst-address=0.0.0.0/0 gateway=$goodgates check-gateway=ping comment="$lbercur"
/ip route remove [find comment=$lbertmp] 

}
SCRIPTT
echo "{ "
echo "#GLBer -- g0 2014 -- alog.ipduh.com"
echo ":local gateways { ${MIKAR} };"
echo "${SCR}"
echo ""
echo "###schedule script###"
echo "/system scheduler add name=glber policy=read,write,test interval=10m ;"




I think that the easiest way to use glber.sh is to ssh to the RouterOS system from a system that runs bash. Or ssh to a system that has bash and the RouterOS system from the same machine ... whatever .... The good thing is that RouterOS understands the line endings used in all the popular operating systems.

Example Usage

Assume we want to create an uplink balancer for the interfaces alpha, beta , gama , delta ,epsilon

These interfaces may be VPNs, PPoE Tunnels, etc
$ wget kod.ipduh.com/lib/glber.sh
$ chmod 755 glber.sh
$ ./glber.sh "alpha beta gama delta epsilon"


You need to ssh or winbox to the mikrotik RouterOS system and copy the configuration that the glber.sh outputs.

The configuration for the alpha beta gama delta epsilon balancing
 ./glber.sh "alpha beta gama delta epsilon"
glber.sh:hola , I will create the configuration for 5 named interfaces

###commands###

/ip route
add dst-address=0.0.0.0/0 gateway=alpha,beta,gama,delta,epsilon check-gateway=ping comment=lbercur ;
/ip firewall nat
add chain=srcnat out-interface=alpha action=masquerade comment=GLBer_alpha_nat ;
add chain=srcnat out-interface=beta action=masquerade comment=GLBer_beta_nat ;
add chain=srcnat out-interface=gama action=masquerade comment=GLBer_gama_nat ;
add chain=srcnat out-interface=delta action=masquerade comment=GLBer_delta_nat ;
add chain=srcnat out-interface=epsilon action=masquerade comment=GLBer_epsilon_nat ;
/ip firewall mangle
add chain=input in-interface=alpha action=mark-connection new-connection-mark=alpha_c comment=GLBer_mangle ;
add chain=output connection-mark=alpha_c action=mark-routing new-routing-mark=to_alpha comment=GLBer_mangle ;
add chain=input in-interface=beta action=mark-connection new-connection-mark=beta_c comment=GLBer_mangle ;
add chain=output connection-mark=beta_c action=mark-routing new-routing-mark=to_beta comment=GLBer_mangle ;
add chain=input in-interface=gama action=mark-connection new-connection-mark=gama_c comment=GLBer_mangle ;
add chain=output connection-mark=gama_c action=mark-routing new-routing-mark=to_gama comment=GLBer_mangle ;
add chain=input in-interface=delta action=mark-connection new-connection-mark=delta_c comment=GLBer_mangle ;
add chain=output connection-mark=delta_c action=mark-routing new-routing-mark=to_delta comment=GLBer_mangle ;
add chain=input in-interface=epsilon action=mark-connection new-connection-mark=epsilon_c comment=GLBer_mangle ;
add chain=output connection-mark=epsilon_c action=mark-routing new-routing-mark=to_epsilon comment=GLBer_mangle ;
/ip route
add dst-address=0.0.0.0/0 gateway=alpha routing-mark=to_alpha comment=GLBER ;
add dst-address=0.0.0.0/0 gateway=beta routing-mark=to_beta comment=GLBER ;
add dst-address=0.0.0.0/0 gateway=gama routing-mark=to_gama comment=GLBER ;
add dst-address=0.0.0.0/0 gateway=delta routing-mark=to_delta comment=GLBER ;
add dst-address=0.0.0.0/0 gateway=epsilon routing-mark=to_epsilon comment=GLBER ;

###script###
###add the following script to the router 'script-repository' and name it glber###

{ 
#GLBer -- g0 2014 -- alog.ipduh.com
:local gateways { "alpha";"beta";"gama";"delta";"epsilon" };
:local goodgates " "
:local gcount 0
:local coma ""
:local lbercur "lbercur"
:local lbertmp "lbertmp"
:local pong "8.8.8.8"

:foreach g in=$gateways do={
:if ( $gcount > 0 ) do={ :set coma (",") }
:if ([/ping $pong interface="$g" count=3] = 0) do={  }  else={ 
:set $goodgates ( "$goodgates" . "$coma" . "$g" ) ;
:set gcount ($gcount+1) 
}
};

/ip route set [find comment=$lbercur] distance=2  
/ip route add dst-address=0.0.0.0/0 gateway=$goodgates check-gateway=ping comment="$lbertmp"
/ip route remove [find comment=$lbercur] 
/ip route add dst-address=0.0.0.0/0 gateway=$goodgates check-gateway=ping comment="$lbercur"
/ip route remove [find comment=$lbertmp] 

}

###schedule script###
/system scheduler add name=glber policy=read,write,test interval=10m ;





In RouterOS the routing table is flushed every 10 minutes and then there is a good chance ( depending on the number of the uplinks ) to reset the masqueraded connections.

The RouterOS glber script runs every 10 minutes and resets the equal cost multipath route therefore I think that it raises the chance for the masqueraded connections to reset in a 10 minutes period.

In a 5 uplinks setup the chance for a connection to not reset should fall to 4% ( I did not have the patience to verify it yet ). Adding three lines of code to glber should raise the probability that a connection does not reset every 10 minutes up to 1/uplinks. I did not need it in my setup. I wanted outgoing connections to reset often. The thing needed a session was in the internal network and resetting facebook connections was considered a feature.

It is possible ( though not-tested enough) to balance differently per uplink.
eg: 25% of connections from alpha , 25% of connections from beta and 50% of connections from gama would be
$ ./glber.sh "alpha beta gama gama"
and 75% of the connections from alpha and 25% of the connections from beta would be
$ ./glber.sh "alpha alpha alpha beta"




Mikrotik RouterOS Uplink Balancer