Projet

Général

Profil

Télécharger (17,2 ko) Statistiques
| Branche: | Tag: | Révision:

univnautes / usr / local / www / diag_packet_capture.php @ 77a4e6d7

1
<?php
2
/*
3

    
4
	Redistribution and use in source and binary forms, with or without
5
	modification, are permitted provided that the following conditions are met:
6

    
7
	1. Redistributions of source code must retain the above copyright notice,
8
	this list of conditions and the following disclaimer.
9

    
10
	2. Redistributions in binary form must reproduce the above copyright
11
	notice, this list of conditions and the following disclaimer in the
12
	documentation and/or other materials provided with the distribution.
13

    
14
	THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
15
	INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
16
	AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
17
	AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
18
	OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19
	SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20
	INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21
	CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22
	ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
23
	POSSIBILITY OF SUCH DAMAGE.
24
*/
25

    
26
/*
27
	pfSense_BUILDER_BINARIES:	/bin/ps	/usr/bin/grep	/usr/sbin/tcpdump
28
	pfSense_MODULE:	routing
29
*/
30

    
31
##|+PRIV
32
##|*IDENT=page-diagnostics-packetcapture
33
##|*NAME=Diagnostics: Packet Capture page
34
##|*DESCR=Allow access to the 'Diagnostics: Packet Capture' page.
35
##|*MATCH=diag_packet_capture.php*
36
##|-PRIV
37

    
38
$allowautocomplete = true;
39

    
40
function fixup_host_logic($value) {
41
	return str_replace(array(" ", ",", "+", "|", "!"), array("", "and ", "and ", "or ", "not "), $value);
42
}
43
function strip_host_logic($value) {
44
	return str_replace(array(" ", ",", "+", "|", "!"), array("", "", "", "", ""), $value);
45
}
46
function get_host_boolean($value, $host) {
47
	$value = str_replace(array("!", $host), array("", ""), $value);
48
	$andor = "";
49
	switch (trim($value)) {
50
		case "|":
51
			$andor = "or ";
52
			break;
53
		case ",":
54
		case "+":
55
			$andor = "and ";
56
			break;
57
	}
58
	return $andor;
59
}
60
function has_not($value) {
61
	return strpos($value, '!') !== false;
62
}
63
function fixup_not($value) {
64
	return str_replace("!", "not ", $value);
65
}
66
function strip_not($value) {
67
	return ltrim(trim($value), '!');
68
}
69

    
70
function fixup_host($value, $position) {
71
	$host = strip_host_logic($value);
72
	$not = has_not($value) ? "not " : "";
73
	$andor = ($position > 0) ? get_host_boolean($value, $host) : "";
74
	if (is_ipaddr($host))
75
		return "{$andor}host {$not}" . $host;
76
	elseif (is_subnet($host))
77
		return "{$andor}net {$not}" . $host;
78
	else
79
		return "";
80
}
81

    
82
if ($_POST['downloadbtn'] == gettext("Download Capture"))
83
	$nocsrf = true;
84

    
85
$pgtitle = array(gettext("Diagnostics"), gettext("Packet Capture"));
86
require_once("guiconfig.inc");
87
require_once("pfsense-utils.inc");
88

    
89
$fp = "/root/";
90
$fn = "packetcapture.cap";
91
$snaplen = 0;//default packet length
92
$count = 100;//default number of packets to capture
93

    
94
$fams = array('ip', 'ip6');
95
$protos = array('icmp', 'icmp6', 'tcp', 'udp', 'arp', 'carp', 'esp',
96
		'!icmp', '!icmp6', '!tcp', '!udp', '!arp', '!carp', '!esp');
97

    
98
$input_errors = array();
99

    
100
$interfaces = get_configured_interface_with_descr();
101
if (isset($config['ipsec']['enable']))
102
	$interfaces['ipsec'] = "IPsec";
