PowerShell – Block IP Addresses On Cisco Firewall

0
22

Plink, Cisco and PowerShell walk into a bar…wait…I just did that gag.

Here is simple script of How to execute command on the Cisco Devices by Powershell script.

I’ve been banging my head against this one for many days. PowerShell automation of Cisco switches through SSH. Easy, right? Not so much. A lot of command line based SSH clients are very old and don’t have a scripting language like PowerShell in mind. More modern ones, or SSH cmdlets made for PowerShell, are expensive for commercial use and I prefer to avoid them when possible. With no native SSH in PowerShell or .NET I needed a good, working solution.

I tried a couple of .NET DLLs, but none of them worked consistently so I tried Plink, the command-line version of the tried and true PuTTy SSH client. While it works well for most SSH connections there is a well-documented issue with Cisco IOS. Well documented online at least. To sum up the issue, when you use -batch to feed Plink.exe a batch file against Cisco IOS it doesn’t work. You usually get an “invalid autocommand” error or something like “only only command per line” if you try to be sneaky and fit it all on one line.

It turns out there is a workaround for this by using StdIn (<) to input the text line by line.  Just one problem. PowerShell doesn’t support StdIn redirection.

This is where it gets messy. In order for Plink.exe to work with Cisco IOS in a PowerShell script you have to call CMD.exe from PowerShell to do a redirect input to Plink.exe, then use a StdOut (>) to redirect the output to a text file that PowerShell can read to validate the success or failure of the command. My head hurts just writing that.

