. * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ require_once("ipsec.inc"); require_once("filter.inc"); require_once("auth.inc"); function vpn_update_daemon_loglevel($category, $level) { global $ipsec_log_cats, $ipsec_log_sevs; if (in_array($category, array_keys($ipsec_log_cats), true) && in_array(intval($level), array_keys($ipsec_log_sevs), true)) { /* if you're setting to -1, need to add "--" to args */ $argterm = ""; if ($level == "-1") { $argterm = "--"; } mwexec("/usr/local/sbin/ipsec stroke loglevel {$category} {$argterm} {$level}"); } } function vpn_logging_cfgtxt() { global $config, $ipsec_log_cats, $ipsec_log_sevs; $cfgtext = array(); foreach (array_keys($ipsec_log_cats) as $cat) { if (is_numeric($config['ipsec']['logging'][$cat]) && in_array(intval($config['ipsec']['logging'][$cat]), array_keys($ipsec_log_sevs), true)) { $cfgtext[] = "${cat} = {$config['ipsec']['logging'][$cat]}"; } } return $cfgtext; } /* include all configuration functions */ function vpn_ipsec_convert_to_modp($index) { $conversion = ""; switch ($index) { case '1': $conversion = "modp768"; break; case '2': $conversion = "modp1024"; break; case '5': $conversion = "modp1536"; break; case '14': $conversion = "modp2048"; break; case '15': $conversion = "modp3072"; break; case '16': $conversion = "modp4096"; break; case '17': $conversion = "modp6144"; break; case '18': $conversion = "modp8192"; break; case '19': $conversion = "ecp256"; break; case '20': $conversion = "ecp384"; break; case '21': $conversion = "ecp521"; break; case '22': $conversion = "modp1024s160"; break; case '23': $conversion = "modp2048s224"; break; case '24': $conversion = "modp2048s256"; break; case '28': $conversion = "ecp256bp"; break; case '29': $conversion = "ecp384bp"; break; case '30': $conversion = "ecp512bp"; break; } return $conversion; } function vpn_ipsec_configure($restart = false) { global $config, $g, $sa, $sn, $p1_ealgos, $p2_ealgos, $ipsec_idhandling; $ipsecstartlock = lock('ipsec', LOCK_EX); /* get the automatic ping_hosts.sh ready */ unlink_if_exists("{$g['vardb_path']}/ipsecpinghosts"); touch("{$g['vardb_path']}/ipsecpinghosts"); $ipsecpinghostsactive = false; /* service may have been enabled, disabled, or otherwise changed in a way requiring rule updates */ filter_configure(); $syscfg = $config['system']; $ipseccfg = $config['ipsec']; if (!ipsec_enabled()) { /* try to stop charon */ mwexec("/usr/local/sbin/ipsec stop"); /* Stop dynamic monitoring */ killbypid("{$g['varrun_path']}/filterdns-ipsec.pid"); /* wait for process to die */ sleep(2); /* IPSEC is off, shutdown enc interface.*/ mwexec("/sbin/ifconfig enc0 down"); unlock($ipsecstartlock); return 0; } $a_phase1 = $config['ipsec']['phase1']; $a_phase2 = $config['ipsec']['phase2']; $a_client = $config['ipsec']['client']; $certpath = "{$g['varetc_path']}/ipsec/ipsec.d/certs"; $capath = "{$g['varetc_path']}/ipsec/ipsec.d/cacerts"; $keypath = "{$g['varetc_path']}/ipsec/ipsec.d/private"; $crlpath = "{$g['varetc_path']}/ipsec/ipsec.d/crls"; mwexec("/sbin/ifconfig enc0 up"); /* needed for config files */ if (!is_dir("{$g['varetc_path']}/ipsec")) { mkdir("{$g['varetc_path']}/ipsec"); } if (!is_dir("{$g['varetc_path']}/ipsec/ipsec.d")) { mkdir("{$g['varetc_path']}/ipsec/ipsec.d"); } // delete these paths first to ensure old CAs, certs and CRLs aren't left behind. redmine #5238 rmdir_recursive($capath); rmdir_recursive($keypath); rmdir_recursive($crlpath); rmdir_recursive($certpath); if (!is_dir($capath)) { mkdir($capath); } if (!is_dir($keypath)) { mkdir($keypath); } if (!is_dir($crlpath)) { mkdir($crlpath); } if (!is_dir($certpath)) { mkdir($certpath); } if (!is_dir("{$g['varetc_path']}/ipsec/ipsec.d/aacerts")) { mkdir("{$g['varetc_path']}/ipsec/ipsec.d/aacerts"); } if (!is_dir("{$g['varetc_path']}/ipsec/ipsec.d/acerts")) { mkdir("{$g['varetc_path']}/ipsec/ipsec.d/acerts"); } if (!is_dir("{$g['varetc_path']}/ipsec/ipsec.d/ocspcerts")) { mkdir("{$g['varetc_path']}/ipsec/ipsec.d/ocspcerts"); } if (!is_dir("{$g['varetc_path']}/ipsec/ipsec.d/reqs")) { mkdir("{$g['varetc_path']}/ipsec/ipsec.d/reqs"); } if (!file_exists("/usr/local/etc/ipsec.d") || !is_link("/usr/local/etc/ipsec.d")) { conf_mount_rw(); if (file_exists("/usr/local/etc/ipsec.d")) { rmdir_recursive("/usr/local/etc/ipsec.d"); } @symlink("{$g['varetc_path']}/ipsec/ipsec.d", "/usr/local/etc/ipsec.d"); conf_mount_ro(); } if (!file_exists("{$g['varetc_path']}/etc/strongswan.d") || !is_link("{$g['varetc_path']}/etc/strongswan.d")) { conf_mount_rw(); if (is_link("{$g['varetc_path']}/etc/strongswan.d")) { @unlink("{$g['varetc_path']}/etc/strongswan.d"); } else { rmdir_recursive("{$g['varetc_path']}/etc/strongswan.d"); } @symlink("/usr/local/etc/strongswan.d", "{$g['varetc_path']}/ipsec/strongswan.d"); conf_mount_ro(); } if (!file_exists("/usr/local/etc/strongswan.conf") || !is_link("/usr/local/etc/strongswan.conf")) { conf_mount_rw(); @unlink("/usr/local/etc/strongswan.conf"); @symlink("{$g['varetc_path']}/ipsec/strongswan.conf", "/usr/local/etc/strongswan.conf"); conf_mount_ro(); } if (!file_exists("/usr/local/etc/ipsec.conf") || !is_link("/usr/local/etc/ipsec.conf")) { conf_mount_rw(); @unlink("/usr/local/etc/ipsec.conf"); @symlink("{$g['varetc_path']}/ipsec/ipsec.conf", "/usr/local/etc/ipsec.conf"); conf_mount_ro(); } if (platform_booting()) { echo gettext("Configuring IPsec VPN... "); } /* resolve all local, peer addresses and setup pings */ $ipmap = array(); $rgmap = array(); $filterdns_list = array(); $aggressive_mode_psk = false; unset($iflist); $ifacesuse = array(); $mobile_ipsec_auth = ""; if (is_array($a_phase1) && count($a_phase1)) { $ipsecpinghosts = ""; /* step through each phase1 entry */ foreach ($a_phase1 as $ph1ent) { if (isset($ph1ent['disabled'])) { continue; } if (substr($ph1ent['interface'], 0, 4) == "_vip") { $vpninterface = get_configured_vip_interface($ph1ent['interface']); $ifacesuse[] = get_real_interface($vpninterface); } else { $vpninterface = get_failover_interface($ph1ent['interface']); if (substr($vpninterface, 0, 4) == "_vip") { $vpninterface = get_configured_vip_interface($vpninterface); $ifacesuse[] = get_real_interface($vpninterface); } elseif (!empty($vpninterface)) { $ifacesuse[] = $vpninterface; } } if ($ph1ent['mode'] == "aggressive" && ($ph1ent['authentication_method'] == "pre_shared_key" || $ph1ent['authentication_method'] == "xauth_psk_server")) { $aggressive_mode_psk = true; } $ikeid = $ph1ent['ikeid']; $ep = ipsec_get_phase1_src($ph1ent); if (!is_ipaddr($ep)) { log_error(sprintf(gettext("IPsec ERROR: Could not find phase 1 source for connection %s. Omitting from configuration file."), $ph1ent['descr'])); continue; } if (!in_array($ep, $ipmap)) { $ipmap[] = $ep; } /* see if this tunnel has a hostname for the remote-gateway. If so, try to resolve it now and add it to the list for filterdns */ if (isset ($ph1ent['mobile'])) { $mobile_ipsec_auth = $ph1ent['authentication_method']; continue; } $rg = $ph1ent['remote-gateway']; if (!is_ipaddr($rg)) { $filterdns_list[] = "{$rg}"; add_hostname_to_watch($rg); if (!platform_booting()) { $rg = resolve_retry($rg); } if (!is_ipaddr($rg)) { continue; } } if (array_search($rg, $rgmap)) { log_error(sprintf(gettext("The remote gateway %s already exists on another phase 1 entry"), $rg)); continue; } $rgmap[$ph1ent['remote-gateway']] = $rg; if (is_array($a_phase2)) { /* step through each phase2 entry */ foreach ($a_phase2 as $ph2ent) { if (isset($ph2ent['disabled'])) { continue; } if ($ikeid != $ph2ent['ikeid']) { continue; } /* add an ipsec pinghosts entry */ if ($ph2ent['pinghost']) { if (!is_array($iflist)) { $iflist = get_configured_interface_list(); } $srcip = null; $local_subnet = ipsec_idinfo_to_cidr($ph2ent['localid'], true, $ph2ent['mode']); if (is_ipaddrv6($ph2ent['pinghost'])) { foreach ($iflist as $ifent => $ifname) { $interface_ip = get_interface_ipv6($ifent); if (!is_ipaddrv6($interface_ip)) { continue; } if (ip_in_subnet($interface_ip, $local_subnet)) { $srcip = $interface_ip; break; } } } else { foreach ($iflist as $ifent => $ifname) { $interface_ip = get_interface_ip($ifent); if (!is_ipaddrv4($interface_ip)) { continue; } if ($local_subnet == "0.0.0.0/0" || ip_in_subnet($interface_ip, $local_subnet)) { $srcip = $interface_ip; break; } } } /* if no valid src IP was found in configured interfaces, try the vips */ if (is_null($srcip)) { $viplist = get_configured_vip_list(); foreach ($viplist as $vip => $address) { if (ip_in_subnet($address, $local_subnet)) { $srcip = $address; break; } } } $dstip = $ph2ent['pinghost']; if (is_ipaddrv6($dstip)) { $family = "inet6"; } else { $family = "inet"; } if (is_ipaddr($srcip)) { $ipsecpinghosts[] = "{$srcip}|{$dstip}|3|||||{$family}|\n"; $ipsecpinghostsactive = true; } } } } } @file_put_contents("{$g['vardb_path']}/ipsecpinghosts", $ipsecpinghosts); unset($ipsecpinghosts); } unset($iflist); $accept_unencrypted = ""; if (isset($config['ipsec']['acceptunencryptedmainmode'])) { $accept_unencrypted = "accept_unencrypted_mainmode_messages = yes"; } $stronconf = ''; if (file_exists("{$g['varetc_path']}/ipsec/strongswan.conf")) { $stronconf = file_get_contents("{$g['varetc_path']}/ipsec/strongswan.conf"); } $i_dont_care_about_security_and_use_aggressive_mode_psk = ""; if ($aggressive_mode_psk) { log_error("WARNING: Setting i_dont_care_about_security_and_use_aggressive_mode_psk option because a phase 1 is configured using aggressive mode with pre-shared keys. This is not a secure configuration."); if (!empty($stronconf) && strpos($stronconf, 'i_dont_care_about_security_and_use_aggressive_mode_psk') === FALSE) { $restart = true; } $i_dont_care_about_security_and_use_aggressive_mode_psk = "i_dont_care_about_security_and_use_aggressive_mode_psk=yes"; } $unity_enabled = isset($config['ipsec']['unityplugin']) ? 'yes' : 'no'; $makebeforebreak = ''; if (isset($config['ipsec']['makebeforebreak'])) { $makebeforebreak = 'make_before_break = yes'; } if (isset($config['ipsec']['enableinterfacesuse'])) { if (!empty($ifacesuse)) { $ifacesuse = 'interfaces_use = ' . implode(',', array_unique($ifacesuse)); } else { $ifacesuse = ''; } } else { $ifacesuse = ''; } unset($stronconf); $strongswanlog = ""; $ipsecloglevels = vpn_logging_cfgtxt(); if (is_array($ipsecloglevels)) { foreach ($ipsecloglevels as $loglevel) { $strongswanlog .= "\t\t\t" . $loglevel . "\n"; } } $strongswan = << 0) { $strongswan .= ","; } if ($authcfg == "system") { $authcfg = "Local Database"; } $strongswan .= $authcfg; $firstsed = 1; } $strongswan .= "\n"; $strongswan .= "\t\t}\n"; } } $strongswan .= "\n\t}\n}\n"; @file_put_contents("{$g['varetc_path']}/ipsec/strongswan.conf", $strongswan); unset($strongswan); /* write out CRL files */ if (is_array($config['crl']) && count($config['crl'])) { foreach ($config['crl'] as $crl) { if (!isset($crl['text'])) { log_error(sprintf(gettext("Warning: Missing CRL data for %s"), $crl['descr'])); continue; } $fpath = "{$crlpath}/{$crl['refid']}.crl"; if (!@file_put_contents($fpath, base64_decode($crl['text']))) { log_error(sprintf(gettext("Error: Cannot write IPsec CRL file for %s"), $crl['descr'])); continue; } } } $pskconf = ""; $vpncas = array(); if (is_array($a_phase1) && count($a_phase1)) { foreach ($a_phase1 as $ph1ent) { if (isset($ph1ent['disabled'])) { continue; } if (strstr($ph1ent['authentication_method'], 'rsa') || in_array($ph1ent['authentication_method'], array('eap-mschapv2', 'eap-tls', 'eap-radius'))) { $certline = ''; $ikeid = $ph1ent['ikeid']; $cert = lookup_cert($ph1ent['certref']); if (!$cert) { log_error(sprintf(gettext("Error: Invalid phase1 certificate reference for %s"), $ph1ent['name'])); continue; } /* add signing CA cert chain of server cert * to the list of CAs to write */ $cachain = ca_chain_array($cert); if ($cachain && is_array($cachain)) { foreach ($cachain as $cacrt) { $vpncas[$cacrt['refid']] = $cacrt; } } @chmod($certpath, 0600); $ph1keyfile = "{$keypath}/cert-{$ikeid}.key"; if (!file_put_contents($ph1keyfile, base64_decode($cert['prv']))) { log_error(sprintf(gettext("Error: Cannot write phase1 key file for %s"), $ph1ent['name'])); continue; } @chmod($ph1keyfile, 0600); $ph1certfile = "{$certpath}/cert-{$ikeid}.crt"; if (!file_put_contents($ph1certfile, base64_decode($cert['crt']))) { log_error(sprintf(gettext("Error: Cannot write phase1 certificate file for %s"), $ph1ent['name'])); @unlink($ph1keyfile); continue; } @chmod($ph1certfile, 0600); /* XXX" Traffic selectors? */ $pskconf .= " : RSA {$ph1keyfile}\n"; } else { list ($myid_type, $myid_data) = ipsec_find_id($ph1ent, 'local'); list ($peerid_type, $peerid_data) = ipsec_find_id($ph1ent, 'peer', $rgmap); $myid = trim($myid_data); if (empty($peerid_data)) { continue; } if ($myid_type == 'fqdn' && !empty($myid)) { $myid = "@{$myid}"; } $myid = isset($ph1ent['mobile']) ? trim($myid_data) : "%any"; $peerid = ($peerid_data != 'allusers') ? trim($peerid_data) : ''; if ($peerid_type == 'fqdn' && !empty($peerid)) { $peerid = "@{$peerid}"; } if (!empty($ph1ent['pre-shared-key'])) { $pskconf .= "{$myid} {$peerid} : PSK 0s" . base64_encode(trim($ph1ent['pre-shared-key'])) . "\n"; if (isset($ph1ent['mobile'])) { $pskconf .= " : PSK 0s" . base64_encode(trim($ph1ent['pre-shared-key'])) . "\n"; } } } /* if the client authenticates with a cert add the * client cert CA chain to the list of CAs to write */ if (in_array($ph1ent['authentication_method'], array('rsasig', 'eap-tls', 'xauth_rsa_server'))) { if (!empty($ph1ent['caref']) && !array_key_exists($ph1ent['caref'], $vpncas)) { $thisca = lookup_ca($ph1ent['caref']); $vpncas[$ph1ent['caref']] = $thisca; /* follow chain up to root */ $cachain = ca_chain_array($thisca); if ($cachain and is_array($cachain)) { foreach ($cachain as $cacrt) { $vpncas[$cacrt['refid']] = $cacrt; } } } } } } /* write the required CAs */ foreach ($vpncas as $carefid => $cadata) { $cacrt = base64_decode($cadata['crt']); $cacrtattrs = openssl_x509_parse($cacrt); if (!is_array($cacrtattrs) || !isset($cacrtattrs['hash'])) { log_error(sprintf(gettext("Error: Invalid certificate hash info for %s"), $cadata['descr'])); continue; } $cafilename = "{$capath}/{$cacrtattrs['hash']}.0.crt"; if (!@file_put_contents($cafilename, $cacrt)) { log_error(sprintf(gettext("Error: Cannot write IPsec CA file for %s"), $cadata['descr'])); continue; } } /* Add user PSKs */ if (is_array($config['system']) && is_array($config['system']['user'])) { foreach ($config['system']['user'] as $user) { if (!empty($user['ipsecpsk'])) { $pskconf .= "{$myid} {$user['name']} : PSK 0s" . base64_encode($user['ipsecpsk']) . "\n"; } } unset($user); } /* add PSKs for mobile clients */ if (is_array($ipseccfg['mobilekey'])) { foreach ($ipseccfg['mobilekey'] as $key) { if ($key['ident'] == "allusers") { $key['ident'] = '%any'; } if ($key['ident'] == "any") { $key['ident'] = '%any'; } if (empty($key['type'])) { $key['type'] = 'PSK'; } $pskconf .= " {$key['ident']} : {$key['type']} 0s" . base64_encode($key['pre-shared-key']) . "\n"; } unset($key); } @file_put_contents("{$g['varetc_path']}/ipsec/ipsec.secrets", $pskconf); chmod("{$g['varetc_path']}/ipsec/ipsec.secrets", 0600); unset($pskconf); $uniqueids = 'yes'; if (!empty($config['ipsec']['uniqueids'])) { if (array_key_exists($config['ipsec']['uniqueids'], $ipsec_idhandling)) { $uniqueids = $config['ipsec']['uniqueids']; } } $natfilterrules = false; /* begin ipsec.conf */ $ipsecconf = ""; $enablecompression = false; if (is_array($a_phase1) && count($a_phase1)) { $ipsecconf .= "# This file is automatically generated. Do not edit\n"; $ipsecconf .= "config setup\n\tuniqueids = {$uniqueids}\n"; if (isset($config['ipsec']['strictcrlpolicy'])) { $ipsecconf .= "\tstrictcrlpolicy = yes \n"; } if (!isset($config['ipsec']['noshuntlaninterfaces'])) { if ($config['interfaces']['lan']) { $lanip = get_interface_ip("lan"); if (!empty($lanip) && is_ipaddrv4($lanip)) { $lansn = get_interface_subnet("lan"); $lansa = gen_subnet($lanip, $lansn); $ipsecconf .= <<= $key_lo; $keylen -= $key_step) { if (!empty($ph2ent['hash-algorithm-option']) && is_array($ph2ent['hash-algorithm-option'])) { foreach ($ph2ent['hash-algorithm-option'] as $halgo) { $halgo = str_replace('hmac_', '', $halgo); $tmpealgo = "{$ealg_id}{$keylen}-{$halgo}"; $modp = vpn_ipsec_convert_to_modp($ph2ent['pfsgroup']); if (!empty($modp)) { $tmpealgo .= "-{$modp}"; } $ealgoESPsp2arr[] = $tmpealgo; } } else { $tmpealgo = "{$ealg_id}{$keylen}"; $modp = vpn_ipsec_convert_to_modp($ph2ent['pfsgroup']); if (!empty($modp)) { $tmpealgo .= "-{$modp}"; } $ealgoESPsp2arr[] = $tmpealgo; } } } } else { if (!empty($ph2ent['hash-algorithm-option']) && is_array($ph2ent['hash-algorithm-option'])) { foreach ($ph2ent['hash-algorithm-option'] as $halgo) { $halgo = str_replace('hmac_', '', $halgo); $tmpealgo = "{$ealg_id}{$ealg_kl}-{$halgo}"; $modp = vpn_ipsec_convert_to_modp($ph2ent['pfsgroup']); if (!empty($modp)) { $tmpealgo .= "-{$modp}"; } $ealgoESPsp2arr[] = $tmpealgo; } } else { $tmpealgo = "{$ealg_id}{$ealg_kl}"; $modp = vpn_ipsec_convert_to_modp($ph2ent['pfsgroup']); if (!empty($modp)) { $tmpealgo .= "-{$modp}"; } $ealgoESPsp2arr[] = $tmpealgo; } } } } } else if ($ph2ent['protocol'] == 'ah') { if (!empty($ph2ent['hash-algorithm-option']) && is_array($ph2ent['hash-algorithm-option'])) { $modp = vpn_ipsec_convert_to_modp($ph2ent['pfsgroup']); foreach ($ph2ent['hash-algorithm-option'] as $tmpAHalgo) { $tmpAHalgo = str_replace('hmac_', '', $tmpAHalgo); if (!empty($modp)) { $tmpAHalgo = "-{$modp}"; } $ealgoAHsp2arr[] = $tmpAHalgo; } } } $reqids[] = $ph2ent['reqid']; if (!empty($ph2ent['lifetime'])) { if ($ipseclifetime == 0 || intval($ipseclifetime) > intval($ph2ent['lifetime'])) { $ipseclifetime = intval($ph2ent['lifetime']); } } } } $ipsecconnect =<< 0) { $ipsecconnect .= "\tlifetime = {$ipseclifetime}s\n"; } if (!empty($rightsourceip)) { $ipsecconnect .= "{$rightsourceip}"; } if (!empty($ealgosp1)) { $ipsecconnect .= "\t{$ealgosp1}\n"; } if (!empty($ealgoAHsp2arr)) { $ipsecconnect .= "\tah = " . join(',', $ealgoAHsp2arr) . "!\n"; } if (!empty($ealgoESPsp2arr)) { $ipsecconnect .= "\tesp = " . join(',', $ealgoESPsp2arr) . "!\n"; } if (!empty($authentication)) { $ipsecconnect .= "\t{$authentication}\n"; } if (!empty($peerid_spec)) { $ipsecconnect .= "\trightid = {$peerid_spec}\n"; } if ($keyexchange != 'ikev2') { $ipsecconnect .= "\taggressive = {$aggressive}\n"; } if (!isset($ph1ent['mobile']) && ($keyexchange == 'ikev1' || isset($ph1ent['splitconn']))) { if (!empty($rightsubnet_spec)) { $ipsecfin = ''; foreach ($rightsubnet_spec as $idx => $rsubnet) { $ipsecfin .= "\nconn con{$ph1ent['ikeid']}00{$idx}\n"; //if (!empty($reqids[$idx])) { // $ipsecfin .= "\treqid = " . $reqids[$idx] . "\n"; //} $ipsecfin .= $ipsecconnect; $ipsecfin .= "\trightsubnet = {$rsubnet}\n"; $ipsecfin .= "\tleftsubnet = " . $leftsubnet_spec[$idx] . "\n"; } } else { log_error(sprintf(gettext("No phase2 specifications for tunnel with REQID = %s"), $ikeid)); } } else { $ipsecfin = "\nconn con{$ph1ent['ikeid']}\n"; //if (!empty($reqids[$idx])) { // $ipsecfin .= "\treqid = " . $reqids[0] . "\n"; //} $ipsecfin .= $ipsecconnect; if (!isset($ph1ent['mobile']) && !empty($rightsubnet_spec)) { $tempsubnets = array(); foreach ($rightsubnet_spec as $rightsubnet) { $tempsubnets[$rightsubnet] = $rightsubnet; } $ipsecfin .= "\trightsubnet = " . join(",", $tempsubnets) . "\n"; unset($tempsubnets, $rightsubnet); } if (!empty($leftsubnet_spec)) { $tempsubnets = array(); foreach ($leftsubnet_spec as $leftsubnet) { $tempsubnets[$leftsubnet] = $leftsubnet; } $ipsecfin .= "\tleftsubnet = " . join(",", $tempsubnets) . "\n"; unset($tempsubnets, $leftsubnet); } } $ipsecconf .= $ipsecfin; unset($ipsecfin); } } @file_put_contents("{$g['varetc_path']}/ipsec/ipsec.conf", $ipsecconf); unset($ipsecconf); /* end ipsec.conf */ if ($enablecompression === true) { set_single_sysctl('net.inet.ipcomp.ipcomp_enable', 1); } else { set_single_sysctl('net.inet.ipcomp.ipcomp_enable', 0); } /* manage process */ if ($restart === true) { mwexec("/usr/local/sbin/ipsec restart", false); } else { if (isvalidpid("{$g['varrun_path']}/starter.charon.pid")) { /* Update configuration changes */ /* Read secrets */ mwexec("/usr/local/sbin/ipsec rereadall", false); mwexec("/usr/local/sbin/ipsec reload", false); } else { mwexec("/usr/local/sbin/ipsec start", false); } } // run ping_hosts.sh once if it's enabled to avoid wait for minicron if ($ipsecpinghostsactive == true) { mwexec_bg("/usr/local/bin/ping_hosts.sh"); } if ($natfilterrules == true) { filter_configure(); } /* start filterdns, if necessary */ if (count($filterdns_list) > 0) { $interval = 60; if (!empty($ipseccfg['dns-interval']) && is_numeric($ipseccfg['dns-interval'])) { $interval = $ipseccfg['dns-interval']; } $hostnames = ""; array_unique($filterdns_list); foreach ($filterdns_list as $hostname) { $hostnames .= "cmd {$hostname} '/usr/local/sbin/pfSctl -c \"service reload ipsecdns\"'\n"; } file_put_contents("{$g['varetc_path']}/ipsec/filterdns-ipsec.hosts", $hostnames); unset($hostnames); if (isvalidpid("{$g['varrun_path']}/filterdns-ipsec.pid")) { sigkillbypid("{$g['varrun_path']}/filterdns-ipsec.pid", "HUP"); } else { mwexec("/usr/local/sbin/filterdns -p {$g['varrun_path']}/filterdns-ipsec.pid -i {$interval} -c {$g['varetc_path']}/ipsec/filterdns-ipsec.hosts -d 1"); } } else { killbypid("{$g['varrun_path']}/filterdns-ipsec.pid"); @unlink("{$g['varrun_path']}/filterdns-ipsec.pid"); } if (platform_booting()) { echo "done\n"; } unlock($ipsecstartlock); return count($filterdns_list); } /* * Forcefully restart IPsec * This is required for when dynamic interfaces reload * For all other occasions the normal vpn_ipsec_configure() * will gracefully reload the settings without restarting */ function vpn_ipsec_force_reload($interface = "") { global $g, $config; if (!ipsec_enabled()) { return; } $ipseccfg = $config['ipsec']; if (!empty($interface) && is_array($ipseccfg['phase1'])) { $found = false; foreach ($ipseccfg['phase1'] as $ipsec) { if (!isset($ipsec['disabled']) && ($ipsec['interface'] == $interface)) { $found = true; break; } } if (!$found) { log_error(sprintf(gettext("Ignoring IPsec reload since there are no tunnels on interface %s"), $interface)); return; } } /* If we get this far then we need to take action. */ log_error(gettext("Forcefully reloading IPsec")); vpn_ipsec_configure(); } /* master setup for vpn (mpd) */ function vpn_setup() { /* start pppoe server */ vpn_pppoes_configure(); /* setup l2tp */ vpn_l2tp_configure(); } function vpn_netgraph_support() { $iflist = get_configured_interface_list(); foreach ($iflist as $iface) { $realif = get_real_interface($iface); /* Get support for netgraph(4) from the nic */ $ifinfo = pfSense_get_interface_addresses($realif); if (!empty($ifinfo) && in_array($ifinfo['iftype'], array("ether", "vlan", "bridge"))) { pfSense_ngctl_attach(".", $realif); } } } function vpn_pppoes_configure() { global $config; if (is_array($config['pppoes']['pppoe'])) { foreach ($config['pppoes']['pppoe'] as $pppoe) { vpn_pppoe_configure($pppoe); } } } function vpn_pppoe_configure(&$pppoecfg) { global $config, $g; $syscfg = $config['system']; /* create directory if it does not exist */ if (!is_dir("{$g['varetc_path']}/pppoe{$pppoecfg['pppoeid']}-vpn")) { mkdir("{$g['varetc_path']}/pppoe{$pppoecfg['pppoeid']}-vpn"); } if (platform_booting()) { if (!$pppoecfg['mode'] || ($pppoecfg['mode'] == "off")) { return 0; } echo gettext("Configuring PPPoE Server service... "); } else { /* kill mpd */ killbypid("{$g['varrun_path']}/pppoe{$pppoecfg['pppoeid']}-vpn.pid"); /* wait for process to die */ sleep(2); } switch ($pppoecfg['mode']) { case 'server': $pppoe_interface = get_real_interface($pppoecfg['interface']); if ($pppoecfg['paporchap'] == "chap") { $paporchap = "set link enable chap"; } else { $paporchap = "set link enable pap"; } /* write mpd.conf */ $fd = fopen("{$g['varetc_path']}/pppoe{$pppoecfg['pppoeid']}-vpn/mpd.conf", "w"); if (!$fd) { printf(gettext("Error: cannot open mpd.conf in vpn_pppoe_configure().") . "\n"); return 1; } $mpdconf = "\n\n"; $mpdconf .= "poes:\n"; for ($i = 0; $i < $pppoecfg['n_pppoe_units']; $i++) { $mpdconf .= " load poes{$pppoecfg['pppoeid']}{$i}\n"; } for ($i = 0; $i < $pppoecfg['n_pppoe_units']; $i++) { $clientip = ip_after($pppoecfg['remoteip'], $i); if (isset($pppoecfg['radius']['radiusissueips']) && isset($pppoecfg['radius']['server']['enable'])) { $issue_ip_type = "set ipcp ranges {$pppoecfg['localip']}/32 0.0.0.0/0"; } else { $issue_ip_type = "set ipcp ranges {$pppoecfg['localip']}/32 {$clientip}/32"; } $mpdconf .=<< 0)) { $pppoemaxlogins = $pppoecfg['n_pppoe_maxlogin']; } else { $pppoemaxlogins = 1; } $mpdconf .=<<