Skip to content

Commit

Permalink
Rework how IPsec VTI interfaces and reqid specifications for same are…
Browse files Browse the repository at this point in the history
… formed. Ticket #8544
  • Loading branch information
jim-p committed Jun 5, 2018
1 parent 6576782 commit 235c051
Show file tree
Hide file tree
Showing 7 changed files with 119 additions and 63 deletions.
136 changes: 108 additions & 28 deletions src/etc/inc/interfaces.inc
Expand Up @@ -1212,6 +1212,45 @@ function interface_gif_configure(&$gif, $gifkey = "") {
return $gifif;
}

/* Build a list of IPsec interfaces */
function interface_ipsec_vti_list_p1($ph1ent) {
global $config;
$iface_list = array();

if (empty($ph1ent) || !is_array($ph1ent) || !is_array($config['ipsec']['phase2'])) {
return $iface_list;
}

$vtisubnet_spec = ipsec_vti($ph1ent, true);
if ((!$vtisubnet_spec || !is_array($vtisubnet_spec))) {
return $iface_list;
}

/* With IKEv1 or v2+Split, each P2 gets its own conn/reqid/interface */
if (!isset($ph1ent['mobile']) && ($keyexchange == 'ikev1' || isset($ph1ent['splitconn']))) {
foreach ($vtisubnet_spec as $idx => $vtisub) {
$iface_list["ipsec{$ph1ent['ikeid']}00{$idx}"] = gettext("IPsec VTI") . ": ".htmlspecialchars($ph1ent['descr'] . " / " . $vtisub['descr']);
}
} else {
/* For IKEv2, only create one interface with additional addresses as aliases */
$iface_list["ipsec{$ph1ent['ikeid']}000"] = gettext("IPsec VTI") . ": ".htmlspecialchars($ph1ent['descr']);
}
return $iface_list;
}
function interface_ipsec_vti_list_all() {
global $config;
$iface_list = array();
if (is_array($config['ipsec']) && is_array($config['ipsec']['phase1']) && is_array($config['ipsec']['phase2'])) {
foreach ($config['ipsec']['phase1'] as $ph1ent) {
if ($ph1ent['disabled']) {
continue;
}
$iface_list = array_merge($iface_list, interface_ipsec_vti_list_p1($ph1ent));
}
}
return $iface_list;
}