######################################################################################################################################
 ##
 ##   Script Name : FIREWALL_BLOCK_IPADDRESS.ps1
 ##   Author       : Ravinder Jaiswal
 ##   Purpose     : Script will block the IPAddresses mentioned in the IPADRESSES.txt on all the Firewalls mentioned in the DEVICE_LIST.txt 
 ##   Pre-quisites: 1.plink.exe, 2.DEVICE_LIST.txt, 3.IPADDRESSES_LIST.txt files must exist in script folder.
 ##   Usage       : Before execution please changes the configuration area as per the requirement and schedule the script.
 ##                 1. Add the Devices (Switch,Firewall) IP Addresses in the DEVICE_LIST.txt
 ##                 2. Add the IPAddresses or IPSubnet in the IPADDRESS_LIST.txt which needs to be blocked. E.g: 1.1.1.1 or 1.1.1.1/24
 ##                 3. Update the Device commands in the the arrary $SSHCMD in the script.
 ##   Output      : SCRIPTLOG_<DATE>.log will contains overall details.
 ##                 DEVICELOG_<IPADDRESS>_<DATE>.log --seperate log will be generated for each device. E.g:DEVICELOG_10.99.101.75_20190405.log
 ##
 ######################################################################################################################################
 
 $ErrorActionPreference = "SilentlyContinue"
 
 ############### CONFIGURATION AREA START ####################
 $DATE = get-date -uFormat "%Y%m%d"
 $SCRIPT:SW = ""
 $SCRIPT:SW = [Diagnostics.Stopwatch]::StartNew()
 #$SCRIPTPATH = split-path -parent $MyInvocation.MyCommand.Definition
 $SCRIPTPATH = "\\localhost\scripts\FIREWALL"
 $PLINKPATH = "$SCRIPTPATH\plink.exe"
 $SSHCMDFILE = "$SCRIPTPATH\SSHCMD.txt"
 $DEVICE_LIST_PATH = "$SCRIPTPATH\DEVICE_LIST.txt"
 $IPADDRESS_LIST_PATH = "$SCRIPTPATH\IPADDRESS_LIST.txt"
 $IPADDRESSLIMIT = 1000
 $LOGPATH = "$SCRIPTPATH\LOGS"
 $SCRIPTLOG = "$LOGPATH\SCRIPTLOG_$date.log"
 $TMPDEVICELOGNAME = "$LOGPATH\templog.log"
 $USERNAME = 'username'
 $PASSWORD = 'password123'
 ############### CONFIGURATION AREA END ####################
 
 function Get-IPrange
 {
     <#
       .SYNOPSIS
         Get the IP addresses in a range
       .EXAMPLE
        Get-IPrange -start 192.168.8.2 -end 192.168.8.20
        Get-IPrange -ip 192.168.8.2 -mask 255.255.255.0 
        Get-IPrange -ip 192.168.8.3 -cidr 24
     #>
     param
     (
       [string]$start,
       [string]$end,
       [string]$ip,
       [string]$mask,
       [int]$cidr
     )
     function function2 () {
       param ($ip)
       $octets = ""
       $octets = $ip.split(".")
       return [int64]([int64]$octets[0]*16777216 +[int64]$octets[1]*65536 +[int64]$octets[2]*256 +[int64]$octets[3])
     }
     function function1() {
       param ([int64]$int)
       return (([math]::truncate($int/16777216)).tostring()+"."+([math]::truncate(($int%16777216)/65536)).tostring()+"."+([math]::truncate(($int%65536)/256)).tostring()+"."+([math]::truncate($int%256)).tostring() )
     }
 
     if ($ip) {$ipaddr = [Net.IPAddress]::Parse($ip)}
     if ($cidr) {$maskaddr = [Net.IPAddress]::Parse((function1 -int ([convert]::ToInt64(("1"*$cidr+"0"*(32-$cidr)),2)))) }
     if ($mask) {$maskaddr = [Net.IPAddress]::Parse($mask)}
     if ($ip) {$networkaddr = new-object net.ipaddress ($maskaddr.address -band $ipaddr.address)}
     if ($ip) {$broadcastaddr = new-object net.ipaddress (([system.net.ipaddress]::parse("255.255.255.255").address -bxor $maskaddr.address -bor $networkaddr.address))}
    
     $startaddr = ""
     $endaddr = ""
     if ($ip) {
       $startaddr = function2 -ip $networkaddr.ipaddresstostring
       $endaddr = function2 -ip $broadcastaddr.ipaddresstostring
     } else {
       $startaddr = function2 -ip $start
       $endaddr = function2 -ip $end
     }
 
     for ($i = $startaddr; $i -le $endaddr; $i++) {
       function1 -int $i
     }
 }
 #####################VALIDATION START ########################
 if (!(Test-Path $LOGPATH)) {
   New-Item "$LOGPATH" -type directory
   Write-Output "$(Get-Date) - [ERROR] - LOG folder not found. Hence created inside $SCRIPTPATH folder." >> $SCRIPTLOG
   Write-Host "LOG folder not found. Hence created inside $SCRIPTPATH folder."
 }
 if (!(Test-Path $PLINKPATH)) {
   Write-Output "$(Get-Date) - [ERROR] -PLINK.EXE not found. Please verify if PLINK.EXE file exist inside $SCRIPTPATH folder." >> $SCRIPTLOG
   Write-Host "PLINK.EXE not found. Please check PLINK.EXE if file exist inside $SCRIPTPATH folder."
   EXIT
 }
 $DEVICE_LIST = Get-Content $DEVICE_LIST_PATH
 if(($DEVICE_LIST -eq "") -or ($DEVICE_LIST -eq $null)){
   Write-Output "$(Get-Date) - [ERROR] - No Devices found. Please verify if DEVICE_LIST.txt file exist inside $SCRIPTPATH folder. It should not be blank." >> $SCRIPTLOG
   Write-Host "No Devices found. Please verify if DEVICE_LIST.txt file exist inside $SCRIPTPATH folder. It should not be blank."
   EXIT
 }
 $IPADDRESS_LIST = Get-Content $IPADDRESS_LIST_PATH
 if(($IPADDRESS_LIST -eq "") -or ($IPADDRESS_LIST -eq $null)){
   Write-Output "$(Get-Date) - [ERROR] - No IP Address found. Please verify if IPADDRESS_LIST.txt file exist inside $SCRIPTPATH folder. It should not be blank." >> $SCRIPTLOG
   Write-Host "No IP Address found. Please verify if IPADDRESS_LIST.txt file exist inside $SCRIPTPATH folder. It should not be blank."
   EXIT
 }
 if($IPADDRESS_LIST.Count -gt $IPADDRESSLIMIT){
     Write-Output "$(Get-Date) - [ERROR] - Total number of IP Address to be blocked on Devices is exceeding the Limit $UserLimit." >> $SCRIPTLOG
     Write-Host "Total number of IP Address to be blocked on Devices is exceeding the Limit $UserLimit."
     EXIT
 }
 
 $IPADDRESS_LIST2 = ""
 $IPADDRESS_LIST2 = $IPADDRESS_LIST | Where-Object { $_ -notlike "10.*" -and $_ -notlike "*/*"}
 $IPSUBNET_LIST = ""
 $IPSUBNET_LIST = $IPADDRESS_LIST | Where-Object { $_ -like "*/*"}
 $IPSUBNET = ""
 Foreach($IPSUBNET in $IPSUBNET_LIST){
     $IPSUBNET = $IPSUBNET.Split('/')
     $IPSUBNET = Get-IPrange -ip $IPSUBNET[0]  -cidr $IPSUBNET[1]
     $IPADDRESS_LIST2 += $IPSUBNET
 }
 if(($IPADDRESS_LIST2 -eq "") -or ($IPADDRESS_LIST2 -eq $null)){
   Write-Output "$(Get-Date) - [ERROR] - No processable IP Address found. Please verfiy IP Addresses mentioned in $IPADDRESS_LIST_PATH file." >> $SCRIPTLOG
   Write-Host "No processable IP Address found. Please verfiy IP Addresses mentioned in $IPADDRESS_LIST_PATH file."
   EXIT
 }
 ######################### VALIDATION END ########################
 
 ######################## MAIN START ##############################
 foreach($DEVICE in $DEVICE_LIST) {
     $SCRIPT:SWD = ""
     $SCRIPT:SWD = [Diagnostics.Stopwatch]::StartNew()
     $DEVICELOG = ""
     $DEVICELOG = "$LOGPATH\DEVICELOG_$DEVICE_$date.log"
     Write-Output "****************************************************************************************" >> $DEVICELOG
     Write-Output "                       $DEVICE - FIREWALL BLOCKED IP ADDRESSES LOGS"                      >> $DEVICELOG
     Write-Output "****************************************************************************************" >> $DEVICELOG
     Write-Output "--------------------------------------------------------------------------------------------------" >> $SCRIPTLOG
     Write-Output "$(Get-Date) - [INFO] - Script Execution Started for Device $DEVICE" >> $SCRIPTLOG
     Write-Output "----------------------------------------------------------------------------------------" >> $DEVICELOG
     Write-Output "Script Execution Start Time : $(get-date)" >> $DEVICELOG
     Write-Output "----------------------------------------------------------------------------------------" >> $DEVICELOG
     write-host *********************************************************
     write-host "Working on the DEVICE:$DEVICE"                          
     write-host *********************************************************
     foreach($IPADDRESS2 in $IPADDRESS_LIST2) {
         $SSHCMD = ""
         $SSHCMD = @"
 en
 config t
 object-group network blocked_network
 network-object host $IPADDRESS2
 exit
 exit
 exit
 "@
         if (Test-Path $SSHCMDFILE) {
             Remove-Item $SSHCMDFILE
         }
         $SSHCMD | out-file $SSHCMDFILE
         #Converts the file to ASCII format (separate file)#
         $LINES = ""
         $LINES = Get-Content $SSHCMDFILE
         $LINES | out-file -encoding Ascii $SSHCMDFILE
         $INSTALL_CMD = "cmd.exe"
         $INSTALL_ARGS = ""
         #$INSTALL_ARGS = "/c `" `"$PLINKPATH`" -ssh -2 -l $username -pw $password $DEVICE -batch < `"$SSHCMDFILE`" >> `"$SCRIPTPATH\$DEVICE`_$date`.txt`" `"" 
         $INSTALL_ARGS = "/c `" `"$PLINKPATH`" -ssh -2 -l $username -pw $password $DEVICE -batch < `"$SSHCMDFILE`" > `"$TMPDEVICELOGNAME`" `"" 
         #Run command and wait for exit
         $PLINKCMD = "" 
         $PLINKCMD = [System.Diagnostics.Process]::Start("$INSTALL_CMD","$INSTALL_ARGS") 
         $PLINKCMD.WaitForExit()
         $OUTPUT = ""
         $OUTPUT = get-content $TMPDEVICELOGNAME
         Write-Output  $OUTPUT >> $DEVICELOG
         Write-Output "----------------------------------------------------------------------------------------" >> $DEVICELOG
         #Start-Sleep -s 3
     }
     $SCRIPT:SWD.Stop()
     $etd = [string]::Format("{0:0.##}", $SCRIPT:SWD.Elapsed.TotalMilliseconds/1000/60)
     Write-Output "$(Get-Date) - [INFO] - Script Execution Ended for Device $DEVICE" >> $SCRIPTLOG
     Write-Output "$(Get-Date) - [INFO] - Script Execution Time is $etd minutes for Device $DEVICE." >> $SCRIPTLOG
     Write-Output "Script Execution End Time : $(get-date)." >> $DEVICELOG
     Write-Output "Script Execution Time is $etd minutes." >> $DEVICELOG
     Write-Output  "----------------------------------------------------------------------------------------`r`n`r`n" >> $DEVICELOG
 }
 $SCRIPT:SW.Stop()
 $et = [string]::Format("{0:0.##}", $SCRIPT:SW.Elapsed.TotalMilliseconds/1000/60)
 Write-Output "--------------------------------------------------------------------------------------------------" >> $SCRIPTLOG
 Write-Output "$(Get-Date) - [INFO] - Total Script Execution Time is $et minutes." >> $SCRIPTLOG
 Write-Output "--------------------------------------------------------------------------------------------------`r`n`r`n" >> $SCRIPTLOG
 EXIT
 ############################ MAIN END ############################

 

 

SHARE
Previous articlePowerShell – Delete a Folder or File from the Command Line
mm
Hi, I’m Ravinder Jaiswal. I’m the person behind this website. Thank you for visiting the website! My website is all about Microsoft, VMware, Red Hat, Citrix and other technologies. I have 14+ years of IT experience. I am AZURE, MCSA 2016, MCSE 2016, RHCSA 7, RHCE 7, VCP-DCV 6.5, VCP-DTM 6.1, ITILv3 certified.