Firewall topology within a second – V2.0

Posted on September 16, 2013

5



There are time consuming jobs like creating a topology about the network of big companies, if they have an issue or some problem or it should be just dokumented as our ISO27001 Standard expects and it must be always up-to-date…
I created a script that uses perl to build from the cisco asa firewall running configuration a dot file and from the dot file it generates with graphviz a topology in png and svg format. The png is a readonly format, the svg can be changed with Microsoft Visio or with dia.
The perl script required a graphviz installed on the system where it runs!

This script V2.0 uses the interface settings, the static routes and the vpn crypto configs like crypto maps and acls (Lan-to-Lan crypto maps and dynamic crypto maps are supported). The Nat tables can be important for the topology to (and the dynamic routes too.), they are coming later. First I should learn Perl and Objet oriented programing better, this code os really ugly and just a one big script…

Here is the script. Since I cannot upload perl script (because they are suspicious or what…) I have to hide it within a png picture.
asa-graphviz-builder_with_tables_newIf you cannot figure out, how to get the perl sript from the png file just write me. :-) at least I will see if somebody needs the script…

Update (30.01.2014):
The code can be reached here:
http://code.google.com/p/network-topology-with-graphviz/source/browse/

Use the perl code with the name asa-graphviz-builder_with_tables.pl.

Here is an example how the script can be used:

1. The configuration is as follows:

hostname asa-voice
domain-name mycompany.com
name 172.6.16.0 dmz3
name 20.20.20.250 dmz3router
!
interface GigabitEthernet0/0
 channel-group 1 mode active
 no nameif
 no security-level
 no ip address
!
interface GigabitEthernet0/1
 channel-group 1 mode active
 no nameif
 no security-level
 no ip address
!
interface GigabitEthernet0/2
 channel-group 2 mode active
!
interface GigabitEthernet0/3
 channel-group 2 mode active
!
interface GigabitEthernet0/4
 shutdown
 no nameif
 no security-level
 no ip address
!
interface GigabitEthernet0/5
 shutdown
 no nameif
 no security-level
 no ip address
!
interface GigabitEthernet0/6
 channel-group 4 mode active
 no nameif
 no security-level
 no ip address
!
interface GigabitEthernet0/7
 channel-group 4 mode active
 no nameif
 no security-level
 no ip address
!
interface Management0/0
 nameif management
 security-level 100
 ip address 30.30.30.0 255.255.255.0
 management-only
!
interface Port-channel1
 no nameif
 no security-level
 no ip address
!
interface Port-channel1.1001
 description dmz1
 vlan 1001
 nameif dmz1
 security-level 0
 ip address 20.20.20.1 255.255.255.192 standby 20.20.20.2 
!
interface Port-channel2
 description LAN/STATE Failover Interface
!
interface Port-channel4
 no nameif
 no security-level
 no ip address
!
interface Port-channel4.721
 description inside
 vlan 721
 nameif inside
 security-level 100
 ip address 10.10.10.1 255.255.255.0 standby 10.10.10.1 
!
object network myproduct-test-nat
 host 10.1.4.5
object-group network fa-externalcompany-dev
 description externalcompany - Development and QA
 network-object 80.80.80.0 255.255.255.0
 network-object host 80.80.10.1
object-group network fa-externalcompany-preprod
 description externalcompany - Pre Production (Test)
 network-object 90.90.90.8 255.255.255.248
 network-object 90.70.10.0 255.255.255.0
object-group network fa-externalcompany-prod
 description externalcompany - Production (Live)
 network-object 100.100.90.8 255.255.255.248
 network-object 130.130.10.0 255.255.255.0
