Project

General

Profile

Download (14.3 KB) Statistics
| Branch: | Tag: | Revision:
1
<?php
2
/*
3
 * status_openvpn.php
4
 *
5
 * part of pfSense (https://www.pfsense.org)
6
 * Copyright (c) 2004-2013 BSD Perimeter
7
 * Copyright (c) 2013-2016 Electric Sheep Fencing
8
 * Copyright (c) 2014-2024 Rubicon Communications, LLC (Netgate)
9
 * Copyright (c) 2008 Shrew Soft Inc.
10
 * All rights reserved.
11
 *
12
 * Licensed under the Apache License, Version 2.0 (the "License");
13
 * you may not use this file except in compliance with the License.
14
 * You may obtain a copy of the License at
15
 *
16
 * http://www.apache.org/licenses/LICENSE-2.0
17
 *
18
 * Unless required by applicable law or agreed to in writing, software
19
 * distributed under the License is distributed on an "AS IS" BASIS,
20
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
21
 * See the License for the specific language governing permissions and
22
 * limitations under the License.
23
 */
24

    
25
##|+PRIV
26
##|*IDENT=page-status-openvpn
27
##|*NAME=Status: OpenVPN
28
##|*DESCR=Allow access to the 'Status: OpenVPN' page.
29
##|*MATCH=status_openvpn.php*
30
##|-PRIV
31

    
32
$pgtitle = array(gettext("Status"), gettext("OpenVPN"));
33
$shortcut_section = "openvpn";
34

    
35
require_once("guiconfig.inc");
36
require_once("openvpn.inc");
37
require_once("shortcuts.inc");
38
require_once("service-utils.inc");
39

    
40
$servers = openvpn_get_active_servers();
41
$sk_servers = openvpn_get_active_servers("p2p");
42
$clients = openvpn_get_active_clients();
43

    
44
/* Handle AJAX */
45
if ($_POST['action']) {
46
	if ($_POST['action'] == "kill") {
47
		$port      = $_POST['port'];
48
		$remipp    = $_POST['remipp'];
49
		$client_id = $_POST['client_id'];
50
		$error     = false;
51

    
52
		/* Validate remote IP address and port. */
53
		if (!is_ipaddrwithport($remipp)) {
54
			$error = true;
55
		}
56
		/* Validate submitted server ID */
57
		$found_server = false;
58
		foreach ($servers as $server) {
59
			if ($port == $server['mgmt']) {
60
				$found_server = true;
61
			} else {
62
				continue;
63
			}
64
		}
65

    
66
		if (!$error && $found_server) {
67
			$retval = openvpn_kill_client($port, $remipp, $client_id);
68
			echo htmlentities("|{$port}|{$remipp}|{$retval}|");
69
		} else {
70
			echo gettext("invalid input");
71
		}
72
		exit;
73
	}
74
}
75
if ($_POST['action']) {
76
	if (($_POST['action'] == "showrule") && is_numeric($_POST['vpnid']) &&
77
	    !preg_match("/[^a-zA-Z0-9\.\-_]/", $_POST['username']) && is_port($_POST['port'])) {
78
		$rulesfile = "{$g['tmp_path']}/ovpn_ovpns{$_POST['vpnid']}_{$_POST['username']}_{$_POST['port']}.rules";
79
		if (file_exists($rulesfile)) {
80
			$rule_text = base64_encode(file_get_contents($rulesfile));
81
			echo $rule_text;
82
		}
83
		exit;
84
	}
85
}
86

    
87
include("head.inc"); ?>
88

    
89
<form action="status_openvpn.php" method="get" name="iform">
90
<script type="text/javascript">
91
//<![CDATA[
92
	function killClient(mport, remipp, client_id) {
93
		if (client_id === '') {
94
			$('a[id="i:' + mport + ":" + remipp + '"]').first().children('i').removeClass().addClass('fa-solid fa-cog fa-spin text-danger');
95
		} else {
96
			$('a[id="i:' + mport + ":" + remipp + '"]').last().children('i').removeClass().addClass('fa-solid fa-cog fa-spin text-danger');
97
		}
98

    
99
		$.ajax(
100
			"<?=$_SERVER['SCRIPT_NAME'];?>",
101
			{
102
				type: "post",
103
				data: {
104
					action:           "kill",
105
					port:		  mport,
106
					remipp:		  remipp,
107
					client_id:	  client_id
108
				},
109
				complete: killComplete
110
			}
111
		);
112
	}
