4. Scripts
4.1. Intro
When I have to do things twice, I get bored. When I have to do it three
times, I create a script to automate it.
My switch still uses telnet (yes I know) and I used expect to interface with my
switch.
The following template will be used.
#!/usr/bin/expect set timeout 60 set ip 192.168.10.1 set user cisco set password secret spawn telnet $ip expect "ername:" send "$user\r" expect "assword: " send "$password\r" expect "DEMO" send "enable\r" expect "assword: " send "$password\r" expect "DEMO" send -- "exit\r"
Because I have a test of short duration and becaise I am on a stand-alone network
without connection to the rest of the world, I can put the password in my script.
In a real life situation that would be unthinkable.
the DEMO is a part of the prompt for the switch. If you are very precise, you could
put in the exact prompt that will be presented (
DEMO>
or
DEMO#
in enable mode, and so on for the different config modes. That will make the scripts
better, but this will do for our test.
4.2. Resetting scripts with expect
If a port needs to be reset, you can log in to the switch, do
enable
and
conf t
and type all the IOS commands by hand. Or you could use an expect script.
#!/usr/bin/expect set port [lindex $argv 0] set mac [lindex $argv 1] set timeout 60 set ip 192.168.10.1 set user cisco set password secret spawn telnet $ip expect "ername:" send "$user\r" expect "assword: " send "$password\r" expect "DEMO>" send "enable\r" expect "assword: " send "$password\r" expect "DEMO" send "conf t\r" expect "DEMO" send "int fa0/$port\r" expect "DEMO" send "shut\r" expect "DEMO" send "end\r" expect "DEMO" send "conf t\r" expect "DEMO" send "int fa0/$port\r" expect "DEMO" send "no shut\r" expect "DEMO" send "end\r" expect "DEMO" send -- "exit\r"
It should not be dificult to create scripts for the main transactions. I created expect scripts for the following.
script
|
purpose
|
commands
|
down_port.xpct
|
make a port admin down
|
conf t int fa0/port shut end |
remove
mac
on
port
sticky.exp
|
remove a sticky mac from a port
|
conf t int fa0/port shut no switchport port-security mac-address sticky mac no shut |
reset_port.xpct
|
reset a port
|
conf t int fa0/port shut no shut end |
show_port.xpct
|
show settings
|
sh run interface fa0/port sh port-security interface fa0/port |
4.3. A demo menu
This test was part of a demonstration of how port security works. I used the following script to hide the
nitty gritty details from the audience.
#!/bin/bash TMP=/tmp/rgh.$$ sudo tail -f /var/log/messages | grep PSECURE_VIOLATION & tokill=$!
The syslog messages about port security violations are written over the
menu. This shows that we actually see an alert when something is happening.
disp(){ printf "%4.4s %16.16s %16.16s %12.12s\n" port allowed last_seen status for port in 1 2 3 4 5 6 7 8 9 10 11 12 ; do expect show_port.xpct $port | sed 's/\r//' > $TMP mac=`awk '/switchport port-security mac-address.*[0-9a-f]+\.[0-9a-f]/{print $NF}' $TMP` lastseen=`sed -n 's/Last Source Address:Vlan *: *//p' $TMP | sed 's/:1*0//'` status=`sed -n 's/Port Status *: *//p' $TMP` nstat='unknown' case a$status in (aSecure-up) nstat='UP' ;; (aSecure-down) nstat='No device' ;; (aSecure-shutdown) if [ "$mac" = "" ] ; then nstat='No device' else nstat="Violation" fi ;; esac if grep '^ *shutdown' $TMP > /dev/null ; then nstat='adm down' fi printf "%4.4s %16.16s %16.16s %12.12s\n" "$port" "$mac" "$lastseen" "$nstat" done rm -f $TMP }
The goal of this function is to provide a display of what is actually happening. It shows
a table that is easier to interpret than the standard IOS output.
rmmac(){ port=$1 expect show_port.xpct $port | sed 's/\r//' > $TMP mac=`awk '/switchport port-security mac-address.*[0-9a-f]+\.[0-9a-f]/{print $NF}' $TMP` if [ "$mac" != "" ] ; then expect remove_mac_on_port_sticky.exp $port $mac fi }
This function removes a MAC ID from a port. The function first looks
which MAC ID is available on the port.
reset(){ port=$1 expect reset_port.xpct $port } down(){ port=$1 expect down_port.xpct $port }
These functions reset a port (shut, no shut) or just shut the port.
quit=no while [ $quit = no ] ; do clear disp echo "d for shut down a port" echo "n for new MAC id" echo "r for reset port" echo "q for quit" echo "enter for refresh" read line case a$line in (ar) echo -n "Port nummer : " read line reset $line ;; (ad) echo -n "Port nummer : " read line down $line ;; (an) echo -n "Port nummer : " read line rmmac $line ;; (aq) quit=yes ;; esac done sudo pkill tail exit
The main loop presents a simple menu.