Using Notepad++ to Mirror Cisco ACLs

Having an occasional need to create mirrored access-list entries, I was seriously considering writing a PERL script to automate this process. Before I really got started on it, I stumbled on a pretty cool feature in Notepad++. This feature basically uses PERL style REGEX to do more sophisticated searches within a document. In addition to this feature, the replace function allows referencing back-referenced strings in the replace field. This article will look at these features in Notepad++ and demonstrate their use to mirror Cisco ACLs.

For those who are less than comfortable creating regular expressions, we will go through a step by step example of what this looks like. Additionally, we will see how to scope the replacement by selecting an area of text. Finally, we will see how we can streamline the execution of this task by using a macro. After seeing how these features can be utilized together to create a solution, you’re sure to have some time-saving ideas for your own organization.

Our goal for this exercise is to mirror two ACLs. We will start out with a named and a numbered ACL that will be mirrored. These ACLs will include things layer 4 ports and log options that create challenges for simple mirroring routines.

//named acl
ip access-list extended inbound
 permit icmp host 192.0.2.1 192.168.1.0 0.0.0.255 log
 permit udp host 192.0.2.2 host 192.168.1.244 eq 80
 permit tcp 192.0.2.0 0.0.0.255 range www 100 any log
 permit gre any host 192.168.2.2

//numbered acl
access-list 101 permit icmp host 192.0.2.1 192.168.1.0 0.0.0.255 log
access-list 101 permit udp host 192.0.2.2 host 192.168.1.244 eq 80
access-list 101 permit tcp 192.0.2.0 0.0.0.255 range www 100 any log
access-list 101 permit gre any host 192.168.2.2

//goal
//named acl
ip access-list extended outbound
 permit icmp 192.168.1.0 0.0.0.255 host 192.0.2.1 log
 permit udp host 192.168.1.244 eq 80 host 192.0.2.2
 permit tcp any 192.0.2.0 0.0.0.255 range ww 100 log
 permit gre host 192.168.2.2 any

//numbered acl 
access-list 102 permit icmp 192.168.1.0 0.0.0.255 host 192.0.2.1 log
access-list 102 permit udp host 192.168.1.244 eq 80 host 192.0.2.2
access-list 102 permit tcp any 192.0.2.0 0.0.0.255 range www 100 log
access-list 102 permit gre host 192.168.2.2 any

If you are thinking ahead, the first thing to notice in the Notepad++ Search and Replace Option is “Regular Expression”. Setting this option allows for searches using PERL style regular expressions. It also allows for matches inside parenthesis “()” to be treated as back-references. Therefore, the contents of the first set of parenthesis will be saved in $1. The second set will be saved in $2, and so on. These variables can be used in the replace field to manipulate the output. To expand this into a step-by-step approach, the first thing we should look at is an expression that matches access lists and breaks them into their discrete components.

Regular Express for ACLs

(permit|deny)(\s+[0-9a-zA-Z_-]+)(\s+any|\s+host\s+\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}|\s+\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\s+\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})(\s+eq\s+[0-9a-zA-z_-]+|\s+neq\s+[0-9a-zA-z_-]+|\s+gt\s+[0-9a-zA-z_-]+|\s+lt\s+[0-9a-zA-z_-]+|\s+range\s+[0-9a-zA-z_-]+\s+[0-9a-zA-z_-]+)?(\s+any|\s+host\s+\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}|\s+\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\s+\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})(\s+eq\s+[0-9a-zA-z_-]+|\s+neq\s+[0-9a-zA-z_-]+|\s+gt\s+[0-9a-zA-z_-]+|\s+lt\s+[0-9a-zA-z_-]+|\s+range\s+[0-9a-zA-z_-]+\s+[0-9a-zA-z_-]+)?(.?)

Updated Expression Also Works For Nexus

(permit|deny)(\s+[0-9a-zA-Z_-]+)(\s+any|\s+host\s+\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}|\s+\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\/\d{1,2}|\s\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\s\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})(\s+eq\s+[0-9a-zA-z_-]+|\s+neq\s+[0-9a-zA-z_-]+|\s+gt\s+[0-9a-zA-z_-]+|\s+lt\s+[0-9a-zA-z_-]+|\s+range\s+[0-9a-zA-z_-]+\s+[0-9a-zA-z_-]+)?(\s+any|\s+host\s+\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}|\s+\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\/\d{1,2}|\s\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\s\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})(\s+eq\s+[0-9a-zA-z_-]+|\s+neq\s+[0-9a-zA-z_-]+|\s+gt\s+[0-9a-zA-z_-]+|\s+lt\s+[0-9a-zA-z_-]+|\s+range\s+[0-9a-zA-z_-]+\s+[0-9a-zA-z_-]+)?(.?)

If you are following along, it is probably a good idea to copy this entire string into the text editor of your choice.

Components of the Expression