113

    
114
	function killComplete(req) {
115
		var values = req.responseText.split("|");
116
		if (values[3] != "0") {
117
	//		alert('<?=gettext("An error occurred.");?>' + ' (' + values[3] + ')');
118
			return;
119
		}
120

    
121
		$('tr[id="r:' + values[1] + ":" + values[2] + '"]').each(
122
			function(index,row) { $(row).fadeOut(1000); }
123
		);
124
	}
125

    
126
	function showRuleContents(vpnid, username, port) {
127
			$('#rulesviewer_text').text("...Loading...");
128
			$('#rulesviewer').modal('show');
129

    
130
			$.ajax(
131
				"<?=$_SERVER['SCRIPT_NAME'];?>",
132
				{
133
					type: 'post',
134
					data: {
135
						vpnid:           vpnid,
136
						username:     username,
137
						port:             port,
138
						action:      'showrule'
139
					},
140
					complete: ruleComplete
141
				}
142
			);
143
	}
144

    
145
	function ruleComplete(req) {
146
			$('#rulesviewer_text').text(atob(req.responseText));
147
			$('#rulesviewer_text').attr('readonly', true);
148
	}
149

    
150
//]]>
151
</script>
152

    
153
<?php
154
	$i = 0;
155
	foreach ($servers as $server):
156
?>
157

    
158
<div class="panel panel-default">
159
		<div class="panel-heading"><h2 class="panel-title">ovpns<?= $server['vpnid'] ?>: <?=htmlspecialchars($server['name']);?> / <?=gettext('Client Connections') . ": " . ($server['conns'][0]['common_name'] != '[error]' ? sizeof($server['conns']) : '0');?></h2></div>
160
		<div class="panel-body table-responsive">
161
			<table class="table table-striped table-hover table-condensed sortable-theme-bootstrap" data-sortable>
162
				<thead>
163
					<tr>
164
						<th><?=gettext("Common Name")?></th>
165
						<th><?=gettext("Real Address")?></th>
166
						<th><?=gettext("Virtual Address"); ?></th>
167
						<th><?=gettext("Last Change"); ?></th>
168
						<th><?=gettext("Bytes Sent")?></th>
169
						<th><?=gettext("Bytes Received")?></th>
170
						<th><?=gettext("Cipher")?></th>
171
						<th><?=gettext("Actions")?></th>
172
					</tr>
173
				</thead>
174
				<tbody>
175

    
176
					<?php
177
							foreach ($server['conns'] as $conn):
178
								$remote_port = substr($conn['remote_host'], strpos($conn['remote_host'], ':') + 1);
179
								$rulesfile = "{$g['tmp_path']}/ovpn_ovpns{$server['vpnid']}_{$conn['user_name']}_{$remote_port}.rules";
180
					?>
181
					<tr id="<?php echo "r:{$server['mgmt']}:{$conn['remote_host']}"; ?>">
182
						<td>
183
							<?=$conn['common_name'];?>
184
					<?php if (!empty($conn['common_name']) && !empty($conn['user_name']) && ($conn['user_name'] != "UNDEF")): ?>
185
							<br />
186
					<?php endif; ?>
187
					<?php if (!empty($conn['user_name']) && ($conn['user_name'] != "UNDEF")): ?>
188
							<?=$conn['user_name'];?>
189
					<?php endif; ?>
190
						</td>
191
						<td><?=$conn['remote_host'];?></td>
192
						<td>
193
							<?=$conn['virtual_addr'];?>
194
					<?php if (!empty($conn['virtual_addr']) && !empty($conn['virtual_addr6'])): ?>
