diff --git a/src/etc/inc/plugins.inc.d/ipsec.inc b/src/etc/inc/plugins.inc.d/ipsec.inc index 1e588e931..cc180d71e 100644 --- a/src/etc/inc/plugins.inc.d/ipsec.inc +++ b/src/etc/inc/plugins.inc.d/ipsec.inc @@ -536,6 +536,36 @@ function ipsec_convert_to_modp($index) return $convertion; } +/** + * load manual defined spd entries using setkey + */ +function load_manual_spd() +{ + global $config; + $spd_entries = array(); + if (!empty($config['ipsec']['phase1']) && !empty($config['ipsec']['phase2'])) { + foreach ($config['ipsec']['phase1'] as $ph1ent) { + foreach ($config['ipsec']['phase2'] as $ph2ent) { + if (!isset($ph2ent['disabled']) && $ph1ent['ikeid'] == $ph2ent['ikeid'] && !empty($ph2ent['spd'])) { + $myid_data = ipsec_find_id($ph1ent, "local"); + $peerid_spec = ipsec_find_id($ph1ent, "peer"); + foreach (explode(',', $ph2ent['spd']) as $local_net) { + $proto = $ph2ent['mode'] == "tunnel" ? "4" : "6"; + $remote_net = ipsec_idinfo_to_cidr($ph2ent['remoteid'], false, $ph2ent['mode']); + $spd_entries[] = sprintf("spdadd -%s %s %s any -P out ipsec %s/tunnel/%s-%s/require;", + $proto, trim($local_net), $remote_net, $ph2ent['protocol'], + $myid_data, $peerid_spec); + } + } + } + } + $tmpfname = tempnam("/tmp", "setkey"); + file_put_contents($tmpfname, implode("\n", $spd_entries) . "\n"); + mwexec("/sbin/setkey -f ". $tmpfname, true); + unlink($tmpfname); + } +} + function ipsec_configure_do($verbose = false, $interface = '') { global $config, $p2_ealgos, $ipsec_loglevels; @@ -1432,6 +1462,8 @@ EOD; } else { killbypid('/var/run/filterdns-ipsec.pid'); } + // load manually defined SPD entries + load_manual_spd(); if ($verbose) { echo "done.\n"; diff --git a/src/www/vpn_ipsec_phase2.php b/src/www/vpn_ipsec_phase2.php index 7c05cf903..bd7121ffe 100644 --- a/src/www/vpn_ipsec_phase2.php +++ b/src/www/vpn_ipsec_phase2.php @@ -145,7 +145,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'GET') { // initialize form data $pconfig = array(); - $phase2_fields = "ikeid,mode,descr,uniqid,proto,hash-algorithm-option,pfsgroup,pfsgroup,lifetime,pinghost,protocol"; + $phase2_fields = "ikeid,mode,descr,uniqid,proto,hash-algorithm-option,pfsgroup,pfsgroup,lifetime,pinghost,protocol,spd"; if ($p2index !== null) { // 1-on-1 copy foreach (explode(",", $phase2_fields) as $fieldname) { @@ -344,9 +344,18 @@ if ($_SERVER['REQUEST_METHOD'] === 'GET') { $input_errors[] = gettext("The P2 lifetime must be an integer."); } + if (!empty($pconfig['spd'])) { + foreach (explode(',', $pconfig['spd']) as $spd_entry) { + if (($pconfig['mode'] == "tunnel" && !is_subnetv4(trim($spd_entry))) || + ($pconfig['mode'] == "tunnel6" && !is_subnetv6(trim($spd_entry)))) { + $input_errors[] = sprintf(gettext('SPD "%s" is not a valid network, it should match the tunnel type (IPv4/IPv6).'), $spd_entry) ; + } + } + } + if (count($input_errors) == 0) { $ph2ent = array(); - $copy_fields = "ikeid,uniqid,mode,pfsgroup,lifetime,pinghost,descr,protocol"; + $copy_fields = "ikeid,uniqid,mode,pfsgroup,lifetime,pinghost,descr,protocol,spd"; // 1-on-1 copy foreach (explode(",", $copy_fields) as $fieldname) { @@ -704,6 +713,23 @@ endif; ?> + +