Skip to content

Commit

Permalink
ipsec: allow tunnel isolation compatibility mode
Browse files Browse the repository at this point in the history
At least FortiGate doesn't like meshing the phase 2 entries so
instead isolete each phase 2 entry in its own tunnel.  This is
supposedly IKEv1 trickery, but it works...

Also see: https://wiki.strongswan.org/projects/strongswan/wiki/FAQ#Multiple-subnets-per-SA
Also see: https://lists.strongswan.org/pipermail/users/2013-March/004478.html
  • Loading branch information
fichtner committed Aug 19, 2016
1 parent e7140a5 commit fb5e786
Show file tree
Hide file tree
Showing 2 changed files with 68 additions and 29 deletions.
82 changes: 54 additions & 28 deletions src/etc/inc/ipsec.inc
Expand Up @@ -1115,7 +1115,6 @@ conn con<<connectionId>>
installpolicy = yes
{$tunneltype}
{$dpdline}
auto = {$conn_auto}
left = {$left_spec}
right = {$right_spec}
leftid = {$myid_data}
Expand Down Expand Up @@ -1157,42 +1156,69 @@ EOD;
if (!empty($ealgoAHsp2arr[$idx])) {
$tmpconf .= "\tah = " . join(',', $ealgoAHsp2arr[$idx]) . "!\n";
}
$tmpconf .= "\tauto = {$conn_auto}";
$ipsecconf .= $tmpconf;
}
} else {
// mobile and ikev2
$tmpconf = str_replace('<<connectionId>>', "{$ph1ent['ikeid']}", $connEntry);
if (!empty($rightsubnet_spec)) {
$tmpconf .= "\trightsubnet = " . join(',', array_unique($rightsubnet_spec)) . "\n";
}
if (!empty($leftsubnet_spec)) {
$tmpconf .= "\tleftsubnet = " . join(',', array_unique($leftsubnet_spec)) . "\n";
}
// merge esp phase 2 arrays.
$esp_content = array();
foreach ($ealgoESPsp2arr as $ealgoESPsp2arr_details) {
foreach ($ealgoESPsp2arr_details as $esp_item) {
if (!in_array($esp_item, $esp_content)) {
$esp_content[] = $esp_item;
if (isset($ph1ent['tunnel_isolation'])) {
$ipsecconf .= str_replace('<<connectionId>>', "{$ph1ent['ikeid']}-000", $connEntry);
for ($idx = 0; $idx < count($leftsubnet_spec); ++$idx) {
// requires leading empty line:
$tmpconf = array('');
// fix for strongSwan to pick up the correct connection
// name from the first configured tunnel ($idx == 0):
$conn_suffix = $idx ? sprintf('-%03d', $idx) : '';
$tmpconf[] = "conn con{$ph1ent['ikeid']}{$conn_suffix}";
$tmpconf[] = "\trightsubnet = {$rightsubnet_spec[$idx]}";
$tmpconf[] = "\tleftsubnet = {$leftsubnet_spec[$idx]}";
if (!empty($ealgoESPsp2arr[$idx])) {
$tmpconf[] = "\tesp = " . join(',', $ealgoESPsp2arr[$idx]) . '!';
}
if (!empty($ealgoAHsp2arr[$idx])) {
$tmpconf[] = "\tah = " . join(',', $ealgoAHsp2arr[$idx]) . '!';
}
$tmpconf[] = "\talso = con{$ph1ent['ikeid']}-000";
$tmpconf[] = "\tauto = {$conn_auto}";
// requires trailing empty line:
$tmpconf[] = '';
$ipsecconf .= join("\n", $tmpconf);
}
}
// merge ah phase 2 arrays.
$ah_content = array();
foreach ($ealgoAHsp2arr as $ealgoAHsp2arr_details) {
foreach ($ealgoAHsp2arr_details as $ah_item) {
if (!in_array($ah_item, $ah_content)) {
$ah_content[] = $ah_item;
} else {
$tmpconf = str_replace('<<connectionId>>', "{$ph1ent['ikeid']}", $connEntry);
if (!empty($rightsubnet_spec)) {
$tmpconf .= "\trightsubnet = " . join(',', array_unique($rightsubnet_spec)) . "\n";
}
if (!empty($leftsubnet_spec)) {
$tmpconf .= "\tleftsubnet = " . join(',', array_unique($leftsubnet_spec)) . "\n";
}
// merge esp phase 2 arrays.
$esp_content = array();
foreach ($ealgoESPsp2arr as $ealgoESPsp2arr_details) {
foreach ($ealgoESPsp2arr_details as $esp_item) {
if (!in_array($esp_item, $esp_content)) {
$esp_content[] = $esp_item;
}
}
}
// merge ah phase 2 arrays.
$ah_content = array();
foreach ($ealgoAHsp2arr as $ealgoAHsp2arr_details) {
foreach ($ealgoAHsp2arr_details as $ah_item) {
if (!in_array($ah_item, $ah_content)) {
$ah_content[] = $ah_item;
}
}
}
if (!empty($esp_content)) {
$tmpconf .= "\tesp = " . join(',', $esp_content) . "!\n";
}
if (!empty($ah_content)) {
$tmpconf .= "\tah = " . join(',', $ah_content) . "!\n";
}
$tmpconf .= "\tauto = {$conn_auto}";
$ipsecconf .= $tmpconf;
}
if (!empty($esp_content)) {
$tmpconf .= "\tesp = " . join(',', $esp_content) . "!\n";
}
if (!empty($ah_content)) {
$tmpconf .= "\tah = " . join(',', $ah_content) . "!\n";
}
$ipsecconf .= $tmpconf;
}
}
}
Expand Down
15 changes: 14 additions & 1 deletion src/www/vpn_ipsec_phase1.php
Expand Up @@ -87,7 +87,7 @@ function ipsec_ikeid_next() {
$phase1_fields = "mode,protocol,myid_type,myid_data,peerid_type,peerid_data
,encryption-algorithm,hash-algorithm,dhgroup,lifetime,authentication_method,descr,nat_traversal
,interface,iketype,dpd_delay,dpd_maxfail,remote-gateway,pre-shared-key,certref
,caref,reauth_enable,rekey_enable, auto";
,caref,reauth_enable,rekey_enable,auto,tunnel_isolation";
if (isset($p1index) && isset($config['ipsec']['phase1'][$p1index])) {
// 1-on-1 copy
foreach (explode(",", $phase1_fields) as $fieldname) {
Expand Down Expand Up @@ -359,6 +359,10 @@ function ipsec_ikeid_next() {
$ph1ent['rekey_enable'] = true;
}

if (isset($pconfig['tunnel_isolation'])) {
$ph1ent['tunnel_isolation'] = true;
}

if (isset($pconfig['dpd_enable'])) {
$ph1ent['dpd_delay'] = $pconfig['dpd_delay'];
$ph1ent['dpd_maxfail'] = $pconfig['dpd_maxfail'];
Expand Down Expand Up @@ -920,6 +924,15 @@ function ipsec_ikeid_next() {
</div>
</td>
</tr>
<tr>
<td><a id="help_for_tunnel_isolation" href="#" class="showhelp"><i class="fa fa-info-circle"></i></a> <?=gettext('Tunnel Isolation') ?></td>
<td>
<input name="tunnel_isolation" type="checkbox" id="tunnel_isolation" value="yes" <?= !empty($pconfig['tunnel_isolation']) ? 'checked="checked"' : '' ?>/>
<div class="hidden" for="help_for_tunnel_isolation">
<?= gettext('This option will create a tunnel for each phase 2 entry for IKEv2 interoperability with e.g. FortiGate devices.') ?>
</div>
</td>
</tr>
<tr>
<td><a id="help_for_nat_traversal" href="#" class="showhelp"><i class="fa fa-info-circle"></i></a> <?=gettext("NAT Traversal"); ?></td>
<td>
Expand Down

0 comments on commit fb5e786

Please sign in to comment.