automation, configuration, scripting, Uncategorized, wireless topics

Perl script for bulk update of radius server settings on Cisco WLCs

The task, which one may encounter, is to update radius authentication or accounting server settings on Cisco local wireless controllers (WLC) due to either IP of  radius authentication or accounting server is changed (e.g. old servers were scrapped, new ones deployed) or shared secret is changed or should be updated due to other reasons. Shown below script can do such tasks for Cisco WLCs as in my case such changes had to be done on ~60 local WLCs (with manual work such change would be quite stressful, prone to errors and took quite a lot of time).

Initial data and assumptions are:

1) per Cisco WLCs command line, there are no command options to reset shared secret for radius authentication or accounting server:

config radius acct

Pic.1 – Command line options of radius server on Cisco WLC command line

So if someone needs to update shared secret for radius authentication or accounting server, per Cisco’s design it is needed to delete related radius from WLC’s config and then to add it with new password (similar procedure if it is the case of changed IP of radius authentication or accounting server).

2) script below is using Net::SSH::Expect package. If someone uses Debian Linux or its derivatives, I would recommend to install such Perl package as .deb package (I will create separate topic about that), as CPAN or other ways of installation Perl modules sometimes hadn’t worked per my experience.

3) IP addresses of all WLCs, which should go through the change of radius authentication/accounting server, are stored in a separate text file (one IP per one line) which is passed as an argument to the script. For example, if presented script in your case is called “change_wlc_ALL_rad_acc_settings1_0_0.pl” then command to run the script will look following way (in such case file with WLCs IPs is “all_WLCs.txt” is located in the same folder with the script):

command line

Pic.2 – Example of running the provided script

4) script will automatically search defined by you SSIDs which are utilizing related radius authentication or accounting server. For this example script expects that such SSID names contain ABC, KLM, XYZ strings for identification them by regex.

5) “your_username” and “your_password” to authorise on WLCs should be replaced by yours

6) per Cisco’s design, to delete related radius authentication or accounting server it is firstly needed to disable all related SSIDs, which are using it, and delete related radius server from setting of such SSIDs. Script below expects that SSIDs “ABC”, “KLM” and  “XYZ” are using related radius server, so script will search these IDs of such SSIDs to remove related radius server from their settings.

7) script expects that radius accounting server in such example has IP 10.20.30.40 and will search it via regex to identify its ID for further changes with WLC’s  commands

8) script assumes that radius accounting ID on Cisco WLC should be 17 and it is using “acc_shared_secret” shared secret

9) to document all logging output (forchecking that all is executed as expected), tee command can be used, e.g.

@debian:~/scripts# ./change_wlc_ALL_rad_acc_settings1_0_0.pl all_WLCs.txt | tee /tmp/log_changes.log

this will save all output to /tmp/log_changes.log (and will show on console as well)

10) in script there are no correct mechanism to catch error due to unavailability of a certain WLC in a list, where it tries to establish SSH, or authentication problem to access SSH. In these two cases scrip will finish itself with error (such drawback to be improved)

Script itself is following :

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


use Net::SSH::Expect;

my $filename = $ARGV[0];

