Skip to content

Commit

Permalink
Rework IPsec P1 Lifetime GUI options. Fixes #9983
Browse files Browse the repository at this point in the history
  • Loading branch information
jim-p committed Dec 18, 2019
1 parent 8af4e81 commit 9701089
Show file tree
Hide file tree
Showing 5 changed files with 103 additions and 116 deletions.
2 changes: 1 addition & 1 deletion src/etc/inc/globals.inc
Expand Up @@ -71,7 +71,7 @@ $g = array(
"disablecrashreporter" => false,
"crashreporterurl" => "https://crashreporter.pfsense.org/crash_reporter.php",
"debug" => false,
"latest_config" => "19.9",
"latest_config" => "20.0",
"minimum_ram_warning" => "101",
"minimum_ram_warning_text" => "128 MB",
"wan_interface_name" => "wan",
Expand Down
40 changes: 10 additions & 30 deletions src/etc/inc/ipsec.inc
Expand Up @@ -2048,37 +2048,17 @@ function ipsec_setup_tunnels() {
$child_params['dpd_action'] = "none";
}

/* Auto or IKEv1, setup reauthentication */
if (($ikeversion == 0) || ($ikeversion == 1)) {
/* IKEv1 uses reauth, not rekey. Reauth with IKEv2 can be problematic. */
if (isset($ph1ent['reauth_enable'])) {
$conn['reauth_time'] = "0s";
/* If reauth is disabled, set P1 lifetime as over_time */
$conn['over_time'] = "{$ph1ent['lifetime']}s";
} else {
/* Reauth at 90% of requested lifetime, set hard limit at full (relative) lifetime */
$conn['reauth_time'] = (int)($ph1ent['lifetime'] * 0.90) . "s";
$conn['over_time'] = (int)($ph1ent['lifetime'] * 0.10) . "s";
}
}
/* Auto or IKEv2, setup rekey */
/* Reauth (Any) */
$conn['reauth_time'] = (empty($ph1ent['reauth_time']) ? "0" : $ph1ent['reauth_time']) . "s";

/* Rekey (IKEv2 or Auto only, not supported by IKEv1) */
if (($ikeversion == 0) || ($ikeversion == 2)) {
/* IKEv2 uses rekey, reauth may cause problems */
if (isset($ph1ent['rekey_enable'])) {
$conn['rekey_time'] = "0s";
/* If rekey is disabled, set P1 lifetime as over_time */
$conn['over_time'] = "{$ph1ent['lifetime']}s";
} else {
if (!empty($ph1ent['margintime'])) {
/* If margintime is set, use that to calculate over_time and rekey_time */
$conn['rekey_time'] = ($ph1ent['lifetime'] - $ph1ent['margintime']) . "s";
$conn['over_time'] = "{$ph1ent['margintime']}s";
} else {
/* Rekey at 90% of requested lifetime, set hard limit at full (relative) lifetime */
$conn['rekey_time'] = (int)($ph1ent['lifetime'] * 0.90) . "s";
$conn['over_time'] = (int)($ph1ent['lifetime'] * 0.10) . "s";
}
}
$conn['rekey_time'] = (empty($ph1ent['rekey_time']) ? "0" : $ph1ent['rekey_time']) . "s";
}

/* Over Time */
if (!empty($ph1ent['over_time'])) {
$conn['over_time'] = "{$ph1ent['over_time']}s";
}

/* NAT Traversal */
Expand Down
36 changes: 36 additions & 0 deletions src/etc/inc/upgrade_config.inc
Expand Up @@ -6076,6 +6076,42 @@ function upgrade_198_to_199() {
}
}

