Skip to content

HTTPS clone URL

Subversion checkout URL

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