103
foreach (array('server', 'client') as $mode) {
104
	if (is_array($config['openvpn']["openvpn-{$mode}"])) {
105
		foreach ($config['openvpn']["openvpn-{$mode}"] as $id => $setting) {
106
			if (!isset($setting['disable'])) {
107
				$interfaces['ovpn' . substr($mode, 0, 1) . $setting['vpnid']] = gettext("OpenVPN") . " ".$mode.": ".htmlspecialchars($setting['description']);
108
			}
109
		}
110
	}
111
}
112

    
113
if ($_POST) {
114
	$host = $_POST['host'];
115
	$selectedif = $_POST['interface'];
116
	$count = $_POST['count'];
117
	$snaplen = $_POST['snaplen'];
118
	$port = $_POST['port'];
119
	$detail = $_POST['detail'];
120
	$fam = $_POST['fam'];
121
	$proto = $_POST['proto'];
122

    
123
	if (!array_key_exists($selectedif, $interfaces)) {
124
		$input_errors[] = gettext("Invalid interface.");
125
	}
126
	if ($fam !== "" && $fam !== "ip" && $fam !== "ip6") {
127
		$input_errors[] = gettext("Invalid address family.");
128
	}
129
	if ($proto !== "" && !in_array(strip_not($proto), $protos)) {
130
		$input_errors[] = gettext("Invalid protocol.");
131
	}
132
	
133
	if ($host != "") {
134
		$host_string = str_replace(array(" ", "|", ","), array("", "#|", "#+"), $host);
135
		if (strpos($host_string, '#') === false) {
136
			$hosts = array($host);
137
		} else {
138
			$hosts = explode('#', $host_string);
139
		}
140
		foreach ($hosts as $h) {
141
			if (!is_subnet(strip_host_logic($h)) && !is_ipaddr(strip_host_logic($h))) {
142
				$input_errors[] = sprintf(gettext("A valid IP address or CIDR block must be specified. [%s]"), $h);
143
			}
144
		}
145
	}
146
	if ($port != "") {
147
		if (!is_port(strip_not($port))) {
148
			$input_errors[] = gettext("Invalid value specified for port.");
149
		}
150
	}
151
	if ($snaplen == "") {
152
		$snaplen = 0;
153
	} else {
154
		if (!is_numeric($snaplen) || $snaplen < 0) {
155
			$input_errors[] = gettext("Invalid value specified for packet length.");
156
		}
157
	}
158
	if ($count == "") {
159
		$count = 0;
160
	} else {
161
		if (!is_numeric($count) || $count < 0) {
162
			$input_errors[] = gettext("Invalid value specified for packet count.");
163
		}
164
	}
165

    
166
	if (!count($input_errors)) {
167
		$do_tcpdump = true;
168

    
169
		conf_mount_rw();
170

    
171
		if ($_POST['promiscuous']) {
172
			//if promiscuous mode is checked
173
			$disablepromiscuous = "";
174
		} else {
175
			//if promiscuous mode is unchecked
176
			$disablepromiscuous = "-p";
177
		}
178

    
179
		if ($_POST['dnsquery']) {
180
			//if dns lookup is checked
181
			$disabledns = "";
182
		} else {
183
			//if dns lookup is unchecked
184
			$disabledns = "-n";
185
		}
186

    
187
		if ($_POST['startbtn'] != "" ) {
188
			$action = gettext("Start");
189

    
190
			//delete previous packet capture if it exists
191
			if (file_exists($fp.$fn))
192
				unlink ($fp.$fn);
193

    
194
		} elseif ($_POST['stopbtn']!= "") {
195
			$action = gettext("Stop");
196
			$processes_running = trim(shell_exec("/bin/ps axw -O pid= | /usr/bin/grep tcpdump | /usr/bin/grep {$fn} | /usr/bin/egrep -v '(pflog|grep)'"));
197

    
198
			//explode processes into an array, (delimiter is new line)
199
			$processes_running_array = explode("\n", $processes_running);
200

    
201
			//kill each of the packetcapture processes
202
			foreach ($processes_running_array as $process) {
203
				$process_id_pos = strpos($process, ' ');
204
				$process_id = substr($process, 0, $process_id_pos);
205
				exec("kill $process_id");
206
			}
207

    
208
		} elseif ($_POST['downloadbtn']!= "") {
209
			//download file
210
			$fs = filesize($fp.$fn);
211
			header("Content-Type: application/octet-stream");
212
			header("Content-Disposition: attachment; filename=$fn");
213
			header("Content-Length: $fs");
214
			readfile($fp.$fn);
215
			exit;
216
		}
217
	}
218
} else {
219
	$do_tcpdump = false;
220
}
221

    
222
include("head.inc"); ?>
223

    
224
<body link="#000000" vlink="#0000CC" alink="#0000CC">
225

    
226
<?php
227
include("fbegin.inc");
228
?>
229

    
230
<?php if ($input_errors) print_input_errors($input_errors); ?>
231

    
232
<table width="100%" border="0" cellpadding="0" cellspacing="0" summary="diag packet capture">
233
	<tr><td>