if (open(my $fh, '<:encoding(UTF-8)', $filename)) {
while ( <$fh> ) {
chomp;
@fields = split(' ', $_);

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("your_username");
$ssh->waitfor('Password:', 7) or print "prompt 'Password' not found after 7 second";
$ssh->send("your_password");
$ssh->waitfor('(Cisco Controller)', 7) or print "prompt 'Cisco Controller' not found";
print ($ssh->exec("config paging disable"));

#------search and identify WLAN ID of ABC------#
print ("Checking ABC WLAN id numbern");
$ssh_session =$ssh->exec("show wlan summary");
print ($$ssh_session);

#cutting line with related WLAN information:
($matching) = $ssh_session=~ /([^n]*ABC+)/is;
print ("n$matching");

my $ABC_wlan_id;
$matching =~ m/(d+)/g;
if ($matching ne "") {

$ABC_wlan_id=$1;
}
else {
$ABC_wlan_id=0;
}

print ("nn print ABC id= $ABC_wlan_id n");

#--search and identify WLAN ID of KLM--#

print ("Checking KLM WLAN id numbern");
$ssh_session =$ssh->exec("show wlan summary");
print ($$ssh_session);

#cutting line with related WLAN information:
($matching) = $ssh_session=~ /([^n]*KLM+)/is;
print ("n$matching");

my $KLM_wlan_id;
$matching =~ m/(d+)/g;
if ($matching ne "") {

$KLM_wlan_id=$1;
}
else {
$KLM_wlan_id=0;

}

print ("nn print KLM id= $KLM_wlan_id n");

#---search and identify WLAN ID of XYZ---#

print ("Checking XYZ WLAN id numbern");
#print ($ssh->exec("show wlan summary"));
$ssh_session =$ssh->exec("show wlan summary");
print ($$ssh_session);

#cutting line with related WLAN information:

($matching) = $ssh_session=~ /([^n]*XYZ+)/is;
print ("n$matching");

my $XYZ_wlan_id;
$matching =~ m/(d+)/g;
if ($matching ne "") {

#print ("n matching parameter= $matchingn");
$XYZ_wlan_id=$1;

}
else {
$XYZ_wlan_id=0;
}

print ("nn print XYZ id= $XYZ_wlan_id n");

#---------acc radius part----------#

$ssh_session =$ssh->exec("show radius summary");
print ($$ssh_session);
($matching) = $ssh_session=~ /([^n]*10.20.30.40+)/is;
print ("n$matching");
$matching =~ m/(d+)/g;
my $rad_id100;
if ($matching ne "") {
$rad_id100=$1;
}
else {
$rad_id100=0
}
print ("nn radius accounting id= $rad_id100 n");

#---apply related commands for changes---#
print("n disabling mentioned WLAN ABC");
print ($ssh->exec("config wlan disable $ABC_wlan_idn"));

print("n disabling mentioned WLAN KLM ");
print ($ssh->exec("config wlan disable $KLM _wlan_idn"));

print("n disabling mentioned WLAN XYZ ");
print ($ssh->exec("config wlan disable $XYZ _wlan_idn"));

print("n deleting acc radius server under ABC, SSID ID= $ABC_wlan_idn");
print ($ssh->exec("config wlan radius_server acct delete $ABC_wlan_id all"));
print("n deleting acc radius server under KLM, SSID ID= $KLM_wlan_idn");
print ($ssh->exec("config wlan radius_server acct delete $KLM_wlan_id all"));
print("n deleting acc radius server under XYZ, SSID ID= $XYZ_wlan_idn");
print ($ssh->exec("config wlan radius_server acct delete $XYZ_wlan_id all"));
print ("n radius acc ID is $rad_id100 n");
print("n deleting acc radius server under radius settings on WLC n");
print ($ssh->exec("config radius acc delete $rad_id100"));

# create radius acc server and enable WLANs

print("n adding acc radius server (with id=17) under radius settings on WLC n");
print ($ssh->exec("config radius acct add 17 10.20.30.40 1813 ascii acc_shared_secret"));
print ($ssh->exec("config radius acct network 17 enable"));
print ($ssh->exec("config radius acct disable 17"));
print ($ssh->exec("config radius acct retransmit-timeout 17 5"));
print ($ssh->exec("config radius acct enable 17"));

print("n adding acc radius server under ABC, SSID ID= $ABC_wlan_id n");
print ($ssh->exec("config wlan radius_server acct add $ABC_wlan_id 17"));
print ($ssh->exec("config wlan enable $ABC_wlan_id"));

print("n adding acc radius server under KLM, SSID ID= $KLM_wlan_id n");
print ($ssh->exec("config wlan radius_server acct add $KLM_wlan_id 17"));
print ($ssh->exec("config wlan enable $KLM_wlan_id"));

print("n adding acc radius server under XYZ, SSID ID= $XYZ_wlan_id n");
print ($ssh->exec("config wlan radius_server acct add $XYZ_wlan_id 17"));
print ($ssh->exec("config wlan enable $XYZ_wlan_id"));
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' $!";
}

network components, network design, wireless topics

Connection of Cisco WLC and Aruba switch

It is a fact that Cisco WLCs per their design supports only LAG type or protocol which has no negotiation (in this aspect LAG considered as non-LACP and non-PaGP etherchannel technique, in some documentation though LAG (link aggregation groups) may be considered as a general term for all types of protocols to build etherchannel ). LAG on Cisco switches can be recognized by null in the “protocol” field, as shown below:

etherchannel Pic.1 – Po1,Po2 – LAG etherchannels

In Lab environment following hardware was used and connected:

etherchannel for cisco WLC

Pic.2 – Lab topology to test LAG support by Aruba switch

Configuration on Cisco WLCs (enabled LAG) and on Aruba core2  L3 switch are shown below:

LAG_WLC

Pic3 – LAG settings on WLC1

LACP_Aruba

Pic4 – LACP configuration and verification on Aruba core2  L3 switch

Ping and SSH from core1 to WLC via such etherchannel were successful. Per such example, Aruba automatically negotiates LACP or LAG based on what is configured on the other end.

wireless topics

licenses for WLC 5508 in HA SSO

  1. On cisco documentations there is no clear statement (at least I did not find it) about license requirements for WLC 5508 to convert into HA SSO. Per design it is needed at least 50 access point licenses on a WLC, which should be used as standby (by default WLCs are in primary mode), otherwise with attempt to set it as a standby it will suggest to check amount of AP licenses and not allow to set itself on standby mode. For WLC, which will work as primary, there are no license requirements  (per my understanding it should have at least one access point license). When these requirement met HA SSO can be established on 5508 WLCs.

Second case is when secondary WLC is HA-SKU. In this case WLC has no licenses and it can be recognized by absence of possibility to install any license (option “Management->Software activation ->Commands” is absent on HA-SKU) .

2. There might be a case when secondary WLC has more than 50 licenses, which can be re-hosted to primary. To do this it is needed to request Cisco TAC to generate related license file “*.lic” based on information with serial numbers of primary and standby WLCs, on which you are re-hosting licenses. Afterwards, it is needed to import *.lic file dedicated for primary WLC into it (standby WLC does not have any commands to operate with licenses and even if you reboot primary WLC, it will not allow any action, see picture below).

HA_SSO_Licenses

Uncategorized, wireless topics

Evaluate amount of user sessions from remote controllers on anchor

if someone has deployed Cisco guest anchor wireless controller, which by design can support up to 71 remote controllers, it is useful to evaluate from which remote controller how much user sessions come. To achieve this it is necessary to  get initial data from anchor controller via command “show client wlan 1” (lets assume you evaluating users on WLAN id #1):

(Cisco Controller) >show client wlan 1

Number of Clients in WLAN…………………… 1970

MAC Address                  AP Name             Status    Auth Protocol Port Wired Mobility Role Device Type
—————–                     —————–          ————-     —-    —————- —- —– —————————-

00:08:22:a6:87:34  10.10.1.12       Associated Yes Mobile 13   No Export Anchor Android
00:6d:52:01:60:41  10.1.20.25       Associated Yes Mobile 13 No Export Anchor Unclassified
00:6d:52:05:31:1c   10.11.17.10   Associated Yes Mobile 13 No Export Anchor Unclassified
00:6d:52:eb:48:08   10.20.96.22    Associated Yes Mobile 13 No Export Anchor Unclassified
00:ae:fa:52:59:e3    10.30.0.22       Associated Yes Mobile 13 No Export Anchor Unclassified
00:b3:62:10:80:69   10.44.0.24     Associated Yes Mobile 13 No Export Anchor Unclassified

If you have hundreds and thousands of such connections, it is more convenient to use   following command on the first step, which saves your time pressing all  the time confirmation button for the next page of data:

(Cisco Controller) >config paging disable

After data about user connections has been gathered in a file (e.g. /tmp/result.txt),  following command can be applied:

cat /tmp/result.txt | awk ‘{ print $2 }’ | sort | uniq -c | sort -rn

which will offer you following result:

840 10.22.30.11
652 10.1.20.25
546 10.46.40.20
517 10.34.55.78
489 10.45.100.11
488 10.16.200.233
etc.

This gives youa sorted list by amount of user connections (I would call it importance weight), which is a first column of the result, and IP address of respective remote wireless controller.

 

 

Uncategorized, wireless topics

how to quickly update peer settings on guest anchor WLC

Lets imagine someone has a Cisco anchor for “guest wifi” with configured wrong(outdated) peers and there is a task to remove them all with minimum effort.

For that it is needed to

1)establish SSH to such anchor

2) issue command to get the list of all configured peers “show mobility summary”

