automation, configuration, network components, scripting, Uncategorized

script on expect language to push batch changes to cisco and aruba switches / routers

Notes about the script:

– in such particular case script pushes new syslog server 10.10.10.21 to configuration and saves config file
– script works almost without changes on cisco and aruba (on cisco though syntax is “logging host <…>” on aruba it is “logging <…>”)
– script will terminate itself with error if it will be not able to establish ssh to any of mentioned switches/routers where it needs to do changes
– logging from aruba is a mambo-jumbo and not accepted as a solution (the same result I get if doing logging via tee command of Expect script and with Expect’s logging possibility by log_file command (in my script its log_file -a $Directory/session_$host.log) )
– script expects that directory /tmp/logs exists, hence either it should be created manually or by adjusting provided script
– “log_file” command in script closes logging for each host, otherwise I got complaints from Expect related to not closed logging
– script reads IP addresses of each aruba / cisco switch or router from a file, which is given as a parameter to a script:

case for cisco
./set_syslog_on_cisco_v1.0.ex /tmp/cisco.txt | tee /tmp/cisco_syslog.log

case for aruba
./set_syslog_on_aruba_v1.0.ex /tmp/aruba.txt | tee /tmp/aruba_syslog.log

below is example of script for aruba case, for cisco case one line should be changed:

compare

 

#!/usr/bin/expect -f

set timeout 20

set file [lindex $argv 0];

set f [open “$file”]

set hosts [split [read $f] “n”]

close $f

foreach host $hosts {

if {$host != “”} {

send “echo host is $hostr”

sleep 2

set Username “your_username”

set Password “your_password”

set Directory /tmp/logs

log_file -a $Directory/session_$host.log

send_log “### /START-SSH-SESSION/ IP: $host @ [exec date] ###r”

spawn ssh -o “StrictHostKeyChecking no” $Username@$host

expect “*assword: ”

send “$Passwordr”

expect “#”

send “conf tr”

expect “(config)#”

send “logging 10.10.10.21r”

expect “(config)#”

send “endr”

expect “#”

send “wr memr”

expect “#”
send “r”

send “logoutr”

sleep 2

send_log “r### /END-SSH-SESSION/ IP: $host @ [exec date] ###r”

log_file;
}
}

configuration, Uncategorized, wireless topics

Peers configuration for guest wifi on Cisco wireless controllers

Infrastructure diagram for guest wifi service is well known:
guest wifi topology

            Pic.1 – Diagram for guest wifi service (diagram is taken from “design guide”)

Between local wireless controllers located on site (shown and named as “campus controllers” or “foreign WLCs”) and wireless controller located in DMZ (shown and named usually as “anchor controller”) should be configured and built EoIP tunnel. This article is dedicated to describe how correctly to configure this tunnel, as no documentation from cisco.com has such detailed information.

For functioning guest wifi service status of a tunnel should be UP (local WLC and anchor WLC show status of this tunnel as UP when all is correct):

peers status

Pic.2 – EoIP tunnel is established

To build a peer it is needed

1) IP address of management interface on remote peer (if you do configuration on anchor, its need IP of management interface on foreign WLC and vice versa – for foreign WLC its needed management IP of anchor WLC)

2) member MAC address: is tricky case as it is needed to use MAC address of virtual interface of the remote site. If any side (local WLCs or anchor WLC(s)) is in HA-SSO mode, then its needed to use high-availability virtual MAC address, which can be received by command (or from GUI via https access)

(Cisco Controller) >show redundancy summary

3) Group name – is Local Mobility Group of remote side and it is cAsE senSiTivE

peer parameters

Pic.3 – EoIP tunnel is established

If at least one of 1), 2) or 3) is not fulfilled peer will not be up and will show “data path is down” or “control path is down”.

4) firewall rules between anchor WLC (usually located in DMZ) and local WLCs should be cleared. From my experience such ports are needed:

“Legacy mobility: IP Protocol 97 for user data traffic, UDP Port 16666”