/* Update IPsec reauth and rekey variable names and values based on existing settings
* https://redmine.pfsense.org/issues/9983
*/
function upgrade_199_to_200() {
global $config;
init_config_arr(array('ipsec', 'phase1'));
foreach ($config['ipsec']['phase1'] as & $ph1ent) {
/* Convert lifetime to reauth_time since that's how previous
* versions behaved. */
if (isset($ph1ent['reauth_enable'])) {
$ph1ent['reauth_time'] = "0";
/* If reauth is disabled, set hard P1 lifetime limit */
$ph1ent['over_time'] = $ph1ent['lifetime'];
} else {
/* Reauth at 90% of requested lifetime, set hard limit at full (relative) lifetime */
$ph1ent['reauth_time'] = (int)($ph1ent['lifetime'] * 0.90);
$ph1ent['over_time'] = (int)($ph1ent['lifetime'] * 0.10);
}
/* Auto or IKEv2, rekey items */
if (($ph1ent['iketype'] == 'ikev2') || ($ph1ent['iketype'] == 'auto')) {
if (isset($ph1ent['rekey_enable'])) {
/* Disable rekey */
$ph1ent['rekey_time'] = "0";
$ph1ent['reauth_time'] = "0";
/* If rekey is disabled, set hard P1 lifetime limit */
$ph1ent['over_time'] = $ph1ent['lifetime'];
} elseif (!empty($ph1ent['margintime'])) {
/* If margintime is set, use that to calculate over_time and reauth_time */
$ph1ent['reauth_time'] = ($ph1ent['lifetime'] - $ph1ent['margintime']);
$ph1ent['over_time'] = $ph1ent['margintime'];
}
}
unset($ph1ent['lifetime'], $ph1ent['reauth_enable'], $ph1ent['rekey_enable'], $ph1ent['margintime']);
}
}

