Skip to content
Homepage » Blog » Automating SSH Connection Checks for Thousands of Access Points: A Scripting Solution

Automating SSH Connection Checks for Thousands of Access Points: A Scripting Solution

In this article, I will explore a quick and efficient way to check whether wireless access points (APs) at a given location have SSH (Secure Shell) enabled and readily accessible. To address this challenge, I will introduce a Python script that can examine over 1000 APs within minutes and record the results in a file. The motivation behind developing such a script stems from practical experiences, particularly during network migrations and the establishment of new locations where APs are centrally managed by pair of wireless controllers. The lack of SSH access to APs can pose significant challenges when remote troubleshooting is necessary, making it essential to verify accessibility well in advance.

Before I dive into translating the script components, let’s begin with the required script modules:

This script will operate on a wireless network controller and access points from Cisco, running on the IOSXE software platform. It has been tested on software version 17.9.x, but it is unlikely to encounter issues on older software versions. If any problems do arise on older versions, please inform me in the comments section to keep everyone informed.

When all the files are downloaded and placed in a single directory along with the integrated development environment (IDE) ready, we can begin. Let’s shed light on how it works.

I’ll begin with a description of the imported libraries. Some are standard libraries, while two modules have been written by me to enhance code functionality and improve code readability. These modules are named connecthandlerc9800 and parsedtextfsmc9800. You can find a description of these modules in the following post: Cisco WLC 9800 Python Script: devices with the APIPA address

import connecthandlerc9800 as chc9800
from parsedtextfsmc9800 import parsedtextfsm
import socket
import datetime
import json

The only novelty introduced with this script is the function available in the connecthandlerc9800 module called test_tcp_connection().

"""Checking the TCP connection to the host."""
def test_tcp_connection(host,port=22,timeout=3):
    try:
        with socket.create_connection((host,port),timeout):
            return True
    except:
        return False

The function attempts to create a socket connection to the provided host and port with the specified timeout. If the connection is successful, it returns True, indicating that the TCP connection is established. If the connection cannot be established or times out, it returns False, indicating that the TCP connection failed. This code is helpful for testing network connectivity to a remote host on a specific port.

Now that we know what is being imported, it’s time to describe the available functions in the main script code.

""" Defining the list of access points to be checked"""
def ap_list(wlc,command,template):
    wlc_command_output = chc9800.connecthandlerc9800(wlc,command)
    parsed_wlc_command_output = parsedtextfsm(template,wlc_command_output)
    ap_list = list(map(lambda d: {k: d[k] for k in ['AP_Name', 'IP_Address'] if k in d}, parsed_wlc_command_output))
    return ap_list

This code defines a Python function named ap_list. It is used to retrieve a list of access points (APs) from the Wireless Controller to be checked based on specific parameters.

""" Analyzing the progress of the script's operation """
def progress_percentage(current_ap,all_aps):
    global start_percentage, start_time
    percentage = int(round(current_ap / all_aps, 1) * 100)
    if percentage > start_percentage:
        start_percentage = percentage
        current_time = datetime.datetime.now()
        elapsed_time = current_time - start_time
        formatted_time = format_duration(elapsed_time)
        print(f"Processed {percentage}% of APs. Time passed: {formatted_time}")

This code is used to track and display the progress of a script that processes a list of access points by calculating the percentage completed and providing time-based updates.

Now it’s time to bring everything together and utilize it for its intended purpose, which is to verify the ability to establish an SSH connection to the access points.

"""" Data for connecting to the controller. """

wlc = {
    'host': input("Provide the WLC IP address: "),
    'device_type': 'cisco_ios',
    'username': input("Enter WLC username: "),
    'password': input("Enter WLC password: "),
    'port': 22,
    'secret': input("Enter WLC secret password: "),
}

ap_summary_command = 'show ap summary'
ap_summary_template = 'wlc_c9800_show_ap_summary'

""" List of APs that will be checked for the possibility of establishing an SSH connection. """
ap_list = ap_list(wlc,ap_summary_command,ap_summary_template)


The provided code is used to set up parameters and retrieve a list of access points (APs) from a Wireless LAN Controller (WLC). It collects user input for connecting to the WLC, defines a command to retrieve AP summaries, specifies a template for parsing the command’s output, and then creates a list of APs using these settings. The expected outcome is to have a list of APs that can be used for further analysis or operations within a script or program.

ap_no_access = []
start_percentage, start_time = 0, datetime.datetime.now()
current_ap = 0

"""Filter APs to which you cannot connect via SSH."""
for ap in ap_list:
    current_ap += 1
    progress_percentage(current_ap, len(ap_list))
    is_alive = chc9800.test_tcp_connection(ap['IP_Address'])
    if not is_alive:
        ap_no_access.append(ap)

The provided code is used to filter a list of access points (APs) and identify those to which an SSH connection cannot be established. It maintains a list called ap_no_access to store APs that fail the SSH connection test. It also tracks and displays the progress of processing each AP.

""" Saving the results to a file. """

current_time = datetime.datetime.now()
timestamp = current_time.strftime("%d_%b_%Y_%H_%M_%S")
file_name = f'ap_no_access_date_{timestamp}'

with open(file_name, 'wt') as file:
    json.dump(ap_no_access, file, indent = 4)

end_time = datetime.datetime.now()

elapsed_time = end_time - start_time
formatted_time = format_duration(elapsed_time)

print("\nCode execution ended. Time passed: ", formatted_time, '\n')
print(f'File created and saved. Name: {file_name}')

The expected outcome is to have a JSON file containing the access points for which an SSH connection could not be established, along with a timestamp in the filename. Additionally, the code will print a message indicating the end of execution and the time it took to run the code, as well as the name of the created and saved JSON file.

Summary

By running this script, you can efficiently identify and document APs that are not accessible via SSH, aiding in network management and troubleshooting. The results are saved in a JSON file for future reference and analysis.

5 1 vote
Article Rating
Subscribe
Notify of
guest

0 Comment
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x