1
|
<?php
|
2
|
/*
|
3
|
* openvpn.inc
|
4
|
*
|
5
|
* part of pfSense (https://www.pfsense.org)
|
6
|
* Copyright (c) 2006 Fernando Lemos
|
7
|
* Copyright (c) 2006-2013 BSD Perimeter
|
8
|
* Copyright (c) 2013-2016 Electric Sheep Fencing
|
9
|
* Copyright (c) 2014-2025 Rubicon Communications, LLC (Netgate)
|
10
|
* All rights reserved.
|
11
|
*
|
12
|
* This file was rewritten from scratch by Fernando Lemos but
|
13
|
* *MIGHT* contain code previously written by:
|
14
|
*
|
15
|
* Copyright (c) 2005 Peter Allgeyer <allgeyer_AT_web.de>
|
16
|
* Copyright (c) 2004 Peter Curran (peter@closeconsultants.com).
|
17
|
* All rights reserved.
|
18
|
*
|
19
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
20
|
* you may not use this file except in compliance with the License.
|
21
|
* You may obtain a copy of the License at
|
22
|
*
|
23
|
* http://www.apache.org/licenses/LICENSE-2.0
|
24
|
*
|
25
|
* Unless required by applicable law or agreed to in writing, software
|
26
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
27
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
28
|
* See the License for the specific language governing permissions and
|
29
|
* limitations under the License.
|
30
|
*/
|
31
|
|
32
|
require_once('config.inc');
|
33
|
require_once('config.lib.inc');
|
34
|
require_once("certs.inc");
|
35
|
require_once('pfsense-utils.inc');
|
36
|
require_once("auth.inc");
|
37
|
|
38
|
global $openvpn_sharedkey_warning;
|
39
|
$openvpn_sharedkey_warning = gettext(
|
40
|
'OpenVPN has deprecated shared key mode as it does not meet current security standards. ' .
|
41
|
'Shared key mode will be removed from future versions. ' .
|
42
|
'Convert any existing shared key VPNs to TLS and do not configure any new shared key OpenVPN instances.'
|
43
|
);
|
44
|
|
45
|
global $openvpn_prots;
|
46
|
$openvpn_prots = array(
|
47
|
"UDP4" => "UDP on IPv4 only",
|
48
|
"UDP6" => "UDP on IPv6 only",
|
49
|
"TCP4" => "TCP on IPv4 only",
|
50
|
"TCP6" => "TCP on IPv6 only",
|
51
|
"UDP" => "UDP IPv4 and IPv6 on all interfaces (multihome)",
|
52
|
"TCP" => "TCP IPv4 and IPv6 on all interfaces (multihome)"
|
53
|
);
|
54
|
|
55
|
global $openvpn_dev_mode;
|
56
|
$openvpn_dev_mode = array(
|
57
|
"tun" => "tun - Layer 3 Tunnel Mode",
|
58
|
"tap" => "tap - Layer 2 Tap Mode"
|
59
|
);
|
60
|
|
61
|
global $openvpn_verbosity_level;
|
62
|
$openvpn_verbosity_level = array(
|
63
|
0 => gettext("none"),
|
64
|
1 => gettext("default"),
|
65
|
2 => "2",
|
66
|
3 => gettext("3 (recommended)"),
|
67
|
4 => "4",
|
68
|
5 => "5",
|
69
|
6 => "6",
|
70
|
7 => "7",
|
71
|
8 => "8",
|
72
|
9 => "9",
|
73
|
10 => "10",
|
74
|
11 => "11"
|
75
|
);
|
76
|
|
77
|
/*
|
78
|
* The User Auth mode below is disabled because
|
79
|
* OpenVPN erroneously requires that we provide
|
80
|
* a CA configuration parameter. In this mode,
|
81
|
* clients don't send a certificate so there is
|
82
|
* no need for a CA. If we require that admins
|
83
|
* provide one in the pfSense UI due to a bogus
|
84
|
* requirement imposed by OpenVPN, it could be
|
85
|
* considered very confusing ( I know I was ).
|
86
|
*
|
87
|
* -mgrooms
|
88
|
*/
|
89
|
|
90
|
global $openvpn_dh_lengths;
|
91
|
$openvpn_dh_lengths = array(
|
92
|
1024 => "1024 bit",
|
93
|
2048 => "2048 bit",
|
94
|
3072 => "3072 bit",
|
95
|
4096 => "4096 bit",
|
96
|
6144 => "6144 bit",
|
97
|
7680 => "7680 bit",
|
98
|
8192 => "8192 bit",
|
99
|
15360 => "15360 bit",
|
100
|
16384 => "16384 bit",
|
101
|
"none" => "ECDH Only"
|
102
|
);
|
103
|
foreach ($openvpn_dh_lengths as $idx => $dhlen) {
|
104
|
if (is_numeric($idx) && !file_exists("/etc/dh-parameters.{$idx}")) {
|
105
|
unset($openvpn_dh_lengths[$idx]);
|
106
|
}
|
107
|
}
|
108
|
|
109
|
global $openvpn_cert_depths;
|
110
|
$openvpn_cert_depths = array(
|
111
|
1 => gettext("One (Client+Server)"),
|
112
|
2 => gettext("Two (Client+Intermediate+Server)"),
|
113
|
3 => gettext("Three (Client+2xIntermediate+Server)"),
|
114
|
4 => gettext("Four (Client+3xIntermediate+Server)"),
|
115
|
5 => gettext("Five (Client+4xIntermediate+Server)")
|
116
|
);
|
117
|
|
118
|
global $openvpn_server_modes;
|
119
|
$openvpn_server_modes = array(
|
120
|
'p2p_tls' => gettext("Peer to Peer ( SSL/TLS )"),
|
121
|
'p2p_shared_key' => gettext("Peer to Peer ( Shared Key )"),
|
122
|
'server_tls' => gettext("Remote Access ( SSL/TLS )"),
|
123
|
'server_user' => gettext("Remote Access ( User Auth )"),
|
124
|
'server_tls_user' => gettext("Remote Access ( SSL/TLS + User Auth )"));
|
125
|
|
126
|
global $openvpn_tls_server_modes;
|
127
|
$openvpn_tls_server_modes = array('p2p_tls', 'server_tls', 'server_user', 'server_tls_user');
|
128
|
|
129
|
global $openvpn_client_modes;
|
130
|
$openvpn_client_modes = array(
|
131
|
'p2p_tls' => gettext("Peer to Peer ( SSL/TLS )"),
|
132
|
'p2p_shared_key' => gettext("Peer to Peer ( Shared Key )"));
|
133
|
|
134
|
global $openvpn_allow_compression;
|
135
|
$openvpn_allow_compression = array(
|
136
|
'asym' => gettext("Decompress incoming, do not compress outgoing (Asymmetric)"),
|
137
|
'no' => gettext("Refuse any non-stub compression (Most secure)"),
|
138
|
'yes' => gettext("Compress packets (WARNING: Potentially dangerous!)"),
|
139
|
);
|
140
|
|
141
|
global $openvpn_compression_modes;
|
142
|
$openvpn_compression_modes = array(
|
143
|
'' => gettext("Disable Compression [Omit Preference]"),
|
144
|
'none' => gettext("Disable Compression, retain compression packet framing [compress]"),
|
145
|
'stub' => gettext("Enable Compression (stub) [compress stub]"),
|
146
|
'stub-v2' => gettext("Enable Compression (stub v2) [compress stub-v2]"),
|
147
|
'lz4' => gettext("LZ4 Compression [compress lz4]"),
|
148
|
'lz4-v2' => gettext("LZ4 Compression v2 [compress lz4-v2]"),
|
149
|
'lzo' => gettext("LZO Compression [compress lzo, equivalent to comp-lzo yes for compatibility]"),
|
150
|
'noadapt' => gettext("Omit Preference, + Disable Adaptive LZO Compression [Legacy style, comp-noadapt]"),
|
151
|
'adaptive' => gettext("Adaptive LZO Compression [Legacy style, comp-lzo adaptive]"),
|
152
|
'yes' => gettext("LZO Compression [Legacy style, comp-lzo yes]"),
|
153
|
'no' => gettext("No LZO Compression [Legacy style, comp-lzo no]"),
|
154
|
);
|
155
|
|
156
|
global $openvpn_topologies;
|
157
|
$openvpn_topologies = array(
|
158
|
'subnet' => gettext("Subnet -- One IP address per client in a common subnet"),
|
159
|
'net30' => gettext("net30 -- Isolated /30 network per client")
|
160
|
);
|
161
|
|
162
|
global $openvpn_tls_modes;
|
163
|
$openvpn_tls_modes = array(
|
164
|
'auth' => gettext("TLS Authentication"),
|
165
|
'crypt' => gettext("TLS Encryption and Authentication")
|
166
|
);
|
167
|
|
168
|
global $openvpn_ping_method;
|
169
|
$openvpn_ping_method = array(
|
170
|
'keepalive' => gettext("keepalive -- Use keepalive helper to define ping configuration"),
|
171
|
'ping' => gettext("ping -- Define ping/ping-exit/ping-restart manually")
|
172
|
);
|
173
|
|
174
|
global $openvpn_default_keepalive_interval;
|
175
|
$openvpn_default_keepalive_interval = 10;
|
176
|
|
177
|
global $openvpn_default_keepalive_timeout;
|
178
|
$openvpn_default_keepalive_timeout = 60;
|
179
|
|
180
|
global $openvpn_ping_action;
|
181
|
$openvpn_ping_action = array(
|
182
|
'ping_restart' => gettext("ping-restart -- Restart OpenVPN after timeout"),
|
183
|
'ping_exit' => gettext("ping-exit -- Exit OpenVPN after timeout")
|
184
|
);
|
185
|
|
186
|
global $openvpn_exit_notify_server;
|
187
|
$openvpn_exit_notify_server = array(
|
188
|
'none' => gettext("Disabled"),
|
189
|
'1' => gettext("Reconnect to this server / Retry once"),
|
190
|
'2' => gettext("Reconnect to next server / Retry twice"),
|
191
|
);
|
192
|
|
193
|
global $openvpn_exit_notify_client;
|
194
|
$openvpn_exit_notify_client = array(
|
195
|
'none' => gettext("Disabled"),
|
196
|
);
|
197
|
for ($i=1; $i<=5; $i++) {
|
198
|
$openvpn_exit_notify_client[$i] = sprintf(gettext("Retry %dx"), $i);
|
199
|
}
|
200
|
|
201
|
function openvpn_build_mode_list() {
|
202
|
global $openvpn_server_modes;
|
203
|
|
204
|
$list = array();
|
205
|
|
206
|
foreach ($openvpn_server_modes as $name => $desc) {
|
207
|
$list[$name] = $desc;
|
208
|
}
|
209
|
|
210
|
return($list);
|
211
|
}
|
212
|
|
213
|
function openvpn_name(string $mode, array $settings, string $type = 'if') : string {
|
214
|
switch ($type) {
|
215
|
case 'if':
|
216
|
$prefix = ($mode == 'server') ? 'ovpns' : 'ovpnc';
|
217
|
break;
|
218
|
case 'dev':
|
219
|
$prefix = array_get_path($settings, 'dev_mode', 'tun');
|
220
|
break;
|
221
|
case 'generic':
|
222
|
$prefix = ($mode == 'server') ? 'server' : 'client';
|
223
|
break;
|
224
|
default:
|
225
|
$prefix = '';
|
226
|
break;
|
227
|
}
|
228
|
|
229
|
$id = array_get_path($settings, 'vpnid', '');
|
230
|
return "{$prefix}{$id}";
|
231
|
}
|
232
|
|
233
|
global $openvpn_interfacenames;
|
234
|
function convert_openvpn_interface_to_friendly_descr($if) {
|
235
|
global $openvpn_interfacenames;
|
236
|
if (!is_array($openvpn_interfacenames)) {
|
237
|
$openvpn_interfacenames = openvpn_build_if_list();
|
238
|
}
|
239
|
foreach($openvpn_interfacenames as $key => $value) {
|
240
|
list($item_if, $item_ip) = explode("|", $key);
|
241
|
if ($if == $item_if) {
|
242
|
return $value;
|
243
|
}
|
244
|
}
|
245
|
}
|
246
|
|
247
|
function openvpn_build_if_list() {
|
248
|
$list = array();
|
249
|
|
250
|
$interfaces = get_configured_interface_with_descr();
|
251
|
$viplist = get_configured_vip_list();
|
252
|
foreach ($viplist as $vip => $address) {
|
253
|
$interfaces[$vip.'|'.$address] = $address;
|
254
|
if (get_vip_descr($address)) {
|
255
|
$interfaces[$vip.'|'.$address] .= " (";
|
256
|
$interfaces[$vip.'|'.$address] .= get_vip_descr($address);
|
257
|
$interfaces[$vip.'|'.$address] .= ")";
|
258
|
}
|
259
|
}
|
260
|
|
261
|
$grouplist = return_gateway_groups_array();
|
262
|
foreach ($grouplist as $name => $group) {
|
263
|
if ($group[0]['vip'] != "") {
|
264
|
$vipif = $group[0]['vip'];
|
265
|
} else {
|
266
|
$vipif = $group[0]['int'];
|
267
|
}
|
268
|
|
269
|
$interfaces[$name] = "GW Group {$name}";
|
270
|
}
|
271
|
|
272
|
$interfaces['lo0'] = "Localhost";
|
273
|
$interfaces['any'] = "any";
|
274
|
|
275
|
foreach ($interfaces as $iface => $ifacename) {
|
276
|
$list[$iface] = $ifacename;
|
277
|
}
|
278
|
|
279
|
return($list);
|
280
|
}
|
281
|
|
282
|
function openvpn_build_crl_list() {
|
283
|
$list = array('' => 'None');
|
284
|
|
285
|
foreach (config_get_path('crl', []) as $crl) {
|
286
|
$caname = "";
|
287
|
$ca = lookup_ca($crl['caref']);
|
288
|
$ca = $ca['item'];
|
289
|
|
290
|
if ($ca) {
|
291
|
$caname = " (CA: {$ca['descr']})";
|
292
|
}
|
293
|
|
294
|
$list[$crl['refid']] = $crl['descr'] . $caname;
|
295
|
}
|
296
|
|
297
|
return($list);
|
298
|
}
|
299
|
|
300
|
function openvpn_build_cert_list($include_none = false, $prioritize_server_certs = false) {
|
301
|
$openvpn_compatible_certs = cert_build_list('cert', 'OpenVPN');
|
302
|
|
303
|
if ($include_none) {
|
304
|
$list = array('' => gettext('None (Username and/or Password required)'));
|
305
|
} else {
|
306
|
$list = array();
|
307
|
}
|
308
|
|
309
|
$non_server_list = array();
|
310
|
|
311
|
if ($prioritize_server_certs) {
|
312
|
$list[' '] = gettext("===== Server Certificates =====");
|
313
|
$non_server_list[' '] = gettext("===== Non-Server Certificates =====");
|
314
|
}
|
315
|
|
316
|
foreach (config_get_path('cert', []) as $cert) {
|
317
|
if (!array_key_exists($cert['refid'], $openvpn_compatible_certs)) {
|
318
|
continue;
|
319
|
}
|
320
|
$properties = array();
|
321
|
$propstr = "";
|
322
|
$ca = lookup_ca($cert['caref']);
|
323
|
$ca = $ca['item'];
|
324
|
$purpose = cert_get_purpose($cert['crt'], true);
|
325
|
|
326
|
if ($purpose['server'] == "Yes") {
|
327
|
$properties[] = gettext("Server: Yes");
|
328
|
} elseif ($prioritize_server_certs) {
|
329
|
$properties[] = gettext("Server: NO");
|
330
|
}
|
331
|
if ($ca) {
|
332
|
$properties[] = sprintf(gettext("CA: %s"), $ca['descr']);
|
333
|
}
|
334
|
if (cert_in_use($cert['refid'])) {
|
335
|
$properties[] = gettext("In Use");
|
336
|
}
|
337
|
if (is_cert_revoked($cert)) {
|
338
|
$properties[] = gettext("Revoked");
|
339
|
}
|
340
|
|
341
|
if (!empty($properties)) {
|
342
|
$propstr = " (" . implode(", ", $properties) . ")";
|
343
|
}
|
344
|
|
345
|
if ($prioritize_server_certs) {
|
346
|
if ($purpose['server'] == "Yes") {
|
347
|
$list[$cert['refid']] = $cert['descr'] . $propstr;
|
348
|
} else {
|
349
|
$non_server_list[$cert['refid']] = $cert['descr'] . $propstr;
|
350
|
}
|
351
|
} else {
|
352
|
$list[$cert['refid']] = $cert['descr'] . $propstr;
|
353
|
}
|
354
|
}
|
355
|
|
356
|
return(array('server' => $list, 'non-server' => $non_server_list));
|
357
|
}
|
358
|
|
359
|
function openvpn_build_bridge_list() {
|
360
|
$list = array();
|
361
|
|
362
|
$serverbridge_interface['none'] = "none";
|
363
|
$serverbridge_interface = array_merge($serverbridge_interface, get_configured_interface_with_descr());
|
364
|
$viplist = get_configured_vip_list();
|
365
|
|
366
|
foreach ($viplist as $vip => $address) {
|
367
|
$serverbridge_interface[$vip.'|'.$address] = $address;
|
368
|
if (get_vip_descr($address)) {
|
369
|
$serverbridge_interface[$vip.'|'.$address] .= " (". get_vip_descr($address) .")";
|
370
|
}
|
371
|
}
|
372
|
|
373
|
foreach ($serverbridge_interface as $iface => $ifacename) {
|
374
|
$list[$iface] = htmlspecialchars($ifacename);
|
375
|
}
|
376
|
|
377
|
return($list);
|
378
|
}
|
379
|
|
380
|
function openvpn_create_key() {
|
381
|
|
382
|
$fp = popen("/usr/local/sbin/openvpn --genkey secret /dev/stdout 2>/dev/null", "r");
|
383
|
if (!$fp) {
|
384
|
return false;
|
385
|
}
|
386
|
|
387
|
$rslt = stream_get_contents($fp);
|
388
|
pclose($fp);
|
389
|
|
390
|
return $rslt;
|
391
|
}
|
392
|
|
393
|
function openvpn_create_dhparams($bits) {
|
394
|
|
395
|
$fp = popen("/usr/bin/openssl dhparam {$bits} 2>/dev/null", "r");
|
396
|
if (!$fp) {
|
397
|
return false;
|
398
|
}
|
399
|
|
400
|
$rslt = stream_get_contents($fp);
|
401
|
pclose($fp);
|
402
|
|
403
|
return $rslt;
|
404
|
}
|
405
|
|
406
|
function openvpn_vpnid_used($vpnid) {
|
407
|
foreach (["server", "client"] as $mode) {
|
408
|
foreach (config_get_path("openvpn/openvpn-{$mode}", []) as $settings) {
|
409
|
if ($vpnid == $settings['vpnid']) {
|
410
|
return true;
|
411
|
}
|
412
|
}
|
413
|
}
|
414
|
return false;
|
415
|
}
|
416
|
|
417
|
function openvpn_vpnid_next() {
|
418
|
|
419
|
$vpnid = 1;
|
420
|
while (openvpn_vpnid_used($vpnid)) {
|
421
|
$vpnid++;
|
422
|
}
|
423
|
|
424
|
return $vpnid;
|
425
|
}
|
426
|
|
427
|
function openvpn_port_used($prot, $interface, $port, $curvpnid = 0) {
|
428
|
|
429
|
$ovpn_settings = config_get_path('openvpn/openvpn-server', []);
|
430
|
$ovpn_settings = array_merge($ovpn_settings, config_get_path('openvpn/openvpn-client', []));
|
431
|
|
432
|
foreach ($ovpn_settings as $settings) {
|
433
|
if (isset($settings['disable'])) {
|
434
|
continue;
|
435
|
}
|
436
|
|
437
|
if ($curvpnid != 0 && $curvpnid == $settings['vpnid']) {
|
438
|
continue;
|
439
|
}
|
440
|
|
441
|
/* (TCP|UDP)(4|6) does not conflict unless interface is any */
|
442
|
if (($interface != "any" && $settings['interface'] != "any") &&
|
443
|
(strlen($prot) == 4) &&
|
444
|
(strlen($settings['protocol']) == 4) &&
|
445
|
substr($prot,0,3) == substr($settings['protocol'],0,3) &&
|
446
|
substr($prot,3,1) != substr($settings['protocol'],3,1)) {
|
447
|
continue;
|
448
|
}
|
449
|
|
450
|
if ($port == $settings['local_port'] &&
|
451
|
substr($prot,0,3) == substr($settings['protocol'],0,3) &&
|
452
|
($interface == $settings['interface'] ||
|
453
|
$interface == "any" || $settings['interface'] == "any")) {
|
454
|
return $settings['vpnid'];
|
455
|
}
|
456
|
}
|
457
|
|
458
|
return 0;
|
459
|
}
|
460
|
|
461
|
function openvpn_port_next($prot, $interface = "wan") {
|
462
|
|
463
|
$port = 1194;
|
464
|
while (openvpn_port_used($prot, $interface, $port)) {
|
465
|
$port++;
|
466
|
}
|
467
|
while (openvpn_port_used($prot, "any", $port)) {
|
468
|
$port++;
|
469
|
}
|
470
|
|
471
|
return $port;
|
472
|
}
|
473
|
|
474
|
function openvpn_get_cipherlist() {
|
475
|
|
476
|
$ciphers = array();
|
477
|
$cipher_out = shell_exec('/usr/local/sbin/openvpn --show-ciphers | /usr/bin/grep \'(.*key\' | sed \'s/, TLS client\/server mode only//\'');
|
478
|
$cipher_lines = explode("\n", trim($cipher_out));
|
479
|
sort($cipher_lines);
|
480
|
foreach ($cipher_lines as $line) {
|
481
|
$words = explode(' ', $line, 2);
|
482
|
$ciphers[$words[0]] = "{$words[0]} {$words[1]}";
|
483
|
}
|
484
|
$ciphers["none"] = gettext("None (No Encryption)");
|
485
|
return $ciphers;
|
486
|
}
|
487
|
|
488
|
function openvpn_get_curvelist() {
|
489
|
global $cert_curve_compatible;
|
490
|
$curves = array();
|
491
|
$curves["none"] = gettext("Use Default");
|
492
|
foreach ($cert_curve_compatible['OpenVPN'] as $curve) {
|
493
|
$curves[$curve] = $curve;
|
494
|
}
|
495
|
return $curves;
|
496
|
}
|
497
|
|
498
|
function openvpn_validate_curve($curve) {
|
499
|
$curves = openvpn_get_curvelist();
|
500
|
return array_key_exists($curve, $curves);
|
501
|
}
|
502
|
|
503
|
/* Obtain the list of digest algorithms supported by openssl and their alternate names */
|
504
|
function openvpn_get_openssldigestmappings() {
|
505
|
$digests = array();
|
506
|
$digest_out = shell_exec('/usr/bin/openssl list -digest-algorithms | /usr/bin/grep "=>"');
|
507
|
$digest_lines = explode("\n", trim($digest_out));
|
508
|
sort($digest_lines);
|
509
|
foreach ($digest_lines as $line) {
|
510
|
$words = explode(' => ', $line, 2);
|
511
|
$digests[$words[0]] = $words[1];
|
512
|
}
|
513
|
return $digests;
|
514
|
}
|
515
|
|
516
|
/* Obtain the list of digest algorithms supported by openvpn */
|
517
|
function openvpn_get_digestlist() {
|
518
|
/* Grab the list from OpenSSL to check for duplicates or aliases */
|
519
|
$openssl_digest_mappings = openvpn_get_openssldigestmappings();
|
520
|
$digests = array();
|
521
|
$digest_out = shell_exec('/usr/local/sbin/openvpn --show-digests | /usr/bin/grep "digest size" | /usr/bin/awk \'{print $1, "(" $2 "-" $3 ")";}\'');
|
522
|
$digest_lines = explode("\n", trim($digest_out));
|
523
|
sort($digest_lines);
|
524
|
foreach ($digest_lines as $line) {
|
525
|
$words = explode(' ', $line);
|
526
|
/* Only add the entry if it is NOT also listed as being an alias/mapping by OpenSSL */
|
527
|
if (!array_key_exists($words[0], $openssl_digest_mappings)) {
|
528
|
$digests[$words[0]] = "{$words[0]} {$words[1]}";
|
529
|
}
|
530
|
}
|
531
|
$digests["none"] = gettext("None (No Authentication)");
|
532
|
return $digests;
|
533
|
}
|
534
|
|
535
|
/* Check to see if a digest name is an alias and if so, find the actual digest
|
536
|
* algorithm instead. Useful for upgrade code that has to translate aliased
|
537
|
* algorithms to their actual names.
|
538
|
*/
|
539
|
function openvpn_remap_digest($digest) {
|
540
|
$openssl_digest_mappings = openvpn_get_openssldigestmappings();
|
541
|
if (array_key_exists($digest, $openssl_digest_mappings)) {
|
542
|
/* Some mappings point to other mappings, keep going until we find the actual digest algorithm */
|
543
|
if (array_key_exists($openssl_digest_mappings[$digest], $openssl_digest_mappings)) {
|
544
|
return openvpn_remap_digest($openssl_digest_mappings[$digest]);
|
545
|
} else {
|
546
|
return $openssl_digest_mappings[$digest];
|
547
|
}
|
548
|
}
|
549
|
return $digest;
|
550
|
}
|
551
|
|
552
|
function openvpn_get_keydirlist() {
|
553
|
$keydirs = array(
|
554
|
'default' => gettext('Use default direction'),
|
555
|
'0' => gettext('Direction 0'),
|
556
|
'1' => gettext('Direction 1'),
|
557
|
'2' => gettext('Both directions'),
|
558
|
);
|
559
|
return $keydirs;
|
560
|
}
|
561
|
|
562
|
function openvpn_get_buffer_values() {
|
563
|
$sendbuf_max = get_single_sysctl('net.inet.tcp.sendbuf_max');
|
564
|
$recvbuf_max = get_single_sysctl('net.inet.tcp.recvbuf_max');
|
565
|
/* Usually these two are equal, but if they are not, take whichever one is lower. */
|
566
|
$buffer_max = ($sendbuf_max <= $recvbuf_max) ? $sendbuf_max : $recvbuf_max;
|
567
|
$buffer_values = array('' => gettext('Default'));
|
568
|
for ($bs = 32; $bs >= 1; $bs /= 2) {
|
569
|
$buffer_values[$buffer_max/$bs] = format_bytes($buffer_max/$bs);
|
570
|
}
|
571
|
return $buffer_values;
|
572
|
}
|
573
|
|
574
|
function openvpn_validate_host($value, $name) {
|
575
|
$value = trim($value);
|
576
|
if (empty($value) || (!is_domain($value) && !is_ipaddr($value))) {
|
577
|
return sprintf(gettext("The field '%s' must contain a valid IP address or domain name."), $name);
|
578
|
}
|
579
|
return false;
|
580
|
}
|
581
|
|
582
|
function openvpn_validate_port($value, $name, $first_port = 0) {
|
583
|
$value = trim($value);
|
584
|
if (!is_numeric($first_port)) {
|
585
|
$first_port = 0;
|
586
|
}
|
587
|
if (empty($value) || !is_numeric($value) || $value < $first_port || ($value > 65535)) {
|
588
|
return sprintf(gettext("The field '%s' must contain a valid port, ranging from %s to 65535."), $name, $first_port);
|
589
|
}
|
590
|
return false;
|
591
|
}
|
592
|
|
593
|
function openvpn_validate_cidr($value, $name, $multiple = false, $ipproto = "ipv4", $alias = false) {
|
594
|
$value = trim($value);
|
595
|
$error = false;
|
596
|
if (empty($value)) {
|
597
|
return false;
|
598
|
}
|
599
|
$networks = explode(',', $value);
|
600
|
|
601
|
if (!$multiple && (count($networks) > 1)) {
|
602
|
return sprintf(gettext("The field '%1\$s' must contain a single valid %2\$s CIDR range."), $name, $ipproto);
|
603
|
}
|
604
|
|
605
|
foreach ($networks as $network) {
|
606
|
if ($ipproto == "ipv4") {
|
607
|
$error = !openvpn_validate_cidr_ipv4($network, $alias);
|
608
|
} else {
|
609
|
$error = !openvpn_validate_cidr_ipv6($network, $alias);
|
610
|
}
|
611
|
if ($error) {
|
612
|
break;
|
613
|
}
|
614
|
}
|
615
|
|
616
|
if ($error) {
|
617
|
return sprintf(gettext("The field '%1\$s' must contain only valid %2\$s CIDR range(s) or FQDN(s) separated by commas."), $name, $ipproto);
|
618
|
} else {
|
619
|
return false;
|
620
|
}
|
621
|
}
|
622
|
|
623
|
function openvpn_validate_cidr_ipv4($value, $alias = false) {
|
624
|
$value = trim($value);
|
625
|
if (!empty($value)) {
|
626
|
if ($alias && is_alias($value) && in_array(alias_get_type($value), array('host', 'network'))) {
|
627
|
foreach (alias_to_subnets_recursive($value, true) as $net) {
|
628
|
if (!is_subnetv4($net) && !is_fqdn($net)) {
|
629
|
return false;
|
630
|
}
|
631
|
}
|
632
|
return true;
|
633
|
} else {
|
634
|
if (!is_subnetv4($value)) {
|
635
|
return false;
|
636
|
}
|
637
|
}
|
638
|
}
|
639
|
return true;
|
640
|
}
|
641
|
|
642
|
function openvpn_validate_cidr_ipv6($value, $alias = false) {
|
643
|
$value = trim($value);
|
644
|
if (!empty($value)) {
|
645
|
if ($alias && is_alias($value) && in_array(alias_get_type($value), array('host', 'network'))) {
|
646
|
foreach (alias_to_subnets_recursive($value, true) as $net) {
|
647
|
if (!is_subnetv6($net) && !is_fqdn($net)) {
|
648
|
return false;
|
649
|
}
|
650
|
}
|
651
|
return true;
|
652
|
} else {
|
653
|
list($ipv6, $prefix) = explode('/', $value);
|
654
|
if (empty($prefix)) {
|
655
|
$prefix = "128";
|
656
|
}
|
657
|
if (!is_subnetv6($ipv6 . '/' . $prefix)) {
|
658
|
return false;
|
659
|
}
|
660
|
}
|
661
|
}
|
662
|
return true;
|
663
|
}
|
664
|
|
665
|
function openvpn_validate_tunnel_network($value, $ipproto) {
|
666
|
$value = trim($value);
|
667
|
if (!empty($value)) {
|
668
|
if (is_alias($value) && (alias_get_type($value) == 'network')) {
|
669
|
$net = alias_to_subnets_recursive($value);
|
670
|
if ((!is_subnetv4($net[0]) && ($ipproto == 'ipv4')) ||
|
671
|
(!is_subnetv6($net[0]) && ($ipproto == 'ipv6')) ||
|
672
|
(count($net) > 1)) {
|
673
|
return false;
|
674
|
}
|
675
|
return true;
|
676
|
} else {
|
677
|
if ((!is_subnetv4($value) && ($ipproto == 'ipv4')) ||
|
678
|
(!is_subnetv6($value) && ($ipproto == 'ipv6'))) {
|
679
|
return false;
|
680
|
}
|
681
|
}
|
682
|
}
|
683
|
return true;
|
684
|
}
|
685
|
|
686
|
function openvpn_gen_tunnel_network($tunnel_network) {
|
687
|
if (is_alias($tunnel_network)) {
|
688
|
$net = alias_to_subnets_recursive($tunnel_network);
|
689
|
$pair = openvpn_tunnel_network_fix($net[0]);
|
690
|
} else {
|
691
|
$pair = $tunnel_network;
|
692
|
}
|
693
|
return explode('/', $pair);
|
694
|
}
|
695
|
|
696
|
function openvpn_add_dhcpopts(& $settings, & $conf) {
|
697
|
|
698
|
if (!empty($settings['dns_domain'])) {
|
699
|
$conf .= "push \"dhcp-option DOMAIN {$settings['dns_domain']}\"\n";
|
700
|
}
|
701
|
|
702
|
if (!empty($settings['dns_server1'])) {
|
703
|
$dnstype = (is_ipaddrv6($settings['dns_server1'])) ? "DNS6" : "DNS";
|
704
|
$conf .= "push \"dhcp-option {$dnstype} {$settings['dns_server1']}\"\n";
|
705
|
}
|
706
|
if (!empty($settings['dns_server2'])) {
|
707
|
$dnstype = (is_ipaddrv6($settings['dns_server2'])) ? "DNS6" : "DNS";
|
708
|
$conf .= "push \"dhcp-option {$dnstype} {$settings['dns_server2']}\"\n";
|
709
|
}
|
710
|
if (!empty($settings['dns_server3'])) {
|
711
|
$dnstype = (is_ipaddrv6($settings['dns_server3'])) ? "DNS6" : "DNS";
|
712
|
$conf .= "push \"dhcp-option {$dnstype} {$settings['dns_server3']}\"\n";
|
713
|
}
|
714
|
if (!empty($settings['dns_server4'])) {
|
715
|
$dnstype = (is_ipaddrv6($settings['dns_server4'])) ? "DNS6" : "DNS";
|
716
|
$conf .= "push \"dhcp-option {$dnstype} {$settings['dns_server4']}\"\n";
|
717
|
}
|
718
|
|
719
|
if (!empty($settings['push_blockoutsidedns'])) {
|
720
|
$conf .= "push \"block-outside-dns\"\n";
|
721
|
}
|
722
|
if (!empty($settings['push_register_dns'])) {
|
723
|
$conf .= "push \"register-dns\"\n";
|
724
|
}
|
725
|
|
726
|
if (!empty($settings['ntp_server1'])) {
|
727
|
$conf .= "push \"dhcp-option NTP {$settings['ntp_server1']}\"\n";
|
728
|
}
|
729
|
if (!empty($settings['ntp_server2'])) {
|
730
|
$conf .= "push \"dhcp-option NTP {$settings['ntp_server2']}\"\n";
|
731
|
}
|
732
|
|
733
|
if ($settings['netbios_enable']) {
|
734
|
|
735
|
if (!empty($settings['netbios_ntype']) && ($settings['netbios_ntype'] != 0)) {
|
736
|
$conf .= "push \"dhcp-option NBT {$settings['netbios_ntype']}\"\n";
|
737
|
}
|
738
|
if (!empty($settings['netbios_scope'])) {
|
739
|
$conf .= "push \"dhcp-option NBS {$settings['netbios_scope']}\"\n";
|
740
|
}
|
741
|
|
742
|
if (!empty($settings['wins_server1'])) {
|
743
|
$conf .= "push \"dhcp-option WINS {$settings['wins_server1']}\"\n";
|
744
|
}
|
745
|
if (!empty($settings['wins_server2'])) {
|
746
|
$conf .= "push \"dhcp-option WINS {$settings['wins_server2']}\"\n";
|
747
|
}
|
748
|
|
749
|
if (!empty($settings['nbdd_server1'])) {
|
750
|
$conf .= "push \"dhcp-option NBDD {$settings['nbdd_server1']}\"\n";
|
751
|
}
|
752
|
if (!empty($settings['nbdd_server2'])) {
|
753
|
$conf .= "push \"dhcp-option NBDD {$settings['nbdd_server2']}\"\n";
|
754
|
}
|
755
|
}
|
756
|
|
757
|
if ($settings['gwredir']) {
|
758
|
$conf .= "push \"redirect-gateway def1\"\n";
|
759
|
}
|
760
|
if ($settings['gwredir6']) {
|
761
|
$conf .= "push \"redirect-gateway ipv6\"\n";
|
762
|
}
|
763
|
}
|
764
|
|
765
|
function openvpn_add_custom(& $settings, & $conf) {
|
766
|
|
767
|
if ($settings['custom_options']) {
|
768
|
|
769
|
$options = explode(';', $settings['custom_options']);
|
770
|
|
771
|
if (is_array($options)) {
|
772
|
foreach ($options as $option) {
|
773
|
$conf .= "$option\n";
|
774
|
}
|
775
|
} else {
|
776
|
$conf .= "{$settings['custom_options']}\n";
|
777
|
}
|
778
|
}
|
779
|
}
|
780
|
|
781
|
function openvpn_add_keyfile(& $data, & $conf, $mode_id, $directive, $opt = "") {
|
782
|
global $g;
|
783
|
|
784
|
$fpath = "{$g['openvpn_base']}/{$mode_id}/{$directive}";
|
785
|
openvpn_create_dirs();
|
786
|
file_put_contents($fpath, base64_decode($data));
|
787
|
//chown($fpath, 'nobody');
|
788
|
//chgrp($fpath, 'nobody');
|
789
|
@chmod($fpath, 0600);
|
790
|
|
791
|
$conf .= "{$directive} {$fpath} {$opt}\n";
|
792
|
}
|
793
|
|
794
|
function openvpn_delete_tmp($mode, $id) {
|
795
|
global $g;
|
796
|
|
797
|
/* delete temporary files created by connect script */
|
798
|
if (($mode == "server") && (isset($id))) {
|
799
|
unlink_if_exists("{$g['tmp_path']}/ovpn_ovpns{$id}_*.rules");
|
800
|
}
|
801
|
|
802
|
/* delete temporary files created by OpenVPN; only delete old files to
|
803
|
* avoid deleting files potentially still in use by another OpenVPN process
|
804
|
*/
|
805
|
$tmpfiles = array_filter(glob("{$g['tmp_path']}/openvpn_cc*.tmp"),'is_file');
|
806
|
if (!empty($tmpfiles)) {
|
807
|
foreach ($tmpfiles as $tmpfile) {
|
808
|
if ((time() - filemtime($tmpfile)) > 60) {
|
809
|
@unlink_if_exists($tmpfile);
|
810
|
}
|
811
|
}
|
812
|
}
|
813
|
}
|
814
|
|
815
|
function openvpn_reconfigure($mode, $settings) {
|
816
|
global $g, $openvpn_tls_server_modes, $openvpn_dh_lengths, $openvpn_default_keepalive_interval, $openvpn_default_keepalive_timeout;
|
817
|
|
818
|
if (empty($settings)) {
|
819
|
return;
|
820
|
}
|
821
|
if (isset($settings['disable'])) {
|
822
|
return;
|
823
|
}
|
824
|
openvpn_create_dirs();
|
825
|
/*
|
826
|
* NOTE: Deleting tap devices causes spontaneous reboots. Instead,
|
827
|
* we use a vpnid number which is allocated for a particular client
|
828
|
* or server configuration. ( see openvpn_vpnid_next() )
|
829
|
*/
|
830
|
|
831
|
$vpnid = $settings['vpnid'];
|
832
|
$mode_id = openvpn_name($mode, $settings, 'generic');
|
833
|
/* defaults to tun */
|
834
|
if (!isset($settings['dev_mode'])) {
|
835
|
$settings['dev_mode'] = "tun";
|
836
|
}
|
837
|
$tunname = openvpn_name($mode, $settings, 'dev');
|
838
|
$devname = openvpn_name($mode, $settings);
|
839
|
|
840
|
/* is our device already configured */
|
841
|
if (!does_interface_exist($devname)) {
|
842
|
|
843
|
/* create the tap device if required */
|
844
|
if (!file_exists("/dev/{$tunname}")) {
|
845
|
exec("/sbin/ifconfig " . escapeshellarg($tunname) . " create");
|
846
|
}
|
847
|
|
848
|
/* rename the device */
|
849
|
mwexec("/sbin/ifconfig " . escapeshellarg($tunname) . " name " . escapeshellarg($devname));
|
850
|
|
851
|
/* add the device to the openvpn group */
|
852
|
mwexec("/sbin/ifconfig " . escapeshellarg($devname) . " group openvpn");
|
853
|
|
854
|
$ifname = convert_real_interface_to_friendly_interface_name($devname);
|
855
|
$grouptmp = (!empty($ifname)) ? link_interface_to_group($ifname) : null;
|
856
|
if (!empty($grouptmp)) {
|
857
|
array_walk($grouptmp, 'interface_group_add_member');
|
858
|
}
|
859
|
unset($grouptmp, $ifname);
|
860
|
}
|
861
|
|
862
|
$pfile = g_get('varrun_path') . "/openvpn_{$mode_id}.pid";
|
863
|
$proto = strtolower($settings['protocol']);
|
864
|
if (substr($settings['protocol'], 0, 3) == "TCP") {
|
865
|
$proto = "{$proto}-{$mode}";
|
866
|
}
|
867
|
$dev_mode = $settings['dev_mode'];
|
868
|
$fbcipher = $settings['data_ciphers_fallback'];
|
869
|
// OpenVPN defaults to SHA1, so use it when unset to maintain compatibility.
|
870
|
$digest = !empty($settings['digest']) ? $settings['digest'] : "SHA1";
|
871
|
|
872
|
$interface = $settings['interface'];
|
873
|
// The IP address in the settings can be an IPv4 or IPv6 address associated with the interface
|
874
|
$ipaddr = $settings['ipaddr'];
|
875
|
|
876
|
// If a specific ip address (VIP) is requested, use it.
|
877
|
// Otherwise, if a specific interface is requested, use it
|
878
|
// If "any" interface was selected, local directive will be omitted.
|
879
|
if (is_ipaddrv4($ipaddr)) {
|
880
|
$iface_ip = $ipaddr;
|
881
|
} elseif (!empty($interface) && strcmp($interface, "any")) {
|
882
|
$iface_ip=get_interface_ip($interface);
|
883
|
}
|
884
|
if (is_ipaddrv6($ipaddr)) {
|
885
|
$iface_ipv6 = $ipaddr;
|
886
|
} elseif (!empty($interface) && strcmp($interface, "any")) {
|
887
|
/* get correct interface name for 6RD/6to4 interfaces
|
888
|
* see https://redmine.pfsense.org/issues/11674 */
|
889
|
if (is_stf_interface($settings['interface'])) {
|
890
|
$iface_ipv6=get_interface_ipv6($settings['interface']);
|
891
|
} else {
|
892
|
$iface_ipv6=get_interface_ipv6($interface);
|
893
|
}
|
894
|
}
|
895
|
|
896
|
$conf = "dev {$devname}\n";
|
897
|
if (isset($settings['verbosity_level'])) {
|
898
|
$conf .= "verb {$settings['verbosity_level']}\n";
|
899
|
}
|
900
|
|
901
|
$conf .= "dev-type {$settings['dev_mode']}\n";
|
902
|
$conf .= "dev-node /dev/{$tunname}\n";
|
903
|
$conf .= "writepid {$pfile}\n";
|
904
|
$conf .= "#user nobody\n";
|
905
|
$conf .= "#group nobody\n";
|
906
|
$conf .= "script-security 3\n";
|
907
|
$conf .= "daemon\n";
|
908
|
|
909
|
if (!empty($settings['ping_method']) &&
|
910
|
$settings['ping_method'] == 'ping') {
|
911
|
$conf .= "ping {$settings['ping_seconds']}\n";
|
912
|
|
913
|
if (!empty($settings['ping_push'])) {
|
914
|
$conf .= "push \"ping {$settings['ping_seconds']}\"\n";
|
915
|
}
|
916
|
|
917
|
$action = str_replace("_", "-", $settings['ping_action']);
|
918
|
$conf .= "{$action} {$settings['ping_action_seconds']}\n";
|
919
|
|
920
|
if (!empty($settings['ping_action_push'])) {
|
921
|
$conf .= "push \"{$action} " .
|
922
|
"{$settings['ping_action_seconds']}\"\n";
|
923
|
}
|
924
|
} else {
|
925
|
$conf .= "keepalive " .
|
926
|
($settings['keepalive_interval']
|
927
|
?: $openvpn_default_keepalive_interval) . " " .
|
928
|
($settings['keepalive_timeout']
|
929
|
?: $openvpn_default_keepalive_timeout) . "\n";
|
930
|
}
|
931
|
|
932
|
$conf .= "ping-timer-rem\n";
|
933
|
$conf .= "persist-tun\n";
|
934
|
$conf .= "persist-key\n";
|
935
|
$conf .= "proto {$proto}\n";
|
936
|
$conf .= "auth {$digest}\n";
|
937
|
if ($settings['dns_add']) {
|
938
|
$conf .= "up /usr/local/sbin/ovpn-dnslinkup\n";
|
939
|
} else {
|
940
|
$conf .= "up /usr/local/sbin/ovpn-linkup\n";
|
941
|
}
|
942
|
$conf .= "down /usr/local/sbin/ovpn-linkdown\n";
|
943
|
if (file_exists("/usr/local/sbin/openvpn.attributes.sh")) {
|
944
|
switch ($settings['mode']) {
|
945
|
case 'server_user':
|
946
|
case 'server_tls_user':
|
947
|
case 'server_tls':
|
948
|
$conf .= "client-connect /usr/local/sbin/openvpn.attributes.sh\n";
|
949
|
$conf .= "client-disconnect /usr/local/sbin/openvpn.attributes.sh\n";
|
950
|
break;
|
951
|
}
|
952
|
}
|
953
|
if ($settings['dev_mode'] === 'tun' && config_path_enabled('unbound') &&
|
954
|
config_path_enabled('unbound','regovpnclients')) {
|
955
|
if (($settings['mode'] == 'server_tls') || ($settings['mode'] == 'server_tls_user') ||
|
956
|
(($settings['mode'] == 'server_user') && ($settings['username_as_common_name'] == 'enabled'))) {
|
957
|
$domain = !empty($settings['dns_domain']) ? $settings['dns_domain'] : config_get_path('system/domain');
|
958
|
if (is_domain($domain)) {
|
959
|
$conf .= "learn-address \"/usr/local/sbin/openvpn.learn-address.sh $domain\"\n";
|
960
|
}
|
961
|
}
|
962
|
}
|
963
|
|
964
|
/*
|
965
|
* When binding specific address, wait cases where interface is in
|
966
|
* tentative state otherwise it will fail
|
967
|
*/
|
968
|
$wait_tentative = false;
|
969
|
|
970
|
/* Determine the local IP to use - and make sure it matches with the selected protocol. */
|
971
|
switch ($settings['protocol']) {
|
972
|
case 'UDP':
|
973
|
case 'TCP':
|
974
|
$conf .= "multihome\n";
|
975
|
break;
|
976
|
case 'UDP4':
|
977
|
case 'TCP4':
|
978
|
if (is_ipaddrv4($iface_ip)) {
|
979
|
$conf .= "local {$iface_ip}\n";
|
980
|
}
|
981
|
if ($settings['interface'] == "any") {
|
982
|
$conf .= "multihome\n";
|
983
|
}
|
984
|
break;
|
985
|
case 'UDP6':
|
986
|
case 'TCP6':
|
987
|
if (is_ipaddrv6($iface_ipv6)) {
|
988
|
$conf .= "local {$iface_ipv6}\n";
|
989
|
$wait_tentative = true;
|
990
|
}
|
991
|
if ($settings['interface'] == "any") {
|
992
|
$conf .= "multihome\n";
|
993
|
}
|
994
|
break;
|
995
|
default:
|
996
|
}
|
997
|
|
998
|
// server specific settings
|
999
|
if ($mode == 'server') {
|
1000
|
|
1001
|
list($ip, $cidr) = openvpn_gen_tunnel_network($settings['tunnel_network']);
|
1002
|
list($ipv6, $prefix) = openvpn_gen_tunnel_network($settings['tunnel_networkv6']);
|
1003
|
$mask = gen_subnet_mask($cidr);
|
1004
|
|
1005
|
// configure tls modes
|
1006
|
switch ($settings['mode']) {
|
1007
|
case 'p2p_tls':
|
1008
|
case 'server_tls':
|
1009
|
case 'server_user':
|
1010
|
case 'server_tls_user':
|
1011
|
$conf .= "tls-server\n";
|
1012
|
break;
|
1013
|
}
|
1014
|
|
1015
|
// configure p2p/server modes
|
1016
|
switch ($settings['mode']) {
|
1017
|
case 'p2p_tls':
|
1018
|
// If the CIDR is less than a /30, OpenVPN will complain if you try to
|
1019
|
// use the server directive. It works for a single client without it.
|
1020
|
// See ticket #1417
|
1021
|
if ((!empty($ip) && !empty($mask)) ||
|
1022
|
(!empty($ipv6) && !empty($prefix))) {
|
1023
|
$add_ccd = false;
|
1024
|
if (is_ipaddr($ip) && ($cidr < 30)) {
|
1025
|
$add_ccd = true;
|
1026
|
$conf .= "server {$ip} {$mask}\n";
|
1027
|
}
|
1028
|
if (is_ipaddr($ipv6)) {
|
1029
|
$add_ccd = true;
|
1030
|
$conf .= "server-ipv6 {$ipv6}/{$prefix}\n";
|
1031
|
}
|
1032
|
if ($add_ccd) {
|
1033
|
$conf .= "client-config-dir {$g['openvpn_base']}/server{$vpnid}/csc\n";
|
1034
|
}
|
1035
|
}
|
1036
|
case 'p2p_shared_key':
|
1037
|
if (!empty($ip) && !empty($mask)) {
|
1038
|
list($ip1, $ip2) = openvpn_get_interface_ip($ip, $cidr);
|
1039
|
if ($settings['dev_mode'] == 'tun') {
|
1040
|
$conf .= "ifconfig {$ip1} {$ip2}\n";
|
1041
|
} else {
|
1042
|
$conf .= "ifconfig {$ip1} {$mask}\n";
|
1043
|
}
|
1044
|
}
|
1045
|
if (!empty($ipv6) && !empty($prefix)) {
|
1046
|
list($ipv6_1, $ipv6_2) = openvpn_get_interface_ipv6($ipv6, $prefix);
|
1047
|
if ($settings['dev_mode'] == 'tun') {
|
1048
|
$conf .= "ifconfig-ipv6 {$ipv6_1} {$ipv6_2}\n";
|
1049
|
} else {
|
1050
|
$conf .= "ifconfig-ipv6 {$ipv6_1}/{$prefix} {$ipv6_2}\n";
|
1051
|
}
|
1052
|
}
|
1053
|
break;
|
1054
|
case 'server_tls':
|
1055
|
case 'server_user':
|
1056
|
case 'server_tls_user':
|
1057
|
if ((!empty($ip) && !empty($mask)) ||
|
1058
|
(!empty($ipv6) && !empty($prefix))) {
|
1059
|
if (is_ipaddr($ip)) {
|
1060
|
$conf .= "server {$ip} {$mask}\n";
|
1061
|
}
|
1062
|
if (is_ipaddr($ipv6)) {
|
1063
|
$conf .= "server-ipv6 {$ipv6}/{$prefix}\n";
|
1064
|
}
|
1065
|
$conf .= "client-config-dir {$g['openvpn_base']}/server{$vpnid}/csc\n";
|
1066
|
} else {
|
1067
|
if ($settings['serverbridge_dhcp']) {
|
1068
|
if ((!empty($settings['serverbridge_interface'])) && (strcmp($settings['serverbridge_interface'], "none"))) {
|
1069
|
$biface_ip=get_interface_ip($settings['serverbridge_interface']);
|
1070
|
$biface_sm=gen_subnet_mask(get_interface_subnet($settings['serverbridge_interface']));
|
1071
|
if (is_ipaddrv4($biface_ip) && is_ipaddrv4($settings['serverbridge_dhcp_start']) && is_ipaddrv4($settings['serverbridge_dhcp_end'])) {
|
1072
|
$conf .= "server-bridge {$biface_ip} {$biface_sm} {$settings['serverbridge_dhcp_start']} {$settings['serverbridge_dhcp_end']}\n";
|
1073
|
$conf .= "client-config-dir {$g['openvpn_base']}/server{$vpnid}/csc\n";
|
1074
|
} else {
|
1075
|
$conf .= "mode server\n";
|
1076
|
}
|
1077
|
if (!empty($settings['serverbridge_routegateway']) && is_ipaddrv4($biface_ip)) {
|
1078
|
$conf .= "push \"route-gateway {$biface_ip}\"\n";
|
1079
|
}
|
1080
|
/* OpenVPN doesn't support this yet, clients do not recognize the option fully.
|
1081
|
$biface_ip6=get_interface_ipv6($settings['serverbridge_interface']);
|
1082
|
if (!empty($settings['serverbridge_routegateway']) && is_ipaddrv6($biface_ip6)) {
|
1083
|
$conf .= "push \"route-ipv6-gateway {$biface_ip6}\"\n";
|
1084
|
}
|
1085
|
*/
|
1086
|
} else {
|
1087
|
$conf .= "mode server\n";
|
1088
|
}
|
1089
|
}
|
1090
|
}
|
1091
|
break;
|
1092
|
}
|
1093
|
|
1094
|
// configure user auth modes
|
1095
|
switch ($settings['mode']) {
|
1096
|
case 'server_user':
|
1097
|
$conf .= "verify-client-cert none\n";
|
1098
|
case 'server_tls_user':
|
1099
|
/* username-as-common-name is not compatible with server-bridge */
|
1100
|
if ((stristr($conf, "server-bridge") === false) &&
|
1101
|
($settings['username_as_common_name'] != 'disabled')) {
|
1102
|
$conf .= "username-as-common-name\n";
|
1103
|
}
|
1104
|
if (!empty($settings['authmode'])) {
|
1105
|
$strictusercn = "false";
|
1106
|
if ($settings['strictusercn']) {
|
1107
|
$strictusercn = "true";
|
1108
|
}
|
1109
|
$conf .= openvpn_authscript_string($settings['authmode'], $strictusercn, $mode_id, $settings['local_port']);
|
1110
|
}
|
1111
|
break;
|
1112
|
}
|
1113
|
if (!isset($settings['cert_depth']) && (strstr($settings['mode'], 'tls'))) {
|
1114
|
$settings['cert_depth'] = 1;
|
1115
|
}
|
1116
|
if (is_numeric($settings['cert_depth'])) {
|
1117
|
if (($mode == 'client') && empty($settings['certref'])) {
|
1118
|
$cert = "";
|
1119
|
} else {
|
1120
|
$cert = lookup_cert($settings['certref']);
|
1121
|
$cert = $cert['item'];
|
1122
|
// The script 'openvpn.tls-verify.php' (called by 'ovpn_auth_verify') does not verify the CN - the CN is effectively unused.
|
1123
|
$servercn = urlencode(cert_get_cn($cert['crt']));
|
1124
|
$conf .= "tls-verify \"/usr/local/sbin/ovpn_auth_verify tls '{$servercn}' {$settings['cert_depth']}\"\n";
|
1125
|
}
|
1126
|
}
|
1127
|
|
1128
|
// The local port to listen on
|
1129
|
$conf .= "lport {$settings['local_port']}\n";
|
1130
|
|
1131
|
// The management port to listen on
|
1132
|
// Use unix socket to overcome the problem on any type of server
|
1133
|
$conf .= "management {$g['openvpn_base']}/{$mode_id}/sock unix\n";
|
1134
|
//$conf .= "management 127.0.0.1 {$settings['local_port']}\n";
|
1135
|
|
1136
|
if ($settings['maxclients']) {
|
1137
|
$conf .= "max-clients {$settings['maxclients']}\n";
|
1138
|
}
|
1139
|
|
1140
|
// Can we push routes, and should we?
|
1141
|
if ($settings['local_network'] && !$settings['gwredir']) {
|
1142
|
$conf .= openvpn_gen_routes($settings['local_network'], "ipv4", true);
|
1143
|
}
|
1144
|
if ($settings['local_networkv6'] && !$settings['gwredir6']) {
|
1145
|
$conf .= openvpn_gen_routes($settings['local_networkv6'], "ipv6", true);
|
1146
|
}
|
1147
|
|
1148
|
switch ($settings['mode']) {
|
1149
|
case 'server_tls':
|
1150
|
case 'server_user':
|
1151
|
case 'server_tls_user':
|
1152
|
// Configure client dhcp options
|
1153
|
openvpn_add_dhcpopts($settings, $conf);
|
1154
|
if ($settings['client2client']) {
|
1155
|
$conf .= "client-to-client\n";
|
1156
|
}
|
1157
|
break;
|
1158
|
}
|
1159
|
$connlimit = "0";
|
1160
|
if ($settings['mode'] != 'p2p_shared_key' &&
|
1161
|
isset($settings['duplicate_cn'])) {
|
1162
|
$conf .= "duplicate-cn\n";
|
1163
|
if ($settings['connlimit']) {
|
1164
|
$connlimit = "{$settings['connlimit']}";
|
1165
|
}
|
1166
|
}
|
1167
|
if (($settings['mode'] != 'p2p_shared_key') &&
|
1168
|
isset($settings['remote_cert_tls'])) {
|
1169
|
$conf .= "remote-cert-tls client\n";
|
1170
|
}
|
1171
|
}
|
1172
|
|
1173
|
// client specific settings
|
1174
|
|
1175
|
if ($mode == 'client') {
|
1176
|
|
1177
|
$add_pull = false;
|
1178
|
// configure p2p mode
|
1179
|
if ($settings['mode'] == 'p2p_tls') {
|
1180
|
$conf .= "tls-client\n";
|
1181
|
}
|
1182
|
|
1183
|
// If there is no bind option at all (ip and/or port), add "nobind" directive
|
1184
|
// Otherwise, use the local port if defined, failing that, use lport 0 to
|
1185
|
// ensure a random source port.
|
1186
|
if ((empty($iface_ip)) && empty($iface_ipv6) && (!$settings['local_port'])) {
|
1187
|
$conf .= "nobind\n";
|
1188
|
} elseif ($settings['local_port']) {
|
1189
|
$conf .= "lport {$settings['local_port']}\n";
|
1190
|
} else {
|
1191
|
$conf .= "lport 0\n";
|
1192
|
}
|
1193
|
|
1194
|
// Use unix socket to overcome the problem on any type of server
|
1195
|
$conf .= "management {$g['openvpn_base']}/{$mode_id}/sock unix\n";
|
1196
|
|
1197
|
// The remote server
|
1198
|
$remoteproto = strtolower($settings['protocol']);
|
1199
|
if (substr($remoteproto, 0, 3) == "tcp") {
|
1200
|
$remoteproto .= "-{$mode}";
|
1201
|
}
|
1202
|
$conf .= "remote {$settings['server_addr']} {$settings['server_port']} {$remoteproto}\n";
|
1203
|
|
1204
|
if (!empty($settings['use_shaper'])) {
|
1205
|
$conf .= "shaper {$settings['use_shaper']}\n";
|
1206
|
}
|
1207
|
|
1208
|
if (!empty($settings['tunnel_network'])) {
|
1209
|
list($ip, $cidr) = openvpn_gen_tunnel_network($settings['tunnel_network']);
|
1210
|
$mask = gen_subnet_mask($cidr);
|
1211
|
list($ip1, $ip2) = openvpn_get_interface_ip($ip, $cidr);
|
1212
|
if (($settings['dev_mode'] == 'tun') &&
|
1213
|
(($settings['topology'] == 'net30') ||
|
1214
|
($cidr >= 30))) {
|
1215
|
$conf .= "ifconfig {$ip2} {$ip1}\n";
|
1216
|
} else {
|
1217
|
$conf .= "ifconfig {$ip2} {$mask}\n";
|
1218
|
if ($settings['mode'] == 'p2p_tls') {
|
1219
|
$add_pull = true;
|
1220
|
}
|
1221
|
}
|
1222
|
}
|
1223
|
|
1224
|
if (!empty($settings['tunnel_networkv6'])) {
|
1225
|
list($ipv6, $prefix) = explode('/', trim($settings['tunnel_networkv6']));
|
1226
|
list($ipv6_1, $ipv6_2) = openvpn_get_interface_ipv6($ipv6, $prefix);
|
1227
|
if ($settings['dev_mode'] == 'tun') {
|
1228
|
$conf .= "ifconfig-ipv6 {$ipv6_2} {$ipv6_1}\n";
|
1229
|
} else {
|
1230
|
$conf .= "ifconfig-ipv6 {$ipv6_1}/{$prefix} {$ipv6_2}\n";
|
1231
|
if ($settings['mode'] == 'p2p_tls') {
|
1232
|
$add_pull = true;
|
1233
|
}
|
1234
|
}
|
1235
|
}
|
1236
|
|
1237
|
/* If both tunnel networks are empty, then pull from server. */
|
1238
|
if (empty($settings['tunnel_network']) &&
|
1239
|
empty($settings['tunnel_networkv6'])) {
|
1240
|
$add_pull = true;
|
1241
|
}
|
1242
|
|
1243
|
/* Only add "pull" if the tunnel network is undefined or using tap mode.
|
1244
|
OpenVPN can't pull settings from a server in point-to-point mode. */
|
1245
|
if (($settings['mode'] == 'p2p_tls') && $add_pull) {
|
1246
|
$conf .= "pull\n";
|
1247
|
}
|
1248
|
|
1249
|
if (($settings['auth_user'] || $settings['auth_pass']) && $settings['mode'] == "p2p_tls") {
|
1250
|
$up_file = "{$g['openvpn_base']}/{$mode_id}/up";
|
1251
|
$conf .= "auth-user-pass {$up_file}\n";
|
1252
|
if (!$settings['auth-retry-none']) {
|
1253
|
$conf .= "auth-retry nointeract\n";
|
1254
|
}
|
1255
|
if ($settings['auth_user']) {
|
1256
|
$userpass = "{$settings['auth_user']}\n";
|
1257
|
} else {
|
1258
|
$userpass = "";
|
1259
|
}
|
1260
|
if ($settings['auth_pass']) {
|
1261
|
$userpass .= "{$settings['auth_pass']}\n";
|
1262
|
}
|
1263
|
// If only auth_pass is given, then it acts like a user name and we put a blank line where pass would normally go.
|
1264
|
if (!($settings['auth_user'] && $settings['auth_pass'])) {
|
1265
|
$userpass .= "\n";
|
1266
|
}
|
1267
|
file_put_contents($up_file, $userpass);
|
1268
|
}
|
1269
|
|
1270
|
if ($settings['proxy_addr']) {
|
1271
|
$conf .= "http-proxy {$settings['proxy_addr']} {$settings['proxy_port']}";
|
1272
|
if ($settings['proxy_authtype'] != "none") {
|
1273
|
$conf .= " {$g['openvpn_base']}/{$mode_id}/proxy_auth {$settings['proxy_authtype']}";
|
1274
|
$proxypas = "{$settings['proxy_user']}\n";
|
1275
|
$proxypas .= "{$settings['proxy_passwd']}\n";
|
1276
|
file_put_contents("{$g['openvpn_base']}/{$mode_id}/proxy_auth", $proxypas);
|
1277
|
}
|
1278
|
$conf .= " \n";
|
1279
|
}
|
1280
|
|
1281
|
if (($settings['mode'] != 'shared_key') &&
|
1282
|
isset($settings['remote_cert_tls'])) {
|
1283
|
$conf .= "remote-cert-tls server\n";
|
1284
|
}
|
1285
|
}
|
1286
|
|
1287
|
// Add a remote network route if set, and only for p2p modes.
|
1288
|
if ((substr($settings['mode'], 0, 3) == "p2p") && (openvpn_validate_cidr($settings['remote_network'], "", true, "ipv4", true) === FALSE)) {
|
1289
|
$conf .= openvpn_gen_routes($settings['remote_network'], "ipv4", false);
|
1290
|
}
|
1291
|
// Add a remote network route if set, and only for p2p modes.
|
1292
|
if ((substr($settings['mode'], 0, 3) == "p2p") && (openvpn_validate_cidr($settings['remote_networkv6'], "", true, "ipv6", true) === FALSE)) {
|
1293
|
$conf .= openvpn_gen_routes($settings['remote_networkv6'], "ipv6", false);
|
1294
|
}
|
1295
|
|
1296
|
// Write the settings for the keys
|
1297
|
switch ($settings['mode']) {
|
1298
|
case 'p2p_shared_key':
|
1299
|
openvpn_add_keyfile($settings['shared_key'], $conf, $mode_id, "secret");
|
1300
|
break;
|
1301
|
case 'p2p_tls':
|
1302
|
case 'server_tls':
|
1303
|
case 'server_tls_user':
|
1304
|
case 'server_user':
|
1305
|
// ca_chain_array() expects parameter to be passed by reference.
|
1306
|
// avoid passing the whole settings array, as param names or
|
1307
|
// types might change in future releases.
|
1308
|
$param = array('caref' => $settings['caref']);
|
1309
|
$cas = ca_chain_array($param);
|
1310
|
$capath = "{$g['openvpn_base']}/{$mode_id}/ca";
|
1311
|
/* Cleanup old CA/CRL references */
|
1312
|
@unlink_if_exists("{$capath}/*.0");
|
1313
|
@unlink_if_exists("{$capath}/*.r*");
|
1314
|
/* Find the CRL listed in the settings */
|
1315
|
if (!empty($settings['crlref'])) {
|
1316
|
$crl_item_config = lookup_crl($settings['crlref']);
|
1317
|
$crl = &$crl_item_config['item'];
|
1318
|
crl_update($crl_item_config);
|
1319
|
}
|
1320
|
/* For each CA in the chain, setup the CApath */
|
1321
|
foreach ($cas as $ca) {
|
1322
|
ca_setup_capath($ca, $capath, $crl);
|
1323
|
}
|
1324
|
$conf .= "capath {$capath}\n";
|
1325
|
unset($cas, $param);
|
1326
|
|
1327
|
if (!empty($settings['certref'])) {
|
1328
|
$cert = lookup_cert($settings['certref']);
|
1329
|
$cert = $cert['item'];
|
1330
|
openvpn_add_keyfile($cert['crt'], $conf, $mode_id, "cert");
|
1331
|
openvpn_add_keyfile($cert['prv'], $conf, $mode_id, "key");
|
1332
|
}
|
1333
|
if ($mode == 'server') {
|
1334
|
if (is_numeric($settings['dh_length'])) {
|
1335
|
if (!in_array($settings['dh_length'], array_keys($openvpn_dh_lengths))) {
|
1336
|
/* The user selected a DH parameter length that does not have a corresponding file. */
|
1337
|
log_error(gettext("Failed to construct OpenVPN server configuration. The selected DH Parameter length cannot be used."));
|
1338
|
return;
|
1339
|
}
|
1340
|
$dh_file = "{$g['etc_path']}/dh-parameters.{$settings['dh_length']}";
|
1341
|
} else {
|
1342
|
$dh_file = $settings['dh_length'];
|
1343
|
}
|
1344
|
$conf .= "dh {$dh_file}\n";
|
1345
|
if (!empty($settings['ecdh_curve']) && ($settings['ecdh_curve'] != "none") && openvpn_validate_curve($settings['ecdh_curve'])) {
|
1346
|
$conf .= "ecdh-curve {$settings['ecdh_curve']}\n";
|
1347
|
}
|
1348
|
}
|
1349
|
if ($settings['tls']) {
|
1350
|
if ($settings['tls_type'] == "crypt") {
|
1351
|
$tls_directive = "tls-crypt";
|
1352
|
$tlsopt = "";
|
1353
|
} else {
|
1354
|
$tls_directive = "tls-auth";
|
1355
|
if ($mode == "server") {
|
1356
|
switch($settings['tlsauth_keydir']){
|
1357
|
case '1':
|
1358
|
$tlsopt = 1;
|
1359
|
break;
|
1360
|
case '2':
|
1361
|
$tlsopt = '';
|
1362
|
break;
|
1363
|
default:
|
1364
|
$tlsopt = 0;
|
1365
|
break;
|
1366
|
}
|
1367
|
} else {
|
1368
|
switch($settings['tlsauth_keydir']){
|
1369
|
case '0':
|
1370
|
$tlsopt = 0;
|
1371
|
break;
|
1372
|
case '2':
|
1373
|
$tlsopt = '';
|
1374
|
break;
|
1375
|
default:
|
1376
|
$tlsopt = 1;
|
1377
|
break;
|
1378
|
}
|
1379
|
}
|
1380
|
}
|
1381
|
openvpn_add_keyfile($settings['tls'], $conf, $mode_id, $tls_directive, $tlsopt);
|
1382
|
}
|
1383
|
break;
|
1384
|
}
|
1385
|
|
1386
|
/* Data encryption cipher support.
|
1387
|
* If it is not set, assume enabled since that is OpenVPN's default.
|
1388
|
* Note that diabling this is now deprecated and will be removed in a future version of OpenVPN */
|
1389
|
if ($settings['mode'] == "p2p_shared_key") {
|
1390
|
$conf .= "cipher {$fbcipher}\n";
|
1391
|
} else {
|
1392
|
/* Build data ciphers list from configuration. */
|
1393
|
$conf .= "data-ciphers " . str_replace(',', ':', openvpn_build_data_cipher_list($settings['data_ciphers'], $fbcipher)) . "\n";
|
1394
|
$conf .= "data-ciphers-fallback {$fbcipher}\n";
|
1395
|
}
|
1396
|
|
1397
|
if (!empty($settings['allow_compression'])) {
|
1398
|
$conf .= "allow-compression {$settings['allow_compression']}\n";
|
1399
|
}
|
1400
|
|
1401
|
$compression = "";
|
1402
|
switch ($settings['compression']) {
|
1403
|
case 'none':
|
1404
|
$settings['compression'] = '';
|
1405
|
case 'lz4':
|
1406
|
case 'lz4-v2':
|
1407
|
case 'lzo':
|
1408
|
case 'stub':
|
1409
|
case 'stub-v2':
|
1410
|
$compression .= "compress {$settings['compression']}";
|
1411
|
break;
|
1412
|
case 'noadapt':
|
1413
|
$compression .= "comp-noadapt";
|
1414
|
break;
|
1415
|
case 'adaptive':
|
1416
|
case 'yes':
|
1417
|
case 'no':
|
1418
|
$compression .= "comp-lzo {$settings['compression']}";
|
1419
|
break;
|
1420
|
default:
|
1421
|
/* Add nothing to the configuration */
|
1422
|
break;
|
1423
|
}
|
1424
|
|
1425
|
if (($settings['allow_compression'] != 'no') &&
|
1426
|
!empty($compression)) {
|
1427
|
$conf .= "{$compression}\n";
|
1428
|
if ($settings['compression_push']) {
|
1429
|
$conf .= "push \"{$compression}\"\n";
|
1430
|
}
|
1431
|
}
|
1432
|
|
1433
|
if ($settings['passtos']) {
|
1434
|
$conf .= "passtos\n";
|
1435
|
}
|
1436
|
|
1437
|
if ($mode == 'client') {
|
1438
|
$conf .= "resolv-retry infinite\n";
|
1439
|
}
|
1440
|
|
1441
|
if ($settings['dynamic_ip']) {
|
1442
|
$conf .= "persist-remote-ip\n";
|
1443
|
$conf .= "float\n";
|
1444
|
}
|
1445
|
|
1446
|
// If the server is not a TLS server or it has a tunnel network CIDR less than a /30, skip this.
|
1447
|
if (in_array($settings['mode'], $openvpn_tls_server_modes) &&
|
1448
|
(!empty($ip) && !empty($mask) && ($cidr < 30)) &&
|
1449
|
($settings['dev_mode'] != "tap")) {
|
1450
|
if (empty($settings['topology'])) {
|
1451
|
$settings['topology'] = "subnet";
|
1452
|
}
|
1453
|
$conf .= "topology {$settings['topology']}\n";
|
1454
|
}
|
1455
|
|
1456
|
// New client features
|
1457
|
if ($mode == "client") {
|
1458
|
// Dont add/remove routes checkbox
|
1459
|
if ($settings['route_no_exec']) {
|
1460
|
$conf .= "route-noexec\n";
|
1461
|
}
|
1462
|
}
|
1463
|
|
1464
|
/* UDP Fast I/O. Only compatible with UDP and also not compatible with OpenVPN's "shaper" directive. */
|
1465
|
if ($settings['udp_fast_io']
|
1466
|
&& (strtolower(substr($settings['protocol'], 0, 3)) == "udp")
|
1467
|
&& (empty($settings['use_shaper']))) {
|
1468
|
$conf .= "fast-io\n";
|
1469
|
}
|
1470
|
|
1471
|
/* Exit Notify.
|
1472
|
* Only compatible with UDP and specific combinations of
|
1473
|
* modes and settings, including:
|
1474
|
* if type is server AND
|
1475
|
* mode is not shared key AND
|
1476
|
* tunnel network CIDR mask < 30 AND
|
1477
|
* tunnel network is not blank
|
1478
|
* if type is client AND
|
1479
|
* mode is not shared key AND
|
1480
|
* tunnel network is blank OR
|
1481
|
* tunnel network CIDR mask < 30
|
1482
|
*/
|
1483
|
list($ip, $cidr) = openvpn_gen_tunnel_network($settings['tunnel_network']);
|
1484
|
if ((!empty($settings['exit_notify']) &&
|
1485
|
is_numericint($settings['exit_notify']) &&
|
1486
|
(strtolower(substr($settings['protocol'], 0, 3)) == "udp")) &&
|
1487
|
((($mode == "server") && (($settings['mode'] != 'p2p_shared_key') && (($cidr < 30) && !empty($ip)))) ||
|
1488
|
(($mode == "client") && (($settings['mode'] != 'p2p_shared_key') && (($cidr < 30) || empty($ip)))))) {
|
1489
|
$conf .= "explicit-exit-notify {$settings['exit_notify']}\n";
|
1490
|
}
|
1491
|
|
1492
|
/* Inactive Seconds
|
1493
|
* Has similar restrictions to Exit Notify (above) but only for server mode.
|
1494
|
*/
|
1495
|
if (!empty($settings['inactive_seconds']) &&
|
1496
|
!(($mode == "server") && (($settings['mode'] == 'p2p_shared_key') || (($cidr >= 30) || empty($ip))))) {
|
1497
|
$conf .= "inactive {$settings['inactive_seconds']}\n";
|
1498
|
}
|
1499
|
|
1500
|
/* Send and Receive Buffer Settings */
|
1501
|
if (is_numericint($settings['sndrcvbuf'])
|
1502
|
&& ($settings['sndrcvbuf'] > 0)
|
1503
|
&& ($settings['sndrcvbuf'] <= get_single_sysctl('net.inet.tcp.sendbuf_max'))
|
1504
|
&& ($settings['sndrcvbuf'] <= get_single_sysctl('net.inet.tcp.recvbuf_max'))) {
|
1505
|
$conf .= "sndbuf {$settings['sndrcvbuf']}\n";
|
1506
|
$conf .= "rcvbuf {$settings['sndrcvbuf']}\n";
|
1507
|
}
|
1508
|
|
1509
|
openvpn_add_custom($settings, $conf);
|
1510
|
|
1511
|
/* add nopull option after custom options, see https://redmine.pfsense.org/issues/11448 */
|
1512
|
if (($mode == "client") && $settings['route_no_pull']) {
|
1513
|
// Dont pull routes checkbox
|
1514
|
$conf .= "route-nopull\n";
|
1515
|
}
|
1516
|
|
1517
|
openvpn_create_dirs();
|
1518
|
$fpath = "{$g['openvpn_base']}/{$mode_id}/config.ovpn";
|
1519
|
file_put_contents($fpath, $conf);
|
1520
|
unset($conf);
|
1521
|
$fpath = "{$g['openvpn_base']}/{$mode_id}/interface";
|
1522
|
file_put_contents($fpath, get_failover_interface($interface));
|
1523
|
$fpath = "{$g['openvpn_base']}/{$mode_id}/connuserlimit";
|
1524
|
file_put_contents($fpath, $connlimit);
|
1525
|
//chown($fpath, 'nobody');
|
1526
|
//chgrp($fpath, 'nobody');
|
1527
|
@chmod("{$g['openvpn_base']}/{$mode_id}/config.ovpn", 0600);
|
1528
|
@chmod("{$g['openvpn_base']}/{$mode_id}/interface", 0600);
|
1529
|
@chmod("{$g['openvpn_base']}/{$mode_id}/key", 0600);
|
1530
|
@chmod("{$g['openvpn_base']}/{$mode_id}/tls-auth", 0600);
|
1531
|
@chmod("{$g['openvpn_base']}/{$mode_id}/conf", 0600);
|
1532
|
@chmod("{$g['openvpn_base']}/{$mode_id}/connuserlimit", 0600);
|
1533
|
|
1534
|
if ($wait_tentative) {
|
1535
|
interface_wait_tentative($interface);
|
1536
|
}
|
1537
|
}
|
1538
|
|
1539
|
function openvpn_stop_process($mode, $settings) {
|
1540
|
global $g;
|
1541
|
|
1542
|
$mode_id = openvpn_name($mode, $settings, 'generic');
|
1543
|
$pfile = g_get('varrun_path')."/openvpn_{$mode_id}.pid";
|
1544
|
if (file_exists($pfile)) {
|
1545
|
|
1546
|
/* read the pid file */
|
1547
|
$pid = rtrim(file_get_contents($pfile));
|
1548
|
unlink($pfile);
|
1549
|
syslog(LOG_INFO, "OpenVPN terminate old pid: {$pid}");
|
1550
|
|
1551
|
/* send a term signal to the process */
|
1552
|
posix_kill($pid, SIGTERM);
|
1553
|
|
1554
|
/* wait until the process exits, or timeout and kill it */
|
1555
|
$i = 0;
|
1556
|
while (posix_kill($pid, 0)) {
|
1557
|
usleep(250000);
|
1558
|
if ($i > 10) {
|
1559
|
log_error(sprintf(gettext('OpenVPN ID %1$s PID %2$s still running, killing.'), $mode_id, $pid));
|
1560
|
posix_kill($pid, SIGKILL);
|
1561
|
usleep(500000);
|
1562
|
}
|
1563
|
$i++;
|
1564
|
}
|
1565
|
}
|
1566
|
}
|
1567
|
|
1568
|
function openvpn_restart($mode, $settings) {
|
1569
|
global $g;
|
1570
|
|
1571
|
$vpnid = $settings['vpnid'];
|
1572
|
$mode_id = openvpn_name($mode, $settings, 'generic');
|
1573
|
$lockhandle = lock("openvpnservice{$mode_id}", LOCK_EX);
|
1574
|
openvpn_reconfigure($mode, $settings);
|
1575
|
openvpn_stop_process($mode, $settings);
|
1576
|
|
1577
|
if (isset($settings['disable'])) {
|
1578
|
openvpn_delete($mode, $settings);
|
1579
|
unlock($lockhandle);
|
1580
|
return;
|
1581
|
}
|
1582
|
|
1583
|
openvpn_delete_tmp($mode, $vpnid);
|
1584
|
|
1585
|
/* Do not start an instance if we are not CARP master on this vip! */
|
1586
|
if (strstr($settings['interface'], "_vip")) {
|
1587
|
$carpstatus = get_carp_bind_status($settings['interface']);
|
1588
|
/* Do not start an instance if vip aliased to BACKUP CARP
|
1589
|
* see https://redmine.pfsense.org/issues/11793 */
|
1590
|
if (in_array($carpstatus, array('BACKUP', 'INIT'))) {
|
1591
|
unlock($lockhandle);
|
1592
|
return;
|
1593
|
}
|
1594
|
}
|
1595
|
|
1596
|
/* Check if client is bound to a gateway group */
|
1597
|
$a_groups = return_gateway_groups_array(true);
|
1598
|
if (is_array($a_groups[$settings['interface']])) {
|
1599
|
/* the interface is a gateway group. If a vip is defined and its a CARP backup then do not start */
|
1600
|
if (($a_groups[$settings['interface']][0]['vip'] <> "") && (!in_array(get_carp_interface_status($a_groups[$settings['interface']][0]['vip']), array("MASTER", "")))) {
|
1601
|
unlock($lockhandle);
|
1602
|
return;
|
1603
|
}
|
1604
|
}
|
1605
|
|
1606
|
/* start the new process */
|
1607
|
$fpath = "{$g['openvpn_base']}/{$mode_id}/config.ovpn";
|
1608
|
openvpn_clear_route($mode, $settings);
|
1609
|
$res = mwexec("/usr/local/sbin/openvpn --config " . escapeshellarg($fpath));
|
1610
|
if ($res == 0) {
|
1611
|
$i = 0;
|
1612
|
$pfile = g_get('varrun_path')."/openvpn_{$mode_id}.pid";
|
1613
|
$pid = "--";
|
1614
|
while ($i < 3000) {
|
1615
|
if (isvalidpid($pfile)) {
|
1616
|
$pid = rtrim(file_get_contents($pfile));
|
1617
|
break;
|
1618
|
}
|
1619
|
usleep(1000);
|
1620
|
$i++;
|
1621
|
}
|
1622
|
syslog(LOG_INFO, "OpenVPN PID written: {$pid}");
|
1623
|
} else {
|
1624
|
syslog(LOG_ERR, "OpenVPN failed to start");
|
1625
|
}
|
1626
|
if (!is_platform_booting()) {
|
1627
|
send_event("filter reload");
|
1628
|
}
|
1629
|
unlock($lockhandle);
|
1630
|
}
|
1631
|
|
1632
|
function openvpn_delete($mode, $settings) {
|
1633
|
global $g;
|
1634
|
|
1635
|
$vpnid = $settings['vpnid'];
|
1636
|
$mode_id = openvpn_name($mode, $settings, 'generic');
|
1637
|
|
1638
|
openvpn_stop_process($mode, $settings);
|
1639
|
|
1640
|
/* destroy the device */
|
1641
|
pfSense_interface_destroy(openvpn_name($mode, $settings));
|
1642
|
|
1643
|
/* Invalidate cache */
|
1644
|
get_interface_arr(true);
|
1645
|
|
1646
|
/* remove the configuration files */
|
1647
|
unlink_if_exists("{$g['openvpn_base']}/{$mode_id}/*/*");
|
1648
|
unlink_if_exists("{$g['openvpn_base']}/{$mode_id}/*");
|
1649
|
openvpn_delete_tmp($mode, $vpnid);
|
1650
|
filter_configure();
|
1651
|
}
|
1652
|
|
1653
|
function openvpn_resync_csc($settings) {
|
1654
|
global $g, $openvpn_tls_server_modes;
|
1655
|
if (isset($settings['disable'])) {
|
1656
|
openvpn_delete_csc($settings);
|
1657
|
return;
|
1658
|
}
|
1659
|
openvpn_create_dirs();
|
1660
|
|
1661
|
/* Some options remove the gateway or topology which are required;
|
1662
|
* in such cases, these can be automatically determined. */
|
1663
|
$auto_config_gateway4 = false;
|
1664
|
$auto_config_gateway6 = false;
|
1665
|
$auto_config_topology = false;
|
1666
|
|
1667
|
if (empty($settings['server_list'])) {
|
1668
|
$csc_server_list = array();
|
1669
|
} else {
|
1670
|
$csc_server_list = explode(",", $settings['server_list']);
|
1671
|
}
|
1672
|
|
1673
|
$conf = '';
|
1674
|
if ($settings['block']) {
|
1675
|
$conf .= "disable\n";
|
1676
|
}
|
1677
|
|
1678
|
// Reset options
|
1679
|
if (isset($settings['push_reset'])) {
|
1680
|
if (isset($settings['keep_minimal'])) {
|
1681
|
$auto_config_gateway4 = true;
|
1682
|
$auto_config_gateway6 = true;
|
1683
|
$auto_config_topology = true;
|
1684
|
}
|
1685
|
$conf .= "push-reset\n";
|
1686
|
} elseif (!empty($settings['remove_options'])) {
|
1687
|
foreach (explode(',', $settings['remove_options']) as $option) {
|
1688
|
if (isset($settings['keep_minimal']) && ($option == 'remove_route')) {
|
1689
|
$auto_config_gateway4 = true;
|
1690
|
$auto_config_gateway6 = true;
|
1691
|
}
|
1692
|
$options = match ($option) {
|
1693
|
'remove_route' => 'route',
|
1694
|
'remove_iroute' => 'iroute',
|
1695
|
'remove_redirect_gateway' => 'redirect-gateway',
|
1696
|
'remove_inactive' => 'inactive',
|
1697
|
'remove_ping' => 'ping',
|
1698
|
'remove_ping_action' => ['ping-restart', 'ping-exit'],
|
1699
|
'remove_blockoutsidedns' => 'block-outside-dns',
|
1700
|
'remove_dnsdomain' => '"dhcp-option DOMAIN"',
|
1701
|
'remove_dnsservers' => '"dhcp-option DNS"',
|
1702
|
'remove_ntpservers' => '"dhcp-option NTP"',
|
1703
|
'remove_netbios_ntype' => '"dhcp-option NBT"',
|
1704
|
'remove_netbios_scope' => '"dhcp-option NBS"',
|
1705
|
'remove_wins' => '"dhcp-option WINS"'
|
1706
|
};
|
1707
|
if (is_array($options)) {
|
1708
|
foreach ($options as $option_name) {
|
1709
|
$conf .= "push-remove {$option_name}\n";
|
1710
|
}
|
1711
|
} else {
|
1712
|
$conf .= "push-remove {$options}\n";
|
1713
|
}
|
1714
|
}
|
1715
|
}
|
1716
|
|
1717
|
// Local network route options
|
1718
|
if ($settings['local_network']) {
|
1719
|
$conf .= openvpn_gen_routes($settings['local_network'], "ipv4", true);
|
1720
|
}
|
1721
|
if ($settings['local_networkv6']) {
|
1722
|
$conf .= openvpn_gen_routes($settings['local_networkv6'], "ipv6", true);
|
1723
|
}
|
1724
|
|
1725
|
// Remote network iroute options
|
1726
|
if (openvpn_validate_cidr($settings['remote_network'], "", true, "ipv4", true) === FALSE) {
|
1727
|
$conf .= openvpn_gen_routes($settings['remote_network'], "ipv4", false, true);
|
1728
|
}
|
1729
|
if (openvpn_validate_cidr($settings['remote_networkv6'], "", true, "ipv6", true) === FALSE) {
|
1730
|
$conf .= openvpn_gen_routes($settings['remote_networkv6'], "ipv6", false, true);
|
1731
|
}
|
1732
|
|
1733
|
// Gatewy override options
|
1734
|
if (!empty($settings['gateway'])) {
|
1735
|
$auto_config_gateway4 = false;
|
1736
|
$conf .= "push \"route-gateway {$settings['gateway']}\"\n";
|
1737
|
}
|
1738
|
if (!empty($settings['gateway6'])) {
|
1739
|
$auto_config_gateway6 = false;
|
1740
|
$conf .= "push \"route-ipv6-gateway {$settings['gateway6']}\"\n";
|
1741
|
}
|
1742
|
|
1743
|
// Inactivity override options
|
1744
|
if (isset($settings['inactive_seconds'])) {
|
1745
|
$conf .= "push \"inactive {$settings['inactive_seconds']}\"\n";
|
1746
|
}
|
1747
|
|
1748
|
// Ping override options
|
1749
|
if (isset($settings['ping_seconds'])) {
|
1750
|
$conf .= "push \"ping {$settings['ping_seconds']}\"\n";
|
1751
|
}
|
1752
|
if (isset($settings['ping_action'])) {
|
1753
|
$action = str_replace("_", "-", $settings['ping_action']);
|
1754
|
$conf .= "push \"{$action} {$settings['ping_action_seconds']}\"\n";
|
1755
|
}
|
1756
|
|
1757
|
// DHCP and gateway redirect options
|
1758
|
openvpn_add_dhcpopts($settings, $conf);
|
1759
|
|
1760
|
// Custom options
|
1761
|
openvpn_add_custom($settings, $conf);
|
1762
|
|
1763
|
/* Loop through servers, find which ones can use this CSC */
|
1764
|
foreach (config_get_path('openvpn/openvpn-server', []) as $serversettings) {
|
1765
|
if (isset($serversettings['disable'])) {
|
1766
|
continue;
|
1767
|
}
|
1768
|
if (in_array($serversettings['mode'], $openvpn_tls_server_modes)) {
|
1769
|
if ($serversettings['vpnid'] && (empty($csc_server_list) || in_array($serversettings['vpnid'], $csc_server_list))) {
|
1770
|
$csc_path = "{$g['openvpn_base']}/server{$serversettings['vpnid']}/csc/" . basename($settings['common_name']);
|
1771
|
$csc_conf = $conf;
|
1772
|
|
1773
|
/* Topology is depends on the server configuration.
|
1774
|
* TAP mode always uses a subnet topology */
|
1775
|
$topology = ($serversettings['dev_mode'] == 'tap') ? 'subnet' : $serversettings['topology'];
|
1776
|
if ($auto_config_topology) {
|
1777
|
$csc_conf .= "push \"topology {$topology}\"\n";
|
1778
|
}
|
1779
|
|
1780
|
/* The gateway is the first usable address in the tunnel network.
|
1781
|
* If the tunnel network is not set, the gateway must be manually
|
1782
|
* defined. This can happen when using a net30 topology and
|
1783
|
* resetting options. */
|
1784
|
if ($auto_config_gateway6) {
|
1785
|
// IPv6 always uses a subnet topology
|
1786
|
$tunnel_network = null;
|
1787
|
if (!empty($settings['tunnel_networkv6'])) {
|
1788
|
$tunnel_network = $settings['tunnel_networkv6'];
|
1789
|
} elseif (!empty($serversettings['tunnel_networkv6'])) {
|
1790
|
$tunnel_network = $serversettings['tunnel_networkv6'];
|
1791
|
}
|
1792
|
if (!empty($tunnel_network)) {
|
1793
|
$tunnel_network_parts = openvpn_gen_tunnel_network($tunnel_network);
|
1794
|
$gateway = ip6_after(gen_subnetv6($tunnel_network_parts[0], $tunnel_network_parts[1]));
|
1795
|
$csc_conf .= "push \"route-ipv6-gateway {$gateway}\"\n";
|
1796
|
}
|
1797
|
}
|
1798
|
if ($auto_config_gateway4) {
|
1799
|
$tunnel_network = null;
|
1800
|
if ($topology == "subnet") {
|
1801
|
// The client tunnel network is assumed to be the same as the server's
|
1802
|
$tunnel_network = $serversettings['tunnel_network'];
|
1803
|
} elseif (!empty($settings['tunnel_network'])) {
|
1804
|
$tunnel_network = $settings['tunnel_network'];
|
1805
|
}
|
1806
|
if (!empty($tunnel_network)) {
|
1807
|
$tunnel_network_parts = openvpn_gen_tunnel_network($tunnel_network);
|
1808
|
$gateway = ip_after(gen_subnetv4($tunnel_network_parts[0], $tunnel_network_parts[1]), 1);
|
1809
|
$csc_conf .= "push \"route-gateway {$gateway}\"\n";
|
1810
|
}
|
1811
|
}
|
1812
|
|
1813
|
if (!empty($serversettings['tunnel_network']) && !empty($settings['tunnel_network'])) {
|
1814
|
list($ip, $mask) = openvpn_gen_tunnel_network($settings['tunnel_network']);
|
1815
|
if (($serversettings['dev_mode'] == 'tap') || ($serversettings['topology'] == "subnet")) {
|
1816
|
$csc_conf .= "ifconfig-push {$ip} " . gen_subnet_mask($mask) . "\n";
|
1817
|
} else {
|
1818
|
/* Because this is being pushed, the order from the client's point of view. */
|
1819
|
$baselong = gen_subnetv4($ip, $mask);
|
1820
|
$serverip = ip_after($baselong, 1);
|
1821
|
$clientip = ip_after($baselong, 2);
|
1822
|
$csc_conf .= "ifconfig-push {$clientip} {$serverip}\n";
|
1823
|
}
|
1824
|
}
|
1825
|
|
1826
|
if (!empty($serversettings['tunnel_networkv6']) && !empty($settings['tunnel_networkv6'])) {
|
1827
|
list($ipv6, $prefix) = openvpn_gen_tunnel_network($serversettings['tunnel_networkv6']);
|
1828
|
list($ipv6_1, $ipv6_2) = openvpn_get_interface_ipv6($ipv6, $prefix);
|
1829
|
$csc_conf .= "ifconfig-ipv6-push {$settings['tunnel_networkv6']} {$ipv6_1}\n";
|
1830
|
}
|
1831
|
|
1832
|
file_put_contents($csc_path, $csc_conf);
|
1833
|
chown($csc_path, 'nobody');
|
1834
|
chgrp($csc_path, 'nobody');
|
1835
|
}
|
1836
|
}
|
1837
|
}
|
1838
|
}
|
1839
|
|
1840
|
function openvpn_resync_csc_all() {
|
1841
|
foreach (config_get_path('openvpn/openvpn-csc', []) as $settings) {
|
1842
|
openvpn_resync_csc($settings);
|
1843
|
}
|
1844
|
}
|
1845
|
|
1846
|
function openvpn_delete_csc($settings) {
|
1847
|
global $g, $openvpn_tls_server_modes;
|
1848
|
if (empty($settings['server_list'])) {
|
1849
|
$csc_server_list = array();
|
1850
|
} else {
|
1851
|
$csc_server_list = explode(",", $settings['server_list']);
|
1852
|
}
|
1853
|
|
1854
|
/* Loop through servers, find which ones used this CSC */
|
1855
|
foreach (config_get_path('openvpn/openvpn-server', []) as $serversettings) {
|
1856
|
if (isset($serversettings['disable'])) {
|
1857
|
continue;
|
1858
|
}
|
1859
|
if (in_array($serversettings['mode'], $openvpn_tls_server_modes)) {
|
1860
|
if ($serversettings['vpnid'] && (empty($csc_server_list) || in_array($serversettings['vpnid'], $csc_server_list))) {
|
1861
|
$csc_path = "{$g['openvpn_base']}/server{$serversettings['vpnid']}/csc/" . basename($settings['common_name']);
|
1862
|
unlink_if_exists($csc_path);
|
1863
|
}
|
1864
|
}
|
1865
|
}
|
1866
|
}
|
1867
|
|
1868
|
// Resync the configuration and restart the VPN
|
1869
|
function openvpn_resync($mode, $settings) {
|
1870
|
openvpn_restart($mode, $settings);
|
1871
|
}
|
1872
|
|
1873
|
// Resync and restart all VPNs
|
1874
|
function openvpn_resync_all($interface = "", $protocol = "") {
|
1875
|
global $g;
|
1876
|
|
1877
|
if ($interface <> "") {
|
1878
|
log_error(sprintf(gettext("Resyncing OpenVPN instances for interface %s."), convert_friendly_interface_to_friendly_descr($interface)));
|
1879
|
} else {
|
1880
|
log_error(gettext("Resyncing OpenVPN instances."));
|
1881
|
}
|
1882
|
|
1883
|
// Check if OpenVPN clients and servers require a resync.
|
1884
|
foreach (array("server", "client") as $type) {
|
1885
|
foreach (config_get_path("openvpn/openvpn-{$type}", []) as $settings) {
|
1886
|
if (isset($settings['disable'])) {
|
1887
|
continue;
|
1888
|
}
|
1889
|
if (!empty($protocol) &&
|
1890
|
((($protocol == 'inet') && strstr($settings['protocol'], "6")) ||
|
1891
|
(($protocol == 'inet6') && strstr($settings['protocol'], "4")))) {
|
1892
|
continue;
|
1893
|
}
|
1894
|
$fpath = "{$g['openvpn_base']}/{$type}{$settings['vpnid']}/interface";
|
1895
|
$gw_group_change = FALSE;
|
1896
|
$ip_change = ($interface === "") ||
|
1897
|
($interface === $settings['interface']);
|
1898
|
|
1899
|
if (!$ip_change && file_exists($fpath)) {
|
1900
|
$gw_group_change =
|
1901
|
(trim(file_get_contents($fpath), " \t\n") !=
|
1902
|
get_failover_interface(
|
1903
|
$settings['interface']));
|
1904
|
}
|
1905
|
|
1906
|
if ($ip_change || $gw_group_change) {
|
1907
|
if (!$dirs) {
|
1908
|
openvpn_create_dirs();
|
1909
|
}
|
1910
|
openvpn_resync($type, $settings);
|
1911
|
$restarted = true;
|
1912
|
$dirs = true;
|
1913
|
}
|
1914
|
}
|
1915
|
}
|
1916
|
|
1917
|
if ($restarted) {
|
1918
|
openvpn_resync_csc_all();
|
1919
|
|
1920
|
/* configure OpenVPN-parent QinQ interfaces after creating OpenVPN interfaces
|
1921
|
* see https://redmine.pfsense.org/issues/11662 */
|
1922
|
if (is_platform_booting()) {
|
1923
|
/* Refresh the cache; the parent interface may not yet exist in the cache. */
|
1924
|
get_interface_arr(true);
|
1925
|
interfaces_qinq_configure(true);
|
1926
|
/* Configure all qinq interface addresses and add them to their
|
1927
|
* bridges. See https://redmine.pfsense.org/issues/13225,
|
1928
|
* https://redmine.pfsense.org/issues/13666 */
|
1929
|
foreach (config_get_path('interfaces', []) as $ifname => $iface) {
|
1930
|
$qinq = interface_is_qinq($iface['if']);
|
1931
|
if ($qinq && strstr($qinq['if'], "ovpn")) {
|
1932
|
interface_configure($ifname);
|
1933
|
}
|
1934
|
}
|
1935
|
}
|
1936
|
}
|
1937
|
}
|
1938
|
|
1939
|
// Resync and restart all VPNs using a gateway group.
|
1940
|
function openvpn_resync_gwgroup($gwgroupname = "") {
|
1941
|
if ($gwgroupname <> "") {
|
1942
|
foreach (["server", "client"] as $mode) {
|
1943
|
foreach (config_get_path("openvpn/openvpn-{$mode}", []) as $settings) {
|
1944
|
if ($gwgroupname == $settings['interface']) {
|
1945
|
log_error(sprintf(gettext('Resyncing OpenVPN for gateway group %1$s %2$s %3$s.'), $gwgroupname, $mode, $settings["description"]));
|
1946
|
openvpn_resync('server', $settings);
|
1947
|
}
|
1948
|
}
|
1949
|
}
|
1950
|
// Note: no need to resysnc Client Specific (csc) here, as changes to the OpenVPN real interface do not effect these.
|
1951
|
} else {
|
1952
|
log_error(gettext("openvpn_resync_gwgroup called with null gwgroup parameter."));
|
1953
|
}
|
1954
|
}
|
1955
|
|
1956
|
function openvpn_get_active_servers($type="multipoint") {
|
1957
|
global $g;
|
1958
|
|
1959
|
$servers = array();
|
1960
|
foreach (config_get_path('openvpn/openvpn-server', []) as $settings) {
|
1961
|
if (empty($settings) || isset($settings['disable'])) {
|
1962
|
continue;
|
1963
|
}
|
1964
|
|
1965
|
$prot = $settings['protocol'];
|
1966
|
$port = $settings['local_port'];
|
1967
|
|
1968
|
$server = array();
|
1969
|
$server['port'] = ($settings['local_port']) ? $settings['local_port'] : 1194;
|
1970
|
$server['mode'] = $settings['mode'];
|
1971
|
if ($settings['description']) {
|
1972
|
$server['name'] = "{$settings['description']} {$prot}:{$port}";
|
1973
|
} else {
|
1974
|
$server['name'] = "Server {$prot}:{$port}";
|
1975
|
}
|
1976
|
$server['conns'] = array();
|
1977
|
$server['vpnid'] = $settings['vpnid'];
|
1978
|
$server['mgmt'] = "server{$server['vpnid']}";
|
1979
|
$socket = "unix://{$g['openvpn_base']}/{$server['mgmt']}/sock";
|
1980
|
list($tn, $sm) = openvpn_gen_tunnel_network($settings['tunnel_network']);
|
1981
|
|
1982
|
if ((($server['mode'] == "p2p_shared_key") ||
|
1983
|
(($settings['dev_mode'] == 'tap') && empty($settings['tunnel_network']) && ($server['mode'] == 'p2p_tls')) ||
|
1984
|
($sm >= 30)) &&
|
1985
|
($type == "p2p")) {
|
1986
|
$servers[] = openvpn_get_client_status($server, $socket);
|
1987
|
} elseif (($server['mode'] != "p2p_shared_key") &&
|
1988
|
!(($settings['dev_mode'] == 'tap') && empty($settings['tunnel_network']) && ($server['mode'] == 'p2p_tls')) &&
|
1989
|
($type == "multipoint") &&
|
1990
|
($sm < 30)) {
|
1991
|
$servers[] = openvpn_get_server_status($server, $socket);
|
1992
|
}
|
1993
|
}
|
1994
|
|
1995
|
return $servers;
|
1996
|
}
|
1997
|
|
1998
|
function openvpn_get_server_status($server, $socket) {
|
1999
|
$errval = null;
|
2000
|
$errstr = null;
|
2001
|
$fp = @stream_socket_client($socket, $errval, $errstr, 1);
|
2002
|
if ($fp) {
|
2003
|
stream_set_timeout($fp, 1);
|
2004
|
|
2005
|
/* send our status request */
|
2006
|
fputs($fp, "status 2\n");
|
2007
|
|
2008
|
/* recv all response lines */
|
2009
|
while (!feof($fp)) {
|
2010
|
|
2011
|
/* read the next line */
|
2012
|
$line = fgets($fp, 1024);
|
2013
|
|
2014
|
$info = stream_get_meta_data($fp);
|
2015
|
if ($info['timed_out']) {
|
2016
|
break;
|
2017
|
}
|
2018
|
|
2019
|
/* parse header list line */
|
2020
|
if (strstr($line, "HEADER")) {
|
2021
|
continue;
|
2022
|
}
|
2023
|
|
2024
|
/* parse end of output line */
|
2025
|
if (strstr($line, "END") || strstr($line, "ERROR")) {
|
2026
|
break;
|
2027
|
}
|
2028
|
|
2029
|
/* parse client list line */
|
2030
|
if (strstr($line, "CLIENT_LIST")) {
|
2031
|
$list = explode(",", $line);
|
2032
|
$conn = array();
|
2033
|
$conn['common_name'] = $list[1];
|
2034
|
$conn['remote_host'] = $list[2];
|
2035
|
$conn['virtual_addr'] = $list[3];
|
2036
|
$conn['virtual_addr6'] = $list[4];
|
2037
|
$conn['bytes_recv'] = $list[5];
|
2038
|
$conn['bytes_sent'] = $list[6];
|
2039
|
$conn['connect_time'] = $list[7];
|
2040
|
$conn['connect_time_unix'] = $list[8];
|
2041
|
$conn['user_name'] = $list[9];
|
2042
|
$conn['client_id'] = $list[10];
|
2043
|
$conn['peer_id'] = $list[11];
|
2044
|
$conn['cipher'] = $list[12];
|
2045
|
$server['conns'][] = $conn;
|
2046
|
}
|
2047
|
/* parse routing table lines */
|
2048
|
if (strstr($line, "ROUTING_TABLE")) {
|
2049
|
$list = explode(",", $line);
|
2050
|
$conn = array();
|
2051
|
$conn['virtual_addr'] = $list[1];
|
2052
|
$conn['common_name'] = $list[2];
|
2053
|
$conn['remote_host'] = $list[3];
|
2054
|
$conn['last_time'] = $list[4];
|
2055
|
$server['routes'][] = $conn;
|
2056
|
}
|
2057
|
}
|
2058
|
|
2059
|
/* cleanup */
|
2060
|
fclose($fp);
|
2061
|
} else {
|
2062
|
$conn = array();
|
2063
|
$conn['common_name'] = "[error]";
|
2064
|
$conn['remote_host'] = gettext("Unable to contact daemon");
|
2065
|
$conn['virtual_addr'] = gettext("Service not running?");
|
2066
|
$conn['bytes_recv'] = 0;
|
2067
|
$conn['bytes_sent'] = 0;
|
2068
|
$conn['connect_time'] = 0;
|
2069
|
$server['conns'][] = $conn;
|
2070
|
}
|
2071
|
return $server;
|
2072
|
}
|
2073
|
|
2074
|
function openvpn_get_active_clients() {
|
2075
|
global $g;
|
2076
|
|
2077
|
$clients = array();
|
2078
|
foreach (config_get_path('openvpn/openvpn-client', []) as $settings) {
|
2079
|
if (empty($settings) || isset($settings['disable'])) {
|
2080
|
continue;
|
2081
|
}
|
2082
|
|
2083
|
$prot = $settings['protocol'];
|
2084
|
$port = ($settings['local_port']) ? ":{$settings['local_port']}" : "";
|
2085
|
|
2086
|
$client = array();
|
2087
|
$client['port'] = $settings['local_port'];
|
2088
|
if ($settings['description']) {
|
2089
|
$client['name'] = "{$settings['description']} {$prot}{$port}";
|
2090
|
} else {
|
2091
|
$client['name'] = "Client {$prot}{$port}";
|
2092
|
}
|
2093
|
|
2094
|
$client['vpnid'] = $settings['vpnid'];
|
2095
|
$client['mgmt'] = "client{$client['vpnid']}";
|
2096
|
$socket = "unix://{$g['openvpn_base']}/{$client['mgmt']}/sock";
|
2097
|
$client['status']="down";
|
2098
|
|
2099
|
$clients[] = openvpn_get_client_status($client, $socket);
|
2100
|
}
|
2101
|
return $clients;
|
2102
|
}
|
2103
|
|
2104
|
function openvpn_get_client_status($client, $socket) {
|
2105
|
$errval = null;
|
2106
|
$errstr = null;
|
2107
|
$fp = @stream_socket_client($socket, $errval, $errstr, 1);
|
2108
|
if ($fp) {
|
2109
|
stream_set_timeout($fp, 1);
|
2110
|
/* send our status request */
|
2111
|
fputs($fp, "state 1\n");
|
2112
|
|
2113
|
/* recv all response lines */
|
2114
|
while (!feof($fp)) {
|
2115
|
/* read the next line */
|
2116
|
$line = fgets($fp, 1024);
|
2117
|
|
2118
|
$info = stream_get_meta_data($fp);
|
2119
|
if ($info['timed_out']) {
|
2120
|
break;
|
2121
|
}
|
2122
|
|
2123
|
/* Get the client state */
|
2124
|
if (substr_count($line, ',') >= 7) {
|
2125
|
$list = explode(",", trim($line));
|
2126
|
$list = array_map('trim', $list);
|
2127
|
|
2128
|
$client['connect_time'] = date("D M j G:i:s Y", $list[0]);
|
2129
|
$client['state'] = $list[1];
|
2130
|
$client['state_detail'] = $list[2];
|
2131
|
$client['virtual_addr'] = $list[3];
|
2132
|
$client['remote_host'] = $list[4];
|
2133
|
$client['remote_port'] = $list[5];
|
2134
|
$client['local_host'] = $list[6];
|
2135
|
$client['local_port'] = $list[7];
|
2136
|
$client['virtual_addr6'] = $list[8];
|
2137
|
|
2138
|
switch (trim($client['state'])) {
|
2139
|
case 'CONNECTED':
|
2140
|
$client['status'] = gettext("Connected");
|
2141
|
break;
|
2142
|
case 'CONNECTING':
|
2143
|
$client['status'] = gettext("Connecting");
|
2144
|
break;
|
2145
|
case 'TCP_CONNECT':
|
2146
|
$client['status'] = gettext("Connecting to TCP Server");
|
2147
|
break;
|
2148
|
case 'ASSIGN_IP':
|
2149
|
$client['status'] = gettext("Configuring Interface/Waiting");
|
2150
|
break;
|
2151
|
case 'WAIT':
|
2152
|
$client['status'] = gettext("Waiting for response from peer");
|
2153
|
break;
|
2154
|
case 'RECONNECTING':
|
2155
|
switch ($client['state_detail']) {
|
2156
|
case 'server_poll':
|
2157
|
$client['status'] = gettext("Waiting for peer connection");
|
2158
|
$client['state_detail'] = '';
|
2159
|
break;
|
2160
|
case 'tls-error':
|
2161
|
$client['status'] = gettext("TLS Error, reconnecting");
|
2162
|
$client['state_detail'] = '';
|
2163
|
break;
|
2164
|
default:
|
2165
|
$client['status'] = gettext("Reconnecting");
|
2166
|
break;
|
2167
|
}
|
2168
|
break;
|
2169
|
case 'AUTH':
|
2170
|
$client['status'] = gettext("Authenticating");
|
2171
|
break;
|
2172
|
case 'AUTH_PENDING':
|
2173
|
$client['status'] = gettext("Authentication pending");
|
2174
|
break;
|
2175
|
case 'GET_CONFIG':
|
2176
|
$client['status'] = gettext("Pulling configuration from server");
|
2177
|
break;
|
2178
|
case 'ADD_ROUTES':
|
2179
|
$client['status'] = gettext("Adding routes to system");
|
2180
|
break;
|
2181
|
case 'RESOLVE':
|
2182
|
$client['status'] = gettext("Resolving peer hostname via DNS");
|
2183
|
break;
|
2184
|
default:
|
2185
|
$client['status'] = ucwords(strtolower(str_replace(array('_', '-'), ' ', $client['state'])));
|
2186
|
break;
|
2187
|
}
|
2188
|
|
2189
|
if (!empty($client['state_detail'])) {
|
2190
|
$client['status'] .= " (" . ucwords(strtolower(str_replace(array('_', '-'), ' ', $client['state_detail']))) . ")";
|
2191
|
}
|
2192
|
|
2193
|
}
|
2194
|
/* parse end of output line */
|
2195
|
if (strstr($line, "END") || strstr($line, "ERROR")) {
|
2196
|
break;
|
2197
|
}
|
2198
|
}
|
2199
|
|
2200
|
/* If up, get read/write stats */
|
2201
|
if (strcmp($client['state'], "CONNECTED") == 0) {
|
2202
|
fputs($fp, "status 2\n");
|
2203
|
/* recv all response lines */
|
2204
|
while (!feof($fp)) {
|
2205
|
/* read the next line */
|
2206
|
$line = fgets($fp, 1024);
|
2207
|
|
2208
|
$info = stream_get_meta_data($fp);
|
2209
|
if ($info['timed_out']) {
|
2210
|
break;
|
2211
|
}
|
2212
|
|
2213
|
if (strstr($line, "TCP/UDP read bytes")) {
|
2214
|
$list = explode(",", $line);
|
2215
|
$client['bytes_recv'] = $list[1];
|
2216
|
}
|
2217
|
|
2218
|
if (strstr($line, "TCP/UDP write bytes")) {
|
2219
|
$list = explode(",", $line);
|
2220
|
$client['bytes_sent'] = $list[1];
|
2221
|
}
|
2222
|
|
2223
|
/* parse end of output line */
|
2224
|
if (strstr($line, "END")) {
|
2225
|
break;
|
2226
|
}
|
2227
|
}
|
2228
|
}
|
2229
|
|
2230
|
fclose($fp);
|
2231
|
|
2232
|
} else {
|
2233
|
$client['remote_host'] = gettext("Unable to contact daemon");
|
2234
|
$client['virtual_addr'] = gettext("Service not running?");
|
2235
|
$client['bytes_recv'] = 0;
|
2236
|
$client['bytes_sent'] = 0;
|
2237
|
$client['connect_time'] = 0;
|
2238
|
}
|
2239
|
return $client;
|
2240
|
}
|
2241
|
|
2242
|
function openvpn_kill_client($port, $remipp, $client_id) {
|
2243
|
global $g;
|
2244
|
$killed = -1;
|
2245
|
|
2246
|
$port = basename($port);
|
2247
|
$sock_path = "{$g['openvpn_base']}/{$port}/sock";
|
2248
|
/* If the socket doesn't exist, or if the remote IP address and port are
|
2249
|
* not valid, then do not proceed. */
|
2250
|
if (!file_exists($sock_path) ||
|
2251
|
!is_ipaddrwithport($remipp)) {
|
2252
|
return $killed;
|
2253
|
}
|
2254
|
$socket = "unix://{$sock_path}";
|
2255
|
$errval = null;
|
2256
|
$errstr = null;
|
2257
|
|
2258
|
/* open a tcp connection to the management port of each server */
|
2259
|
$fp = @stream_socket_client($socket, $errval, $errstr, 1);
|
2260
|
$killed = -1;
|
2261
|
if ($fp) {
|
2262
|
stream_set_timeout($fp, 1);
|
2263
|
if (is_numeric($client_id)) {
|
2264
|
/* terminate remote client, see https://redmine.pfsense.org/issues/12416 */
|
2265
|
fputs($fp, "client-kill {$client_id} HALT\n");
|
2266
|
} else {
|
2267
|
fputs($fp, "kill {$remipp}\n");
|
2268
|
}
|
2269
|
while (!feof($fp)) {
|
2270
|
$line = fgets($fp, 1024);
|
2271
|
|
2272
|
$info = stream_get_meta_data($fp);
|
2273
|
if ($info['timed_out']) {
|
2274
|
break;
|
2275
|
}
|
2276
|
|
2277
|
/* parse header list line */
|
2278
|
if (strpos($line, "INFO:") !== false) {
|
2279
|
continue;
|
2280
|
}
|
2281
|
if (strpos($line, "SUCCESS") !== false) {
|
2282
|
$killed = 0;
|
2283
|
}
|
2284
|
break;
|
2285
|
}
|
2286
|
fclose($fp);
|
2287
|
}
|
2288
|
return $killed;
|
2289
|
}
|
2290
|
|
2291
|
function openvpn_refresh_crls() {
|
2292
|
global $g;
|
2293
|
|
2294
|
openvpn_create_dirs();
|
2295
|
|
2296
|
foreach (config_get_path('openvpn/openvpn-server', []) as $settings) {
|
2297
|
if (empty($settings)) {
|
2298
|
continue;
|
2299
|
}
|
2300
|
if (isset($settings['disable'])) {
|
2301
|
continue;
|
2302
|
}
|
2303
|
// Write the settings for the keys
|
2304
|
switch ($settings['mode']) {
|
2305
|
case 'p2p_tls':
|
2306
|
case 'server_tls':
|
2307
|
case 'server_tls_user':
|
2308
|
case 'server_user':
|
2309
|
$param = array('caref' => $settings['caref']);
|
2310
|
$cas = ca_chain_array($param);
|
2311
|
$capath = "{$g['openvpn_base']}/server{$settings['vpnid']}/ca";
|
2312
|
if (!empty($settings['crlref'])) {
|
2313
|
$crl_item_config = lookup_crl($settings['crlref']);
|
2314
|
$crl = &$crl_item_config['item'];
|
2315
|
crl_update($crl_item_config);
|
2316
|
}
|
2317
|
foreach ($cas as $ca) {
|
2318
|
ca_setup_capath($ca, $capath, $crl, true);
|
2319
|
}
|
2320
|
unset($cas, $param, $capath, $crl);
|
2321
|
break;
|
2322
|
}
|
2323
|
}
|
2324
|
}
|
2325
|
|
2326
|
function openvpn_create_dirs() {
|
2327
|
global $g, $openvpn_tls_server_modes;
|
2328
|
if (!is_dir(g_get('openvpn_base'))) {
|
2329
|
safe_mkdir(g_get('openvpn_base'), 0750);
|
2330
|
}
|
2331
|
|
2332
|
foreach(array('server', 'client') as $mode) {
|
2333
|
foreach (config_get_path("openvpn/openvpn-{$mode}", []) as $settings) {
|
2334
|
if (isset($settings['disable'])) {
|
2335
|
continue;
|
2336
|
}
|
2337
|
$target = "{$g['openvpn_base']}/{$mode}{$settings['vpnid']}";
|
2338
|
$csctarget = "{$target}/csc/";
|
2339
|
@unlink_if_exists($csctarget);
|
2340
|
@safe_mkdir($target);
|
2341
|
if (in_array($settings['mode'], $openvpn_tls_server_modes)) {
|
2342
|
@safe_mkdir($csctarget);
|
2343
|
}
|
2344
|
}
|
2345
|
}
|
2346
|
}
|
2347
|
|
2348
|
function openvpn_get_interface_ip($ip, $cidr) {
|
2349
|
$subnet = gen_subnetv4($ip, $cidr);
|
2350
|
if ($cidr == 31) {
|
2351
|
$ip1 = $subnet;
|
2352
|
} else {
|
2353
|
$ip1 = ip_after($subnet);
|
2354
|
}
|
2355
|
$ip2 = ip_after($ip1);
|
2356
|
return array($ip1, $ip2);
|
2357
|
}
|
2358
|
|
2359
|
function openvpn_get_interface_ipv6($ipv6, $prefix) {
|
2360
|
$basev6 = gen_subnetv6($ipv6, $prefix);
|
2361
|
// Is there a better way to do this math?
|
2362
|
$ipv6_arr = explode(':', $basev6);
|
2363
|
$last = hexdec(array_pop($ipv6_arr));
|
2364
|
if ($prefix == 127) {
|
2365
|
$last--;
|
2366
|
}
|
2367
|
$ipv6_1 = text_to_compressed_ip6(implode(':', $ipv6_arr) . ':' . dechex($last + 1));
|
2368
|
$ipv6_2 = text_to_compressed_ip6(implode(':', $ipv6_arr) . ':' . dechex($last + 2));
|
2369
|
return array($ipv6_1, $ipv6_2);
|
2370
|
}
|
2371
|
|
2372
|
function openvpn_clear_route($mode, $settings) {
|
2373
|
if (empty($settings['tunnel_network'])) {
|
2374
|
return;
|
2375
|
}
|
2376
|
list($ip, $cidr) = openvpn_gen_tunnel_network($settings['tunnel_network']);
|
2377
|
$mask = gen_subnet_mask($cidr);
|
2378
|
$clear_route = false;
|
2379
|
|
2380
|
switch ($settings['mode']) {
|
2381
|
case 'shared_key':
|
2382
|
$clear_route = true;
|
2383
|
break;
|
2384
|
case 'p2p_tls':
|
2385
|
case 'p2p_shared_key':
|
2386
|
if ($cidr >= 30) {
|
2387
|
$clear_route = true;
|
2388
|
}
|
2389
|
break;
|
2390
|
}
|
2391
|
|
2392
|
if ($clear_route && !empty($ip) && !empty($mask)) {
|
2393
|
list($ip1, $ip2) = openvpn_get_interface_ip($ip, $cidr);
|
2394
|
$ip_to_clear = ($mode == "server") ? $ip1 : $ip2;
|
2395
|
/* XXX: Family for route? */
|
2396
|
mwexec("/sbin/route -q delete {$ip_to_clear}");
|
2397
|
}
|
2398
|
}
|
2399
|
|
2400
|
function openvpn_gen_routes($value, $ipproto = "ipv4", $push = false, $iroute = false) {
|
2401
|
$routes = "";
|
2402
|
$networks = array();
|
2403
|
if (empty($value)) {
|
2404
|
return "";
|
2405
|
}
|
2406
|
$tmpnetworks = explode(',', $value);
|
2407
|
|
2408
|
/* Remove empty entries from network array, which otherwise may lead to
|
2409
|
* invalid route statements.
|
2410
|
* https://redmine.pfsense.org/issues/14919
|
2411
|
*/
|
2412
|
$tmpnetworks = array_filter($tmpnetworks, function ($tnet) {
|
2413
|
return !empty(trim($tnet));
|
2414
|
});
|
2415
|
|
2416
|
foreach ($tmpnetworks as $network) {
|
2417
|
if (is_alias($network)) {
|
2418
|
foreach (alias_to_subnets_recursive($network, true) as $net) {
|
2419
|
if ((($ipproto == "ipv4") && is_subnetv4($net)) ||
|
2420
|
(($ipproto == "ipv6") && is_subnetv6($net))) {
|
2421
|
$networks[] = $net;
|
2422
|
} elseif (is_fqdn($net)) {
|
2423
|
if ($ipproto == "ipv4" ) {
|
2424
|
$recordtypes = array(DNS_A);
|
2425
|
$mask = "/32";
|
2426
|
} else {
|
2427
|
$recordtypes = array(DNS_AAAA);
|
2428
|
$mask = "/128";
|
2429
|
}
|
2430
|
$domips = resolve_host_addresses($net, $recordtypes, false);
|
2431
|
if (!empty($domips)) {
|
2432
|
foreach ($domips as $net) {
|
2433
|
$networks[] = $net . $mask;
|
2434
|
}
|
2435
|
} else {
|
2436
|
log_error(gettext("Failed to resolve {$net}. Skipping OpenVPN route entry."));
|
2437
|
}
|
2438
|
}
|
2439
|
}
|
2440
|
} else {
|
2441
|
$networks[] = $network;
|
2442
|
}
|
2443
|
}
|
2444
|
|
2445
|
foreach ($networks as $network) {
|
2446
|
if ($ipproto == "ipv4") {
|
2447
|
$route = openvpn_gen_route_ipv4($network, $iroute);
|
2448
|
} else {
|
2449
|
$route = openvpn_gen_route_ipv6($network, $iroute);
|
2450
|
}
|
2451
|
|
2452
|
if ($push) {
|
2453
|
$routes .= "push \"{$route}\"\n";
|
2454
|
} else {
|
2455
|
$routes .= "{$route}\n";
|
2456
|
}
|
2457
|
}
|
2458
|
return $routes;
|
2459
|
}
|
2460
|
|
2461
|
function openvpn_gen_route_ipv4($network, $iroute = false) {
|
2462
|
$i = ($iroute) ? "i" : "";
|
2463
|
list($ip, $mask) = explode('/', trim($network));
|
2464
|
$mask = gen_subnet_mask($mask);
|
2465
|
return "{$i}route $ip $mask";
|
2466
|
}
|
2467
|
|
2468
|
function openvpn_gen_route_ipv6($network, $iroute = false) {
|
2469
|
$i = ($iroute) ? "i" : "";
|
2470
|
list($ipv6, $prefix) = explode('/', trim($network));
|
2471
|
if (empty($prefix) && !is_numeric($prefix)) {
|
2472
|
$prefix = "128";
|
2473
|
}
|
2474
|
return "{$i}route-ipv6 {$ipv6}/{$prefix}";
|
2475
|
}
|
2476
|
|
2477
|
function openvpn_get_settings($mode, $vpnid) {
|
2478
|
foreach (["server", "client"] as $mode) {
|
2479
|
foreach (config_get_path("openvpn/openvpn-{$mode}", []) as $settings) {
|
2480
|
if (isset($settings['disable'])) {
|
2481
|
continue;
|
2482
|
}
|
2483
|
|
2484
|
if ($vpnid != 0 && $vpnid == $settings['vpnid']) {
|
2485
|
return $settings;
|
2486
|
}
|
2487
|
}
|
2488
|
}
|
2489
|
return array();
|
2490
|
}
|
2491
|
|
2492
|
function openvpn_restart_by_vpnid($mode, $vpnid) {
|
2493
|
$settings = openvpn_get_settings($mode, $vpnid);
|
2494
|
openvpn_restart($mode, $settings);
|
2495
|
}
|
2496
|
|
2497
|
/****f* certs/openvpn_is_tunnel_network_in_use
|
2498
|
* NAME
|
2499
|
* openvpn_is_tunnel_network_in_use
|
2500
|
* Check if the supplied network is in use as an OpenVPN server or client
|
2501
|
* tunnel network
|
2502
|
* INPUTS
|
2503
|
* $net : The IPv4 or IPv6 network to check
|
2504
|
* RESULT
|
2505
|
* boolean value: true if the network is in use, false otherwise.
|
2506
|
******/
|
2507
|
|
2508
|
function openvpn_is_tunnel_network_in_use($net) {
|
2509
|
/* Determine whether to check IPv4 or IPv6 tunnel networks */
|
2510
|
$tocheck = 'tunnel_network';
|
2511
|
if (is_v6($net)) {
|
2512
|
$tocheck .= "v6";
|
2513
|
}
|
2514
|
/* Check all OpenVPN clients and servers for this tunnel network */
|
2515
|
foreach(array('server', 'client') as $mode) {
|
2516
|
foreach (config_get_path("openvpn/openvpn-{$mode}", []) as $ovpn) {
|
2517
|
if (!empty($ovpn[$tocheck]) &&
|
2518
|
($ovpn[$tocheck] == $net)) {
|
2519
|
return true;
|
2520
|
}
|
2521
|
}
|
2522
|
}
|
2523
|
return false;
|
2524
|
}
|
2525
|
|
2526
|
function openvpn_build_data_cipher_list($data_ciphers = 'AES-256-GCM,AES-128-GCM,CHACHA20-POLY1305', $fallback_cipher = 'AES-256-GCM') {
|
2527
|
/* If the data_ciphers list is empty, populate it with the fallback cipher. */
|
2528
|
if (empty($data_ciphers)) {
|
2529
|
$data_ciphers = $fallback_cipher;
|
2530
|
}
|
2531
|
/* Add the fallback cipher to the data ciphers list if it isn't already present */
|
2532
|
if (!in_array($fallback_cipher, explode(',', $data_ciphers))) {
|
2533
|
$data_ciphers .= ',' . $fallback_cipher;
|
2534
|
}
|
2535
|
return $data_ciphers;
|
2536
|
}
|
2537
|
|
2538
|
function openvpn_authscript_string($authmode, $strictusercn, $mode_id, $local_port) {
|
2539
|
return "plugin /usr/local/lib/openvpn/plugins/openvpn-plugin-auth-script.so /usr/local/sbin/ovpn_auth_verify_async user " . base64_encode($authmode) . " {$strictusercn} {$mode_id} {$local_port}\n";
|
2540
|
}
|
2541
|
|
2542
|
function openvpn_inuse($id, $mode) {
|
2543
|
foreach (get_configured_interface_list(true) as $if) {
|
2544
|
if (config_get_path("interfaces/{$if}/if") == openvpn_name($mode, ['vpnid' => $id])) {
|
2545
|
return true;
|
2546
|
}
|
2547
|
}
|
2548
|
|
2549
|
return false;
|
2550
|
}
|
2551
|
|
2552
|
function openvpn_tunnel_network_fix($tunnel_network) {
|
2553
|
$tunnel_network = trim($tunnel_network);
|
2554
|
if (is_subnet($tunnel_network)) {
|
2555
|
/* convert to correct network address,
|
2556
|
* see https://redmine.pfsense.org/issues/11416 */
|
2557
|
list($tunnel_ip, $tunnel_netmask) = explode('/', $tunnel_network);
|
2558
|
$tunnel_network = gen_subnet($tunnel_ip, $tunnel_netmask) . '/' . $tunnel_netmask;
|
2559
|
}
|
2560
|
return $tunnel_network;
|
2561
|
}
|
2562
|
|
2563
|
?>
|