!
access-list tun-externalcompany remark #ID00032 Fa. externalcompany live
access-list tun-externalcompany extended permit ip object myproduct-test-nat object-group fa-externalcompany-prod time-range End-Dec-2035 
access-list tun-externalcompany-dev remark #ID00042 Fa. externalcompany test
access-list tun-externalcompany-dev extended permit ip object myproduct-test-nat object-group fa-externalcompany-dev time-range End-Dec-2035 
access-list tun-externalcompany-preprod remark #ID00042 Fa. externalcompany preprod
access-list tun-externalcompany-preprod extended permit ip object myproduct-test-nat object-group fa-externalcompany-preprod time-range End-Dec-2035 
!
route dmz1 dmz3 255.255.255.0 dmz3router 1
route dmz1 0.0.0.0 0.0.0.0 20.20.20.254 1
route inside 10.1.0.0 255.0.0.0 10.10.10.254 1
route inside 30.1.0.0 255.0.0.0 10.10.10.254 1
route inside 172.16.1.1 255.255.255.255 10.10.10.254 1
route inside 192.168.1.1 255.255.255.255 10.10.10.250 1
!
crypto ipsec ikev1 transform-set ESP-AES-256-SHA esp-aes-256 esp-sha-hmac
crypto ipsec df-bit clear-df dmz1
crypto dynamic-map extcompany2-dynmap 2 match address tun-externalcompany
crypto dynamic-map extcompany2-dynmap 2 set ikev1 transform-set ESP-AES-256-SHA
crypto dynamic-map extcompany2-dynmap 2 set security-association lifetime seconds 3600
crypto map companies 2 ipsec-isakmp dynamic extcompany2-dynmap
crypto map companies 4 match address tun-externalcompany-dev
crypto map companies 4 set pfs 
crypto map companies 4 set peer 6.6.6.6 
crypto map companies 4 set ikev1 transform-set ESP-AES-256-SHA
crypto map companies 4 set security-association lifetime seconds 3600
crypto map companies 6 match address tun-externalcompany-preprod
crypto map companies 6 set pfs 
crypto map companies 6 set peer 7.7.7.7 
crypto map companies 6 set ikev1 transform-set ESP-AES-256-SHA
crypto map companies 6 set security-association lifetime seconds 3600
crypto map companies interface dmz1
crypto isakmp identity address 
no crypto isakmp nat-traversal
crypto ikev1 enable www
crypto ikev1 policy 10
 authentication pre-share
 encryption aes-256
 hash sha
 group 2
 lifetime 86400
!
tunnel-group 6.6.6.6 type ipsec-l2l
tunnel-group 6.6.6.6 ipsec-attributes
 ikev1 pre-shared-key mysecret1
tunnel-group 7.7.7.7 type ipsec-l2l
tunnel-group 7.7.7.7 ipsec-attributes
 ikev1 pre-shared-key mysecret2
tunnel-group extcompany2 type ipsec-l2l
tunnel-group extcompany2 ipsec-attributes
 ikev1 pre-shared-key secret3

Here is the dot file generated:

#Saving output to cisco-asa-test.dot.dot
digraph G {
rankdir=LR

# 1.) Description: node for the firewall
# Syntax: firewall1 [shape=none, fontsize=11, label="firewall1", labelloc="b", image="firewall.gif"]

"asa-voice" [shape=none, fontsize=11, label="asa-voice", labelloc="b", image="firewall.gif"]

# 2.) Description: nodes for directly connected nets
# Syntax:
# Nets1 [shape=none, fontsize=11, label="10.1.1.0/24\ndomainname1", image="cloud.gif"]
# Netz12700132 [shape=none, fontsize=11, label="127.0.0.1/32\n", image="cloud.gif"]

Netz3030300 [shape=none, fontsize=11, label="30.30.30.0/24\n vlan no", image="cloud.gif"]
Netz2020201 [shape=none, fontsize=11, label="20.20.20.0/26\n vlan 1001", image="cloud.gif"]
Netz1010101 [shape=none, fontsize=11, label="10.10.10.0/24\n vlan 721", image="cloud.gif"]

# 3.) Description: nodes for static route nets
# Syntax: Rnetstorouter10101010 [shape=Mrecord, fontsize=11, label="10.1.1.0/24\n10.1.2.0/24", style=filled, fillcolor=red]
# Syntax: Rhoststorouter10101010 [shape=Mrecord, fontsize=11, label="10.1.1.1/32\n10.1.2.20/32", style=filled, fillcolor=red]

RNetstorouter202020250[shape=Mrecord, fontsize=11, label="Network routes|172.6.16.0/24|", style=filled, fillcolor=gold]
RNetstorouter202020254[shape=Mrecord, fontsize=11, label="Network routes|0.0.0.0/0|", style=filled, fillcolor=gold]
RNetstorouter101010254[shape=Mrecord, fontsize=11, label="Network routes|10.0.0.0/8|30.0.0.0/8|", style=filled, fillcolor=gold]
RHoststorouter101010254[shape=Mrecord, fontsize=11, label="Host routes|172.16.1.1/32|", style=filled, fillcolor=darkkhaki]
RHoststorouter101010250[shape=Mrecord, fontsize=11, label="Host routes|192.168.1.1/32|", style=filled, fillcolor=darkkhaki]

# 4.) Description: nodes for crypto acl destinations
# Syntax: RnetstoIPSecPeer1010101 [shape=Mrecord, fontsize=11, label="10.1.1.0/24\n10.1.2.0/24", style=filled, fillcolor=red]
# Syntax: RhoststoIPSecPeer1010101 [shape=Mrecord, fontsize=11, label="10.1.1.1/32\n10.1.2.20/32", style=filled, fillcolor=red]

RNetstoIPSecPeer254254254250[shape=Mrecord, fontsize=11, label="Networks|100.100.90.8/29|130.130.10.0/24|", style=filled, fillcolor=firebrick1]
RNetstoIPSecPeer6666[shape=Mrecord, fontsize=11, label="Networks|80.80.80.0/24|", style=filled, fillcolor=firebrick1]
RHoststoIPSecPeer6666[shape=Mrecord, fontsize=11, label="Hosts|80.80.10.1/32|", style=filled, fillcolor=firebrick3]
RNetstoIPSecPeer7777[shape=Mrecord, fontsize=11, label="Networks|90.90.90.8/29|90.70.10.0/24|", style=filled, fillcolor=firebrick1]

# 5.) Description: nodes for next hops
# Syntax: Router1010102 [shape=none, fontsize=11, label="", image="router.gif"]

Router202020250 [shape=none, fontsize=11, label="20.20.20.250", labelloc="b", image="router.gif"]
Router202020254 [shape=none, fontsize=11, label="20.20.20.254", labelloc="b", image="router.gif"]
Router101010254 [shape=none, fontsize=11, label="10.10.10.254", labelloc="b", image="router.gif"]
Router101010250 [shape=none, fontsize=11, label="10.10.10.250", labelloc="b", image="router.gif"]

# 6.) Description: nodes for IPSec Peer node
# Syntax: IPSecPeer1010101 [shape=none, fontsize=11, label="10.10.10.1", image="router.gif"]

IPSecPeer254254254250 [shape=none, fontsize=11, label="dynamic IP\nESP-AES-256-SHA\ntun-externalcompany", labelloc="b", image="router.gif"]
IPSecPeer6666 [shape=none, fontsize=11, label="6.6.6.6\nESP-AES-256-SHA\ntun-externalcompany-dev", labelloc="b", image="router.gif"]
IPSecPeer7777 [shape=none, fontsize=11, label="7.7.7.7\nESP-AES-256-SHA\ntun-externalcompany-preprod", labelloc="b", image="router.gif"]

# 7.) Description: record based node for firewall interface tables for the right side
# Syntax: FirewallIFsR [shape=Mrecord, fontsize=11, label=" IF1 sec-level SEC-LEVEL\n10.1.1.1| IF2 sec-level SEC-LEVEL\n10.1.2.1", style=filled, fillcolor=firebrick]

"asa-voiceIFsR" [shape=Mrecord, fontsize=11, label=" dmz1 sec-level 0\n20.20.20.1/\26|", style=filled, fillcolor=firebrick]

# 8.) Description: record based node for firewall interface tables for the left side
# Syntax: FirewallIFsR [shape=Mrecord, fontsize=11, label=" IF3 sec-level SEC-LEVEL\n10.1.3.1| IF4 sec-level SEC-LEVEL\n10.1.4.1", style=filled, fillcolor=firebrick]

"asa-voiceIFsL" [shape=Mrecord, fontsize=11, label=" management sec-level 100\n30.30.30.0/\24| inside sec-level 100\n10.10.10.1/\24|", style=filled, fillcolor=firebrick]

# 9.) Description: edges for 'firewall interface on the left side' to direct net to router and to remote net
# Syntax:# RNetstoIPSecPeer6666 -> IPSecPeer6666 [dir=back]# RHoststoIPSecPeer6666 -> IPSecPeer6666 [dir=back]# IPSecPeer6666 -> RNetstorouter202020254 [dir=back]# Netz5 -> Router1 [dir=back]
# Router1 -> Netz3[headlabel="10.1.3.2", dir=back]
# Netz3 -> FirewallIFsL:IF1 [dir=back]


RNetstorouter101010254 -> Router101010254 [dir=back]
RHoststorouter101010254 -> Router101010254 [dir=back]
RHoststorouter101010250 -> Router101010250 [dir=back]

Router101010254 -> Netz1010101 [dir=back]
Router101010250 -> Netz1010101 [dir=back]

Netz3030300 -> "asa-voiceIFsL":"management" [dir=back]
Netz1010101 -> "asa-voiceIFsL":"inside" [dir=back]

# 10.) Description: edges for firewall interface table to firewall
# Syntax:"
# FirewallIFsL -> Firewall [dir=none, penwidth=50, color=firebrick]
# Firewall -> FirewallIFsR [dir=none, penwidth=50, color=firebrick]

"asa-voiceIFsL" -> "asa-voice" [dir=none, penwidth=50, color=firebrick]
"asa-voice" -> "asa-voiceIFsR" [dir=none, penwidth=50, color=firebrick]

# 11.) Description: edges for 'firewall interface on the right side' to direct net to router and to remote net
# Syntax:
# Firewall1IFsR:IF3 -> Netz3
# Netz3 -> Router1 [headlabel="10.1.3.2"]
# Router1 -> Netz5

"asa-voiceIFsR":"dmz1" -> Netz2020201

Netz2020201 -> Router202020250
Netz2020201 -> Router202020254

Router202020250 -> RNetstorouter202020250
Router202020254 -> RNetstorouter202020254

IPSecPeer254254254250 -> RNetstoIPSecPeer254254254250 [dir=back]
IPSecPeer254254254250 -> RNetstoIPSecPeer254254254250 [dir=back]
IPSecPeer6666 -> RNetstoIPSecPeer6666 [dir=back]
IPSecPeer6666 -> RHoststoIPSecPeer6666 [dir=back]
IPSecPeer7777 -> RNetstoIPSecPeer7777 [dir=back]
IPSecPeer7777 -> RNetstoIPSecPeer7777 [dir=back]

RNetstorouter202020254 -> IPSecPeer254254254250 [dir=back]
RNetstorouter202020254 -> IPSecPeer6666 [dir=back]
RNetstorouter202020254 -> IPSecPeer7777 [dir=back]
}