234
	<form action="diag_packet_capture.php" method="post" name="iform" id="iform">
235
	<table width="100%" border="0" cellpadding="6" cellspacing="0" summary="table">
236
		<tr>
237
			<td colspan="3" valign="top" class="listtopic"><?=gettext("Packet capture");?></td>
238
		</tr>
239
		<tr>
240
			<td width="17%" valign="top" class="vncellreq"><?=gettext("Interface");?></td>
241
			<td width="32%" class="vtable">
242
			<select name="interface">
243
			<?php
244
			?>
245
			<?php foreach ($interfaces as $iface => $ifacename): ?>
246
				<option value="<?=$iface;?>" <?php if ($selectedif == $iface) echo "selected=\"selected\""; ?>>
247
				<?php echo $ifacename;?>
248
				</option>
249
			<?php endforeach; ?>
250
			</select>
251
			<br /><?=gettext("Select the interface on which to capture traffic.");?>
252
			</td>
253
		</tr>
254
		<tr>
255
			<td width="17%" valign="top" class="vncellreq"><?=gettext("Promiscuous");?></td>
256
			<td width="51%" class="vtable">
257
			<input name="promiscuous" type="checkbox"<?php if($_POST['promiscuous']) echo " checked=\"checked\""; ?> />
258
			<br /><?=gettext("If checked, the");?> <a target="_blank" href="http://www.freebsd.org/cgi/man.cgi?query=tcpdump&amp;apropos=0&amp;sektion=0&amp;manpath=FreeBSD+8.3-stable&amp;arch=default&amp;format=html"><?= gettext("packet capture")?></a> <?= gettext("will be performed using promiscuous mode.");?>
259
			<br /><b><?=gettext("Note");?>: </b><?=gettext("Some network adapters do not support or work well in promiscuous mode.");?>
260
			</td>
261
		</tr>
262
		<tr>
263
			<td width="17%" valign="top" class="vncellreq"><?=gettext("Address Family");?></td>
264
			<td colspan="2" width="83%" class="vtable">
265
			<select name="fam">
266
				<option value="">Any</option>
267
				<option value="ip" <?php if ($fam == "ip") echo "selected=\"selected\""; ?>>IPv4 Only</option>
268
				<option value="ip6" <?php if ($fam == "ip6") echo "selected=\"selected\""; ?>>IPv6 Only</option>
269
			</select>
270
			<br /><?=gettext("Select the type of traffic to be captured, either Any, IPv4 only or IPv6 only.");?>
271
			</td>
272
		</tr>
273
		<tr>
274
			<td width="17%" valign="top" class="vncellreq"><?=gettext("Protocol");?></td>
275
			<td colspan="2" width="83%" class="vtable">
276
			<select name="proto">
277
				<option value="">Any</option>
278
				<option value="icmp" <?php if ($proto == "icmp") echo "selected=\"selected\""; ?>>ICMP</option>
279
				<option value="!icmp" <?php if ($proto == "!icmp") echo "selected=\"selected\""; ?>>Exclude ICMP</option>
280
				<option value="icmp6" <?php if ($proto == "icmp6") echo "selected=\"selected\""; ?>>ICMPv6</option>
281
				<option value="!icmp6" <?php if ($proto == "!icmp6") echo "selected=\"selected\""; ?>>Exclude ICMPv6</option>
282
				<option value="tcp" <?php if ($proto == "tcp") echo "selected=\"selected\""; ?>>TCP</option>
283
				<option value="!tcp" <?php if ($proto == "!tcp") echo "selected=\"selected\""; ?>>Exclude TCP</option>
284
				<option value="udp" <?php if ($proto == "udp") echo "selected=\"selected\""; ?>>UDP</option>
285
				<option value="!udp" <?php if ($proto == "!udp") echo "selected=\"selected\""; ?>>Exclude UDP</option>
286
				<option value="arp" <?php if ($proto == "arp") echo "selected=\"selected\""; ?>>ARP</option>
287
				<option value="!arp" <?php if ($proto == "!arp") echo "selected=\"selected\""; ?>>Exclude ARP</option>
288
				<option value="carp" <?php if ($proto == "carp") echo "selected=\"selected\""; ?>>CARP (VRRP)</option>
289
				<option value="!carp" <?php if ($proto == "!carp") echo "selected=\"selected\""; ?>>Exclude CARP (VRRP)</option>
290
				<option value="esp" <?php if ($proto == "esp") echo "selected=\"selected\""; ?>>ESP</option>
291
			</select>