195
							<br />
196
					<?php endif; ?>
197
							<?=$conn['virtual_addr6'];?>
198
						</td>
199
						<td><?=$conn['connect_time'];?></td>
200
						<td data-value="<?=trim($conn['bytes_sent'])?>"><?=format_bytes($conn['bytes_sent']);?></td>
201
						<td data-value="<?=trim($conn['bytes_recv'])?>"><?=format_bytes($conn['bytes_recv']);?></td>
202
						<td data-value="<?=trim($conn['cipher'])?>"><?=$conn['cipher'];?></td>
203
						<td>
204

    
205
					<?php if (file_exists($rulesfile)): ?>
206
							<a
207
							onclick="showRuleContents('<?=$server['vpnid'];?>', '<?=$conn['user_name'];?>', '<?=$remote_port;?>');" style="cursor:pointer;"
208
							   title="<?php echo gettext("Show RADIUS ACL generated ruleset"); ?>">
209
							<i class="fa-solid fa-info"></i>
210
							</a>&nbsp;
211
					<?php endif; ?>
212
							<a
213
							   onclick="killClient('<?=$server['mgmt'];?>', '<?=$conn['remote_host'];?>', '');" style="cursor:pointer;"
214
							   id="<?php echo "i:{$server['mgmt']}:{$conn['remote_host']}"; ?>"
215
							   title="<?php echo sprintf(gettext("Kill client connection from %s"), $conn['remote_host']); ?>">
216
							<i class="fa-solid fa-times"></i>
217
							</a>&nbsp;
218
							<a
219
							   onclick="killClient('<?=$server['mgmt'];?>', '<?=$conn['remote_host'];?>', '<?=$conn['client_id'];?>');" style="cursor:pointer;"
220
							   id="<?php echo "i:{$server['mgmt']}:{$conn['remote_host']}"; ?>"
221
							   title="<?php echo sprintf(gettext("Halt client connection from %s"), $conn['remote_host']); ?>">
222
							<i class="fa-solid fa-times-circle text-danger"></i>
223
							</a>
224
						</td>
225
					</tr>
226
					<?php
227
							endforeach;
228
					?>
229
				</tbody>
230
				<tfoot>
231
					<tr>
232
						<td colspan="7">
233
						</td>
234
						<td colspan="1">
235
							<?php $ssvc = find_service_by_openvpn_vpnid($server['vpnid']); ?>
236
							<?= get_service_status_icon($ssvc, false, true, false, "service_state"); ?>
237
							<?= get_service_control_links($ssvc); ?>
238
						</td>
239
					</tr>
240
				</tfoot>
241
			</table>
242
		</div>
243
</div>
244
<?php
245
		if (is_array($server['routes']) && count($server['routes'])):
246
?>
247
<div id="shroutebut-<?= $i ?>">
248
	<button type="button" class="btn btn-info" onClick="show_routes('tabroute-<?= $i ?>','shroutebut-<?= $i ?>')" value="<?php echo gettext("Show Routing Table"); ?>">
249
		<i class="fa-solid fa-plus-circle icon-embed-btn"></i>
250
		<?php echo gettext("Show Routing Table"); ?>
251
	</button>
252
	- <?= gettext("Display OpenVPN's internal routing table for this server.") ?>
253
	<br /><br />
254
</div>
255
<div class="panel panel-default" id="tabroute-<?=$i?>" style="display: none;">
256
		<div class="panel-heading"><h2 class="panel-title"><?=htmlspecialchars($server['name']);?> <?=gettext("Routing Table"); ?></h2></div>
257
		<div class="panel-body table-responsive">
258
			<table class="table table-striped table-hover table-condensed sortable-theme-bootstrap" data-sortable>
259
				<thead>
260
					<tr>
261
						<th><?=gettext("Common Name"); ?></th>
262
						<th><?=gettext("Real Address"); ?></th>
263
						<th><?=gettext("Target Network"); ?></th>
264
						<th><?=gettext("Last Used"); ?></th>
265
					</tr>
266
				</thead>
267
				<tbody>
