]>
Commit | Line | Data |
---|---|---|
ac1cfefa | 1 | #!/usr/bin/perl |
70df8302 MT |
2 | ############################################################################### |
3 | # # | |
4 | # IPFire.org - A linux based firewall # | |
e7e1a351 | 5 | # Copyright (C) 2007-2023 IPFire Team <info@ipfire.org> # |
70df8302 MT |
6 | # # |
7 | # This program is free software: you can redistribute it and/or modify # | |
8 | # it under the terms of the GNU General Public License as published by # | |
9 | # the Free Software Foundation, either version 3 of the License, or # | |
10 | # (at your option) any later version. # | |
11 | # # | |
12 | # This program is distributed in the hope that it will be useful, # | |
13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of # | |
14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # | |
15 | # GNU General Public License for more details. # | |
16 | # # | |
17 | # You should have received a copy of the GNU General Public License # | |
18 | # along with this program. If not, see <http://www.gnu.org/licenses/>. # | |
19 | # # | |
20 | ############################################################################### | |
ac1cfefa | 21 | |
75bc929e | 22 | use strict; |
5653e551 | 23 | use experimental 'smartmatch'; |
ac1cfefa MT |
24 | |
25 | use Net::IPv4Addr qw( :all ); | |
75bc929e | 26 | use Switch; |
ac1cfefa MT |
27 | |
28 | # enable only the following on debugging purpose | |
1465b127 | 29 | #use warnings; |
cb5e9c6c | 30 | #use CGI::Carp 'fatalsToBrowser'; |
ac1cfefa | 31 | |
986e08d9 | 32 | require '/var/ipfire/general-functions.pl'; |
ac1cfefa MT |
33 | require "${General::swroot}/lang.pl"; |
34 | require "${General::swroot}/header.pl"; | |
3d3fbe7d | 35 | require "${General::swroot}/location-functions.pl"; |
ac1cfefa | 36 | |
c8a8778f MT |
37 | my $colour_multicast = "#A0A0A0"; |
38 | ||
9b37e91e KMK |
39 | # sort arguments for connection tracking table |
40 | # the sort field. eg. 1=src IP, 2=dst IP, 3=src port, 4=dst port | |
41 | my $SORT_FIELD = 0; | |
42 | # the sort order. (a)scending orr (d)escending | |
43 | my $SORT_ORDER = 0; | |
44 | # cgi query arguments | |
45 | my %cgiin; | |
46 | # debug mode | |
47 | my $debug = 0; | |
48 | ||
49 | # retrieve query arguments | |
50 | # note: let a-z A-Z and 0-9 pass as value only | |
51 | if (length ($ENV{'QUERY_STRING'}) > 0){ | |
52 | my $name; | |
53 | my $value; | |
54 | my $buffer = $ENV{'QUERY_STRING'}; | |
55 | my @pairs = split(/&/, $buffer); | |
56 | foreach my $pair (@pairs){ | |
57 | ($name, $value) = split(/=/, $pair); | |
58 | $value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg; # e.g. "%20" => " " | |
59 | $value =~ s/[^a-zA-Z0-9]*//g; # a-Z 0-9 will pass | |
66c36198 | 60 | $cgiin{$name} = $value; |
9b37e91e KMK |
61 | } |
62 | } | |
63 | ||
75bc929e MT |
64 | &Header::showhttpheaders(); |
65 | ||
66 | my @network=(); | |
67 | my @masklen=(); | |
68 | my @colour=(); | |
69 | ||
70 | my %netsettings=(); | |
71 | &General::readhash("${General::swroot}/ethernet/settings", \%netsettings); | |
72 | ||
9b37e91e KMK |
73 | # output cgi query arrguments to browser on debug |
74 | if ( $debug ){ | |
75 | &Header::openbox('100%', 'center', 'DEBUG'); | |
76 | my $debugCount = 0; | |
77 | foreach my $line (sort keys %cgiin) { | |
78 | print "$line = '$cgiin{$line}'<br />\n"; | |
79 | $debugCount++; | |
80 | } | |
81 | print " Count: $debugCount\n"; | |
82 | &Header::closebox(); | |
83 | } | |
84 | ||
ac1cfefa MT |
85 | #workaround to suppress a warning when a variable is used only once |
86 | my @dummy = ( ${Header::table1colour} ); | |
87 | undef (@dummy); | |
88 | ||
9b37e91e KMK |
89 | # check sorting arguments |
90 | if ( $cgiin{'sort_field'} ~~ [ '1','2','3','4','5','6','7','8','9' ] ) { | |
91 | $SORT_FIELD = $cgiin{'sort_field'}; | |
92 | ||
93 | if ( $cgiin{'sort_order'} ~~ [ 'a','d','A','D' ] ) { | |
94 | $SORT_ORDER = lc($cgiin{'sort_order'}); | |
95 | } | |
96 | } | |
97 | ||
98 | # Read and sort the connection tracking table | |
66c36198 PM |
99 | # do sorting |
100 | if ($SORT_FIELD and $SORT_ORDER) { | |
9b37e91e KMK |
101 | # field sorting when sorting arguments are sane |
102 | open(CONNTRACK, "/usr/local/bin/getconntracktable | /usr/local/bin/consort.sh $SORT_FIELD $SORT_ORDER |") or die "Unable to read conntrack table"; | |
103 | } else { | |
104 | # default sorting with no query arguments | |
105 | open(CONNTRACK, "/usr/local/bin/getconntracktable | sort -k 5,5 --numeric-sort --reverse |") or die "Unable to read conntrack table"; | |
106 | } | |
75bc929e MT |
107 | my @conntrack = <CONNTRACK>; |
108 | close(CONNTRACK); | |
ac1cfefa | 109 | |
75bc929e | 110 | # Collect data for the @network array. |
ac1cfefa | 111 | |
75bc929e MT |
112 | # Add Firewall Localhost 127.0.0.1 |
113 | push(@network, '127.0.0.1'); | |
114 | push(@masklen, '255.255.255.255'); | |
115 | push(@colour, ${Header::colourfw}); | |
ac1cfefa | 116 | |
2c42fe6a | 117 | if (open(IP, "${General::swroot}/red/local-ipaddress")) { |
75bc929e MT |
118 | my $redip = <IP>; |
119 | close(IP); | |
120 | ||
121 | chomp $redip; | |
122 | push(@network, $redip); | |
123 | push(@masklen, '255.255.255.255'); | |
124 | push(@colour, ${Header::colourfw}); | |
2c42fe6a MT |
125 | } |
126 | ||
75bc929e MT |
127 | # Add STATIC RED aliases |
128 | if ($netsettings{'RED_DEV'}) { | |
129 | my $aliasfile = "${General::swroot}/ethernet/aliases"; | |
130 | open(ALIASES, $aliasfile) or die 'Unable to open aliases file.'; | |
131 | my @aliases = <ALIASES>; | |
132 | close(ALIASES); | |
133 | ||
134 | # We have a RED eth iface | |
135 | if ($netsettings{'RED_TYPE'} eq 'STATIC') { | |
136 | # We have a STATIC RED eth iface | |
137 | foreach my $line (@aliases) { | |
138 | chomp($line); | |
139 | my @temp = split(/\,/,$line); | |
140 | if ($temp[0]) { | |
141 | push(@network, $temp[0]); | |
142 | push(@masklen, $netsettings{'RED_NETMASK'} ); | |
143 | push(@colour, ${Header::colourfw} ); | |
144 | } | |
145 | } | |
146 | } | |
147 | } | |
ac1cfefa | 148 | |
d39c7076 SS |
149 | # Call safe system_output function to get all available routes. |
150 | my @all_routes = &General::system_output("/sbin/route", "-n"); | |
151 | ||
ac1cfefa MT |
152 | # Add Green Firewall Interface |
153 | push(@network, $netsettings{'GREEN_ADDRESS'}); | |
154 | push(@masklen, "255.255.255.255" ); | |
155 | push(@colour, ${Header::colourfw} ); | |
156 | ||
d4df452e AF |
157 | if ($netsettings{'GREEN_DEV'}) { |
158 | # Add Green Network to Array | |
159 | push(@network, $netsettings{'GREEN_NETADDRESS'}); | |
160 | push(@masklen, $netsettings{'GREEN_NETMASK'} ); | |
75bc929e | 161 | push(@colour, ${Header::colourgreen} ); |
d4df452e AF |
162 | |
163 | # Add Green Routes to Array | |
164 | my @routes = grep (/$netsettings{'GREEN_DEV'}/, @all_routes); | |
165 | foreach my $route (@routes) { | |
166 | chomp($route); | |
167 | my @temp = split(/[\t ]+/, $route); | |
168 | push(@network, $temp[0]); | |
169 | push(@masklen, $temp[2]); | |
170 | push(@colour, ${Header::colourgreen} ); | |
171 | } | |
5433e2c9 MT |
172 | } |
173 | ||
f9aaffa6 MT |
174 | # Add Blue Firewall Interface |
175 | push(@network, $netsettings{'BLUE_ADDRESS'}); | |
176 | push(@masklen, "255.255.255.255" ); | |
177 | push(@colour, ${Header::colourfw} ); | |
178 | ||
5433e2c9 MT |
179 | # Add Blue Network |
180 | if ($netsettings{'BLUE_DEV'}) { | |
75bc929e MT |
181 | push(@network, $netsettings{'BLUE_NETADDRESS'}); |
182 | push(@masklen, $netsettings{'BLUE_NETMASK'} ); | |
183 | push(@colour, ${Header::colourblue} ); | |
184 | ||
185 | # Add Blue Routes to Array | |
d4df452e | 186 | my @routes = grep(/$netsettings{'BLUE_DEV'}/, @all_routes); |
75bc929e MT |
187 | foreach my $route (@routes) { |
188 | chomp($route); | |
189 | my @temp = split(/[\t ]+/, $route); | |
190 | push(@network, $temp[0]); | |
191 | push(@masklen, $temp[2]); | |
192 | push(@colour, ${Header::colourblue} ); | |
193 | } | |
194 | } | |
195 | ||
5ac2ed47 MT |
196 | # Add Orange Firewall Interface |
197 | push(@network, $netsettings{'ORANGE_ADDRESS'}); | |
198 | push(@masklen, "255.255.255.255" ); | |
199 | push(@colour, ${Header::colourfw} ); | |
200 | ||
75bc929e MT |
201 | # Add Orange Network |
202 | if ($netsettings{'ORANGE_DEV'}) { | |
203 | push(@network, $netsettings{'ORANGE_NETADDRESS'}); | |
204 | push(@masklen, $netsettings{'ORANGE_NETMASK'} ); | |
205 | push(@colour, ${Header::colourorange} ); | |
206 | # Add Orange Routes to Array | |
d4df452e | 207 | my @routes = grep(/$netsettings{'ORANGE_DEV'}/, @all_routes); |
75bc929e MT |
208 | foreach my $route (@routes) { |
209 | chomp($route); | |
210 | my @temp = split(/[\t ]+/, $route); | |
211 | push(@network, $temp[0]); | |
212 | push(@masklen, $temp[2]); | |
213 | push(@colour, ${Header::colourorange} ); | |
214 | } | |
5433e2c9 MT |
215 | } |
216 | ||
c8a8778f MT |
217 | # Highlight multicast connections. |
218 | push(@network, "224.0.0.0"); | |
219 | push(@masklen, "239.0.0.0"); | |
220 | push(@colour, $colour_multicast); | |
221 | ||
6e13d0a5 MT |
222 | # Add OpenVPN net and RED/BLUE/ORANGE entry (when appropriate) |
223 | if (-e "${General::swroot}/ovpn/settings") { | |
75bc929e MT |
224 | my %ovpnsettings = (); |
225 | &General::readhash("${General::swroot}/ovpn/settings", \%ovpnsettings); | |
226 | my @tempovpnsubnet = split("\/",$ovpnsettings{'DOVPN_SUBNET'}); | |
227 | ||
228 | # add OpenVPN net | |
229 | push(@network, $tempovpnsubnet[0]); | |
230 | push(@masklen, $tempovpnsubnet[1]); | |
231 | push(@colour, ${Header::colourovpn} ); | |
232 | ||
233 | # add BLUE:port / proto | |
234 | if (($ovpnsettings{'ENABLED_BLUE'} eq 'on') && $netsettings{'BLUE_DEV'}) { | |
235 | push(@network, $netsettings{'BLUE_ADDRESS'} ); | |
236 | push(@masklen, '255.255.255.255' ); | |
237 | push(@colour, ${Header::colourovpn}); | |
238 | } | |
6e13d0a5 | 239 | |
75bc929e MT |
240 | # add ORANGE:port / proto |
241 | if (($ovpnsettings{'ENABLED_ORANGE'} eq 'on') && $netsettings{'ORANGE_DEV'}) { | |
242 | push(@network, $netsettings{'ORANGE_ADDRESS'} ); | |
243 | push(@masklen, '255.255.255.255' ); | |
244 | push(@colour, ${Header::colourovpn} ); | |
245 | } | |
246 | } | |
6e13d0a5 | 247 | |
c7220d6e DH |
248 | # Add OpenVPN net for custom OVPNs |
249 | if (-e "${General::swroot}/ovpn/ccd.conf") { | |
66c36198 | 250 | open(OVPNSUB, "${General::swroot}/ovpn/ccd.conf"); |
c7220d6e DH |
251 | my @ovpnsub = <OVPNSUB>; |
252 | close(OVPNSUB); | |
253 | ||
254 | foreach (@ovpnsub) { | |
255 | my ($network, $mask) = split '/', (split ',', $_)[2]; | |
66c36198 | 256 | |
c7220d6e DH |
257 | $mask = ipv4_cidr2msk($mask) unless &General::validip($mask); |
258 | ||
259 | push(@network, $network); | |
260 | push(@masklen, $mask); | |
261 | push(@colour, ${Header::colourovpn}); | |
262 | } | |
263 | } | |
264 | ||
03435d85 | 265 | open(IPSEC, "${General::swroot}/vpn/config"); |
75bc929e MT |
266 | my @ipsec = <IPSEC>; |
267 | close(IPSEC); | |
7dbf47dc | 268 | |
75bc929e MT |
269 | foreach my $line (@ipsec) { |
270 | my @vpn = split(',', $line); | |
6e13d0a5 | 271 | |
ffeaaef6 | 272 | my @subnets = split(/\|/, $vpn[12]); |
c6fba315 MT |
273 | for my $subnet (@subnets) { |
274 | my ($network, $mask) = split("/", $subnet); | |
275 | ||
276 | if (!&General::validip($mask)) { | |
277 | $mask = ipv4_cidr2msk($mask); | |
278 | } | |
ac1cfefa | 279 | |
c6fba315 MT |
280 | push(@network, $network); |
281 | push(@masklen, $mask); | |
282 | push(@colour, ${Header::colourvpn}); | |
283 | } | |
ac1cfefa | 284 | } |
ac1cfefa | 285 | |
d9ac41d5 MT |
286 | if (-e "${General::swroot}/ovpn/n2nconf") { |
287 | open(OVPNN2N, "${General::swroot}/ovpn/ovpnconfig"); | |
288 | my @ovpnn2n = <OVPNN2N>; | |
289 | close(OVPNN2N); | |
290 | ||
291 | foreach my $line (@ovpnn2n) { | |
292 | my @ovpn = split(',', $line); | |
293 | next if ($ovpn[4] ne 'net'); | |
294 | ||
295 | my ($network, $mask) = split("/", $ovpn[12]); | |
296 | if (!&General::validip($mask)) { | |
297 | $mask = ipv4_cidr2msk($mask); | |
298 | } | |
299 | ||
300 | push(@network, $network); | |
301 | push(@masklen, $mask); | |
302 | push(@colour, ${Header::colourovpn}); | |
303 | } | |
304 | } | |
305 | ||
75bc929e MT |
306 | # Show the page. |
307 | &Header::openpage($Lang::tr{'connections'}, 1, ''); | |
308 | &Header::openbigbox('100%', 'left'); | |
309 | &Header::openbox('100%', 'left', $Lang::tr{'connection tracking'}); | |
c2b15814 | 310 | |
75bc929e MT |
311 | # Print legend. |
312 | print <<END; | |
429c1a3f | 313 | <table style='width:100%'> |
75bc929e | 314 | <tr> |
429c1a3f AH |
315 | <td style='text-align:center;'> |
316 | <b>$Lang::tr{'legend'} :</b> | |
75bc929e | 317 | </td> |
429c1a3f AH |
318 | <td style='text-align:center; color:#FFFFFF; background-color:${Header::colourgreen}; font-weight:bold;'> |
319 | <b>$Lang::tr{'lan'}</b> | |
75bc929e | 320 | </td> |
429c1a3f AH |
321 | <td style='text-align:center; color:#FFFFFF; background-color:${Header::colourred};'> |
322 | <b>$Lang::tr{'internet'}</b> | |
75bc929e | 323 | </td> |
429c1a3f AH |
324 | <td style='text-align:center; color:#FFFFFF; background-color:${Header::colourorange};'> |
325 | <b>$Lang::tr{'dmz'}</b> | |
75bc929e | 326 | </td> |
429c1a3f AH |
327 | <td style='text-align:center; color:#FFFFFF; background-color:${Header::colourblue};'> |
328 | <b>$Lang::tr{'wireless'}</b> | |
75bc929e | 329 | </td> |
429c1a3f AH |
330 | <td style='text-align:center; color:#FFFFFF; background-color:${Header::colourfw};'> |
331 | <b>IPFire</b> | |
75bc929e | 332 | </td> |
429c1a3f AH |
333 | <td style='text-align:center; color:#FFFFFF; background-color:${Header::colourvpn};'> |
334 | <b>$Lang::tr{'vpn'}</b> | |
75bc929e | 335 | </td> |
429c1a3f AH |
336 | <td style='text-align:center; color:#FFFFFF; background-color:${Header::colourovpn};'> |
337 | <b>$Lang::tr{'OpenVPN'}</b> | |
75bc929e | 338 | </td> |
429c1a3f AH |
339 | <td style='text-align:center; color:#FFFFFF; background-color:$colour_multicast;'> |
340 | <b>Multicast</b> | |
c8a8778f | 341 | </td> |
75bc929e MT |
342 | </tr> |
343 | </table> | |
344 | <br> | |
345 | END | |
c2b15814 | 346 | |
9b37e91e KMK |
347 | if ($SORT_FIELD and $SORT_ORDER) { |
348 | my @sort_field_name = ( | |
349 | $Lang::tr{'source ip'}, | |
350 | $Lang::tr{'destination ip'}, | |
351 | $Lang::tr{'source port'}, | |
352 | $Lang::tr{'destination port'}, | |
353 | $Lang::tr{'protocol'}, | |
354 | $Lang::tr{'connection'}.' '.$Lang::tr{'status'}, | |
58543d54 | 355 | $Lang::tr{'expires'}.' ('.$Lang::tr{'hours:minutes:seconds'}.')', |
9b37e91e KMK |
356 | $Lang::tr{'download'}, |
357 | $Lang::tr{'upload'} | |
358 | ); | |
359 | my $sort_order_name; | |
360 | if (lc($SORT_ORDER) eq "a") { | |
361 | $sort_order_name = $Lang::tr{'sort ascending'}; | |
362 | } else { | |
363 | $sort_order_name = $Lang::tr{'sort descending'}; | |
364 | } | |
365 | ||
366 | print <<END | |
367 | <div style="font-weight:bold;margin:10px;font-size: 70%"> | |
368 | $sort_order_name: $sort_field_name[$SORT_FIELD-1] | |
369 | </div> | |
370 | END | |
371 | ; | |
372 | } | |
373 | ||
75bc929e MT |
374 | # Print table header. |
375 | print <<END; | |
429c1a3f AH |
376 | <table style='width:100%'> |
377 | <tr> | |
378 | <th style='text-align:center'> | |
379 | <a href="?sort_field=5&sort_order=d"><img style="width:10px" src="/images/up.gif" alt=""></a> | |
380 | <a href="?sort_field=5&sort_order=a"><img style="width:10px" src="/images/down.gif" alt=""></a> | |
9b37e91e | 381 | </th> |
429c1a3f AH |
382 | <th style='text-align:center' colspan='2'> |
383 | <a href="?sort_field=1&sort_order=d"><img style="width:10px" src="/images/up.gif" alt=""></a> | |
384 | <a href="?sort_field=1&sort_order=a"><img style="width:10px" src="/images/down.gif" alt=""></a> | |
9b37e91e | 385 | |
429c1a3f AH |
386 | <a href="?sort_field=3&sort_order=d"><img style="width:10px" src="/images/up.gif" alt=""></a> |
387 | <a href="?sort_field=3&sort_order=a"><img style="width:10px" src="/images/down.gif" alt=""></a> | |
9b37e91e | 388 | </th> |
ea4620fc | 389 | <th> </th> |
429c1a3f AH |
390 | <th style='text-align:center' colspan='2'> |
391 | <a href="?sort_field=2&sort_order=d"><img style="width:10px" src="/images/up.gif" alt=""></a> | |
392 | <a href="?sort_field=2&sort_order=a"><img style="width:10px" src="/images/down.gif" alt=""></a> | |
9b37e91e | 393 | |
429c1a3f AH |
394 | <a href="?sort_field=4&sort_order=d"><img style="width:10px" src="/images/up.gif" alt=""></a> |
395 | <a href="?sort_field=4&sort_order=a"><img style="width:10px" src="/images/down.gif" alt=""></a> | |
75bc929e | 396 | </th> |
ea4620fc | 397 | <th> </th> |
429c1a3f AH |
398 | <th style='text-align:center'> |
399 | <a href="?sort_field=8&sort_order=d"><img style="width:10px" src="/images/up.gif" alt=""></a> | |
400 | <a href="?sort_field=8&sort_order=a"><img style="width:10px" src="/images/down.gif" alt=""></a> | |
9b37e91e | 401 | |
429c1a3f AH |
402 | <a href="?sort_field=9&sort_order=d"><img style="width:10px" src="/images/up.gif" alt=""></a> |
403 | <a href="?sort_field=9&sort_order=a"><img style="width:10px" src="/images/down.gif" alt=""></a> | |
9b37e91e | 404 | </th> |
429c1a3f AH |
405 | <th style='text-align:center'> |
406 | <a href="?sort_field=6&sort_order=d"><img style="width:10px" src="/images/up.gif" alt=""></a> | |
407 | <a href="?sort_field=6&sort_order=a"><img style="width:10px" src="/images/down.gif" alt=""></a> | |
75bc929e | 408 | </th> |
429c1a3f AH |
409 | <th style='text-align:center'> |
410 | <a href="?sort_field=7&sort_order=d"><img style="width:10px" src="/images/up.gif" alt=""></a> | |
411 | <a href="?sort_field=7&sort_order=a"><img style="width:10px" src="/images/down.gif" alt=""></a> | |
9b37e91e KMK |
412 | </th> |
413 | </tr> | |
429c1a3f AH |
414 | <tr> |
415 | <th style='text-align:center'> | |
9b37e91e KMK |
416 | $Lang::tr{'protocol'} |
417 | </th> | |
429c1a3f | 418 | <th style='text-align:center' colspan='2'> |
9b37e91e KMK |
419 | $Lang::tr{'source ip and port'} |
420 | </th> | |
ea4620fc PM |
421 | <th style='text-align:center'> |
422 | $Lang::tr{'country'} | |
423 | </th> | |
429c1a3f | 424 | <th style='text-align:center' colspan='2'> |
75bc929e MT |
425 | $Lang::tr{'dest ip and port'} |
426 | </th> | |
ea4620fc PM |
427 | <th style='text-align:center'> |
428 | $Lang::tr{'country'} | |
429 | </th> | |
429c1a3f | 430 | <th style='text-align:center'> |
75bc929e MT |
431 | $Lang::tr{'download'} / |
432 | <br>$Lang::tr{'upload'} | |
433 | </th> | |
429c1a3f | 434 | <th style='text-align:center'> |
75bc929e MT |
435 | $Lang::tr{'connection'}<br>$Lang::tr{'status'} |
436 | </th> | |
429c1a3f | 437 | <th style='text-align:center'> |
58543d54 | 438 | $Lang::tr{'expires'}<br>($Lang::tr{'hours:minutes:seconds'}) |
75bc929e MT |
439 | </th> |
440 | </tr> | |
441 | END | |
c2b15814 | 442 | |
75bc929e MT |
443 | foreach my $line (@conntrack) { |
444 | my @conn = split(' ', $line); | |
c2b15814 | 445 | |
75bc929e MT |
446 | # The first bit is the l3 protocol. |
447 | my $l3proto = $conn[0]; | |
c2b15814 | 448 | |
75bc929e MT |
449 | # Skip everything that is not IPv4. |
450 | if ($l3proto ne 'ipv4') { | |
451 | next; | |
452 | } | |
ac1cfefa | 453 | |
75bc929e MT |
454 | # L4 protocol (tcp, udp, ...). |
455 | my $l4proto = $conn[2]; | |
c2b15814 | 456 | |
7d55ca0d | 457 | # Translate unknown protocols. |
75bc929e | 458 | if ($l4proto eq 'unknown') { |
7d55ca0d MT |
459 | my $l4protonum = $conn[3]; |
460 | if ($l4protonum eq '2') { | |
461 | $l4proto = 'IGMP'; | |
462 | } elsif ($l4protonum eq '4') { | |
463 | $l4proto = 'IPv4 Encap'; | |
464 | } elsif ($l4protonum eq '33') { | |
465 | $l4proto = 'DCCP'; | |
466 | } elsif ($l4protonum eq '41') { | |
467 | $l4proto = 'IPv6 Encap'; | |
468 | } elsif ($l4protonum eq '50') { | |
469 | $l4proto = 'ESP'; | |
470 | } elsif ($l4protonum eq '51') { | |
471 | $l4proto = 'AH'; | |
472 | } elsif ($l4protonum eq '132') { | |
473 | $l4proto = 'SCTP'; | |
474 | } else { | |
475 | $l4proto = $l4protonum; | |
476 | } | |
477 | } else { | |
478 | $l4proto = uc($l4proto); | |
75bc929e | 479 | } |
4809e64e | 480 | |
75bc929e MT |
481 | # Source and destination. |
482 | my $sip; | |
c9e01c8c | 483 | my $sip_ret; |
75bc929e | 484 | my $dip; |
c9e01c8c | 485 | my $dip_ret; |
75bc929e | 486 | my $sport; |
c9e01c8c | 487 | my $sport_ret; |
75bc929e | 488 | my $dport; |
c9e01c8c | 489 | my $dport_ret; |
75bc929e MT |
490 | my @packets; |
491 | my @bytes; | |
492 | ||
493 | my $ttl = $conn[4]; | |
494 | my $state; | |
7d55ca0d | 495 | if ($l4proto eq 'TCP') { |
75bc929e MT |
496 | $state = $conn[5]; |
497 | } | |
c2b15814 | 498 | |
75bc929e MT |
499 | # Kick out everything that is not IPv4. |
500 | foreach my $item (@conn) { | |
501 | my ($key, $val) = split('=', $item); | |
502 | ||
503 | switch ($key) { | |
504 | case "src" { | |
c9e01c8c MT |
505 | if ($sip == "") { |
506 | $sip = $val; | |
507 | } else { | |
508 | $dip_ret = $val; | |
509 | } | |
75bc929e MT |
510 | } |
511 | case "dst" { | |
c9e01c8c MT |
512 | if ($dip == "") { |
513 | $dip = $val; | |
514 | } else { | |
515 | $sip_ret = $val; | |
516 | } | |
75bc929e MT |
517 | } |
518 | case "sport" { | |
c9e01c8c MT |
519 | if ($sport == "") { |
520 | $sport = $val; | |
521 | } else { | |
522 | $dport_ret = $val; | |
523 | } | |
75bc929e MT |
524 | } |
525 | case "dport" { | |
c9e01c8c MT |
526 | if ($dport == "") { |
527 | $dport = $val; | |
528 | } else { | |
529 | $sport_ret = $val; | |
530 | } | |
75bc929e MT |
531 | } |
532 | case "packets" { | |
533 | push(@packets, $val); | |
534 | } | |
535 | case "bytes" { | |
536 | push(@bytes, $val); | |
537 | } | |
538 | } | |
539 | } | |
1465b127 | 540 | |
75bc929e | 541 | my $sip_colour = ipcolour($sip); |
e60cd3a4 DH |
542 | # use colour of destination network for DNAT |
543 | my $dip_colour = $dip ne $dip_ret ? ipcolour($dip_ret) : ipcolour($dip); | |
1465b127 | 544 | |
7d55ca0d MT |
545 | my $sserv = ''; |
546 | if ($sport < 1024) { | |
75bc929e | 547 | $sserv = uc(getservbyport($sport, lc($l4proto))); |
7d55ca0d | 548 | } |
1465b127 | 549 | |
7d55ca0d MT |
550 | my $dserv = ''; |
551 | if ($dport < 1024) { | |
75bc929e | 552 | $dserv = uc(getservbyport($dport, lc($l4proto))); |
7d55ca0d | 553 | } |
1465b127 | 554 | |
75bc929e MT |
555 | my $bytes_in = format_bytes($bytes[0]); |
556 | my $bytes_out = format_bytes($bytes[1]); | |
557 | ||
3d3fbe7d | 558 | # enumerate location information |
07e42be9 | 559 | my $srcccode = &Location::Functions::lookup_country_code($sip_ret); |
3d3fbe7d | 560 | my $src_flag_icon = &Location::Functions::get_flag_icon($srcccode); |
07e42be9 | 561 | my $dstccode = &Location::Functions::lookup_country_code($dip_ret); |
3d3fbe7d | 562 | my $dst_flag_icon = &Location::Functions::get_flag_icon($dstccode); |
ea4620fc | 563 | |
75bc929e MT |
564 | # Format TTL |
565 | $ttl = format_time($ttl); | |
566 | ||
c9e01c8c | 567 | my $sip_extra; |
ee299e2e | 568 | if ($sip_ret && $sip ne $sip_ret) { |
429c1a3f | 569 | $sip_extra = "<span style='color:#FFFFFF;'>></span> "; |
c9e01c8c | 570 | $sip_extra .= "<a href='/cgi-bin/ipinfo.cgi?ip=$sip_ret'>"; |
429c1a3f | 571 | $sip_extra .= " <span style='color:#FFFFFF;'>$sip_ret</span>"; |
c9e01c8c MT |
572 | $sip_extra .= "</a>"; |
573 | } | |
574 | ||
575 | my $dip_extra; | |
ee299e2e | 576 | if ($dip_ret && $dip ne $dip_ret) { |
429c1a3f | 577 | $dip_extra = "<span style='color:#FFFFFF;'>></span> "; |
c9e01c8c | 578 | $dip_extra .= "<a href='/cgi-bin/ipinfo.cgi?ip=$dip_ret'>"; |
429c1a3f | 579 | $dip_extra .= " <span style='color:#FFFFFF;'>$dip_ret</span>"; |
c9e01c8c MT |
580 | $dip_extra .= "</a>"; |
581 | } | |
582 | ||
583 | ||
584 | my $sport_extra; | |
585 | if ($sport ne $sport_ret) { | |
586 | my $sserv_ret = ''; | |
587 | if ($sport_ret < 1024) { | |
588 | $sserv_ret = uc(getservbyport($sport_ret, lc($l4proto))); | |
589 | } | |
590 | ||
429c1a3f | 591 | $sport_extra = "<span style='color:#FFFFFF;'>></span> "; |
e90c62b2 | 592 | $sport_extra .= "<a href='https://isc.sans.edu/port.html?port=$sport_ret' target='top' title='$sserv_ret'>"; |
429c1a3f | 593 | $sport_extra .= " <span style='color:#FFFFFF;'>$sport_ret</span>"; |
c9e01c8c MT |
594 | $sport_extra .= "</a>"; |
595 | } | |
596 | ||
597 | my $dport_extra; | |
598 | if ($dport ne $dport_ret) { | |
599 | my $dserv_ret = ''; | |
600 | if ($dport_ret < 1024) { | |
601 | $dserv_ret = uc(getservbyport($dport_ret, lc($l4proto))); | |
602 | } | |
603 | ||
429c1a3f | 604 | $dport_extra = "<span style='color:#FFFFFF;'>></span> "; |
e90c62b2 | 605 | $dport_extra .= "<a href='https://isc.sans.edu/port.html?port=$dport_ret' target='top' title='$dserv_ret'>"; |
429c1a3f | 606 | $dport_extra .= " <span style='color:#FFFFFF;'>$dport_ret</span>"; |
c9e01c8c MT |
607 | $dport_extra .= "</a>"; |
608 | } | |
609 | ||
75bc929e MT |
610 | print <<END; |
611 | <tr> | |
429c1a3f AH |
612 | <td style='text-align:center'>$l4proto</td> |
613 | <td style='text-align:center; background-color:$sip_colour;'> | |
75bc929e | 614 | <a href='/cgi-bin/ipinfo.cgi?ip=$sip'> |
429c1a3f | 615 | <span style='color:#FFFFFF;'>$sip</span> |
75bc929e | 616 | </a> |
c9e01c8c | 617 | $sip_extra |
75bc929e | 618 | </td> |
429c1a3f | 619 | <td style='text-align:center; background-color:$sip_colour;'> |
e90c62b2 | 620 | <a href='https://isc.sans.edu/port.html?port=$sport' target='top' title='$sserv'> |
429c1a3f | 621 | <span style='color:#FFFFFF;'>$sport</span> |
75bc929e | 622 | </a> |
c9e01c8c | 623 | $sport_extra |
75bc929e | 624 | </td> |
ea4620fc PM |
625 | <td style='text-align:center; background-color:$sip_colour;'> |
626 | <a href='country.cgi#$srcccode'><img src='$src_flag_icon' border='0' align='absmiddle' alt='$srcccode' title='$srcccode' /></a> | |
627 | </td> | |
429c1a3f | 628 | <td style='text-align:center; background-color:$dip_colour;'> |
75bc929e | 629 | <a href='/cgi-bin/ipinfo.cgi?ip=$dip'> |
429c1a3f | 630 | <span style='color:#FFFFFF;'>$dip</span> |
75bc929e | 631 | </a> |
c9e01c8c | 632 | $dip_extra |
75bc929e | 633 | </td> |
429c1a3f | 634 | <td style='text-align:center; background-color:$dip_colour;'> |
e90c62b2 | 635 | <a href='https://isc.sans.edu/port.html?port=$dport' target='top' title='$dserv'> |
429c1a3f | 636 | <span style='color:#FFFFFF;'>$dport</span> |
75bc929e | 637 | </a> |
c9e01c8c | 638 | $dport_extra |
75bc929e | 639 | </td> |
ea4620fc PM |
640 | <td style='text-align:center; background-color:$sip_colour;'> |
641 | <a href='country.cgi#$dstccode'><img src='$dst_flag_icon' border='0' align='absmiddle' alt='$dstccode' title='$dstccode' /></a> | |
642 | </td> | |
429c1a3f | 643 | <td style='text-align:center'> |
75bc929e MT |
644 | $bytes_in / $bytes_out |
645 | </td> | |
429c1a3f AH |
646 | <td style='text-align:center'>$state</td> |
647 | <td style='text-align:center'>$ttl</td> | |
75bc929e | 648 | </tr> |
ac1cfefa | 649 | END |
ac1cfefa | 650 | } |
c2b15814 | 651 | |
75bc929e MT |
652 | # Close the main table. |
653 | print "</table>"; | |
ac1cfefa MT |
654 | |
655 | &Header::closebox(); | |
656 | &Header::closebigbox(); | |
657 | &Header::closepage(); | |
658 | ||
75bc929e MT |
659 | sub format_bytes($) { |
660 | my $bytes = shift; | |
661 | my @units = ("B", "k", "M", "G", "T"); | |
662 | ||
663 | foreach my $unit (@units) { | |
664 | if ($bytes < 1024) { | |
665 | return sprintf("%d%s", $bytes, $unit); | |
666 | } | |
c2b15814 | 667 | |
75bc929e MT |
668 | $bytes /= 1024; |
669 | } | |
670 | ||
671 | return sprintf("%d%s", $bytes, $units[$#units]); | |
c2b15814 MT |
672 | } |
673 | ||
75bc929e MT |
674 | sub format_time($) { |
675 | my $time = shift; | |
c2b15814 | 676 | |
75bc929e MT |
677 | my $seconds = $time % 60; |
678 | my $minutes = $time / 60; | |
c2b15814 | 679 | |
75bc929e MT |
680 | my $hours = 0; |
681 | if ($minutes >= 60) { | |
682 | $hours = $minutes / 60; | |
683 | $minutes %= 60; | |
684 | } | |
685 | ||
686 | return sprintf("%3d:%02d:%02d", $hours, $minutes, $seconds); | |
c2b15814 MT |
687 | } |
688 | ||
75bc929e MT |
689 | sub ipcolour($) { |
690 | my $id = 0; | |
691 | my $colour = ${Header::colourred}; | |
692 | my ($ip) = $_[0]; | |
693 | my $found = 0; | |
694 | ||
ee299e2e MT |
695 | if ($ip) { |
696 | foreach my $line (@network) { | |
697 | if ($network[$id] eq '') { | |
698 | $id++; | |
699 | } else { | |
700 | if (!$found && ipv4_in_network($network[$id], $masklen[$id], $ip) ) { | |
701 | $found = 1; | |
702 | $colour = $colour[$id]; | |
703 | } | |
704 | $id++; | |
75bc929e | 705 | } |
75bc929e MT |
706 | } |
707 | } | |
708 | ||
709 | return $colour; | |
c2b15814 MT |
710 | } |
711 | ||
712 | 1; |