Examining Kerio Control Traffic Rules, by converting them to HTML

The other day I came across a script written by Tony Lawrence to convert an exported winroute.cfg configuration from Kerio Control firewall, to HTML, so that it was easier to examine the rules from the firewall, instead of looking at them directly in the configuration file or by loading them into your our firewall.

The idea is very good, especially if your are a consultant for multiple businesses running Kerio Control firewalls. But the script was not perfect, seen with my own eyes.

It lacked the following:

  • The correct colors, for the rules.
  • Interactivity, so that one would be able to provide the path to the winroute.cfg file. (instead of editing the script).
  • The default (fixed) bottom rule, DROP’ing all traffic not match by any of the above rules.
  • Converting some of information in the winroute.cfg, to that used in the Kerio Control web interface.
  • Output the HTML to a file, instead of directly to the command-line.
  • Clean HTML generated, so that it was compliant with for example XHTML 1.0 Strict.

Below is my updated version of Tony Lawrence’s script.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
#!/usr/bin/perl
# Original script by Tony Lawrence, http://aplawrence.com November 2012
# Modification and optimization by Mads Fog Albrechtslund, http://hazenet.dk November 2012

use File::Basename;

if (@ARGV != 1) {
  print STDERR "\nPlease provide the path to your winroute.cfg file, as an argument to the script.\n\n";
  exit 1;
}
if($ARGV[0] =~ /\winroute.cfg$/i) {
}
else {
	print "\n" . $ARGV[0] . " is not a \"winroute.cfg\" file.\n\n";
    exit 1;
}
my $directory = dirname( $ARGV[0] );
open (HTMLFILE, ">" . $directory . "/winroute.html");
@colors=("#FAFFFF","#EFFF11","#C9D8ED","#FFCCCC","#C9EEC6","#D3BFEB","#FDE8CA","#E8E8E8");
open(I,"<:crlf",$ARGV[0]);
$lastseen="";
while (<I>) {
	chomp;
	s/^\s+//;
	$intraffic=1 if /^<list name="TrafficRules/;
	next if /^<list name="TrafficRules/;
	$intraffic=0 if /^<.list>/;
	next if not $intraffic;
	next if /<listitem>/;
	push @holding,$_;
	store_it() if (/<.listitem>/);
}
print HTMLFILE "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\"><!-- <!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\"> --><!-- <!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\"> -->\n";
print HTMLFILE "<html xmlns=\"http://www.w3.org/1999/xhtml\">\n<head>\n<meta http-equiv=\"Content-type\" content=\"text/html;charset=UTF-8\" />\n<title>winroute.html</title>\n</head>\n<body>\n<table>\n";
print HTMLFILE "<tr><th>Rule ID</th>";
print HTMLFILE "<th>Enabled</th>";
print HTMLFILE "<th>Name</th>";
print HTMLFILE "<th>Description</th>";
print HTMLFILE "<th>Source</th>";
print HTMLFILE "<th>Destination</th>";
print HTMLFILE "<th>Inspector</th>";
print HTMLFILE "<th>Service</th>";
print HTMLFILE "<th>Time</th>";
print HTMLFILE "<th>Permit</th>";
print HTMLFILE "<th>Source NAT</th>";
print HTMLFILE "<th>Destination NAT</th></tr>\n";
$x=0;
foreach(@all) {
	$x++;
	@stuff=split /\014/;
	push @disp, "\n<tr>";
	$lastn="";
	foreach(@stuff) {
		$value=value($_);
		$name=name($_);
		$colorvalue=$colors[$value - 1] if ($name eq "Color");
			next if ($name eq "Color");
			if ($name eq $lastn and $lastn) {
				push @disp, "\n<br />$value";
				next;
			}
			if ($name ne $lastn) {
			if ($lastn eq "") {
				$lastn=$name;
				push @disp, "\n";
				} else {
				$lastn=$name;
				push @disp, "</td>\n";
				}

			if (not $value) {
				push @disp, "<td>$name = (unset)";
				next;
			}
			push @disp, "<td>$name = $value";
		}
	}
	foreach(@disp) {
		s/Enabled = 1/ Yes/;
		s/Enabled.*/<b>NOT ENABLED<\/b>/;
		s/PERMIT/Allow/;
		s/DENY/<b>Deny<\/b>/;
		s/DROP/<b>Drop<\/b>/;		
		s/Service = .unset./Service = Any/;
		s/Description = .unset./Service = /;
		s/<td>.*=/<td>/;
		s/list://;
		s/ifgroup:"internet"/Internet Interfaces/;
		s/ifgroup:"trusted"/Trusted\/Local Interfaces/;		
		s/ifgroup://;
		s/vpn-user/VPN clients/;
		s/vpn-tunnel/All VPN Tunnels/;
		s/default/Default/;		
		s/"//g;		
		s/<tr>/<tr style="background-color:$colorvalue">/;
		s/iface://;
		print HTMLFILE;
	}
	print HTMLFILE "</td>\n</tr>\n";
	@disp=();
}
print HTMLFILE "\n<tr style=\"background-color:#FFCCCC\">\n<td> 0</td>\n<td>Yes</td>\n<td> Block other traffic</td>\n<td> Any other communication is denied/droped.</td>\n<td> Any</td>\n<td> Any</td>\n<td></td>\n<td> Any</td>\n<td> (unset)</td>\n<td> <b>Drop</b></td>\n<td> (unset)</td>\n<td> (unset)</td>\n</tr>\n";
print HTMLFILE "\n</table>\n\n</body>\n</html>\n";

sub store_it {
$string="";
$lastseen="";
$lname="";
foreach(@holding) {
if (/<variable name="Order">/) {
	$order=value($_);
	next;
}
next if /<.listitem>/;
$name=name($_);
if ($lastseen =~ /Src/ and $name =~/Proxy/) {
	#print HTMLFILE STDERR "Need Dst $lastseen $name\n";
	$string .= "<variable name=\"Dst\">Any</variable>\014";
	#print HTMLFILE STDERR "$string\n";
}
if ($lastseen =~ /Description/ and $name =~ /Dst/) {
	#print HTMLFILE STDERR "Need Src $lastseen $name\n";
	$string .= "<variable name=\"Src\">Any</variable>\014";
}
$string.="$_\014";
$lastseen=$name;

}
$all[$order-1]=$string;
$string=~s/.$//;
@holding=();
}

sub value {
my @v=/<.*>(.*)<.*>/;
return $v[0];
}
sub name {
my @v=/<variable name="(.*)">.*<.*>/;
return $v[0];
}
close (MYFILE);

print "\nHTML output file generated: " . $directory . "/winroute.html\n\n"