268

    
269
<?php
270
			foreach ($server['routes'] as $conn):
271
?>
272
					<tr id="<?php echo "r:{$server['mgmt']}:{$conn['remote_host']}"; ?>">
273
						<td><?=$conn['common_name'];?></td>
274
						<td><?=$conn['remote_host'];?></td>
275
						<td><?=$conn['virtual_addr'];?></td>
276
						<td><?=$conn['last_time'];?></td>
277
					</tr>
278
<?php
279
			endforeach;
280
?>
281
				</tbody>
282
				<tfoot>
283
					<tr>
284
						<td colspan="4"><?= gettext("An IP address followed by C indicates a host currently connected through the VPN.") ?></td>
285
					</tr>
286
				</tfoot>
287
			</table>
288
		</div>
289
</div>
290
<?php
291
		endif;
292
?>
293
<br />
294
<?php
295
		$i++;
296
	endforeach;
297
?>
298
<br />
299

    
300
<?php
301
	if (!empty($sk_servers)) {
302
?>
303
<div class="panel panel-default">
304
	<div class="panel-heading"><h2 class="panel-title"><?=gettext("Peer to Peer Server Instance Statistics"); ?></h2></div>
305
		<div class="panel-body table-responsive">
306
			<table class="table table-striped table-hover table-condensed sortable-theme-bootstrap" data-sortable>
307
				<thead>
308
					<tr>
309
						<th><?=gettext("Name"); ?></th>
310
						<th><?=gettext("Status"); ?></th>
311
						<th><?=gettext("Last Change"); ?></th>
312
						<th><?=gettext("Virtual Address"); ?></th>
313
						<th><?=gettext("Remote Host"); ?></th>
314
						<th><?=gettext("Bytes Sent"); ?></th>
315
						<th><?=gettext("Bytes Received"); ?></th>
316
						<th><?=gettext("Service"); ?></th>
317
					</tr>
318
				</thead>
319
				<tbody>
320

    
321
<?php
322
		foreach ($sk_servers as $sk_server):
323
?>
324
					<tr id="<?php echo "r:{$sk_server['port']}:{$sk_server['vpnid']}"; ?>">
325
						<td>
326
							ovpns<?=$sk_server['vpnid'];?><br/>
327
							<?=htmlspecialchars($sk_server['name']);?>
328
						</td>
329
						<td><?=$sk_server['status'];?></td>
330
						<td><?=$sk_server['connect_time'];?></td>
331
						<td>
332
							<?=$sk_server['virtual_addr'];?>
333
					<?php if (!empty($sk_server['virtual_addr']) && !empty($sk_server['virtual_addr6'])): ?>
334
							<br />
335
					<?php endif; ?>
336
							<?=$sk_server['virtual_addr6'];?>
337
						</td>
338
						<td><?=$sk_server['remote_host'];?></td>
339
						<td data-value="<?=trim($sk_server['bytes_sent'])?>"><?=format_bytes($sk_server['bytes_sent']);?></td>
340
						<td data-value="<?=trim($sk_server['bytes_recv'])?>"><?=format_bytes($sk_server['bytes_recv']);?></td>
341
						<td>
342
							<?php $ssvc = find_service_by_openvpn_vpnid($sk_server['vpnid']); ?>
343
							<?= get_service_status_icon($ssvc, false, true); ?>
344
							<?= get_service_control_links($ssvc, true); ?>
345
						</td>
346
					</tr>
347
<?php
348
		endforeach;
349
?>
350
				</tbody>
351
			</table>
352
		</div>
353
</div>
354

    
355
<?php
356
	}