(Cisco Controller) >show mobility summary

Mobility Protocol Port……………………… 16666
Default Mobility Domain…………………….. GUEST
Multicast Mode ……………………………. Disabled
Mobility Domain ID for 802.11r………………. 0x78e3
Mobility Keepalive Interval…………………. 10
Mobility Keepalive Count……………………. 3
Mobility Group Members Configured……………. 72
Mobility Control Message DSCP Value………….. 0

Controllers configured in the Mobility Group
MAC Address          IP Address        Group Name          Multicast               IP Status
00:06:f6:62:51:a0   10.20.30.5          guest1                    0.0.0.0     Control and Data Path Down
00:07:7d:c0:52:e0  192.168.20.80    guest2                   0.0.0.0      Control and Data Path Down
00:42:5a:55:53:40  192.168.30.77    guest3                    0.0.0.0     Control and Data Path Down

etc. 72 peers

3) output which was received on step 2),  save into a file (for example: /tmp/peers.txt) on Linux and use good old awk command to extract first column from the output:

awk ‘{print $1}’ /tmp/peers.txt

which will print only column with MAC addresses of peers.

4) prepend “config mobility group member delete” to each line with MAC address. To combine step 3) and step 4) into one step, issue following command:

awk ‘{print $1}’ /tmp/peers.txt | sed ‘s/^/config mobility group member delete /’

5) achieved result copy and paste into Cisco WLC’s command line, e.g.:

(Cisco Controller) >config mobility group member delete 00:06:f6:62:51:a0

(Cisco Controller) >config mobility group member delete 00:07:7d:c0:52:e0

(Cisco Controller) >config mobility group member delete 00:42:5a:55:53:40

etc… for 71 peers…