292
			<br /><?=gettext("Select the protocol to capture, or Any.");?>
293
			</td>
294
		</tr>
295
		<tr>
296
			<td width="17%" valign="top" class="vncellreq"><?=gettext("Host Address");?></td>
297
			<td colspan="2" width="83%" class="vtable">
298
			<input name="host" class="formfld host" id="host" size="20" value="<?=htmlspecialchars($host);?>" />
299
			<br /><?=gettext("This value is either the Source or Destination IP address or subnet in CIDR notation. The packet capture will look for this address in either field.");?>
300
			<br /><?=gettext("Matching can be negated by preceding the value with \"!\". Multiple IP addresses or CIDR subnets may be specified. Comma (\",\") separated values perform a boolean \"and\". Separating with a pipe (\"|\") performs a boolean \"or\".");?>
301
			<br /><?=gettext("If you leave this field blank, all packets on the specified interface will be captured.");?>
302
			</td>
303
		</tr>
304
		<tr>
305
			<td width="17%" valign="top" class="vncellreq"><?=gettext("Port");?></td>
306
			<td colspan="2" width="83%" class="vtable">
307
			<input name="port" class="formfld unknown" id="port" size="5" value="<?=$port;?>" />
308
			<br /><?=gettext("The port can be either the source or destination port. The packet capture will look for this port in either field.");?>
309
			<br /><?=gettext("Leave blank if you do not want to filter by port.");?>
310
			</td>
311
		</tr>
312
		<tr>
313
			<td width="17%" valign="top" class="vncellreq"><?=gettext("Packet Length");?></td>
314
			<td colspan="2" width="83%" class="vtable">
315
			<input name="snaplen" class="formfld unknown" id="snaplen" size="5" value="<?=$snaplen;?>" />
316
			<br /><?=gettext("The Packet length is the number of bytes of each packet that will be captured. Default value is 0, which will capture the entire frame regardless of its size.");?>
317
			</td>
318
		</tr>
319
		<tr>
320
			<td width="17%" valign="top" class="vncellreq"><?=gettext("Count");?></td>
321
			<td colspan="2" width="83%" class="vtable">
322
			<input name="count" class="formfld unknown" id="count" size="5" value="<?=$count;?>" />
323
			<br /><?=gettext("This is the number of packets the packet capture will grab. Default value is 100.") . "<br />" . gettext("Enter 0 (zero) for no count limit.");?>
324
			</td>
325
		</tr>
326
		<tr>
327
			<td width="17%" valign="top" class="vncellreq"><?=gettext("Level of Detail");?></td>
328
			<td colspan="2" width="83%" class="vtable">
329
			<select name="detail" class="formselect" id="detail" size="1">
330
				<option value="normal" <?php if ($detail == "normal") echo "selected=\"selected\""; ?>><?=gettext("Normal");?></option>
331
				<option value="medium" <?php if ($detail == "medium") echo "selected=\"selected\""; ?>><?=gettext("Medium");?></option>
332
				<option value="high"   <?php if ($detail == "high")   echo "selected=\"selected\""; ?>><?=gettext("High");?></option>
333
				<option value="full"   <?php if ($detail == "full")   echo "selected=\"selected\""; ?>><?=gettext("Full");?></option>
334
			</select>
335
			<br /><?=gettext("This is the level of detail that will be displayed after hitting 'Stop' when the packets have been captured.") .  "<br /><b>" .
336
					gettext("Note:") . "</b> " .
337
					gettext("This option does not affect the level of detail when downloading the packet capture.");?>
338
			</td>
339
		</tr>
340
		<tr>
341
			<td width="17%" valign="top" class="vncellreq"><?=gettext("Reverse DNS Lookup");?></td>
342
			<td colspan="2" width="83%" class="vtable">
343
			<input name="dnsquery" type="checkbox" <?php if($_POST['dnsquery']) echo " checked=\"checked\""; ?> />
344
			<br /><?=gettext("This check box will cause the packet capture to perform a reverse DNS lookup associated with all IP addresses.");?>
345
			<br /><b><?=gettext("Note");?>: </b><?=gettext("This option can cause delays for large packet captures.");?>
346
			</td>
347
		</tr>
348
		<tr>
349
			<td width="17%" valign="top">&nbsp;</td>
350
			<td colspan="2" width="83%">
351
<?php
352

    
353
			/* check to see if packet capture tcpdump is already running */
354
			$processcheck = (trim(shell_exec("/bin/ps axw -O pid= | /usr/bin/grep tcpdump | /usr/bin/grep {$fn} | /usr/bin/egrep -v '(pflog|grep)'")));