357
?>
358
<br />
359
<?php
360
	if (!empty($clients)) {
361
?>
362
<div class="panel panel-default">
363
	<div class="panel-heading"><h2 class="panel-title"><?=gettext("Client Instance Statistics"); ?></h2></div>
364
		<div class="panel-body table-responsive">
365
			<table class="table table-striped table-hover table-condensed sortable-theme-bootstrap" data-sortable>
366
				<thead>
367
					<tr>
368
						<th><?=gettext("Name"); ?></th>
369
						<th><?=gettext("Status"); ?></th>
370
						<th><?=gettext("Last Change"); ?></th>
371
						<th><?=gettext("Local Address"); ?></th>
372
						<th><?=gettext("Virtual Address"); ?></th>
373
						<th><?=gettext("Remote Host"); ?></th>
374
						<th><?=gettext("Bytes Sent"); ?></th>
375
						<th><?=gettext("Bytes Received"); ?></th>
376
						<th><?=gettext("Service"); ?></th>
377
					</tr>
378
				</thead>
379
				<tbody>
380

    
381
<?php
382
		foreach ($clients as $client):
383
?>
384
					<tr id="<?php echo "r:{$client['port']}:{$client['vpnid']}"; ?>">
385
						<td>
386
							ovpnc<?= $client['vpnid'] ?><br/>
387
							<?=htmlspecialchars($client['name']);?>
388
						</td>
389
						<td><?=$client['status'];?></td>
390
						<td><?=$client['connect_time'];?></td>
391
						<td>
392
					<?php if (empty($client['local_host']) && empty($client['local_port'])): ?>
393
							(pending)
394
					<?php else: ?>
395
							<?=$client['local_host'];?>:<?=$client['local_port'];?>
396
					<?php endif; ?>
397
						</td>
398
						<td>
399
							<?=$client['virtual_addr'];?>
400
					<?php if (!empty($client['virtual_addr']) && !empty($client['virtual_addr6'])): ?>
401
							<br />
402
					<?php endif; ?>
403
							<?=$client['virtual_addr6'];?>
404
						</td>
405
						<td>
406
					<?php if (empty($client['remote_host']) && empty($client['remote_port'])): ?>
407
							(pending)
408
					<?php else: ?>
409
							<?=$client['remote_host'];?>:<?=$client['remote_port'];?>
410
					<?php endif; ?>
411
						</td>
412
						<td data-value="<?=trim($client['bytes_sent'])?>"><?=format_bytes($client['bytes_sent']);?></td>
413
						<td data-value="<?=trim($client['bytes_recv'])?>"><?=format_bytes($client['bytes_recv']);?></td>
414
						<td>
415
							<?php $ssvc = find_service_by_openvpn_vpnid($client['vpnid']); ?>
416
							<?= get_service_status_icon($ssvc, false, true); ?>
417
							<?= get_service_control_links($ssvc, true); ?>
418
						</td>
419
					</tr>
420
<?php
421
		endforeach;
422
?>
423
				</tbody>
424
			</table>
425
		</div>
426
	</div>
427

    
428
<?php
429
}
430

    
431
if ($DisplayNote) {
432
 	print_info_box(gettext("If there are custom options that override the management features of OpenVPN on a client or server, they will cause that OpenVPN instance to not work correctly with this status page."));
433
}
434

    
435
if ((empty($clients)) && (empty($servers)) && (empty($sk_servers))) {
436
	print_info_box(gettext("No OpenVPN instances defined."));
437
}
438

    
439
// Create a Modal object to display RADIUS ACL generated ruleset
440
$form = new Form(FALSE);
441
$modal = new Modal('RADIUS ACL Generated Ruleset', 'rulesviewer', 'large', 'Close');
442
$modal->addInput(new Form_Textarea (
443
	'rulesviewer_text',
444
	null,
445
	'...Loading...'
446
))->removeClass('form-control')->addClass('row-fluid col-sm-11')->setAttribute('rows', '10')->setAttribute('wrap', 'soft');
447
$form->add($modal);
448
print($form);
449
?>
450
</form>
451

    
452
<script type="text/javascript">
453
//<![CDATA[
454

    
455
function show_routes(id, buttonid) {
456
	document.getElementById(buttonid).innerHTML='';
457
	aodiv = document.getElementById(id);
458
	aodiv.style.display = "block";
459
}
460

    
461
//]]>
462
</script>
463

    
464
<?php include("foot.inc"); ?>
(182-182/232)