root/psad/tags/psad-2.0.2-pre6/parsetest.pl

Revision 907, 11.2 kB (checked in by mbr, 5 years ago)

added parsetest.pl

  • Property svn:eol-style set to native
  • Property svn:executable set to *
  • Property svn:keywords set to Author Date Id Revision
Line 
1 #!/usr/bin/perl -w
2 #
3 #####################################################################
4 #
5 # File: parsetest.pl
6 #
7 # Purpose: To test substr() vs. regex-based packet parser routine
8 #          in psad.
9 #
10 # Execution: perl -d:DProf ./parsetest.pl && dprofpp tmon.out
11 #
12 # Author: Michael Rash
13 #
14 # Sample output (it seems clear that the regex parser is faster):
15 #
16 #    $  perl -d:DProf ./parsetest.pl && dprofpp tmon.out
17 #    Sat Nov  1 09:16:53 2003 .. generating packet array.
18 #    Sat Nov  1 09:16:53 2003 .. parse1()
19 #    Sat Nov  1 09:16:56 2003 .. parse2()
20 #    icmp: 20002
21 #    Total Elapsed Time =  3.30997 Seconds
22 #      User+System Time =  3.30997 Seconds
23 #    Exclusive Times
24 #    %Time ExclSec CumulS #Calls sec/call Csec/c  Name
25 #     82.4   2.730  2.730      1   2.7300 2.7300  main::parse1
26 #     15.7   0.520  0.520      1   0.5200 0.5200  main::parse2
27 #     0.30   0.010  0.010      1   0.0100 0.0100  main::BEGIN
28 #     0.00   0.000 -0.000      1   0.0000      -  strict::import
29 #     0.00   0.000 -0.000      1   0.0000      -  strict::bits
30 #
31 #####################################################################
32 #
33 # $Id$
34 #
35
36 use strict;
37
38 my @arr;
39 my @err_pkts;
40 my $tcp_ctr;
41 my $udp_ctr;
42 my $icmp_ctr;
43 my $test_pkt = 'Oct 31 13:07:46 orthanc kernel: DROP IN=eth0 ' .
44     'OUT= MAC=00:a0:cc:28:42:5a:00:01:5c:22:2e:42:08:00 ' .
45     'SRC=208.205.78.126 DST=68.49.82.239 LEN=92 TOS=0x00 ' .
46     'PREC=0x00 TTL=112 ID=39829 PROTO=ICMP TYPE=8 CODE=0 ' .
47     'ID=59175 SEQ=21559';
48
49 print scalar localtime(), " .. generating packet array.\n";
50 for (my $i=0; $i<=10000; $i++) {
51     push @arr, $test_pkt;
52 }
53
54 print scalar localtime(), " .. parse1()\n";
55 &parse1();
56 print scalar localtime(), " .. parse2()\n";
57 &parse2();
58
59 if ($tcp_ctr) {
60     print "tcp: $tcp_ctr\n";
61 }
62 if ($udp_ctr) {
63     print "udp: $udp_ctr\n";
64 }
65 if ($icmp_ctr) {
66     print "icmp: $icmp_ctr\n";
67 }
68
69 exit 0;
70 #==================================================
71
72 sub parse1() {
73     for my $pkt (@arr) {
74         my $src = '';
75         my $dst = '';
76         my $len = -1;
77         my $tos = '';
78         my $ttl = -1;
79         my $id  = -1;
80         my $proto = '';
81         my $sp    = -1;
82         my $dp    = -1;
83         my $win   = -1;
84         my $type  = -1;
85         my $code  = -1;
86         my $seq   = -1;
87         my $flags = '';
88         my $sid   = 0;
89         my $chain    = '';
90         my $intf     = '';
91         my $in_intf  = '';
92         my $out_intf = '';
93         my $dshield_str = '';
94         my $index;
95
96         my @pkt_fields = split /\s+/, $pkt;
97         for my $arg (@pkt_fields) {
98             $index = index($arg, 'SID');
99             if ($index == 0) {
100                 $sid = substr($arg,
101                     $index + length('SID'));
102             }
103             ### find all of the packet fields
104             $index = index($arg, 'IN=');
105             if ($index == 0) {
106                 $in_intf = substr($arg, $index+3);
107                 next;
108             }
109             $index = index($arg, 'OUT=');
110             if ($index == 0) {
111                 $out_intf = substr($arg, $index+4);
112                 next;
113             }
114             $index = index($arg, 'SRC=');
115             if ($index == 0) {
116                 $src = substr($arg, $index+4);
117                 next;
118             }
119             $index = index($arg, 'DST=');
120             if ($index == 0) {
121                 $dst = substr($arg, $index+4);
122                 next;
123             }
124             $index = index($arg, 'LEN=');
125             if ($index == 0) {
126                 $len = substr($arg, $index+4);
127                 next;
128             }
129             $index = index($arg, 'TOS=');
130             if ($index == 0) {
131                 $tos = substr($arg, $index+4);
132                 next;
133             }
134             $index = index($arg, 'TTL=');
135             if ($index == 0) {
136                 $ttl = substr($arg, $index+4);
137                 next;
138             }
139             $index = index($arg, 'ID=');
140             if ($index == 0) {
141                 $id = substr($arg, $index+3);
142                 next;
143             }
144             $index = index($arg, 'PROTO=');
145             if ($index == 0) {
146                 $proto = substr($arg, $index+6);
147                 next;
148             }
149             $index = index($arg, 'SPT=');
150             if ($index == 0) {
151                 $sp = substr($arg, $index+4);
152                 next;
153             }
154             $index = index($arg, 'DPT=');
155             if ($index == 0) {
156                 $dp = substr($arg, $index+4);
157                 next;
158             }
159             $index = index($arg, 'WINDOW=');
160             if ($index == 0) {
161                 $win = substr($arg, $index+7);
162                 next;
163             }
164             $index = index($arg, 'TYPE=');
165             if ($index == 0) {
166                 $type = substr($arg, $index+5);
167                 next;
168             }
169             $index = index($arg, 'CODE=');
170             if ($index == 0) {
171                 $code = substr($arg, $index+5);
172                 next;
173             }
174             $index = index($arg, 'SEQ=');
175             if ($index == 0) {
176                 $seq = substr($arg, $index+4);
177                 next;
178             }
179         }
180
181         ### get the in/out interface and iptables chain
182         if ($in_intf and not $out_intf) {
183             $intf = $in_intf;
184             $chain = 'input';
185         } elsif ($in_intf and $out_intf) {
186             $intf = $in_intf;
187             $chain = 'forward';
188         } elsif (not $in_intf and $out_intf) {
189             $intf = $out_intf;
190             $chain = 'output';
191         }
192
193         unless ($intf and $chain) {
194             push @err_pkts, $pkt;
195             next PKT;
196         }
197
198         ### May 18 22:21:26 orthanc kernel: DROP IN=eth2 OUT=
199         ### MAC=00:60:1d:23:d0:01:00:60:1d:23:d3:0e:08:00 SRC=192.168.20.25
200         ### DST=192.168.20.1 LEN=60 TOS=0x10 PREC=0x00 TTL=64 ID=47300 DF
201         ### PROTO=TCP SPT=34111 DPT=6345 WINDOW=5840 RES=0x00 SYN URGP=0
202         if ($proto eq 'TCP') {
203             if ($pkt =~ /\sRES=\S+\s*(.*)\s+URGP=/) {
204                     $flags = $1;
205             }
206             $proto = 'tcp';
207             $flags = 'NULL' unless $flags;  ### default to NULL
208             if (!$sid and ($flags =~ /ACK/ || $flags =~ /RST/)) {
209                 push @err_pkts, $pkt;
210                 next PKT;
211             }
212             unless ($flags !~ /WIN/ &&
213                     $flags =~ /ACK/ ||
214                     $flags =~ /SYN/ ||
215                     $flags =~ /RST/ ||
216                     $flags =~ /URG/ ||
217                     $flags =~ /PSH/ ||
218                     $flags =~ /FIN/ ||
219                     $flags eq 'NULL') {
220                 push @err_pkts, $pkt;
221                 next PKT;
222             }
223             ### make sure we have a "reasonable" packet (note that nmap
224             ### can scan port 0 and iptables can report this fact)
225             unless ($src and $dst and $len >= 0 and $tos and $ttl >= 0
226                     and $id >= 0 and $proto and $sp >= 0 and $dp >= 0
227                     and $win >= 0 and $flags) {
228                 push @err_pkts, $pkt;
229                 next PKT;
230             }
231             $tcp_ctr++;
232         ### May 18 22:21:26 orthanc kernel: DROP IN=eth2 OUT=
233         ### MAC=00:60:1d:23:d0:01:00:60:1d:23:d3:0e:08:00
234         ### SRC=192.168.20.25 DST=192.168.20.1 LEN=28 TOS=0x00 PREC=0x00
235         ### TTL=40 ID=47523 PROTO=UDP SPT=57339 DPT=305 LEN=8
236         } elsif ($proto eq 'UDP') {
237             $proto = 'udp';
238             ### make sure we have a "reasonable" packet (note that nmap
239             ### can scan port 0 and iptables can report this fact)
240             unless ($src and $dst and $len >= 0 and $tos and $ttl >= 0
241                     and $id >= 0 and $proto and $sp >= 0 and $dp >= 0) {
242                 push @err_pkts, $pkt;
243                 next PKT;
244             }
245             $udp_ctr++;
246         } elsif ($proto eq 'ICMP') {
247             $proto = 'icmp';
248             unless ($src and $dst and $len >= 0 and $ttl >= 0 and $proto
249                     and $type >= 0 and $code >= 0 and $id >= 0
250                     and $seq >= 0) {
251                 push @err_pkts, $pkt;
252                 next PKT;
253             }
254             $icmp_ctr++;
255         } else {
256             ### Sometimes the iptables log entry gets messed up due to
257             ### buffering issues so we write it to the error log.
258             push @err_pkts, $pkt;
259             next PKT;
260         }
261     }
262     return;
263 }
264
265 sub parse2() {
266     for my $pkt (@arr) {
267         my $src = '';
268         my $dst = '';
269         my $len = -1;
270         my $tos = '';
271         my $ttl = -1;
272         my $id  = -1;
273         my $proto = '';
274         my $sp    = -1;
275         my $dp    = -1;
276         my $win   = -1;
277         my $type  = -1;
278         my $code  = -1;
279         my $seq   = -1;
280         my $flags = '';
281         my $sid   = 0;
282         my $chain    = '';
283         my $intf     = '';
284         my $in_intf  = '';
285         my $out_intf = '';
286         my $dshield_str = '';
287         if ($pkt =~ /SRC=(\S+)\s+DST=(\S+)\s+LEN=(\d+)\s+TOS=(\S+)
288                     \s*.*\s+TTL=(\d+)\s+ID=(\d+)\s*.*\s+PROTO=TCP\s+
289                     SPT=(\d+)\s+DPT=(\d+)\s+WINDOW=(\d+)\s+
290                     RES=\S+\s*(.*)\s+URGP=/x) {
291             ($src, $dst, $len, $tos, $ttl, $id, $sp, $dp, $win, $flags) =
292                 ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10);
293             $proto = 'tcp';
294             $flags = 'NULL' unless $flags;  ### default to NULL
295             if (!$sid and ($flags =~ /ACK/ || $flags =~ /RST/)) {
296                 next PKT;
297             }
298             ### per page 595 of the Camel book, "if /blah1|blah2/"
299             ### can be slower than "if /blah1/ || /blah2/
300             unless ($flags !~ /WIN/ &&
301                     $flags =~ /ACK/ ||
302                     $flags =~ /SYN/ ||
303                     $flags =~ /RST/ ||
304                     $flags =~ /URG/ ||
305                     $flags =~ /PSH/ ||
306                     $flags =~ /FIN/ ||
307                     $flags eq 'NULL') {
308                 push @err_pkts, $pkt;
309                 next PKT;
310             }
311             $tcp_ctr++;
312         ### May 18 22:21:26 orthanc kernel: DROP IN=eth2 OUT=
313         ### MAC=00:60:1d:23:d0:01:00:60:1d:23:d3:0e:08:00
314         ### SRC=192.168.20.25 DST=192.168.20.1 LEN=28 TOS=0x00 PREC=0x00
315         ### TTL=40 ID=47523 PROTO=UDP SPT=57339 DPT=305 LEN=8
316         } elsif ($pkt =~ /SRC=(\S+)\s+DST=(\S+)\s+LEN=(\d+)\s+TOS=(\S+)
317                           \s.*TTL=(\d+)\s+ID=(\d+)\s*.*\s+PROTO=UDP\s+
318                           SPT=(\d+)\s+DPT=(\d+)/x) {
319             ($src, $dst, $len, $tos, $ttl, $id, $sp, $dp) =
320                 ($1,$2,$3,$4,$5,$6,$7,$8);
321             $proto = 'udp';
322             $udp_ctr++;
323         } elsif ($pkt =~ /SRC=(\S+)\s+DST=(\S+)\s+LEN=(\d+).*
324                           TTL=(\d+).*PROTO=ICMP\s+TYPE=(\d+)\s+
325                           CODE=(\d+)\s+ID=(\d+)\s+SEQ=(\d+)/x) {
326             ($src, $dst, $len, $ttl, $type, $code, $id, $seq) =
327                 ($1,$2,$3,$4,$5,$6,$7,$8);
328             $proto = 'icmp';
329             $icmp_ctr++;
330         } else {
331             ### Sometimes the iptables log entry gets messed up due to
332             ### buffering issues so we write it to the error log.
333             push @err_pkts, $pkt;
334             next PKT;
335         }
336         if ($pkt =~ /IN=(\S+)\s+OUT=\s/) {
337             $intf = $1;
338             $chain = 'input';
339         } elsif ($pkt =~ /IN=(\S+)\s+OUT=\S/) {
340             $intf = $1;
341             $chain = 'forward';
342         }
343     }
344     return;
345 }
Note: See TracBrowser for help on using the browser.