Now if you’re like me, that expression just way too complicated. For now, we need to understand that the parenthesis are used to group things and store the values. Additionally, they break the expression into more digestible sections that relate to different parts of an ACL. Let’s start by looking at the components of an ACL. Then we will follow up by demonstrating a REGEX example that will match each of these components.

ACL Components

  • Verb(stored in $1)–permit or deny
  • Protocol(stored in $2)–ip, tcp, udp, etc, or a number between 1 and 255
  • Source IP(stored in $3)–host x.x.x.x, x.x.x.x y.y.y.y, any
  • Source Port[optional](stored in $4)–eq num or name, neq num or name, lt num or name, gt num or name, range
  • Destination IP(stored in $5)–host x.x.x.x, x.x.x.x y.y.y.y, any
  • Destination Port[optional](stored in $6)–eq num or name, neq num or name, lt num or name, gt num or name, range
  • Everything Else to the end of the line(stored in $7)–established, log, echo-reply, etc

Matching the ACL

Looking at each component individually, we first only want to mirror lines that have permit or deny. We will start matching there. Remarks should not be changed and there is no reason to be concerned with anything prior to these keywords. This part of the expression is self explanatory.

(permit|deny)

Next we expect a space followed by an IP protocol number, or a protocol name.

(\s+[0-9a-zA-Z_-]+)

Then we should see a space followed by a source address. This will be represented as host x.x.x.x, x.x.x.x y.y.y.y, or any.

(\s+any|\s+host\s+\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}|\s+\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\s+\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})

Following the source, we may optionally see another space followed by source port information. This could start as eq, neq, lt, gt, or range and conclude with a protocol name or number. The trailing “?” is to indicate it can appear 0 or 1 time.

(\s+eq\s+[0-9a-zA-z_-]+|\s+neq\s+[0-9a-zA-z_-]+|\s+gt\s+[0-9a-zA-z_-]+|\s+lt\s+[0-9a-zA-z_-]+|\s+range\s+[0-9a-zA-z_-]+\s+[0-9a-zA-z_-]+)?

Next we should see a space followed by a destination address. Like the source address, this will be represented as host x.x.x.x, x.x.x.x y.y.y.y, or any.

(\s+any|\s+host\s+\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}|\s+\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\s+\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})

Following the destination, we may optionally see another space followed by a destination port. Again like the source port, this could be eq, neq, lt, gt, or range and the protocol or port information. The trailing “?” is to indicate it can appear 0 or 1 time.

(\s+eq\s+[0-9a-zA-z_-]+|\s+neq\s+[0-9a-zA-z_-]+|\s+gt\s+[0-9a-zA-z_-]+|\s+lt\s+[0-9a-zA-z_-]+|\s+range\s+[0-9a-zA-z_-]+\s+[0-9a-zA-z_-]+)?

The final thing we need to capture is everything else on the end of the line. This will be things like log, established, etc.

(.?)

The completed expression that we will apply against our ACL to mirror entries is as follows (on one line–same as shown above).

(permit|deny)(\s+[0-9a-zA-Z_-]+)(\s+any|\s+host\s+\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}|\s+\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\s+\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})(\s+eq\s+[0-9a-zA-z_-]+|\s+neq\s+[0-9a-zA-z_-]+|\s+gt\s+[0-9a-zA-z_-]+|\s+lt\s+[0-9a-zA-z_-]+|\s+range\s+[0-9a-zA-z_-]+\s+[0-9a-zA-z_-]+)?(\s+any|\s+host\s+\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}|\s+\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\s+\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})(\s+eq\s+[0-9a-zA-z_-]+|\s+neq\s+[0-9a-zA-z_-]+|\s+gt\s+[0-9a-zA-z_-]+|\s+lt\s+[0-9a-zA-z_-]+|\s+range\s+[0-9a-zA-z_-]+\s+[0-9a-zA-z_-]+)?(.?)

Now all that is necessary is to replace everything that is matched by reversing the source IP and source ports with the destination IP and destination ports. To accomplish this, we use the following parameter in the replace field. If you are following along, it may also be beneficial to copy this string into a text editor of your choice.

$1$2$5$6$3$4$7

Manually Using REGEX for Find and Replace

To demonstrate manually executing this in Notepad++, we can use the Replace option. We will start with our “inbound” acl’s (shown below).

//named acl
ip access-list extended inbound
 permit icmp host 192.0.2.1 192.168.1.0 0.0.0.255 log
 permit udp host 192.0.2.2 host 192.168.1.244 eq 80
 permit tcp 192.0.2.0 0.0.0.255 range www 100 any log
 permit gre any host 192.168.2.2

//numbered acl
access-list 101 permit icmp host 192.0.2.1 192.168.1.0 0.0.0.255 log
access-list 101 permit udp host 192.0.2.2 host 192.168.1.244 eq 80
access-list 101 permit tcp 192.0.2.0 0.0.0.255 range www 100 any log
access-list 101 permit gre any host 192.168.2.2

I’ll leave it to you to figure out how you want to name and rename these ACLs. For the purposes of this exercise, I’ll part manually renamed inbound to outbound and 101 to 102. The ACLs below are yet to be mirrored, but have been renamed.

