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.
If 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:
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 |
Ed Davison
December 12, 2013
I would love to get a copy of this perl file.
itsecworks
December 13, 2013
Viewing the secret message :-)
http://www.computerhope.com/issues/ch000861.htm
itsecworks
December 18, 2013
New Release with new Features:
——————————————
# 18.12.13 name commands are prased too. The route entries with names are parsed to IPs.
# 18.12.13 if there is no vlan on the interface where there is an IP, I write “vlan no”
# 18.12.13 the automatic interface positioning is set based on security level.
# if the security-level > 49 put it on the left side, else put on right side.
Javier E. Pérez P.
June 26, 2014
I’m having dificulties getting to run this script, mostly because the perl’s modules it depend. I’ve try in ubuntu and debian, not all the modules are present in the oficial repository of each distibution, I’ve try using cpan, still can’t.
It’s there a lite version? or maybe one .deb elsewhere?
even so, thanks for the input.
itsecworks
July 6, 2014
Currently there is no lite version since noone care of that tool. You would be the first, maybe :-)
If you need the output you can send me your config with fake public ips (and without passwords, preshared keys). I can generate for you an svg file where you can replace the faked ips to the real ones. And the svg file can you open with ms visio and print out and hang on the wall. :-)
For the rest I can create a script that downloads all required perl modules, if you want.