355

    
356
			if ($processcheck != "")
357
				$processisrunning = true;
358
			else
359
				$processisrunning = false;
360

    
361
			if (($action == gettext("Stop") or $action == "") and $processisrunning != true)
362
				echo "<input type=\"submit\" name=\"startbtn\" value=\"" . gettext("Start") . "\" />&nbsp;";
363
			else {
364
				echo "<input type=\"submit\" name=\"stopbtn\" value=\"" . gettext("Stop") . "\" />&nbsp;";
365
			}
366
			if (file_exists($fp.$fn) and $processisrunning != true) {
367
				echo "<input type=\"submit\" name=\"viewbtn\" value=\"" . gettext("View Capture") . "\" />&nbsp;";
368
				echo "<input type=\"submit\" name=\"downloadbtn\" value=\"" . gettext("Download Capture") . "\" />";
369
				echo "<br />" . gettext("The packet capture file was last updated:") . " " . date("F jS, Y g:i:s a.", filemtime($fp.$fn));
370
			}
371
?>
372
			</td>
373
		</tr>
374
	</table>
375
	</form>
376
	<table width="100%" border="0" cellpadding="6" cellspacing="0" summary="results">
377
		<tr>
378
		<td valign="top" colspan="2">
379
<?php
380
		echo "<font face=\"terminal\" size=\"2\">";
381
		if ($processisrunning == true)
382
			echo("<strong>" . gettext("Packet Capture is running.") . "</strong><br />");
383

    
384
		if ($do_tcpdump) {
385
			$matches = array();
386

    
387
			if (in_array($fam, $fams))
388
				$matches[] = $fam;
389

    
390
			if (in_array($proto, $protos)) {
391
				$matches[] = fixup_not($proto);
392
			}
393

    
394
			if ($port != "")
395
				$matches[] = "port ".fixup_not($port);
396

    
397
			if ($host != "") {
398
				$hostmatch = "";
399
				$hostcount = 0;
400
				foreach ($hosts as $h) {
401
					$h = fixup_host($h, $hostcount++);
402
					if (!empty($h))
403
						$hostmatch .= " " . $h;
404
				}
405
				if (!empty($hostmatch))
406
					$matches[] = "({$hostmatch})";
407
			}
408

    
409
			if ($count != "0" ) {
410
				$searchcount = "-c " . $count;
411
			} else {
412
				$searchcount = "";
413
			}
414

    
415
			$selectedif = convert_friendly_interface_to_real_interface_name($selectedif);
416

    
417
			if ($action == gettext("Start")) {
418
				$matchstr = implode($matches, " and ");
419
				echo("<strong>" . gettext("Packet Capture is running.") . "</strong><br />");
420
				$cmd = "/usr/sbin/tcpdump -i {$selectedif} {$disablepromiscuous} {$searchcount} -s {$snaplen} -w {$fp}{$fn} " . escapeshellarg($matchstr);
421
				// Debug
422
				//echo $cmd;
423
				mwexec_bg ($cmd);
424
			} else {
425
				//action = stop
426
				echo("<strong>" . gettext("Packet Capture stopped.") . "<br /><br />" . gettext("Packets Captured:") . "</strong><br />");
427
?>
428
				<script type="text/javascript">
429
				//<![CDATA[
430
				window.onload=function(){
431
					document.getElementById("packetsCaptured").wrap='off';
432
				}
433
				//]]>
434
				</script>
435
				<textarea id="packetsCaptured" style="width:98%" name="code" rows="15" cols="66" readonly="readonly">
436
<?php
437
				$detail_args = "";
438
				switch ($detail) {
439
				case "full":
440
					$detail_args = "-vv -e";
441
					break;
442
				case "high":
443
					$detail_args = "-vv";
444
					break;
445
				case "medium":
446
					$detail_args = "-v";
447
					break;
448
				case "normal":
449
				default:
450
					$detail_args = "-q";
451
					break;
452
				}
453
				system("/usr/sbin/tcpdump {$disabledns} {$detail_args} -r {$fp}{$fn}");
454

    
455
				conf_mount_ro();
456
?>
457
				</textarea>
458
<?php
459
			}
460
		}
461
?>
462
		&nbsp;</font>
463
		</td>
464
		</tr>
465
	</table>
466
	</td></tr>
467
</table>
468

    
469
<?php
470
include("fend.inc");
471
?>
472
</body>
473
</html>
(37-37/254)