function interface_ipsec_vti_configure($ph1ent) {
global $config;

Expand All @@ -1220,52 +1259,90 @@ function interface_ipsec_vti_configure($ph1ent) {
}

$vtisubnet_spec = ipsec_vti($ph1ent, true);
if ((!$vtisubnet_spec || !is_array($vtisubnet_spec))) {
return false;
}

if ($vtisubnet_spec && is_array($vtisubnet_spec)) {
$left_spec = ipsec_get_phase1_src($ph1ent);
$right_spec = $ph1ent['remote-gateway'];
$ipsecif = "ipsec{$ph1ent['ikeid']}";

if (platform_booting() || !does_interface_exist($ipsecif)) {
mwexec("/sbin/ifconfig " . escapeshellarg($ipsecif) . " destroy", false);
mwexec("/sbin/ifconfig " . escapeshellarg($ipsecif) . " create reqid " . escapeshellarg($ph1ent['ikeid']), false);
} else {
mwexec("/sbin/ifconfig " . escapeshellarg($ipsecif) . " create reqid " . escapeshellarg($ph1ent['ikeid']), false);
}
$left_spec = ipsec_get_phase1_src($ph1ent);
$right_spec = $ph1ent['remote-gateway'];

$inet = is_ipaddrv6($left_spec) ? "inet6" : "inet";
mwexec("/sbin/ifconfig " . escapeshellarg($ipsecif) . " {$inet} tunnel " . escapeshellarg($left_spec) . " " . escapeshellarg($right_spec) . " up", false);
$iface_addrs = array();

/* With IKEv1 or v2+Split, each P2 gets its own conn/reqid/interface */
if (!isset($ph1ent['mobile']) && ($keyexchange == 'ikev1' || isset($ph1ent['splitconn']))) {
/* Form a single interface for each P2 entry */
foreach ($vtisubnet_spec as $idx => $vtisub) {
$ipsecifnum = "{$ph1ent['ikeid']}00{$idx}";
if (!is_array($iface_addrs[$ipsecifnum])) {
$iface_addrs[$ipsecifnum] = array();
}
$vtisub['alias'] = "";
$iface_addrs[$ipsecifnum][] = $vtisub;
}
} else {
/* For IKEv2, only create one interface with additional addresses as aliases */
$ipsecifnum = "{$ph1ent['ikeid']}000";
if (!is_array($iface_addrs[$ipsecifnum])) {
$iface_addrs[$ipsecifnum] = array();
}
$have_v4 = false;
$have_v6 = false;
foreach ($vtisubnet_spec as $vtisub) {
$alias = "";
// Alias stuff
$vtisub['alias'] = "";
if (is_ipaddrv6($vtisub['left'])) {
if ($have_v6) {
$alias = " alias";
} else {
// Write out gwv6 file
file_put_contents("/tmp/{$ipsecif}_routerv6", $vtisub['right']);
$vtisub['alias'] = " alias";
}
$inet = "inet6";
$have_v6 = true;
} else {
if ($have_v4) {
$alias = " alias";
} else {
// Write out gw file
file_put_contents("/tmp/{$ipsecif}_router", $vtisub['right']);
$vtisub['alias'] = " alias";
}
$inet = "inet";
$have_v4 = true;
}
/* ifconfig ipsec0 inet <p2 local> <p2 remote> */
mwexec("/sbin/ifconfig " . escapeshellarg($ipsecif) . " {$inet} " . escapeshellarg($vtisub['left']) . " " . escapeshellarg($vtisub['right']) . $alias, false);
$iface_addrs[$ipsecifnum][] = $vtisub;
}
}

if (!platform_booting()) {
system_routing_configure($ipsecif);
foreach ($iface_addrs as $ipsecifnum => $addrs) {
$ipsecif = "ipsec{$ipsecifnum}";
if (!is_array($addrs)) {
continue;
}
// Create IPsec interface
if (platform_booting() || !does_interface_exist($ipsecif)) {
mwexec("/sbin/ifconfig " . escapeshellarg($ipsecif) . " destroy", false);
mwexec("/sbin/ifconfig " . escapeshellarg($ipsecif) . " create reqid " . escapeshellarg($ipsecifnum), false);
} else {
mwexec("/sbin/ifconfig " . escapeshellarg($ipsecif) . " create reqid " . escapeshellarg($ipsecifnum), false);
}

/* Apply the outer tunnel addresses to the interface */
$inet = is_ipaddrv6($left_spec) ? "inet6" : "inet";
mwexec("/sbin/ifconfig " . escapeshellarg($ipsecif) . " {$inet} tunnel " . escapeshellarg($left_spec) . " " . escapeshellarg($right_spec) . " up", false);

/* Loop through all of the addresses for this interface and apply them as needed */
foreach ($addrs as $addr) {
// apply interface addresses
if (is_ipaddrv6($addr['left'])) {
$inet = "inet6";
$gwtype = "v6";
} else {
$inet = "inet";
$gwtype = "";
}

mwexec("/sbin/ifconfig " . escapeshellarg($ipsecif) . " {$inet} " . escapeshellarg($addr['left']) . " " . escapeshellarg($addr['right']) . $addr['alias'], false);
/* If alias is empty, this is the first address on the interface and should be used as the gateway. */
if (empty($addr['alias'])) {
file_put_contents("/tmp/{$ipsecif}_router{$gwtype}", $addr['right']);
}
}
}

if (!platform_booting()) {
system_routing_configure($ipsecif);
}
}

Expand All @@ -1276,6 +1353,9 @@ function interfaces_ipsec_vti_configure() {
}
if (is_array($config['ipsec']) && is_array($config['ipsec']['phase1']) && is_array($config['ipsec']['phase2'])) {
foreach ($config['ipsec']['phase1'] as $ph1ent) {
if ($ph1ent['disabled']) {
continue;
}
interface_ipsec_vti_configure($ph1ent);
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/etc/inc/interfaces_fast.inc
Expand Up @@ -261,7 +261,7 @@ function interface_assign_description_fast($portlist, $friendlyifnames) {
} elseif (substr($portname, 0, 4) == 'ovpn') {
$descr = $portname . " (" . $ovpn_descrs[substr($portname, 5)] . ")";
} elseif (substr($portname, 0, 5) == 'ipsec') {
$descr = $portname . " (" . $ipsec_descrs[substr($portname, 5)] . ")";
$descr = $portname . " (" . $ipsec_descrs[$portname] . ")";
} else {
$descr = $portname . " (" . $portinfo['mac'] . ")";
}
Expand Down
1 change: 1 addition & 0 deletions src/etc/inc/ipsec.inc
Expand Up @@ -888,6 +888,7 @@ function ipsec_vti($ph1ent, $returnaddresses = false) {
$vtisubnet_spec[] = array(
'left' => ipsec_idinfo_to_cidr($ph2ent['localid'], true, $ph2ent['mode']),
'right' => ipsec_idinfo_to_cidr($ph2ent['remoteid'], false, $ph2ent['mode']),
'descr' => $ph2ent['descr'],
);
}
$is_vti = true;
Expand Down
4 changes: 2 additions & 2 deletions src/etc/inc/vpn.inc
Expand Up @@ -1430,7 +1430,7 @@ EOD;
// $ipsecfin .= "\treqid = " . $reqids[$idx] . "\n";
//}
if (!empty($vtireq[$idx])) {
$ipsecfin .= "\treqid = " . $vtireq[$idx] . "\n";
$ipsecfin .= "\treqid = {$ph1ent['ikeid']}00{$idx}\n";
}
$ipsecfin .= $ipsecconnect;
$ipsecfin .= "\trightsubnet = {$rsubnet}\n";
Expand All @@ -1450,7 +1450,7 @@ EOD;
// $ipsecfin .= "\treqid = " . $reqids[0] . "\n";
//}
if (!empty($vtireq[$idx])) {
$ipsecfin .= "\treqid = " . $vtireq[0] . "\n";
$ipsecfin .= "\treqid = {$ph1ent['ikeid']}000\n";
}
$ipsecfin .= $ipsecconnect;
if (!isset($ph1ent['mobile']) && !empty($rightsubnet_spec)) {
Expand Down
12 changes: 2 additions & 10 deletions src/usr/local/www/diag_packet_capture.php
Expand Up @@ -134,16 +134,8 @@ function fixup_host($value, $position) {
}
}
}
if (is_array($config['ipsec']) && is_array($config['ipsec']['phase1']) && is_array($config['ipsec']['phase2'])) {
foreach ($config['ipsec']['phase1'] as $ph1ent) {
if ($ph1ent['disabled']) {
continue;
}
if (ipsec_vti($ph1ent)) {
$interfaces["ipsec{$ph1ent['ikeid']}"] = gettext("IPsec VTI") . ": ".htmlspecialchars($ph1ent['descr']);
}
}
}

$interfaces = array_merge($interfaces, interface_ipsec_vti_list_all());

if ($_POST) {
$host = $_POST['host'];
Expand Down
15 changes: 3 additions & 12 deletions src/usr/local/www/interfaces_assign.php
Expand Up @@ -170,18 +170,9 @@
}

global $ipsec_descrs;
$ipsec_descrs = array();
if (is_array($config['ipsec']) && is_array($config['ipsec']['phase1']) && is_array($config['ipsec']['phase2'])) {
foreach ($config['ipsec']['phase1'] as $ph1ent) {
if ($ph1ent['disabled']) {
continue;
}
if (ipsec_vti($ph1ent)) {
$portname = "ipsec{$ph1ent['ikeid']}";
$portlist[$portname] = $ph1ent;
$ipsec_descrs[$ph1ent['ikeid']] = $ph1ent['descr'];
}
}
$ipsec_descrs = interface_ipsec_vti_list_all();
foreach ($ipsec_descrs as $ifname => $ifdescr) {
$portlist[$ifname] = array('descr' => $ifdescr);
}


Expand Down
12 changes: 2 additions & 10 deletions src/usr/local/www/status_graph.php
Expand Up @@ -51,16 +51,8 @@
}
}
}
if (is_array($config['ipsec']) && is_array($config['ipsec']['phase1']) && is_array($config['ipsec']['phase2'])) {
foreach ($config['ipsec']['phase1'] as $ph1ent) {
if ($ph1ent['disabled']) {
continue;
}
if (ipsec_vti($ph1ent)) {
$ifdescrs["ipsec{$ph1ent['ikeid']}"] = gettext("IPsec VTI") . ": ".htmlspecialchars($ph1ent['descr']);
}
}
}

$ifdescrs = array_merge($ifdescrs, interface_ipsec_vti_list_all());

if ($_REQUEST['if']) {
$curif = $_REQUEST['if'];
Expand Down

0 comments on commit 235c051

Please sign in to comment.