Despite it is called “legacy mobility” it is used by firmware 8.5.140.0, per firewall logs, UDP 16667 is not used, despite it is mentioned as

“New mobility: UDP Port 16666 and 16667”  under related Q&A

Additionally, per my memory, communication for EoIP is initiated from anchor (I’ve never seen such details on cisco documentations), but to be 100% sure, it is recommended to enable ACLs so that EoIP can be initiated from local WLCs as well as from anchor WLC, because for stateful firewall it is important which side initiates communication.

If mentioned in 4) details are not taken into account, then status of EoIP peer will be shown as “control and data path down“, “data path is down” or “control path is down”, depending on what is configured in related access lists.

 

P.S.: it is worse also to mention that Cisco suggests to have identical WLAN settings on local WLC and anchor, e.g. if “11k Neighbor List” is enabled on local WLC under guest wifi WLAN, then such setting should be enabled on anchor as well. The same is true for QoS settings under respective WLAN and other parameters.

 

 

Access control lists, automation, Uncategorized

convert Cisco ACL to Aruba ACL

There is a case when Cisco L3 switch (e.g. core or distribution level) is replaced by Aruba L3 switch. Cisco switch may have a bunch of ACLs on it and Aruba switch has similar syntax of ACLs but it requires numbers in front of each line and double quotes after remark command. Quick and a little dirty solution is to use such Linux command:

awk '{if ($1=="remark") { print (NR)*10, "remark", """$0""" } else if (($1=="permit") || ($1=="deny")) {print (NR-1)*10 " " $s} }'  <path_to_your_ACL_file>

e.g.

convert from such Cisco ACLs:

remark permit ICMP on any direction
permit icmp 0.0.0.0 255.255.255.255 0.0.0.0 255.255.255.255
remark permit CAPWAP on any direction
permit udp 0.0.0.0 255.255.255.255 0.0.0.0 255.255.255.255 range 5246 5247
remark permit TACACS traffic
permit tcp 0.0.0.0 255.255.255.255 gt 1023 10.10.10.201 0.0.0.0 eq 49
remark enable SSH connections
permit tcp 0.0.0.0 255.255.255.255 eq 22 0.0.0.0 255.255.255.255

to such Aruba ACLs:

10 remark "remark permit ICMP on any direction"
10 permit icmp 0.0.0.0 255.255.255.255 0.0.0.0 255.255.255.255
30 remark "remark permit CAPWAP on any direction"
30 permit udp 0.0.0.0 255.255.255.255 0.0.0.0 255.255.255.255 range 5246 5247
50 remark "remark permit TACACS traffic"
50 permit tcp 0.0.0.0 255.255.255.255 gt 1023 10.10.10.201 0.0.0.0 eq 49
70 remark "remark enable SSH connections"
70 permit tcp 0.0.0.0 255.255.255.255 eq 22 0.0.0.0 255.255.255.255

such command has been used:

awk '{if ($1=="remark") { print (NR)*10, "remark", """$0""" } else if (($1=="permit") || ($1=="deny")) {print (NR-1)*10 " " $s} }' /tmp/acl_example.txt

Because NR built-in variable was used in such command some numbers in front of lines are skipped, e.g. 40 in this case. But technically such ACL is still valid and can be used.

automation, scripting, SQL, Uncategorized

SQL-style join functions in excel

Often I have a list or table with switch names approved for firmware upgrade on a certain site, but I have also a list of all network devices running on site with their names and IPs. So mentioned scope of devices for reboot is a sub-scope of all devices on site. The task is to do a JOIN operation with these two tables which I can have in excel. After such successful operation in excel I’ve got what is needed – all devices approved for reboot and their IP addresses, e.g. part of the table:

Name Device IP Vendor Model Partition
b101-f1-p1-acc01-p 10.105.209.33 Cisco WS-C2960X-48FPS-L LAN
b101-f1-p1-acc02 10.105.209.46 Cisco WS-C2960X-48TS-L LAN
b101-f1-p2-acc01-p 10.105.209.35 Cisco WS-C2960X-48FPS-L LAN
b101-f1-p2-acc02 10.105.209.36 Cisco WS-C2960X-48TS-L LAN
b101-f1-p2-acc03 10.105.209.47 Cisco WS-C2960X-48TS-L LAN
b101-f1-p3-acc01 10.105.209.48 Cisco WS-C2960X-48TS-L LAN
b101-f1-p3-acc02 10.105.209.34 Cisco WS-C2960X-48TS-L LAN
b101-f1-r1-acc01-p 10.105.209.11 Cisco WS-C2960X-48FPS-L LAN
b101-f1-r1-acc02 10.105.209.12 Cisco WS-C2960X-48TS-L LAN

Steps can be followed for example from here

 

configuration, scripting, Uncategorized, wireless topics

Script to batch change authentication server on Cisco wireless controllers

Task description:

-there are more than 100 Cisco wireless controllers in a region

– it old authentication radius servers 10.10.0.100 & 10.10.0.101 are approaching end-of-support and should be replaced by  new one 10.10.0.73.

– on each of wireless controller there are can be one or two wifi SSIDs which are using mentioned old radius servers. In this script they will be called “Office1” & “Office2”. Under their settings script will replace old radius servers by new one. Regex are being used to identify under which IDs “Office1” & “Office2” are configured on each particular WLC

– for SSH into each device Perl module Net::SSH::Expect is used

– script output can be logged by Linux tee command to verify that all done correctly

– script reads IP addresses of each WLC from a file, which is given as a parameter to a script:

./this_script.pl file_with_WLCs_IPs.txt | tee result.log

Script itself may be not perfect but done in a short time and describes an approach which can be optimized and made more advanced:


#!/usr/bin/perl
#script to update radius auth servers on local WLCs

use Net::SSH::Expect;
my $filename = $ARGV[0];

