diff options
author | Ermal <eri@pfsense.org> | 2014-08-07 18:51:39 +0000 |
---|---|---|
committer | Ermal <eri@pfsense.org> | 2014-08-07 18:53:12 +0000 |
commit | 0b5fc1d1a6c515d91df5ec1d848b6bbc1a05186b (patch) | |
tree | c826bbf8e6afae9f2e6309e606cfc30f230e9dbc /etc/inc/vpn.inc | |
parent | b31a2c765fcb1042e604cd52908898fa5c0d2321 (diff) | |
download | pfsense-0b5fc1d1a6c515d91df5ec1d848b6bbc1a05186b.zip pfsense-0b5fc1d1a6c515d91df5ec1d848b6bbc1a05186b.tar.gz |
Change the logic of the vpn config generation to make connectivity more stable especially ipsec. Also for IKEv1 just generate the policies and only on traffic start them.
Diffstat (limited to 'etc/inc/vpn.inc')
-rw-r--r-- | etc/inc/vpn.inc | 327 |
1 files changed, 166 insertions, 161 deletions
diff --git a/etc/inc/vpn.inc b/etc/inc/vpn.inc index 39e4333..2e2100b 100644 --- a/etc/inc/vpn.inc +++ b/etc/inc/vpn.inc @@ -269,6 +269,9 @@ charon { # number of worker threads in charon threads = 16 + # NOTE: Allows to send multiple subnets for IKEv1 + cisco_unity = yes + # XXX: There is not much choice here really users win their security! i_dont_care_about_security_and_use_aggressive_mode_psk=yes @@ -475,10 +478,13 @@ EOD; } /* Add user PSKs */ - foreach ($config['system']['user'] as $user) { - if (!empty($user['ipsecpsk'])) { - $pskconf .= "{$user['name']} : PSK \"{$user['ipsecpsk']}\"\n"; + if (is_array($config['system']) && is_array($config['system']['user'])) { + foreach ($config['system']['user'] as $user) { + if (!empty($user['ipsecpsk'])) { + $pskconf .= "{$user['name']} : PSK \"{$user['ipsecpsk']}\"\n"; + } } + unset($user); } /* add PSKs for mobile clients */ @@ -488,6 +494,7 @@ EOD; $key['ident'] = ''; $pskconf .= "{$key['ident']} : PSK \"{$key['pre-shared-key']}\"\n"; } + unset($key); } @file_put_contents("{$g['varetc_path']}/ipsec/ipsec.secrets", $pskconf); @@ -497,182 +504,175 @@ EOD; $natfilterrules = false; /* begin ipsec.conf */ $ipsecconf = ""; - if ((is_array($a_phase1) && count($a_phase1)) || (is_array($a_phase2) && count($a_phase2))) { + if (is_array($a_phase1) && count($a_phase1)) { $ipsecconf .= "# This file is automatically generated. Do not edit\n"; - if (is_array($a_phase2) && count($a_phase2)) { - $ipsecconf .= "config setup\n\tuniqueids = yes\n"; - $ipsecconf .= "\tcharondebug=\"" . vpn_ipsec_configure_loglevels(true) . "\"\n"; + $ipsecconf .= "config setup\n\tuniqueids = yes\n"; + $ipsecconf .= "\tcharondebug=\"" . vpn_ipsec_configure_loglevels(true) . "\"\n"; - foreach ($a_phase2 as $ph2ent) { - $ikeid = $ph2ent['ikeid']; + foreach ($a_phase1 as $ph1ent) { + if (isset($ph1ent['disabled'])) + continue; - $ph1ent = false; - if (!ipsec_lookup_phase1($ph2ent,$ph1ent)) - continue; + if ($ph1ent['mode'] == "aggressive") + $aggressive = "yes"; + else + $aggressive = "no"; - if (isset($ph1ent['disabled'])) - continue; + $ep = ipsec_get_phase1_src($ph1ent); + if (!$ep) + continue; - if (isset($ph2ent['disabled'])) - continue; + $keyexchange = "ikev1"; + if (!empty($ph1ent['iketype']) && $ph1ent['iketype'] != "ikev1") { + $keyexchange = "ikev2"; + $passive = "start"; + } else + $passive = "route"; + + if (isset($ph1ent['mobile'])) { + $right_spec = "%any"; + $passive = 'add'; + } else + $right_spec = $ph1ent['remote-gateway']; + + list ($myid_type, $myid_data) = ipsec_find_id($ph1ent, "local"); + list ($peerid_type, $peerid_data) = ipsec_find_id($ph1ent, "peer", $rgmap); + + /* Only specify peer ID if we are not dealing with a mobile PSK-only tunnel */ + $peerid_spec = ''; + if (!isset($ph1ent['mobile'])) + $peerid_spec = $peerid_data; + + if (is_array($ph1ent['encryption-algorithm']) && !empty($ph1ent['encryption-algorithm']['name']) && !empty($ph1ent['hash-algorithm'])) { + $ealgosp1 = ''; + $ealg_id = $ph1ent['encryption-algorithm']['name']; + $ealg_kl = $ph1ent['encryption-algorithm']['keylen']; + if ($ealg_kl) + $ealgosp1 = "ike = {$ealg_id}{$ealg_kl}-{$ph1ent['hash-algorithm']}"; + else + $ealgosp1 = "ike = {$ealg_id}-{$ph1ent['hash-algorithm']}"; - if (isset($ph2ent['mobile']) && !isset($a_client['enable'])) - continue; + $modp = vpn_ipsec_convert_to_modp($ph1ent['dhgroup']); + if (!empty($modp)) + $ealgosp1 .= "-{$modp}"; - $ikeid = $ph1ent['ikeid']; + if ($keyexchange == "ikev1") + $ealgosp1 .= "!"; + } - if ($ph1ent['mode'] == "aggressive") - $aggressive = "yes"; + if ($ph1ent['dpd_delay'] && $ph1ent['dpd_maxfail']) { + if ($passive == "start") + $dpdline = "dpdaction = restart"; else - $aggressive = "no"; + $dpdline = "dpdaction = clear"; + $dpdline .= "\n\tdpddelay = {$ph1ent['dpd_delay']}s"; + $dpdtimeout = $ph1ent['dpd_delay'] * ($ph1ent['dpd_maxfail'] + 1); + $dpdline .= "\n\tdpdtimeout = {$dpdtimeout}s"; + } else + $dpdline = "dpdaction = none"; + + $ikelifeline = ''; + if ($ph1ent['lifetime']) + $ikelifeline = "ikelifetime = {$ph1ent['lifetime']}s"; + + $authentication = ""; + switch ($ph1ent['authentication_method']) { + case 'xauth_rsa_server': + $authentication = "leftauth = pubkey\n\trightauth = pubkey"; + $authentication .= "\n\trightauth2 = xauth-generic"; + break; + case 'xauth_psk_server': + $authentication = "leftauth = psk\n\trightauth = psk"; + $authentication .= "\n\trightauth2 = xauth-generic"; + break; + case 'pre_shared_key': + $authentication = "leftauth = psk\n\trightauth = psk"; + break; + case 'rsasig': + $authentication = "leftauth = pubkey\n\trightauth = pubkey"; + break; + case 'hybrid_rsa_server': + $authentication = "leftauth = xauth-generic\n\trightauth = pubkey"; + $authentication .= "\n\trightauth2 = xauth"; + break; + } - $ep = ipsec_get_phase1_src($ph1ent); - if (!$ep) - continue; + $left_spec = $ep; - $passive = "start"; - if (isset($ph1ent['mobile'])) { - $rgip = "%any"; - $passive = 'add'; - } else - $rgip = $ph1ent['remote-gateway']; - - $keyexchange = "ikev1"; - if (!empty($ph1ent['iketype']) && $ph1ent['iketype'] != "ikev1") { - $keyexchange = "ikev2"; - $rekey = "rekey = yes"; - } else { - $rekey = "rekey = yes"; - } + $ipseclifetime = 0; + $rightsubnet_spec = array(); + $leftsubnet_spec = array(); + $ealgoAHsp2arr = array(); + $ealgoESPsp2arr = array(); + if (is_array($a_phase2) && count($a_phase2)) { + foreach ($a_phase2 as $ph2ent) { + $ikeid = $ph2ent['ikeid']; + if ($ikeid != $ph1ent['ikeid']) + continue; - list ($myid_type, $myid_data) = ipsec_find_id($ph1ent, "local"); - list ($peerid_type, $peerid_data) = ipsec_find_id($ph1ent, "peer", $rgmap); + if (isset($ph2ent['disabled'])) + continue; - /* Only specify peer ID if we are not dealing with a mobile PSK-only tunnel */ - $peerid_spec = ''; - if (!isset($ph1ent['mobile'])) - $peerid_spec = $peerid_data; - - if (is_array($ph1ent['encryption-algorithm']) && !empty($ph1ent['encryption-algorithm']['name']) && !empty($ph1ent['hash-algorithm'])) { - $ealgosp1 = ''; - $ealg_id = $ph1ent['encryption-algorithm']['name']; - $ealg_kl = $ph1ent['encryption-algorithm']['keylen']; - if ($ealg_kl) - $ealgosp1 = "ike = {$ealg_id}{$ealg_kl}-{$ph1ent['hash-algorithm']}"; - else - $ealgosp1 = "ike = {$ealg_id}-{$ph1ent['hash-algorithm']}"; - - $modp = vpn_ipsec_convert_to_modp($ph1ent['dhgroup']); - if (!empty($modp)) - $ealgosp1 .= "-{$modp}"; - - if ($keyexchange == "ikev1") - $ealgosp1 .= "!"; - } + if (isset($ph2ent['mobile']) && !isset($a_client['enable'])) + continue; - if ($ph1ent['dpd_delay'] && $ph1ent['dpd_maxfail']) { - if ($passive == "start") - $dpdline = "dpdaction = restart"; - else - $dpdline = "dpdaction = clear"; - $dpdline .= "\n\tdpddelay = {$ph1ent['dpd_delay']}s"; - $dpdtimeout = $ph1ent['dpd_delay'] * ($ph1ent['dpd_maxfail'] + 1); - $dpdline .= "\n\tdpdtimeout = {$dpdtimeout}s"; - } else - $dpdline = "dpdaction = none"; - - if (!empty($ph1ent['authentication_method']) && (strpos($ph1ent['authentication_method'], "xauth") || strpos($ph1ent['authentication_method'], "hybrid"))) - $xauth = "xauth = server"; - - $ikelifeline = ''; - if ($ph1ent['lifetime']) - $ikelifeline = "ikelifetime = {$ph1ent['lifetime']}s"; - - $remoteid_spec = ''; if (($ph2ent['mode'] == 'tunnel') or ($ph2ent['mode'] == 'tunnel6')) { $tunneltype = "type = tunnel"; $localid_type = $ph2ent['localid']['type']; - $localid_data = ipsec_idinfo_to_cidr($ph2ent['localid'], false, $ph2ent['mode']); + $leftsubnet_data = ipsec_idinfo_to_cidr($ph2ent['localid'], false, $ph2ent['mode']); /* Do not print localid in some cases, such as a pure-psk or psk/xauth single phase2 mobile tunnel */ if (($localid_type == "none" || $localid_type == "mobile") - && isset($ph1ent['mobile']) - && (ipsec_get_number_of_phase2($ikeid)==1)) - $localid_spec = "%any"; - else { + && isset($ph1ent['mobile']) && (ipsec_get_number_of_phase2($ikeid)==1)) { + $left_spec = '%any'; + } else { if ($localid_type != "address") { $localid_type = "subnet"; } // Don't let an empty subnet into config, it can cause parse errors. Ticket #2201. - if (!is_ipaddr($localid_data) && !is_subnet($localid_data) && ($localid_data != "0.0.0.0/0")) { + if (!is_ipaddr($leftsubnet_data) && !is_subnet($leftsubnet_data) && ($leftsubnet_data != "0.0.0.0/0")) { log_error("Invalid IPsec Phase 2 \"{$ph2ent['descr']}\" - {$ph2ent['localid']['type']} has no subnet."); continue; } - $localid_spec = $ep; if (!empty($ph2ent['natlocalid'])) { - $natlocalid_data = ipsec_idinfo_to_cidr($ph2ent['natlocalid'], false, $ph2ent['mode']); + $natleftsubnet_data = ipsec_idinfo_to_cidr($ph2ent['natlocalid'], false, $ph2ent['mode']); if ($ph2ent['natlocalid']['type'] != "address") { - if (is_subnet($natlocalid_data)) - $localid_data = "{$natlocalid_data}|{$localid_data}"; + if (is_subnet($natleftsubnet_data)) + $leftsubnet_data = "{$natleftsubnet_data}|{$leftsubnet_data}"; } else { - if (is_ipaddr($natlocalid_data)) - $localid_data = "{$natlocalid_data}|{$localid_data}"; + if (is_ipaddr($natleftsubnet_data)) + $leftsubnet_data = "{$natleftsubnet_data}|{$leftsubnet_data}"; } $natfilterrules = true; } } + $leftsubnet_spec[] = $leftsubnet_data; + if (!isset($ph2ent['mobile'])) { - $remoteid_data = ipsec_idinfo_to_cidr($ph2ent['remoteid'], false, $ph2ent['mode']); - $remoteid_spec = "\trightsubnet = {$remoteid_data}"; + $rightsubnet_spec[] = ipsec_idinfo_to_cidr($ph2ent['remoteid'], false, $ph2ent['mode']); } else if (!empty($a_client['pool_address'])) - $remoteid_spec = "\trightsourceip = {$a_client['pool_address']}/{$a_client['pool_netbits']}"; + $rightsubnet_spec[] = "{$a_client['pool_address']}/{$a_client['pool_netbits']}"; } else { $tunneltype = "type = transport"; - $rgip = $ph1ent['remote-gateway']; if ((($ph1ent['authentication_method'] == "xauth_psk_server") || - ($ph1ent['authentication_method'] == "pre_shared_key")) - && isset($ph1ent['mobile'])) - $localid_spec = "%any"; - else { - $localid_data = ipsec_get_phase1_src($ph1ent); - $localid_spec = $ep; - } - if (!isset($ph2ent['mobile'])) { - $remoteid_spec = "\trightsubnet = {$rgip}"; + ($ph1ent['authentication_method'] == "pre_shared_key")) && isset($ph1ent['mobile'])) { + $left_spec = "%any"; + } else { + $leftsubnet_spec[] = ipsec_get_phase1_src($ph1ent); } - } - $authentication = ""; - switch ($ph1ent['authentication_method']) { - case 'xauth_rsa_server': - $authentication = "leftauth = pubkey\n\trightauth = pubkey"; - $authentication .= "\n\trightauth2 = xauth-generic"; - break; - case 'xauth_psk_server': - $authentication = "leftauth = psk\n\trightauth = psk"; - $authentication .= "\n\trightauth2 = xauth-generic"; - break; - case 'pre_shared_key': - $authentication = "leftauth = psk\n\trightauth = psk"; - break; - case 'rsasig': - $authentication = "leftauth = pubkey\n\trightauth = pubkey"; - break; - case 'hybrid_rsa_server': - $authentication = "leftauth = xauth-generic\n\trightauth = pubkey"; - $authentication .= "\n\trightauth2 = xauth"; - break; + + if (!isset($ph2ent['mobile'])) + $rightsubnet_spec[] = $right_spec; } if (isset($a_client['pfs_group'])) $ph2ent['pfsgroup'] = $a_client['pfs_group']; - $ealgosp2 = ''; if ($ph2ent['protocol'] == 'esp') { if (is_array($ph2ent['encryption-algorithm-option']) && is_array($ph2ent['hash-algorithm-option'])) { - $ealgosp2arr = array(); foreach ($ph2ent['encryption-algorithm-option'] as $ealg) { $ealg_id = $ealg['name']; $ealg_kl = $ealg['keylen']; @@ -694,7 +694,7 @@ EOD; $modp = vpn_ipsec_convert_to_modp($ph2ent['pfsgroup']); if (!empty($modp)) $tmpealgo .= "-{$modp}"; - $ealgosp2arr[] = $tmpealgo; + $ealgoESPsp2arr[] = $tmpealgo; } } } @@ -705,64 +705,69 @@ EOD; $modp = vpn_ipsec_convert_to_modp($ph2ent['pfsgroup']); if (!empty($modp)) $tmpealgo .= "-{$modp}"; - $ealgosp2arr[] = $tmpealgo; + $ealgoESPsp2arr[] = $tmpealgo; } } } - $ealgosp2 = "esp = " . join(",", $ealgosp2arr); - unset($ealgosp2arr); - $ealgosp2 .= "!"; } } else if ($ph2ent['protocol'] == 'ah') { if (is_array($ph2ent['hash-algorithm-option'])) { - $ealgosp2 = "ah = " . join(",", $ph2ent['hash-algorithm-option']); - $ealgosp2 = str_replace('hmac_', '', $ealgosp2); $modp = vpn_ipsec_convert_to_modp($ph2ent['pfsgroup']); - if (!empty($modp)) - $ealgosp2 .= "-{$modp}"; - $ealgosp2 .= "!"; + foreach ($ph2ent['hash-algorithm-option'] as $tmpAHalgo) { + $tmpAHalgo = str_replace('hmac_', '', $tmpAHalgo); + if (!empty($modp)) + $tmpAHalgo = "-{$modp}"; + $ealgoAHsp2arr[] = $tmpAHalgo; + } } } - $ipseclifetime = ''; - if ($ph2ent['lifetime']) - $ipseclifeline = "lifetime = {$ph2ent['lifetime']}s"; + if (!empty($ph2ent['lifetime'])) { + if ($ipseclifetime == 0 || intval($ipseclifetime) > intval($ph2ent['lifetime'])) + $ipseclifetime = intval($ph2ent['lifetime']); + } + } + } - $ipsecconf .=<<<EOD + $ipsecconf .=<<<EOD -conn con{$ph1ent['ikeid']}-{$ph2ent['uniqid']} +conn con{$ph1ent['ikeid']} aggressive = {$aggressive} fragmentation = yes keyexchange = {$keyexchange} keyingtries = %forever reauth = yes - {$rekey} + rekey = yes reqid = {$ikeid} installpolicy = yes - {$ikelifeline} - {$ipseclifeline} {$tunneltype} {$dpdline} auto = {$passive} - left = {$localid_spec} - leftsubnet = {$localid_data} - right = {$rgip} + left = {$left_spec} + right = {$right_spec} leftid = {$myid_data} EOD; - if (!empty($remoteid_spec)) - $ipsecconf .= "{$remoteid_spec}\n"; - if (!empty($ealgosp1)) - $ipsecconf .= "\t{$ealgosp1}\n"; - if (!empty($ealgosp2)) - $ipsecconf .= "\t{$ealgosp2}\n"; - if (!empty($authentication)) - $ipsecconf .= "\t{$authentication}\n"; - if (!empty($peerid_spec)) - $ipsecconf .= "\trightid = {$peerid_spec}\n"; - } + if (!empty($ikelifeline)) + $ipsecconf .= "\t{$ikelifeline}\n"; + if ($ipseclifetime > 0) + $ipsecconf .= "\tlifetime = {$ipseclifetime}s\n"; + if (!empty($rightsubnet_spec)) + $ipsecconf .= "\trightsubnet = " . join(",", $rightsubnet_spec) . "\n"; + if (!empty($leftsubnet_spec)) + $ipsecconf .= "\tleftsubnet = " . join(",", $leftsubnet_spec) . "\n"; + if (!empty($ealgosp1)) + $ipsecconf .= "\t{$ealgosp1}\n"; + if (!empty($ealgoAHsp2arr)) + $ipsecconf .= "\tah = " . join(',', $ealgoAHsp2arr) . "!\n"; + if (!empty($ealgoESPsp2arr)) + $ipsecconf .= "\tesp = " . join(',', $ealgoESPsp2arr) . "!\n"; + if (!empty($authentication)) + $ipsecconf .= "\t{$authentication}\n"; + if (!empty($peerid_spec)) + $ipsecconf .= "\trightid = {$peerid_spec}\n"; } } } |