And the png file generated with graphviz and with the dot file:

Cisco ASA Topology

Cisco ASA Topology

To be able to use this script you should install graphviz and perl and the modules usesd in the script.
The modules are in the script like the following:

use Net::Netmask; # This module is cool! Its more than in IP calculator. http://perltips.wikidot.com/module-net:netmask
use List::MoreUtils qw(uniq); # this modul is used for sort and uniq commands
use Array::Utils qw(:all); # this is used for uniq and sort arrays
use Term::Query qw( query); # this is for interactive perl scripting
use Net::Nslookup; # this is for nslookup within perl. in this script I do not use it..
use Regexp::Common; # Identifying IPv4 Addresses

If the command is issued without any parameter is will show a short howto:

test@linux-srv01:~/Documents$ ./asa-graphviz-builder_with_tables.pl 

==| asa-graphviz-builder.pl v. 0.1 beta (10th of July 2013) by Akos (noATemail.com) |==

Syntax:
-------
asa-graphviz-builder.pl  

Mandatory arguments:
-------------------
  : Name of inputfile. This file should contain the Cisco ASA configuration
  : Name of outputfile. This name will be used for the dot file and for the generated png and svg file
Example: ./asa-graphviz-builder.pl asa-test.cfg asa-test.dot
This will generate "asa-test.dot.svg" and "asa-test.dot.png" files

The script works the following way:
1. Collect all the configs of other ASA firewalls with the extention cfg and saves the IPs of the interfaces.
If the next hops is a firewall than it will be signed as a firewall.  It is useful if the firewall has another firewall as a next hop.
This step should be solved with DNS. I mean the DNS hostname of the firewall IPs (A records) should contain a string that identifies them as a firewall. like “fw”.
2. Collect the interface config from the given firewall.
The topologie is horizontal, the firewall has a left side and a right side (the good side with higher security level and a “bad” side with lower security level).
3. Within an interactive part, you should define what you want to see on the left and on the right side. By default the security level counts. If the security-level is greater than 49 then it is on the left side, everything else is on the right side.
4. The script generates a dot file.
4. The script issues 2 commands with dot to generate png file and svg file.

See an example below:

test@linux-srv01:~/Documents$ ./asa-graphviz-builder_with_tables.pl asa-test.cfg asa-test.dot

==| asa-graphviz-builder.pl v. 0.1 beta (10th of July 2013) by Akos (noATemail.com) |==

Loading ASA Configuration-file from asa-firewall1.cfg cfg file...Done

Loading ASA Configuration-file from asa-firewall2.cfg cfg file...Done

Loading ASA Configuration-file from asa-firewall3.cfg cfg file...Done

Loading ASA Configuration-file from asa-test.cfg...Done
Your firewall has the following interfaces: 
interfacename security-level:
management 100
dmz1 0
inside 100

On the graph the interfaces behind the firewall will be on the left side and
the interfaces before the firewall will be on the right side 

On which side of the firewall is the interface  management ? [left] 

On which side of the firewall is the interface  dmz1 ? [right] 

On which side of the firewall is the interface  inside ? [left] 

test@linux-srv01:~/Documents$

the script genereated 3 files:

test@linux-srv01:~/Documents$ ls -lat | head
total 80848
-rw-rw-r-- 1 test test    15903 Sep 17 12:05 asa-test.dot.svg
drwxrwxr-x 3 test test    36864 Sep 17 12:05 .
-rw-rw-r-- 1 test test   155695 Sep 17 12:05 asa-test.dot.png
-rw-rw-r-- 1 test test     3923 Sep 17 12:05 asa-test.dot
-rw-rw-r-- 1 test test     1627 Sep 17 12:04 asa-test.cfg
Advertisement