my $username=”your_username”;
my $password=”your_password”;
if (open(my $fh, ‘<:encoding(UTF-8)’, $filename)) {
while ( <$fh> ) {
chomp;
@fields = split(‘ ‘, $_);

$host1 = $fields[0];
my $ssh = Net::SSH::Expect->new (
host => $host1,
raw_pty => 1
);
print (“Getting into WLC $host1…n”);
$ssh->run_ssh() or print “SSH process couldn’t start: $!”;
$ssh->waitfor(‘Are you sure you want to continue connecting (yes/no)?’, 10) or print “n key already imported n”;
$ssh->send(“yesn”);
$ssh->waitfor(‘User:’, 20) or die “prompt ‘User’ not found after 20 second”;
$ssh->send(” “);
$ssh->send(“$username”);
$ssh->waitfor(‘Password:’, 7) or print “prompt ‘Password’ not found after 7 second”;
$ssh->send(“$password”);
$ssh->waitfor(‘(Cisco Controller)’, 7) or print “prompt ‘Cisco Controller’ not found”;
print ($ssh->exec(“config paging disable”));

print (“Checking ‘Office1’ WLAN id numbern”);
$ssh_session =$ssh->exec(“show wlan summary”);
print ($$ssh_session);

#cutting line with office WLAN information:
($matching) = $ssh_session=~ /([^n]*Office1+)/is;
print (“n$matching”);

my $wlan_id1;
$matching =~ m/(d+)/g;
if ($matching ne “”) {

$wlan_id1=$1;
}
else {
$wlan_id1=0;
}
$ssh_session =$ssh->exec(“show wlan summary”);
print ($$ssh_session);
#cutting line with Office2 WLAN information
($matching) = $ssh_session=~ /([^n]*Office2+)/is;
print (“n$matching”);
$matching =~ m/(d+)/g;

my $wlan_id2;
if ($matching ne “”) {
$wlan_id2=$1;

}
else {
$wlan_id2=0;
}

print (“nn print Office1 wifi id= $wlan_id1, Office2 id=$wlan_id2 n”);
$ssh_session =$ssh->exec(“show radius summary”);
print ($$ssh_session);
($matching) = $ssh_session=~ /([^n]*10.10.0.100+)/is;
print (“n$matching”);
$matching =~ m/(d+)/g;
my $rad_id100;
if ($matching ne “”) {
$rad_id100=$1;
}
else {
$rad_id100=0
}
$ssh_session =$ssh->exec(“show radius summary”);
print ($$ssh_session);
($matching) = $ssh_session=~ /([^n]*10.10.0.101+)/is;
print (“n$matching”);
$matching =~ m/(d+)/g;
my $rad_id101;
if ($matching ne “”) {
$rad_id101=$1;
}
else {
$rad_id101=0;
}
$ssh_session =$ssh->exec(“show radius summary”);
print ($$ssh_session);
($matching) = $ssh_session=~ /([^n]*10.10.0.73+)/is;
print (“n$matching”);
$matching =~ m/(d+)/g;

my $rad_id73;
if ($matching ne “”) {
$rad_id73=$1;
}
else {
$rad_id73=0;
}
print (“n rad_id100 = $rad_id100, rad_id101 = $rad_id101, rad_id73 = $rad_id73 “);

print(“n disabling mentioned WLANs “);
print ($ssh->exec(“config wlan disable $wlan_id1”));
print ($ssh->exec(“config wlan disable $wlan_id2”));
print(“n deleting all auth radius servers under related WLANs “);
print ($ssh->exec(“config wlan radius_server auth delete $wlan_id1 all”));
print ($ssh->exec(“config wlan radius_server auth delete $wlan_id2 all”));

print(“n deleting all auth radius servers under radius settings on WLC “);
print ($ssh->exec(“config radius auth delete $rad_id100”));
print ($ssh->exec(“config radius auth delete $rad_id101”));
print ($ssh->exec(“config radius auth delete $rad_id73”));

# to check the case that auth radius servers have been configured with id equal to 1, otherwise throw warning in log and configure new radius with id=30
if (($rad_id100==1) || ($rad_id101==1) || ($rad_id73==1)) {
print(“n adding new auth radius server (with id=1) under radius settings on WLC n”);
print ($ssh->exec(“config radius auth add 1 10.10.0.73 1812 ascii inf2_acs_key”));
print ($ssh->exec(“config radius auth disable 1”));
print ($ssh->exec(“config radius auth rfc3576 enable 1”));
print ($ssh->exec(“config radius auth retransmit-timeout 1 5”));
print ($ssh->exec(“config radius auth management 1 disable”));
print ($ssh->exec(“config radius auth network 1 enable”));
print ($ssh->exec(“config radius auth enable 1”));
print ($ssh->exec(“config wlan radius_server auth add $wlan_id1 1”));
print ($ssh->exec(“config wlan radius_server auth add $wlan_id2 1”));
print ($ssh->exec(“config wlan enable $wlan_id1”));
print ($ssh->exec(“config wlan enable $wlan_id2”));

}

else {
#my $min_rad_id = min ($rad_id100, $rad_id101, $rad_id73);
print(“n ADDING NEW RADIUS SERVER (WITH ID=30) UNDER RADIUS SETTINGS ON WLC n”);
print ($ssh->exec(“config radius auth add 30 10.10.0.73 1812 ascii inf2_acs_key”));
print ($ssh->exec(“config radius auth disable 30”));
print ($ssh->exec(“config radius auth rfc3576 enable 30”));
print ($ssh->exec(“config radius auth retransmit-timeout 30 5”));
print ($ssh->exec(“config radius auth management 30 disable”));
print ($ssh->exec(“config radius auth network 30 enable”));
print ($ssh->exec(“config radius auth enable 30”));
print ($ssh->exec(“config wlan radius_server auth add $wlan_id1 30”));
print ($ssh->exec(“config wlan radius_server auth add $wlan_id2 30”));
print ($ssh->exec(“config wlan enable $wlan_id1”));
print ($ssh->exec(“config wlan enable $wlan_id2”));
}

print(“n saving configuration file to flash memory n”);
print ($ssh->exec(“save config”));
print ($ssh->exec(“y”));
}
} else {
warn “Could not open file ‘$filename’ $!”;
}