/*
* Special function that is called independent of current config version. It's
* a workaround to have config_upgrade running on older versions after next
Expand Down
16 changes: 12 additions & 4 deletions src/usr/local/www/status_ipsec.php
Expand Up @@ -238,12 +238,20 @@ function print_ipsec_body() {

print("</td>\n");
print("<td>\n");
if (!empty($ikesa['reauth-time'])) {
print("<b>" . gettext("Reauth:") . "</b> ". htmlspecialchars($ikesa['reauth-time']) . gettext("s (") . convert_seconds_to_dhms($ikesa['reauth-time']) . ")");
if ($ikesa['version'] == 2) {
print("<b>" . gettext("Rekey:") . "</b> ");
if (!empty($ikesa['rekey-time'])) {
print(htmlspecialchars($ikesa['rekey-time']) . gettext("s (") . convert_seconds_to_dhms($ikesa['rekey-time']) . ")");
} else {
print(gettext("Disabled"));
}
print("<br/>");
}
if (!empty($ikesa['rekey-time'])) {
print("<b>" . gettext("Rekey:") . "</b> " . htmlspecialchars($ikesa['rekey-time']) . gettext("s (") . convert_seconds_to_dhms($ikesa['rekey-time']) . ")");
print("<b>" . gettext("Reauth:") . "</b> ");
if (!empty($ikesa['reauth-time'])) {
print(htmlspecialchars($ikesa['reauth-time']) . gettext("s (") . convert_seconds_to_dhms($ikesa['reauth-time']) . ")");
} else {
print(gettext("Disabled"));
}
print("</td>\n");
print("<td>\n");
Expand Down
125 changes: 44 additions & 81 deletions src/usr/local/www/vpn_ipsec_phase1.php
Expand Up @@ -97,7 +97,9 @@
$pconfig['peerid_type'] = $a_phase1[$p1index]['peerid_type'];
$pconfig['peerid_data'] = $a_phase1[$p1index]['peerid_data'];
$pconfig['encryption'] = $a_phase1[$p1index]['encryption'];
$pconfig['lifetime'] = $a_phase1[$p1index]['lifetime'];
$pconfig['rekey_time'] = $a_phase1[$p1index]['rekey_time'];
$pconfig['reauth_time'] = $a_phase1[$p1index]['reauth_time'];
$pconfig['over_time'] = $a_phase1[$p1index]['over_time'];
$pconfig['authentication_method'] = $a_phase1[$p1index]['authentication_method'];

if (($pconfig['authentication_method'] == "pre_shared_key") ||
Expand All @@ -115,18 +117,6 @@
$pconfig['mobike'] = $a_phase1[$p1index]['mobike'];
$pconfig['closeaction'] = $a_phase1[$p1index]['closeaction'];

if (isset($a_phase1[$p1index]['reauth_enable'])) {
$pconfig['reauth_enable'] = true;
}

if (isset($a_phase1[$p1index]['rekey_enable'])) {
$pconfig['rekey_enable'] = true;
}

if ($a_phase1[$p1index]['margintime']) {
$pconfig['margintime'] = $a_phase1[$p1index]['margintime'];
}

if (isset($a_phase1[$p1index]['responderonly'])) {
$pconfig['responderonly'] = true;
}
Expand Down Expand Up @@ -159,7 +149,7 @@
$pconfig['myid_type'] = "myaddress";
$pconfig['peerid_type'] = "peeraddress";
$pconfig['authentication_method'] = "pre_shared_key";
$pconfig['lifetime'] = "28800";
$pconfig['reauth_time'] = "28800";
$pconfig['nat_traversal'] = 'on';
$pconfig['mobike'] = 'off';
$pconfig['dpd_enable'] = true;
Expand Down Expand Up @@ -267,22 +257,20 @@
$input_errors[] = gettext("Pre-Shared Key contains invalid characters.");
}

if (($pconfig['lifetime'] && !is_numericint($pconfig['lifetime']))) {
$input_errors[] = gettext("The P1 lifetime must be an integer.");
if (!empty($pconfig['rekey_time']) && !is_numericint($pconfig['rekey_time'])) {
$input_errors[] = gettext("Rekey Time must be an integer.");
}
if (!empty($pconfig['reauth_time']) && !is_numericint($pconfig['reauth_time'])) {
$input_errors[] = gettext("Reauth Time must be an integer.");
}
if (!empty($pconfig['over_time']) && !is_numericint($pconfig['over_time'])) {
$input_errors[] = gettext("Over Time must be an integer.");
}

if (!empty($pconfig['closeaction']) && !array_key_exists($pconfig['closeaction'], $ipsec_closeactions)) {
$input_errors[] = gettext("Invalid Child SA Close Action.");
}

if (!isset($pconfig['rekey_enable']) && $pconfig['margintime']) {
if(!is_numericint($pconfig['margintime'])){
$input_errors[] = gettext("The margintime must be an integer.");
} else if(intval($pconfig['margintime']) >= intval($pconfig['lifetime'])){
$input_errors[] = gettext("The margintime must be smaller than the P1 lifetime.");
}
}

if ($pconfig['remotegw']) {
if (!is_ipaddr($pconfig['remotegw']) && !is_domain($pconfig['remotegw'])) {
$input_errors[] = gettext("A valid remote gateway address or host name must be specified.");
Expand Down Expand Up @@ -498,7 +486,9 @@
$ph1ent['peerid_data'] = $pconfig['peerid_data'];

$ph1ent['encryption'] = $pconfig['encryption'];
$ph1ent['lifetime'] = $pconfig['lifetime'];
$ph1ent['rekey_time'] = $pconfig['rekey_time'];
$ph1ent['reauth_time'] = $pconfig['reauth_time'];
$ph1ent['over_time'] = $pconfig['over_time'];
$ph1ent['pre-shared-key'] = $pconfig['pskey'];
$ph1ent['private-key'] = base64_encode($pconfig['privatekey']);
$ph1ent['certref'] = $pconfig['certref'];
Expand All @@ -511,24 +501,6 @@
$ph1ent['mobike'] = $pconfig['mobike'];
$ph1ent['closeaction'] = $pconfig['closeaction'];

if (isset($pconfig['reauth_enable'])) {
$ph1ent['reauth_enable'] = true;
} else {
unset($ph1ent['reauth_enable']);
}

if (isset($pconfig['rekey_enable'])) {
$ph1ent['rekey_enable'] = true;
} else {
unset($ph1ent['rekey_enable']);
}

if (!isset($pconfig['rekey_enable'])) {
$ph1ent['margintime'] = $pconfig['margintime'];
} else {
unset($ph1ent['margintime']);
}

if (isset($pconfig['responderonly'])) {
$ph1ent['responderonly'] = true;
} else {
Expand Down Expand Up @@ -897,38 +869,40 @@ function build_eal_list() {
$btnaddopt->removeClass('btn-primary')->addClass('btn-success btn-sm');
$section->addInput($btnaddopt);

$section = new Form_Section('NOTITLE');
$section->addInput(new Form_Input(
'lifetime',
'*Lifetime (Seconds)',
'number',
$pconfig['lifetime']
));

$form->add($section);

$section = new Form_Section('Advanced Options');
$section = new Form_Section('Expiration and Replacement');

$section->addInput(new Form_Checkbox(
'rekey_enable',
'Disable rekey',
'Disables renegotiation when a connection is about to expire.',
$pconfig['rekey_enable']
));
$section->addInput(new Form_Input(
'rekey_time',
'Rekey Time',
'number',
$pconfig['rekey_time']
))->setHelp('Time, in seconds, before an IKE SA establishes new keys. This works without interruption. ' .
'Only supported by IKEv2, and is recommended for use with IKEv2. ' .
'Leave blank or enter a value of 0 to disable.');

$section->addInput(new Form_Input(
'margintime',
'Margintime (Seconds)',
'reauth_time',
'Reauth Time',
'number',
$pconfig['margintime']
))->setHelp('How long before connection expiry or keying-channel expiry should attempt to negotiate a replacement begin.');
$pconfig['reauth_time']
))->setHelp('Time, in seconds, before an IKE SA is torn down and recreated from scratch, including authentication. ' .
'This can be disruptive unless both sides support make-before-break and overlapping IKE SA entries. ' .
'Supported by IKEv1 and IKEv2. Leave blank or enter a value of 0 to disable.');

$section->addInput(new Form_Checkbox(
'reauth_enable',
'Disable Reauth',
'Whether rekeying of an IKE_SA should also reauthenticate the peer. In IKEv1, reauthentication is always done.',
$pconfig['reauth_enable']
));
$section->addInput(new Form_Input(
'over_time',
'Over Time',
'number',
$pconfig['over_time']
))->setHelp('Hard IKE SA life time, in seconds, after which the IKE SA will be expired. ' .
'This time is relative to reauthentication and rekey time. ' .
'If left empty, defaults to 10% of whichever timer is higher (reauth or rekey)');

$form->add($section);

$section = new Form_Section('Advanced Options');

$section->addInput(new Form_Checkbox(
'responderonly',
Expand Down Expand Up @@ -1067,14 +1041,14 @@ function iketype_change() {
hideInput('mode', true);
hideInput('mobike', false);
//hideCheckbox('tfc_enable', false);
hideCheckbox('reauth_enable', false);
hideInput('rekey_time', false);
hideCheckbox('splitconn', false);
} else {
hideInput('mode', false);
hideInput('mobike', true);
//hideCheckbox('tfc_enable', true);
//hideInput('tfc_bytes', true);
hideCheckbox('reauth_enable', true);
hideInput('rekey_time', !($('#iketype').val() == 'auto'));
hideCheckbox('splitconn', true);
}
}
Expand Down Expand Up @@ -1199,12 +1173,6 @@ function ealgosel_change(id, bits) {
}
}

function rekeychkbox_change() {
hide = $('#rekey_enable').prop('checked');

hideInput('margintime', hide);
}

function dpdchkbox_change() {
hide = !$('#dpd_enable').prop('checked');

Expand All @@ -1228,11 +1196,6 @@ function dpdchkbox_change() {

// ---------- Monitor elements for change and call the appropriate display functions ----------

// Enable Rekey
$('#rekey_enable').click(function () {
rekeychkbox_change();
});

// Enable DPD
$('#dpd_enable').click(function () {
dpdchkbox_change();
Expand Down

0 comments on commit 9701089

Please sign in to comment.