//named acl
ip access-list extended outbound
 permit icmp host 192.0.2.1 192.168.1.0 0.0.0.255 log
 permit udp host 192.0.2.2 host 192.168.1.244 eq 80
 permit tcp 192.0.2.0 0.0.0.255 range www 100 any log
 permit gre any host 192.168.2.2

//numbered acl
access-list 102 permit icmp host 192.0.2.1 192.168.1.0 0.0.0.255 log
access-list 102 permit udp host 192.0.2.2 host 192.168.1.244 eq 80
access-list 102 permit tcp 192.0.2.0 0.0.0.255 range www 100 any log
access-list 102 permit gre any host 192.168.2.2

Mirroring the ACL’s with Notepad++

Prior to doing a find/replace, it is important to know where your cursor is. I like to make sure my cursor is at the beginning of the document, so processing “down” looks through the entire document. We’ll see how to evaluate “selected” text in a moment.

NPP Img 1

  1. The first step is to click the “Search” button.
  2. In the search dialog box, choose the “Replace” tab.
  3. Enter the regular expression above into the “find” field.
  4. In the replace field, enter “$1$2$5$6$3$4$7” without the quotes.
  5. For Search Mode, select “regular expression”
  6. Click “Replace All”

Replace Box

After following these steps, the ACL’s should be mirrored from above and the output should look like the output below.

//named acl
ip access-list extended outbound
 permit icmp 192.168.1.0 0.0.0.255 host 192.0.2.1 log
 permit udp host 192.168.1.244 eq 80 host 192.0.2.2
 permit tcp any 192.0.2.0 0.0.0.255 range www 100 log
 permit gre host 192.168.2.2 any

//numbered acl
access-list 102 permit icmp 192.168.1.0 0.0.0.255 host 192.0.2.1 log
access-list 102 permit udp host 192.168.1.244 eq 80 host 192.0.2.2
access-list 102 permit tcp any 192.0.2.0 0.0.0.255 range www 100 log
access-list 102 permit gre host 192.168.2.2 any

Streamlining With a Macro

While that is a pretty cool trick, it is still a bit clunky. I like to streamline this type of task by using the macro feature. Additionally, Notepad++ has the option to only evaluate selected text. To create a macro from this process, do the following.

  1. Create a document with an ACL to be mirrored
  2. Highlight to select an area of text
  3. Click “Macro” then “Start Recording”
  4. Click the “Search” button
  5. Choose the “Replace” tab
  6. Insert the Regular Expression into the “Find” field
  7. Insert “$1$2$5$6$3$4$7” into the “Replace” field
  8. Choose “Regular Expression” for Search Mode
  9. Select “In Selection” to limit the scope to the selected text
  10. Click “Replace All”
  11. Close the Search Dialog Box
  12. End the Macro Recording by Choosing “Macro” then “Stop Recording”
  13. Save the Macro to a meaningful name, like “Mirror ACL”, by selecting “Macro” then “Save Current Recorded Macro”

Now you can highlight an area of text, choose “Macro” then “Mirror ACL”. Notepad++ will go through the ACL and reverse the source and destination addresses and ports. It is even possible to create a keyboard shortcut to execute the macro.

Conclusion

Notepad++ is a full featured text editor that has some very powerful features. This article used a combination of several features to pull off a pretty cool task–creating mirrored ACL entries. The specific features utilized were REGEX match with back reference, replacement scoped to selected text and macros. These features can be combined in many different ways to address real world operational challenges. Automating these types of repetitious tasks will lead to more accurate configurations and fewer unexpected outages.

Do you use Notepad++? What are some of your favorite features. Share your use cases with the PacketU community below.

Disclaimer: If you use this technique on production ACLs, it is important to confirm the output. While care has been taken to confirm function in various scenarios, it is possible that your mileage may vary. PacketU cannot be responsible for issue caused by using these techniques.

About Paul Stewart, CCIE 26009 (Security)

Paul is a Network and Security Engineer, Trainer and Blogger who enjoys understanding how things really work. With over 15 years of experience in the technology industry, Paul has helped many organizations build, maintain and secure their networks and systems.
This entry was posted in How-To. Bookmark the permalink.

6 Responses to Using Notepad++ to Mirror Cisco ACLs

  1. Superb post Paul. Really useful. I will give it a go and report back.

    I use Notepad++ at work and I find the Compare plugin is great when needed to look at modifications or differences.

  2. Travis Newshott says:

    Notepad++ is a must-have tool for any engineer – the regex functionality is a daily use for me. I also use it to do all of my scripting in as well because of it’s rich, seamless syntax highlighting.

  3. Pingback: Mirroring Nexus ACLs In Notepad++ - PacketU

  4. mohammed says:

    thanks for the tutrioal , i would share with you same video can help you : https://www.youtube.com/playlist?list=PL0888jE2gIN0EY6Bs8_O1WdWSkfvQy8gG

Comments are closed.