summaryrefslogtreecommitdiffstats
path: root/etc
diff options
context:
space:
mode:
authorMatthew Grooms <mgrooms@pfsense.org>2008-07-11 01:55:30 +0000
committerMatthew Grooms <mgrooms@pfsense.org>2008-07-11 01:55:30 +0000
commita93e56c58af2611650d1f97190ffe54782479423 (patch)
tree4748e51726a04966508a45bd275cf8e0589df7be /etc
parent2a66b533249a31c4b9ea6f90c696998b2ba8ba49 (diff)
downloadpfsense-a93e56c58af2611650d1f97190ffe54782479423.zip
pfsense-a93e56c58af2611650d1f97190ffe54782479423.tar.gz
Overhaul IPsec related code. Shared functions have been consolidated into
a new file named /etc/ipsec.inc. Tunnel definitions have been split into phase1 and phase2. This allows any number of phase2 definitions to be created for a single phase1 definition. Several facets of configuration have also been improved. The key size for variable length algorithms can now be selected and the phase1 ID options have been extended to allow for more flexible configuration. Several NAT-T related issues have also been resolved. Please note, IPsec remote access functionality has been temporarily disabled. An improved implementation will be included in a follow up commit.
Diffstat (limited to 'etc')
-rw-r--r--etc/inc/config.inc178
-rw-r--r--etc/inc/filter.inc243
-rw-r--r--etc/inc/functions.inc3
-rw-r--r--etc/inc/globals.inc4
-rw-r--r--etc/inc/ipsec.inc344
-rw-r--r--etc/inc/vpn.inc864
-rw-r--r--etc/inc/xmlparse.inc2
7 files changed, 1119 insertions, 519 deletions
diff --git a/etc/inc/config.inc b/etc/inc/config.inc
index 2914bae..121a659 100644
--- a/etc/inc/config.inc
+++ b/etc/inc/config.inc
@@ -1260,7 +1260,183 @@ function convert_config() {
$config['version'] = "4.6";
}
- if ($prev_version != $config['version'])
+ /* Convert 4.6 -> 4.7 */
+ if ($config['version'] <= 4.7) {
+
+ /* Upgrade IPsec from tunnel to phase1/phase2 */
+
+ echo "Beginning upgrade to version 4.7\n";
+
+ if(is_array($config['ipsec']['tunnel'])) {
+
+ $a_phase1 = array();
+ $a_phase2 = array();
+ $ikeid = 0;
+
+ foreach ($config['ipsec']['tunnel'] as $tunnel) {
+
+ /* build new phase1 entry */
+
+ $ph1ent['ikeid'] = ++$ikeid;
+
+ if (isset($tunnel['disabled']))
+ $ph1ent['disabled'] = $tunnel['disabled'];
+
+ $ph1ent['interface'] = $tunnel['interface'];
+ $ph1ent['remote-gateway'] = $tunnel['remote-gateway'];
+ $ph1ent['descr'] = $tunnel['descr'];
+
+ $ph1ent['mode'] = $tunnel['p1']['mode'];
+
+ if (isset($tunnel['p1']['myident']['myaddress']))
+ $ph1ent['myid_type'] = "myaddress";
+ if (isset($tunnel['p1']['myident']['address'])) {
+ $ph1ent['myid_type'] = "address";
+ $ph1ent['myid_data'] = $tunnel['p1']['myident']['address'];
+ }
+ if (isset($tunnel['p1']['myident']['fqdn'])) {
+ $ph1ent['myid_type'] = "fqdn";
+ $ph1ent['myid_data'] = $tunnel['p1']['myident']['fqdn'];
+ }
+ if (isset($tunnel['p1']['myident']['user_fqdn'])) {
+ $ph1ent['myid_type'] = "user_fqdn";
+ $ph1ent['myid_data'] = $tunnel['p1']['myident']['user_fqdn'];
+ }
+ if (isset($tunnel['p1']['myident']['asn1dn'])) {
+ $ph1ent['myid_type'] = "asn1dn";
+ $ph1ent['myid_data'] = $tunnel['p1']['myident']['asn1dn'];
+ }
+ if (isset($tunnel['p1']['myident']['dyn_dns'])) {
+ $ph1ent['myid_type'] = "dyn_dns";
+ $ph1ent['myid_data'] = $tunnel['p1']['myident']['dyn_dns'];
+ }
+
+ $ph1ent['peerid_type'] = "peeraddress";
+
+ switch ($tunnel['p1']['encryption-algorithm']) {
+ case "des":
+ $ph1alg = array( 'name' => 'des' );
+ break;
+ case "3des":
+ $ph1alg = array( 'name' => '3des' );
+ break;
+ case "blowfish":
+ $ph1alg = array( 'name' => 'blowfish', 'keylen' => 'auto' );
+ break;
+ case "cast128":
+ $ph1alg = array( 'name' => 'cast128' );
+ break;
+ case "rijndael":
+ $ph1alg = array( 'name' => 'aes', 'keylen' => 'auto' );
+ break;
+ case "rijndael 256":
+ $ph1alg = array( 'name' => 'aes', 'keylen' => '256' );
+ break;
+ }
+
+ $ph1ent['encryption-algorithm'] = $ph1alg;
+ $ph1ent['hash-algorithm'] = $tunnel['p1']['hash-algorithm'];
+ $ph1ent['dhgroup'] = $tunnel['p1']['dhgroup'];
+ $ph1ent['lifetime'] = $tunnel['p1']['lifetime'];
+ $ph1ent['authentication_method'] = $tunnel['p1']['authentication_method'];
+
+ if (isset($tunnel['p1']['pre-shared-key']))
+ $ph1ent['pre-shared-key'] = $tunnel['p1']['pre-shared-key'];
+ if (isset($tunnel['p1']['cert']))
+ $ph1ent['cert'] = $tunnel['p1']['cert'];
+ if (isset($tunnel['p1']['peercert']))
+ $ph1ent['peercert'] = $tunnel['p1']['peercert'];
+ if (isset($tunnel['p1']['private-key']))
+ $ph1ent['private-key'] = $tunnel['p1']['private-key'];
+
+ if (isset($tunnel['pinghost']['pinghost']))
+ $ph1ent['pinghost'] = $tunnel['pinghost'];
+
+ $ph1ent['nat_traversal'] = "on";
+ $ph1ent['dpd_enable'] = 1;
+ $ph1ent['dpd_delay'] = 10;
+ $ph1ent['dpd_maxfail'] = 5;
+
+ $a_phase1[] = $ph1ent;
+
+ /* build new phase2 entry */
+
+ $ph2ent['ikeid'] = $ikeid;
+
+ if (isset($tunnel['disabled']))
+ $ph1ent['disabled'] = $tunnel['disabled'];
+
+ $ph2ent['descr'] = "phase2 for ".$tunnel['descr'];
+
+ $type = "lan";
+ if ($tunnel['local-subnet']['network'])
+ $type = $tunnel['local-subnet']['network'];
+ if ($tunnel['local-subnet']['address']) {
+ list($address,$netbits) = explode("/",$tunnel['local-subnet']['address']);
+ if (is_null($netbits))
+ $type = "address";
+ else
+ $type = "network";
+ }
+
+ switch ($type) {
+ case "address":
+ $ph2ent['localid'] = array('type' => $type,'address' => $address);
+ break;
+ case "network":
+ $ph2ent['localid'] = array('type' => $type,'address' => $address,'netbits' => $netbits);
+ break;
+ default:
+ $ph2ent['localid'] = array('type' => $type);
+ break;
+ }
+
+ list($address,$netbits) = explode("/",$tunnel['remote-subnet']);
+ $ph2ent['remoteid'] = array('type' => 'network','address' => $address,'netbits' => $netbits);
+
+ $ph2ent['protocol'] = $tunnel['p2']['protocol'];
+
+ foreach( $tunnel['p2']['encryption-algorithm-option'] as $tunalg ) {
+ switch ($tunalg) {
+ case "des":
+ $ph2alg = array( 'name' => 'des' );
+ break;
+ case "3des":
+ $ph2alg = array( 'name' => '3des' );
+ break;
+ case "blowfish":
+ $ph2alg = array( 'name' => 'blowfish', 'keylen' => 'auto' );
+ break;
+ case "cast128":
+ $ph2alg = array( 'name' => 'cast128' );
+ break;
+ case "rijndael":
+ $ph2alg = array( 'name' => 'aes', 'keylen' => 'auto' );
+ break;
+ case "rijndael 256":
+ $ph2alg = array( 'name' => 'aes', 'keylen' => '256' );
+ break;
+ }
+
+ $ph2ent['encryption-algorithm-option'][] = $ph2alg;
+ }
+
+ $ph2ent['hash-algorithm-option'] = $tunnel['p2']['hash-algorithm-option'];
+ $ph2ent['pfsgroup'] = $tunnel['p2']['pfsgroup'];
+ $ph2ent['lifetime'] = $tunnel['p2']['lifetime'];
+
+ $a_phase2[] = $ph2ent;
+ }
+
+ unset($config['ipsec']['tunnel']);
+ $config['ipsec']['phase1'] = $a_phase1;
+ $config['ipsec']['phase2'] = $a_phase2;
+ }
+
+ $config['version'] = "4.7";
+ }
+
+// if ($prev_version != $config['version'])
write_config("Upgraded config version level from {$prev_version} to {$config['version']}");
}
diff --git a/etc/inc/filter.inc b/etc/inc/filter.inc
index ebf445d..01b9fd8 100644
--- a/etc/inc/filter.inc
+++ b/etc/inc/filter.inc
@@ -445,10 +445,10 @@ function get_vpns_list() {
$vpns = "";
$vpns_arr = array();
/* ipsec */
- if ($config['ipsec']['tunnel']) {
- foreach ($config['ipsec']['tunnel'] as $tunnel) {
- if(is_subnet($tunnel['remote-subnet'])) {
- $vpns_arr[] = $tunnel['remote-subnet'];
+ if ($config['ipsec']['phase2']) {
+ foreach ($config['ipsec']['phase2'] as $ph2ent) {
+ if(is_subnet($ph2ent['remote-subnet'])) {
+ $vpns_arr[] = $ph2ent['remote-subnet'];
}
}
}
@@ -2953,128 +2953,165 @@ EOD;
update_filter_reload_status("Creating carp rules...");
$ipfrules .= "\n# VPN Rules\n";
- /* is mobile ipsec enabled? if so lets allow some pretty
- * loose rules to allow mobile clients to phone in.
- */
- $ipseccfg = $config['ipsec'];
- if (isset($ipseccfg['mobileclients']['enable'])) {
- $ifdescrs = get_configured_interface_with_descr();
- foreach($ifdescrs as $ifr => $iface) {
- /* only process interfaces with gateway */
- if(! interface_has_gateway($ifr))
- continue;
-
- /* FIXME: make dynamic interface compatible */
- $gateway = lookup_gateway_ip_by_name($config['interfaces'][$ifr]['gateway']);
- $interface = convert_friendly_interface_to_real_interface_name($iface);
- if((is_ipaddr($gateway)) && ($interface <> "")) {
- $route_to = " route-to ( $interface $gateway ) ";
- $reply_to = " reply-to ( $interface $gateway ) ";
- }
- $ifalias = convert_friendly_interface_to_friendly_descr($ifr);
-
- /* pass in rules for IPSEC with reply-to */
- $ipfrules .= "pass in on \${$ifalias} $reply_to proto udp from any to any port = 500 keep state label \"IPsec: Mobile - inbound isakmp\"\n";
- $ipfrules .= "pass in on \${$ifalias} $reply_to proto esp from any to any keep state label \"IPsec: Mobile - inbound esp proto\"\n";
- $ipfrules .= "pass in on \${$ifalias} $reply_to proto ah from any to any keep state label \"IPsec: Mobile - inbound ah proto\"\n";
- /* Pass out rules for IPSEC with route-to */
- $ipfrules .= "pass out on \${$ifalias} $route_to proto udp from any to any port = 500 keep state label \"IPsec: Mobile - inbound isakmp\"\n";
- $ipfrules .= "pass out on \${$ifalias} $route_to proto esp from any to any keep state label \"IPsec: Mobile - inbound esp proto\"\n";
- $ipfrules .= "pass out on \${$ifalias} $route_to proto ah from any to any keep state label \"IPsec: Mobile - inbound ah proto\"\n";
- }
- }
if($config['interfaces']['lan']) {
$lan_ip = $config['interfaces']['lan']['ipaddr'];
$lan_subnet = $config['interfaces']['lan']['subnet'];
}
+
$wanif = get_real_wan_interface();
$wan_ip = find_interface_ip($wanif);
- if($wan_ip) {
- if($config['interfaces']['lan'])
- $internal_subnet = gen_subnet($lan_ip, $lan_subnet) . "/" . $config['interfaces']['lan']['subnet'];
+
+ if ($wan_ip) {
+
/* Is IP Compression enabled? */
- if(isset($config['ipsec']['ipcomp']))
+ if (isset($config['ipsec']['ipcomp']))
exec("/sbin/sysctl net.inet.ipcomp.ipcomp_enable=1");
else
exec("/sbin/sysctl net.inet.ipcomp.ipcomp_enable=0");
/* if list */
- $ifdescrs = get_configured_interface_with_descr();
+ $ifdescrs = get_configured_interface_with_descr();
- if(is_array($config['ipsec']['tunnel']) && isset($config['ipsec']['enable']) && (! isset($ipseccfg['mobileclients']['enable']))) {
- foreach ($config['ipsec']['tunnel'] as $tunnel) {
- if(isset($tunnel['disabled']))
+ /* NOTE : The ipsec related code was odd. I will
+ * need feedback from other developers to get it
+ * completelely sorted out.
+ * -mgrooms 06/07/2008
+ */
+ if(isset($config['ipsec']['enable']) &&
+ is_array($config['ipsec']['phase1']) &&
+ is_array($config['ipsec']['phase2'])) {
+ /* step through all phase1 entries */
+ foreach ($config['ipsec']['phase1'] as $ph1ent) {
+
+ if (isset ($ph1ent['disabled']))
+ continue;
+
+ update_filter_reload_status("Creating IPsec phase1 items for {$ph1ent['descr']}...");
+
+ /* NOTE : the old code built an array with a single
+ * element for each tunnel entry. Why? It was getting
+ * reset on each loop iteration.
+ *
+ * ipsec_ips = array(get_current_wan_address($tunnel['interface']));
+ *
+ * Is the get_current_wan_address function name
+ * misleading or did we always assume the local
+ * endpoint was the WAN interface?
+ */
+
+ /* determine local and remote peer addresses */
+
+ $lgip = vpn_endpoint_determine($ph1ent, $wan_ip);
+
+ $rgip = $ph1ent['remote-gateway'];
+ if(!is_ipaddr($rgip))
+ $rgip = resolve_retry($rgip);
+
+ if (!$lgip) {
+ $ipfrules .= "# ERROR! Unable to determine local IPsec peer address for {$ph1ent['remote-gateway']}\n";
continue;
- update_filter_reload_status("Creating IPsec tunnel items {$tunnel['descr']}...");
- /* if tunnel is disabled, lets skip to next item */
- $ipsec_ips = array(get_current_wan_address($tunnel['interface']));
- /* is this a dynamic dns hostname? */
- $remote_gateway = gethostbyname($tunnel['remote-gateway']);
- if($remote_gateway == "")
- $remote_gateway = $tunnel['remote-gateway'];
- /* do not add items with blank remote_gateway */
- if(!$remote_gateway) {
- $ipfrules .= "# ERROR! Remote gateway not found on {$tunnel['remote-gateway']}\n";
+ }
+ if (!$rgip) {
+ $ipfrules .= "# ERROR! Unable to determine remote IPsec peer address for {$ph1ent['remote-gateway']}\n";
continue;
}
- $local_subnet = return_vpn_subnet($tunnel['local-subnet']);
- foreach($ifdescrs as $ifr => $iface) {
- /* XXX: really needed?! */
- if ($ifr == "lan")
+
+ /* Step through the interface list and the assigned IP
+ * addresses.
+ *
+ * NOTE : I'm not really sure why this is neccessary. We
+ * have already resolved the local and remote endpoints
+ * and the interface is known. If vpn_endpoint_determine
+ * is not good enough to use here, it should be modified
+ * instead of doing the work locally. Otherwise we will
+ * have pf rules that don't match SPD.
+ * -mgrooms 06/07/2008
+ */
+ foreach ($ifdescrs as $ifr => $iface) {
+
+ /* Are we doing the lookups below just to ensure the
+ * interface has an IP address configured?
+ * -mgrooms 06/07/2008
+ */
+
+ if($ifr == "wan")
+ $interface_ip = find_interface_ip(get_real_wan_interface());
+ else
+ $interface_ip = find_interface_ip(convert_friendly_interface_to_real_interface_name($iface));
+
+ if(!$interface_ip)
continue;
- foreach($ipsec_ips as $interface_ip) {
- if($ifr == "wan")
- $interface_ip = find_interface_ip(get_real_wan_interface());
- else
- $interface_ip = find_interface_ip(convert_friendly_interface_to_real_interface_name($iface));
- if(!$interface_ip)
- continue;
- if(!$remote_gateway)
- continue;
- /* only process interfaces with gateway */
- if(! interface_has_gateway($ifr))
+ /* NOTES : We went through a lot of trouble to determine the
+ * real interface address but we still use $lgip ( previously
+ * named $remote_gateway ) below in our rules. Why?
+ *
+ * There is also no statement to avoid adding rules/routes
+ * for interfaces that don't match the one defined in our
+ * phase1 entry ( previously a $tunnel ). Why do we loop if
+ * there is no qualification?
+ * -mgrooms 06/07/2008
+ */
+
+ /* Only process interfaces with gateway */
+ if(! interface_has_gateway($ifr))
+ continue;
+
+ $gateway = lookup_gateway_ip_by_name($config['interfaces'][$ifr]['gateway']);
+ $interface = convert_friendly_interface_to_real_interface_name($iface);
+
+ $route_to = " route-to ( $interface $gateway ) ";
+ $reply_to = " reply-to ( $interface $gateway ) ";
+
+ /* Another conversion. Why? */
+ $ifalias = convert_friendly_interface_to_friendly_descr($ifr);
+
+ /* Add rules to allow IKE to pass */
+ $ipfrules .= "pass out on \${$ifalias} $route_to proto udp from any to {$rgip} port = 500 keep state label \"IPsec: {$ph1ent['descr']} - outbound isakmp\"\n";
+ $ipfrules .= "pass in on \${$ifalias} $reply_to proto udp from {$rgip} to any port = 500 keep state label \"IPsec: {$ph1ent['descr']} - inbound isakmp\"\n";
+
+ /* If NAT-T is enabled, add additional rules */
+ if ($ph1ent['nat_traversal'] != "off" ) {
+ $ipfrules .= "pass out on \${$ifalias} $route_to proto udp from any to {$rgip} port = 4500 keep state label \"IPsec: {$ph1ent['descr']} - outbound nat-t\"\n";
+ $ipfrules .= "pass in on \${$ifalias} $reply_to proto udp from {$rgip} to any port = 4500 keep state label \"IPsec: {$ph1ent['descr']} - inbound nat-t\"\n";
+ }
+
+ /* Step through all phase2 entries and determine
+ * which protocols are in use with this peer
+ */
+ $prot_used_esp = false;
+ $prot_used_ah = false;
+
+ foreach ($config['ipsec']['phase2'] as $ph2ent) {
+
+ /* only evaluate ph2's bound to our ph1 */
+ if ($ph2ent['ikeid'] != $ph1ent['ikeid'])
continue;
- /* FIXME: make dynamic interface compatible */
- $gateway = lookup_gateway_ip_by_name($config['interfaces'][$ifr]['gateway']);
- $interface = convert_friendly_interface_to_real_interface_name($iface);
- if((is_ipaddr($gateway)) && ($interface <> "")) {
- $route_to = " route-to ( $interface $gateway ) ";
- $reply_to = " reply-to ( $interface $gateway ) ";
- }
- $ifalias = convert_friendly_interface_to_friendly_descr($ifr);
- $ipfrules .= "pass out on \${$ifalias} $route_to proto udp from any to {$remote_gateway} port = 500 keep state label \"IPsec: {$tunnel['descr']} - outbound isakmp\"\n";
- $ipfrules .= "pass in on \${$ifalias} $reply_to proto udp from {$remote_gateway} to any port = 500 keep state label \"IPsec: {$tunnel['descr']} - inbound isakmp\"\n";
- if ($tunnel['p2']['protocol'] == 'esp') {
- $ipfrules .= "pass out on \${$ifalias} $route_to proto esp from any to {$remote_gateway} keep state label \"IPsec: {$tunnel['descr']} - outbound esp proto\"\n";
- $ipfrules .= "pass in on \${$ifalias} $reply_to proto esp from {$remote_gateway} to any keep state label \"IPsec: {$tunnel['descr']} - inbound esp proto\"\n";
- }
- if ($tunnel['p2']['protocol'] == 'ah') {
- $ipfrules .= "pass out on \${$ifalias} $route_to proto ah from any to {$remote_gateway} keep state label \"IPsec: {$tunnel['descr']} - outbound ah proto\"\n";
- $ipfrules .= "pass in on \${$ifalias} $reply_to proto ah from {$remote_gateway} to any keep state label \"IPsec: {$tunnel['descr']} - inbound ah proto\"\n";
- }
+ if ($ph2ent['protocol'] == 'esp')
+ $prot_used_esp = true;
+
+ if ($ph2ent['protocol'] == 'ah')
+ $prot_used_ah = true;
}
- }
- }
- }
- /* is mobile ipsec enabled? if so lets allow some pretty
- * loose rules to allow mobile clients to phone in.
- */
- $ipseccfg = $config['ipsec'];
- if (isset($ipseccfg['mobileclients']['enable'])) {
- foreach($ifdescrs as $ifr => $iface) {
- $ifalias = convert_friendly_interface_to_friendly_descr($ifr);
-
- $ipfrules .= "pass in on \${$ifalias} proto udp from any to any port = 500 keep state label \"IPsec: Mobile - inbound isakmp\"\n";
- $ipfrules .= "pass in on \${$ifalias} proto esp from any to any keep state label \"IPsec: Mobile - inbound esp proto\"\n";
- $ipfrules .= "pass in on \${$ifalias} proto ah from any to any keep state label \"IPsec: Mobile - inbound ah proto\"\n";
+ /* Add rules to allow the protocols in use */
+ if ($prot_used_esp) {
+ $ipfrules .= "pass out on \${$ifalias} $route_to proto esp from any to {$rgip} keep state label \"IPsec: {$ph1ent['descr']} - outbound esp proto\"\n";
+ $ipfrules .= "pass in on \${$ifalias} $reply_to proto esp from {$rgip} to any keep state label \"IPsec: {$ph1ent['descr']} - inbound esp proto\"\n";
+ }
+ if ($prot_used_ah) {
+ $ipfrules .= "pass out on \${$ifalias} $route_to proto ah from any to {$rgip} keep state label \"IPsec: {$ph1ent['descr']} - outbound ah proto\"\n";
+ $ipfrules .= "pass in on \${$ifalias} $reply_to proto ah from {$rgip} to any keep state label \"IPsec: {$ph1ent['descr']} - inbound ah proto\"\n";
+ }
+ }
}
}
}
+
$ipfrules .= <<<EOD
+
# Support for allow limiting of TCP connections by establishment rate
anchor "limitingesr"
pass in on $wanif inet proto tcp from port 20 to ($wanif) port > 49000 user proxy flags S/SA keep state label "FTP PROXY: PASV mode data connection"
@@ -3273,10 +3310,10 @@ function carp_sync_xml($url, $password, $sections, $port = 80, $method = 'pfsens
unset ($config_copy['virtualip']['vip'][$x]);
$config_copy['virtualip']['vip'][$x]['descr'] = remove_special_characters($config_copy['virtualip']['vip'][$x]['descr']);
}
- for ($x = 0; $x < count($config_copy['ipsec']['tunnel']); $x++) {
- if (isset ($config_copy['ipsec']['tunnel'][$x]['nosync']))
- unset ($config_copy['ipsec']['tunnel'][$x]);
- $config_copy['ipsec']['tunnel'][$x]['descr'] = remove_special_characters($config_copy['ipsec']['tunnel'][$x]['descr']);
+ for ($x = 0; $x < count($config_copy['ipsec']['phase1']); $x++) {
+ if (isset ($config_copy['ipsec']['phase1'][$x]['nosync']))
+ unset ($config_copy['ipsec']['phase1'][$x]);
+ $config_copy['ipsec']['phase1'][$x]['descr'] = remove_special_characters($config_copy['ipsec']['phase1'][$x]['descr']);
}
foreach($sections as $section) {
diff --git a/etc/inc/functions.inc b/etc/inc/functions.inc
index 8415def..b8ab7fb 100644
--- a/etc/inc/functions.inc
+++ b/etc/inc/functions.inc
@@ -79,9 +79,10 @@ require_once("system.inc");
require_once("openvpn.inc");
require_once("pfsense-utils.inc");
require_once("util.inc");
+require_once("ipsec.inc");
require_once("vpn.inc");
require_once("vslb.inc");
require_once("gwlb.inc");
require_once("notices.inc");
-?> \ No newline at end of file
+?>
diff --git a/etc/inc/globals.inc b/etc/inc/globals.inc
index ec5733a..4e27774 100644
--- a/etc/inc/globals.inc
+++ b/etc/inc/globals.inc
@@ -60,7 +60,7 @@ $g = array(
"n_pppoe_units" => 16, /* this value can be overriden in pppoe->n_pppoe_units */
"pppoe_subnet" => 28, /* this value can be overriden in pppoe->pppoe_subnet */
"debug" => false,
- "latest_config" => "4.6",
+ "latest_config" => "4.7",
"nopkg_platforms" => array("cdrom"),
"minimum_ram_warning" => "115",
"minimum_ram_warning_text" => "128 megabytes",
@@ -87,4 +87,4 @@ $iptos = array("lowdelay", "throughput", "reliability");
/* TCP flags */
$tcpflags = array("syn", "ack", "fin", "rst", "psh", "urg");
-?> \ No newline at end of file
+?>
diff --git a/etc/inc/ipsec.inc b/etc/inc/ipsec.inc
new file mode 100644
index 0000000..23cd4ba
--- /dev/null
+++ b/etc/inc/ipsec.inc
@@ -0,0 +1,344 @@
+<?php
+/*
+ ipsec.inc
+ Copyright (C) 2007 Scott Ullrich
+ Copyright (C) 2008 Shrew Soft Inc
+ All rights reserved.
+
+ Parts of this code was originally based on vpn_ipsec_sad.php
+ Copyright (C) 2003-2004 Manuel Kasper
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/*
+ * Return phase1 local address
+ */
+function ipsec_get_phase1_src(& $ph1ent) {
+
+ if ($ph1ent['interface'])
+ $if = $ph1ent['interface'];
+ else
+ $if = "WAN";
+
+ $realinterface = convert_friendly_interface_to_real_interface_name($if);
+ $interfaceip = find_interface_ip($realinterface);
+
+ return $interfaceip;
+}
+
+/*
+ * Return phase2 idinfo in cidr format
+ */
+function ipsec_idinfo_to_cidr(& $idinfo,$addrbits = false) {
+ global $config;
+
+ switch ($idinfo['type'])
+ {
+ case "address":
+ if ($addrbits)
+ return $idinfo['address']."/32";
+ else
+ return $idinfo['address'];
+ case "network":
+ return $idinfo['address']."/".$idinfo['netbits'];
+ default:
+ $address = $config['interfaces']['lan']['ipaddr'];
+ $netbits = $config['interfaces'][$idinfo['type']]['subnet'];
+ $address = gen_subnet($address,$netbits);
+ return $address."/".$netbits;
+ }
+}
+
+/*
+ * Return phase2 idinfo in address/netmask format
+ */
+function ipsec_idinfo_to_subnet(& $idinfo,$addrbits = false) {
+ global $config;
+
+ switch ($idinfo['type'])
+ {
+ case "address":
+ if ($addrbits)
+ return $idinfo['address']."/255.255.255.255";
+ else
+ return $idinfo['address'];
+ case "network":
+ return $idinfo['address']."/".gen_subnet_mask($idinfo['netbits']);
+ default:
+ $address = $config['interfaces']['lan']['ipaddr'];
+ $netbits = $config['interfaces'][$idinfo['type']]['subnet'];
+ $address = gen_subnet($address,$netbits);
+ $netbits = gen_subnet_mask($netbits);
+ return $address."/".netbits;
+ }
+}
+
+/*
+ * Return phase2 idinfo in text format
+ */
+function ipsec_idinfo_to_text(& $idinfo) {
+
+ switch ($idinfo['type'])
+ {
+ case "address":
+ return $idinfo['address'];
+ case "network":
+ return $idinfo['address']."/".$idinfo['netbits'];
+ default:
+ return strtoupper($idinfo['type']);
+ }
+}
+
+/*
+ * Return phase1 association for phase2
+ */
+function ipsec_lookup_phase1(& $ph2ent,& $ph1ent)
+{
+ global $config;
+ $a_phase1 = $config['ipsec']['phase1'];
+
+ if (is_array($a_phase1) && count($a_phase1)) {
+ foreach ($a_phase1 as $ph1tmp) {
+ if ($ph1tmp['ikeid'] == $ph2ent['ikeid']) {
+ $ph1ent = $ph1tmp;
+ return $ph1ent;
+ }
+ }
+ }
+
+ return false;
+}
+
+/*
+ * Check phase1 communications status
+ */
+function ipsec_phase1_status(& $ph1ent) {
+
+ $loc_ip = get_ipsec_tunnel_src($ph1ent);
+ $rmt_ip = $ph1ent['remote-gateway'];
+
+ if(ipsec_lookup_ipsakmp_sa($loc_ip,$rmt_ip))
+ return true;
+
+ return false;
+}
+
+/*
+ * Check phase2 communications status
+ */
+function ipsec_phase2_status(& $spd,& $sad,& $ph1ent,& $ph2ent) {
+
+ $loc_ip = ipsec_get_phase1_src($ph1ent);
+ $rmt_ip = $ph1ent['remote-gateway'];
+
+ $loc_id = ipsec_idinfo_to_cidr($ph2ent['localid'],true);
+ $rmt_id = ipsec_idinfo_to_cidr($ph2ent['remoteid'],true);
+
+ /* check for established SA in both directions */
+ if( ipsec_lookup_ipsec_sa($spd,$sad,"out",$loc_ip,$rmt_ip,$loc_id,$rmt_id) &&
+ ipsec_lookup_ipsec_sa($spd,$sad,"in",$rmt_ip,$loc_ip,$rmt_id,$loc_id))
+ return true;
+
+ return false;
+}
+
+/*
+ * Return ISAKMP SA details
+ */
+function ipsec_lookup_isakmp_sa($in_srcip,$in_dstip) {
+ /* TODO : use racconctl to lookup iskamp SA */
+ return NULL;
+}
+
+/*
+ * Return IPsec SA details
+ */
+function ipsec_lookup_ipsec_sa(& $spd,& $sad,$dir,$in_srcip,$in_dstip,$in_srcid,$in_dstid) {
+
+ /* match the phase1/2 to an SP */
+
+ foreach($spd as $sp) {
+
+ /* match direction */
+
+ if($dir != $sp['dir'])
+ continue;
+
+ /* match IPs */
+
+ if($in_srcip != $sp['src'])
+ continue;
+ if($in_dstip != $sp['dst'])
+ continue;
+
+ /* add netbits for address IDs */
+
+ $sp_srcid = $sp['srcid'];
+ $sp_dstid = $sp['dstid'];
+
+ if (!strstr($sp_srcid,"/"))
+ $sp_srcid .= '/32';
+ if (!strstr($sp_dstid,"/"))
+ $sp_dstid .= '/32';
+
+ /* match IDs */
+
+ if($in_srcid != $sp_srcid)
+ continue;
+ if($in_dstid != $sp_dstid)
+ continue;
+
+ /* match the SP to a unique SA by reqid */
+
+ foreach($sad as $sa) {
+
+ /* match REQIDs */
+
+ if($sa[reqid] != $sp[reqid])
+ continue;
+
+ /* sanitize for NAT-T ports */
+
+ $sa_srcip = $sa['src'];
+ $sa_dstip = $sa['dst'];
+
+ if (strstr($sa_srcip,"["))
+ $sa_srcip = substr($sa_srcip,0,strcspn($sa_srcip,"["));
+ if (strstr($sa_dstip,"["))
+ $sa_dstip = substr($sa_dstip,0,strcspn($sa_dstip,"["));
+
+ /* match IPs */
+
+ if($in_srcip != $sa_srcip)
+ continue;
+ if($in_dstip != $sa_dstip)
+ continue;
+
+ return $sa;
+ }
+ }
+
+ return NULL;
+}
+
+/*
+ * Return dump of SPD table
+ */
+function ipsec_dump_spd()
+{
+ $fd = @popen("/usr/local/sbin/setkey -DP", "r");
+ $spd = array();
+ if ($fd) {
+ while (!feof($fd)) {
+ $line = chop(fgets($fd));
+ if (!$line)
+ continue;
+ if ($line == "No SPD entries.")
+ break;
+ if ($line[0] != "\t") {
+ if (is_array($cursp))
+ $spd[] = $cursp;
+ $cursp = array();
+ $linea = explode(" ", $line);
+ $cursp['srcid'] = substr($linea[0], 0, strpos($linea[0], "["));
+ $cursp['dstid'] = substr($linea[1], 0, strpos($linea[1], "["));
+ $i = 0;
+ } else if (is_array($cursp)) {
+ $linea = explode(" ", trim($line));
+ switch($i)
+ {
+ case 1:
+ if ($linea[1] == "none") /* don't show default anti-lockout rule */
+ unset($cursp);
+ else
+ $cursp['dir'] = $linea[0];
+ break;
+ case 2:
+ $upperspec = explode("/", $linea[0]);
+ $cursp['proto'] = $upperspec[0];
+ list($cursp['src'], $cursp['dst']) = explode("-", $upperspec[2]);
+ $cursp['reqid'] = substr($upperspec[3], strpos($upperspec[3], "#")+1);
+ break;
+ }
+ }
+ $i++;
+ }
+ if (is_array($cursp) && count($cursp))
+ $spd[] = $cursp;
+ pclose($fd);
+ }
+
+ return $spd;
+}
+
+/*
+ * Return dump of SAD table
+ */
+function ipsec_dump_sad()
+{
+ $fd = @popen("/usr/local/sbin/setkey -D", "r");
+ $sad = array();
+ if ($fd) {
+ while (!feof($fd)) {
+ $line = chop(fgets($fd));
+ if (!$line)
+ continue;
+ if ($line == "No SAD entries.")
+ break;
+ if ($line[0] != "\t")
+ {
+ if (is_array($cursa))
+ $sad[] = $cursa;
+ $cursa = array();
+ list($cursa['src'],$cursa['dst']) = explode(" ", $line);
+ $i = 0;
+ }
+ else
+ {
+ $linea = explode(" ", trim($line));
+ switch ($i) {
+ case 1:
+ $cursa['proto'] = $linea[0];
+ $cursa['spi'] = substr($linea[2], strpos($linea[2], "x")+1, -1);
+ $reqid = substr($linea[3], strpos($linea[3], "=")+1);
+ $cursa['reqid'] = substr($reqid, 0, strcspn($reqid,"("));
+ break;
+ case 2:
+ $cursa['ealgo'] = $linea[1];
+ break;
+ case 3:
+ $cursa['aalgo'] = $linea[1];
+ break;
+ }
+ }
+ $i++;
+ }
+ if (is_array($cursa) && count($cursa))
+ $sad[] = $cursa;
+ pclose($fd);
+ }
+
+ return $sad;
+}
+
+?>
diff --git a/etc/inc/vpn.inc b/etc/inc/vpn.inc
index 91cbdb5..95a115b 100644
--- a/etc/inc/vpn.inc
+++ b/etc/inc/vpn.inc
@@ -3,6 +3,7 @@
/*
vpn.inc
Copyright (C) 2004 Scott Ullrich
+ Copyright (C) 2008 Shrew Soft Inc
All rights reserved.
originally part of m0n0wall (http://m0n0.ch/wall)
@@ -34,6 +35,42 @@
/* include all configuration functions */
require_once ("functions.inc");
+/* IPsec defines */
+$my_identifier_list = array('myaddress' => 'My IP address',
+ 'address' => 'IP address',
+ 'keyid tag' => 'KeyID Tag',
+ 'fqdn' => 'Domain name',
+ 'user_fqdn' => 'User FQDN',
+ 'asn1dn' => 'Distinguished Name',
+ 'dyn_dns' => 'Dynamic DNS');
+
+$peer_identifier_list = array('peeraddress' => 'Peer IP address',
+ 'address' => 'IP address',
+ 'keyid tag' => 'KeyID Tag',
+ 'fqdn' => 'Domain name',
+ 'user_fqdn' => 'User FQDN',
+ 'asn1dn' => 'Distinguished Name');
+
+$p1_ealgos = array(
+ 'aes' => array( 'name' => 'AES', 'keysel' => array( 'lo' => 128, 'hi' => 256, 'step' => 64 ) ),
+ 'blowfish' => array( 'name' => 'Blowfish', 'keysel' => array( 'lo' => 128, 'hi' => 256, 'step' => 8 ) ),
+ '3des' => array( 'name' => '3DES' ),
+ 'cast128' => array( 'name' => 'CAST128' ),
+ 'des' => array( 'name' => 'DES' ) );
+
+$p2_ealgos = array(
+ 'aes' => array( 'name' => 'AES', 'keysel' => array( 'lo' => 128, 'hi' => 256, 'step' => 64 ) ),
+ 'blowfish' => array( 'name' => 'Blowfish', 'keysel' => array( 'lo' => 128, 'hi' => 256, 'step' => 8 ) ),
+ '3des' => array( 'name' => '3DES' ),
+ 'cast128' => array( 'name' => 'CAST128' ),
+ 'des' => array( 'name' => 'DES' ) );
+
+$p1_halgos = array('sha1' => 'SHA1', 'md5' => 'MD5');
+$p1_authentication_methods = array('pre_shared_key' => 'Pre-shared key', 'rsasig' => 'RSA signature');
+$p2_halgos = array('hmac_sha1' => 'SHA1', 'hmac_md5' => 'MD5');
+$p2_protos = array('esp' => 'ESP', 'ah' => 'AH');
+$p2_pfskeygroups = array('0' => 'off', '1' => '1', '2' => '2', '5' => '5');
+
/* master setup for vpn (mpd) */
function vpn_setup() {
/* start pptpd */
@@ -98,8 +135,9 @@ function find_last_gif_device() {
return $last_gif_found;
}
-function vpn_ipsec_configure($ipchg = false) {
- global $config, $g, $sa, $sn;
+function vpn_ipsec_configure($ipchg = false)
+{
+ global $config, $g, $sa, $sn, $p1_ealgos, $p2_ealgos;
mwexec("/sbin/ifconfig enc0 up");
@@ -120,27 +158,26 @@ function vpn_ipsec_configure($ipchg = false) {
}
}
- if(isset($config['ipsec']['preferredoldsa'])) {
+ if(isset($config['ipsec']['preferredoldsa']))
mwexec("/sbin/sysctl net.key.preferred_oldsa=0");
- } else {
+ else
mwexec("/sbin/sysctl -w net.key.preferred_oldsa=-30");
- }
$number_of_gifs = find_last_gif_device();
- for ($x = 0; $x < $number_of_gifs; $x++) {
+ for ($x = 0; $x < $number_of_gifs; $x++)
mwexec("/sbin/ifconfig gif" . $x . " delete");
- }
$curwanip = get_current_wan_address();
$syscfg = $config['system'];
$ipseccfg = $config['ipsec'];
+ $a_phase1 = $config['ipsec']['phase1'];
+ $a_phase2 = $config['ipsec']['phase2'];
$lancfg = $config['interfaces']['lan'];
$lanip = $lancfg['ipaddr'];
$lansa = gen_subnet($lancfg['ipaddr'], $lancfg['subnet']);
$lansn = $lancfg['subnet'];
-
if (!isset($ipseccfg['enable'])) {
mwexec("/sbin/ifconfig enc0 down");
mwexec("/sbin/ifconfig enc0 destroy");
@@ -162,9 +199,8 @@ function vpn_ipsec_configure($ipchg = false) {
return true;
}
- if ($g['booting']) {
+ if ($g['booting'])
echo "Configuring IPsec VPN... ";
- }
if (isset ($ipseccfg['enable'])) {
/* fastforwarding is not compatible with ipsec tunnels */
@@ -177,127 +213,128 @@ function vpn_ipsec_configure($ipchg = false) {
return 0;
}
- if ((is_array($ipseccfg['tunnel']) && count($ipseccfg['tunnel'])) ||
- isset ($ipseccfg['mobileclients']['enable'])) {
-
- $dnswatch_list = array();
- $rgmap = array();
-
- if (is_array($ipseccfg['tunnel']) && count($ipseccfg['tunnel'])) {
- /* generate spd.conf */
- $fd = fopen("{$g['varetc_path']}/spd.conf", "w");
- if (!$fd) {
- printf("Error: cannot open spd.conf in vpn_ipsec_configure().\n");
- return 1;
- }
+ /* resolve all local, peer addresses and setup pings */
+ $ipmap = array();
+ $rgmap = array();
+ $dnswatch_list = array();
+ if (is_array($a_phase1) && count($a_phase1)) {
+ foreach ($a_phase1 as $ph1ent) {
+ if (isset($ph1ent['disabled']))
+ continue;
- $spdconf = "";
+ $ep = vpn_endpoint_determine($ph1ent, $curwanip);
+ if (!$ep)
+ continue;
- $spdconf .= "spdadd {$lansa}/{$lansn} {$lanip}/32 any -P in none;\n";
- $spdconf .= "spdadd {$lanip}/32 {$lansa}/{$lansn} any -P out none;\n";
+ if(!in_array($ep,$ipmap))
+ $ipmap[] = $ep;
- foreach ($ipseccfg['tunnel'] as $tunnel) {
- if (isset ($tunnel['disabled']))
- continue;
+ /* 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 dnswatch */
- /* see if this tunnel has a hostname for the remote-gateway, and if so,
- try to resolve it now and add it to the list for dnswatch */
- if (!is_ipaddr($tunnel['remote-gateway'])) {
- $dnswatch_list[] = $tunnel['remote-gateway'];
- $rgip = resolve_retry($tunnel['remote-gateway']);
-
- if (!$rgip)
- continue;
-
- } else {
- $rgip = $tunnel['remote-gateway'];
- }
- $rgmap[$tunnel['remote-gateway']] = $rgip;
+ $rg = $ph1ent['remote-gateway'];
- $ep = vpn_endpoint_determine($tunnel, $curwanip);
- if (!$ep)
+ if (!is_ipaddr($rg)) {
+ $dnswatch_list[] = $rg;
+ $rg = resolve_retry($rg);
+
+ if (!$rgip)
continue;
+ }
- vpn_localnet_determine($tunnel['local-subnet'], $sa, $sn);
+ $rgmap[$ph1ent['remote-gateway']] = $rg;
- if (is_domain($tunnel['remote-gateway'])) {
- $tmp = gethostbyname($tunnel['remote-gateway']);
- if ($tmp)
- $tunnel['remote-gateway'] = $tmp;
- }
+ /* add an ipsec pinghosts entry */
- /* add entry to host pinger */
- if ($tunnel['pinghost']) {
- $pfd = fopen("/var/db/ipsecpinghosts", "a");
-
- /* if list */
- $iflist = get_configured_interface_list();
-
- foreach ($iflist as $ifent => $ifname) {
- $interface_ip = find_interface_ip($config['interfaces'][$ifname]['if']);
- if (ip_in_subnet($interface_ip, $sa . "/" . $sn))
- $srcip = find_interface_ip($config['interfaces'][$ifname]['if']);
- }
- $dstip = $tunnel['pinghost'];
- fwrite($pfd, "$srcip|$dstip|3\n");
- fclose($pfd);
- }
-
- if (isset ($tunnel['creategif'])) {
- $number_of_gifs = find_last_gif_device();
- $number_of_gifs++;
- $curwanip = get_current_wan_address();
- if ($config['installedpackages']['sasyncd']['config'] <> "")
- foreach ($config['installedpackages']['sasyncd']['config'] as $sasyncd) {
- if ($sasyncd['ip'] <> "")
- $curwanip = $sasyncd['ip'];
- }
- mwexec("/sbin/ifconfig gif" . $number_of_gifs . " tunnel" . $curwanip . " " . $tunnel['remote-gateway']);
- mwexec("/sbin/ifconfig gif" . $number_of_gifs . " {$lansa}/{$lansn} {$lanip}/32");
+ if ($ph1ent['pinghost']) {
+ $pfd = fopen("/var/db/ipsecpinghosts", "a");
+ $iflist = array("lan" => "lan", "wan" => "wan");
+ for ($i = 1; isset($config['interfaces']['opt' . $i]); $i++)
+ $iflist['opt' . $i] = "opt{$i}";
+ foreach ($iflist as $ifent => $ifname) {
+ $interface_ip = find_interface_ip($config['interfaces'][$ifname]['if']);
+ if (ip_in_subnet($interface_ip, $sa . "/" . $sn))
+ $srcip = find_interface_ip($config['interfaces'][$ifname]['if']);
}
+ $dstip = $ph1ent['pinghost'];
+ fwrite($pfd, "$srcip|$dstip|3\n");
+ fclose($pfd);
+ }
+ }
+ }
- $spdconf .= "spdadd {$sa}/{$sn} " .
- "{$tunnel['remote-subnet']} any -P out ipsec " .
- "{$tunnel['p2']['protocol']}/tunnel/{$ep}-" .
- "{$rgip}/unique;\n";
-
- $spdconf .= "spdadd {$tunnel['remote-subnet']} " .
- "{$sa}/{$sn} any -P in ipsec " .
- "{$tunnel['p2']['protocol']}/tunnel/{$rgip}-" .
- "{$ep}/unique;\n";
-
- /* static route needed? */
- if(preg_match("/^carp/i", $tunnel['interface'])) {
- $parentinterface = link_carp_interface_to_parent($tunnel['interface']);
- } else {
- $parentinterface = $tunnel['interface'];
- }
- if($parentinterface <> "wan") {
- /* add endpoint routes to correct gateway on interface */
- if(interface_has_gateway($parentinterface)) {
- $gatewayip = get_interface_gateway("$parentinterface");
- $interfaceip = $config['interfaces'][$parentinterface]['ipaddr'];
- $subnet_bits = $config['interfaces'][$parentinterface]['subnet'];
- $subnet_ip = gen_subnet("{$interfaceip}", "{$subnet_bits}");
- /* if the remote gateway is in the local subnet, then don't add a route */
- if(! ip_in_subnet($tunnel['remote-gateway'], "{$subnet_ip}/{$subnet_bits}")) {
- if(is_ipaddr($gatewayip)) {
- log_error("IPSEC interface is not WAN but {$tunnel['interface']}, adding static route for VPN endpoint {$tunnel['remote-gateway']} via {$gatewayip}");
- mwexec("/sbin/route delete -host {$tunnel['remote-gateway']};/sbin/route add -host {$tunnel['remote-gateway']} {$gatewayip}");
- }
- }
+ /* generate CA certificates files */
+ $cacertnum = 0;
+ if (is_array($ipseccfg['cacert']) && count($ipseccfg['cacert'])) {
+ foreach ($ipseccfg['cacert'] as $cacert) {
+ ++ $cacertnum;
+ if (isset ($cacert['cert'])) {
+ $cert = base64_decode($cacert['cert']);
+ $x509cert = openssl_x509_parse(openssl_x509_read($cert));
+ if (is_array($x509cert) && isset ($x509cert['hash'])) {
+ $fd1 = fopen("{$g['varetc_path']}/{$x509cert['hash']}.0", "w");
+ if (!$fd1) {
+ printf("Error: cannot open {$x509cert['hash']}.0 in vpn.\n");
+ return 1;
}
- } else {
- mwexec("/sbin/route delete -host {$tunnel['remote-gateway']}");
+ chmod("{$g['varetc_path']}/{$x509cert['hash']}.0", 0600);
+ fwrite($fd1, $cert);
+ fclose($fd1);
}
+ }
+ }
+ }
+
+ /* generate psk.txt */
+ $fd = fopen("{$g['varetc_path']}/psk.txt", "w");
+ if (!$fd) {
+ printf("Error: cannot open psk.txt in vpn_ipsec_configure().\n");
+ return 1;
+ }
+
+ $pskconf = "";
+ if (is_array($a_phase1) && count($a_phase1)) {
+ foreach ($a_phase1 as $ph1ent) {
+
+ if (isset($ph1ent['disabled']))
+ continue;
+
+ $rgip = $rgmap[$ph1ent['remote-gateway']];
+ if (!$rgip)
+ continue;
+
+ $peerid_type = $ph1ent['peerid_type'];
+
+ switch ($peerid_type) {
+ case "peeraddress":
+ $peerid_type = "address";
+ $peerid_data = $rgip;
+ break;
+
+ case "address";
+ $peerid_data = $ph1ent['peerid_data'];
+ break;
+
+ case "fqdn";
+ case "keyid tag";
+ case "user_fqdn";
+ $peerid_data = $ph1ent['peerid_data'];
+ break;
}
- fwrite($fd, $spdconf);
- fclose($fd);
+ $pskconf .= "{$peerid_data}\t\t\t{$ph1ent['pre-shared-key']}\n";
}
+ }
+
+ fwrite($fd, $pskconf);
+ fclose($fd);
+ chmod("{$g['varetc_path']}/psk.txt", 0600);
+
+ /* begin racoon.conf */
+ if ((is_array($a_phase1) && count($a_phase1)) ||
+ (is_array($a_phase2) && count($a_phase2))) {
- /* generate racoon.conf */
$fd = fopen("{$g['varetc_path']}/racoon.conf", "w");
if (!$fd) {
printf("Error: cannot open racoon.conf in vpn_ipsec_configure().\n");
@@ -309,395 +346,400 @@ function vpn_ipsec_configure($ipchg = false) {
$racoonconf .= "path pre_shared_key \"{$g['varetc_path']}/psk.txt\";\n\n";
$racoonconf .= "path certificate \"{$g['varetc_path']}\";\n\n";
- /* generate CA certificates files */
- $cacertnum = 0;
- if (is_array($ipseccfg['cacert']) && count($ipseccfg['cacert']))
- foreach ($ipseccfg['cacert'] as $cacert) {
- ++ $cacertnum;
- if (isset ($cacert['cert'])) {
- $cert = base64_decode($cacert['cert']);
- $x509cert = openssl_x509_parse(openssl_x509_read($cert));
- if (is_array($x509cert) && isset ($x509cert['hash'])) {
- $fd1 = fopen("{$g['varetc_path']}/{$x509cert['hash']}.0", "w");
- if (!$fd1) {
- printf("Error: cannot open {$x509cert['hash']}.0 in vpn.\n");
- return 1;
- }
- chmod("{$g['varetc_path']}/{$x509cert['hash']}.0", 0600);
- fwrite($fd1, $cert);
- fclose($fd1);
- }
- }
+ /* begin listen section */
+ if (count($ipmap)) {
+ $racoonconf .= "\nlisten\n";
+ $racoonconf .= "{\n";
+ foreach ($ipmap as $addr) {
+ $racoonconf .= "\tisakmp {$addr} [500];\n";
+ $racoonconf .= "\tisakmp_natt {$addr} [4500];\n";
}
+ $racoonconf .= "}\n\n";
+ }
- $tunnelnumber = 0;
- if (is_array($ipseccfg['tunnel']) && count($ipseccfg['tunnel']))
- foreach ($ipseccfg['tunnel'] as $tunnel) {
+ /* begin remote sections */
+ if (is_array($a_phase1) && count($a_phase1)) {
+ /* begin remote */
+ foreach ($a_phase1 as $ph1ent) {
+ if (isset($ph1ent['disabled']))
+ continue;
- ++ $tunnelnumber;
+ $ikeid = $ph1ent['ikeid'];
- if (isset ($tunnel['disabled']))
+ $ep = vpn_endpoint_determine($ph1ent, $curwanip);
+ if (!$ep)
continue;
+ $myid_type = $ph1ent['myid_type'];
- $rgip = $rgmap[$tunnel['remote-gateway']];
- if (!$rgip)
- continue;
+ switch ($myid_type) {
- $ep = vpn_endpoint_determine($tunnel, $curwanip);
- if (!$ep)
- continue;
+ case "myaddress":
+ $myid_type = "address";
+ $myid_data = $ep;
+ break;
+
+ case "dyn_dns":
+ $myid_data = gethostbyname($ph1ent['myid_data']);
+ break;
- vpn_localnet_determine($tunnel['local-subnet'], $sa, $sn);
-
- if (isset ($tunnel['p1']['myident']['myaddress'])) {
- $myidentt = "address";
- $myident = $ep;
- } elseif (isset ($tunnel['p1']['myident']['address'])) {
- $myidentt = "address";
- $myident = $tunnel['p1']['myident']['address'];
- } elseif (isset ($tunnel['p1']['myident']['fqdn'])) {
- $myidentt = "fqdn";
- $myident = $tunnel['p1']['myident']['fqdn'];
- } elseif (isset ($tunnel['p1']['myident']['ufqdn'])) {
- $myidentt = "user_fqdn";
- $myident = $tunnel['p1']['myident']['ufqdn'];
- } else if (isset($tunnel['p1']['myident']['asn1dn'])) {
- $myidentt = "asn1dn";
- $myident = $tunnel['p1']['myident']['asn1dn'];
- } else if (isset($tunnel['p1']['myident']['asn1dn'])) {
- $myidentt = "asn1dn";
- $myident = $tunnel['p1']['myident']['asn1dn'];
- } elseif (isset ($tunnel['p1']['myident']['dyn_dns'])) {
- $myidentt = "dyn_dns";
- $myident = gethostbyname($tunnel['p1']['myident']['dyn_dns']);
+ case "address";
+ $myid_data = $ph1ent['myid_data'];
+ break;
+
+ case "fqdn";
+ case "keyid tag";
+ case "user_fqdn";
+ case "asn1dn";
+ $myid_data = $ph1ent['myid_data'];
+ if( $myid_data )
+ $myid_data = "\"".$myid_data."\"";
+ break;
}
- if (!($myidentt == "asn1dn" && $myident == "")) {
- $myident = " \"{$myident}\"";
+ $rgip = $rgmap[$ph1ent['remote-gateway']];
+ if (!$rgip)
+ continue;
+
+ $peerid_type = $ph1ent['peerid_type'];
+
+ switch ($peerid_type) {
+ case "peeraddress":
+ $peerid_type = "address";
+ $peerid_data = $rgip;
+ break;
+
+ case "address";
+ $peerid_data = $ph1ent['peerid_data'];
+ break;
+
+ case "fqdn";
+ case "keyid tag";
+ case "user_fqdn";
+ case "asn1dn";
+ $peerid_data = $ph1ent['peerid_data'];
+ if( $peerid_data )
+ $peerid_data = "\"".$peerid_data."\"";
+ break;
}
$nattline = '';
- if (isset($tunnel['natt'])) {
- $nattline = "nat_traversal on;";
- }
+ if (isset($ph1ent['nat_traversal']))
+ $nattline = "nat_traversal {$ph1ent['nat_traversal']};";
- if (isset ($tunnel['p1']['authentication_method'])) {
- $authmethod = $tunnel['p1']['authentication_method'];
- } else {
+ if (isset ($ph1ent['authentication_method']))
+ $authmethod = $ph1ent['authentication_method'];
+ else
$authmethod = 'pre_shared_key';
- }
$certline = '';
if ($authmethod == 'rsasig') {
- if ($tunnel['p1']['cert'] && $tunnel['p1']['private-key']) {
- $cert = base64_decode($tunnel['p1']['cert']);
- $private_key = base64_decode($tunnel['p1']['private-key']);
+ if ($ph1ent['cert'] && $ph1ent['private-key']) {
+ $cert = base64_decode($ph1ent['cert']);
+ $private_key = base64_decode($ph1ent['private-key']);
} else {
/* null certificate/key */
$cert = '';
$private_key = '';
}
- if ($tunnel['p1']['peercert'])
- $peercert = base64_decode($tunnel['p1']['peercert']);
+ if ($ph1ent['peercert'])
+ $peercert = base64_decode($ph1ent['peercert']);
else
$peercert = '';
- $fd1 = fopen("{$g['varetc_path']}/server{$tunnelnumber}-signed.pem", "w");
+ $fd1 = fopen("{$g['varetc_path']}/server{$ikeid}-signed.pem", "w");
if (!$fd1) {
- printf("Error: cannot open server{$tunnelnumber}-signed.pem in vpn.\n");
+ printf("Error: cannot open server{$ikeid}-signed.pem in vpn.\n");
return 1;
}
- chmod("{$g['varetc_path']}/server{$tunnelnumber}-signed.pem", 0600);
+
+ chmod("{$g['varetc_path']}/server{$ikeid}-signed.pem", 0600);
fwrite($fd1, $cert);
fclose($fd1);
- $fd1 = fopen("{$g['varetc_path']}/server{$tunnelnumber}-key.pem", "w");
+ $fd1 = fopen("{$g['varetc_path']}/server{$ikeid}-key.pem", "w");
if (!$fd1) {
- printf("Error: cannot open server{$tunnelnumber}-key.pem in vpn.\n");
+ printf("Error: cannot open server{$ikeid}-key.pem in vpn.\n");
return 1;
}
- chmod("{$g['varetc_path']}/server{$tunnelnumber}-key.pem", 0600);
+ chmod("{$g['varetc_path']}/server{$ikeid}-key.pem", 0600);
fwrite($fd1, $private_key);
fclose($fd1);
- $certline = "certificate_type x509 \"server{$tunnelnumber}-signed.pem\" \"server{$tunnelnumber}-key.pem\";";
+ $certline = "certificate_type x509 \"server{$ikeid}-signed.pem\" \"server{$ikeid}-key.pem\";";
if ($peercert != '') {
- $fd1 = fopen("{$g['varetc_path']}/peer{$tunnelnumber}-signed.pem", "w");
+ $fd1 = fopen("{$g['varetc_path']}/peer{$ikeid}-signed.pem", "w");
if (!$fd1) {
- printf("Error: cannot open server{$tunnelnumber}-signed.pem in vpn.\n");
+ printf("Error: cannot open server{$ikeid}-signed.pem in vpn.\n");
return 1;
}
- chmod("{$g['varetc_path']}/peer{$tunnelnumber}-signed.pem", 0600);
+ chmod("{$g['varetc_path']}/peer{$ikeid}-signed.pem", 0600);
fwrite($fd1, $peercert);
fclose($fd1);
- $certline .=<<<EOD
-
- peers_certfile "peer{$tunnelnumber}-signed.pem";
-EOD;
+ $certline .="peers_certfile \"peer{$ikeid}-signed.pem\"";
}
}
- $myidentifier = $myidentt;
- if (!empty($myident))
- $myidentifier .= ' "' . $myident . '"';
+
+ $ealgos = '';
+ $ealg_id = $ph1ent['encryption-algorithm']['name'];
+ $ealg_kl = $ph1ent['encryption-algorithm']['keylen'];
+ if ($ealg_kl)
+ $ealgos = $ealgos.$ealg_id." ".$ealg_kl;
+ else
+ $ealgos = $ealgos.$ealg_id;
+
+ $lifeline = '';
+ if ($ph1ent['lifetime'])
+ $lifeline = "lifetime time {$ph1ent['lifetime']} secs;";
+
+ /* add remote section to configuration */
+
$racoonconf .=<<<EOD
-remote {$tunnel['remote-gateway']} {
- exchange_mode {$tunnel['p1']['mode']};
- my_identifier {$myidentt}{$myident};
+
+remote {$rgip}
+{
+ ph1id {$ikeid};
+ exchange_mode {$ph1ent['mode']};
+ my_identifier {$myid_type} {$myid_data};
+ peers_identifier {$peerid_type} {$peerid_data};
+ ike_frag on;
{$nattline}
{$certline}
- peers_identifier address {$rgip};
initial_contact on;
- dpd_delay 120; # DPD poll every 120 seconds
- ike_frag on;
support_proxy on;
- proposal_check obey;
+ proposal_check claim;
- proposal \{
- encryption_algorithm {$tunnel['p1']['encryption-algorithm']};
- hash_algorithm {$tunnel['p1']['hash-algorithm']};
+ proposal
+ {
authentication_method {$authmethod};
- dh_group {$tunnel['p1']['dhgroup']};
+ encryption_algorithm ${ealgos};
+ hash_algorithm {$ph1ent['hash-algorithm']};
+ dh_group {$ph1ent['dhgroup']};
+ ${lifeline}
+ }
+}
EOD;
- if ($tunnel['p1']['lifetime'])
- $racoonconf .= " lifetime time {$tunnel['p1']['lifetime']} secs;\n";
-
- $racoonconf .= " }\n";
+ }
+ /* end remote */
+ }
+ /* end remote sections */
+
+ /* begin sainfo sections */
+ if (is_array($a_phase2) && count($a_phase2)) {
+ /* begin sainfo */
+ foreach ($a_phase2 as $ph2ent) {
- if ($tunnel['p1']['lifetime'])
- $racoonconf .= " lifetime time {$tunnel['p1']['lifetime']} secs;\n";
+ $ikeid = $ph2ent['ikeid'];
- $racoonconf .= "}\n\n";
+ $localid_type = $ph2ent['localid']['type'];
+ if ($localid_type != "address")
+ $localid_type = "subnet";
- $p2ealgos = join(",", $tunnel['p2']['encryption-algorithm-option']);
- $p2halgos = join(",", $tunnel['p2']['hash-algorithm-option']);
+ $remoteid_type = $ph2ent['remoteid']['type'];
+ if ($remoteid_type != "address")
+ $remoteid_type = "subnet";
- $racoonconf .=<<<EOD
-sainfo address {$sa}/{$sn} any address {$tunnel['remote-subnet']} any \{
- encryption_algorithm {$p2ealgos};
- authentication_algorithm {$p2halgos};
- compression_algorithm deflate;
+ $localid_data = ipsec_idinfo_to_cidr($ph2ent['localid']);
+ $remoteid_data = ipsec_idinfo_to_cidr($ph2ent['remoteid']);
-EOD;
+ $ealgos = '';
+ $halgos = join(",", $ph2ent['hash-algorithm-option']);
- if ($tunnel['p2']['pfsgroup'])
- $racoonconf .= " pfs_group {$tunnel['p2']['pfsgroup']};\n";
+ $pfsline = '';
+ if ($ph2ent['pfsgroup'])
+ $pfsline = "pfs_group {$ph2ent['pfsgroup']};";
- if ($tunnel['p2']['lifetime'])
- $racoonconf .= " lifetime time {$tunnel['p2']['lifetime']} secs;\n";
+ $lifeline = '';
+ if ($ph2ent['lifetime'])
+ $lifeline = "lifetime time {$ph2ent['lifetime']} secs;";
- $racoonconf .= "}\n\n";
- }
+ foreach ($ph2ent['encryption-algorithm-option'] as $ealg) {
- /* mobile clients? */
- if (isset ($ipseccfg['mobileclients']['enable'])) {
+ $ealg_id = $ealg['name'];
+ $ealg_kl = $ealg['keylen'];
- $tunnel = $ipseccfg['mobileclients'];
+ if ($ealg_kl) {
+ if( $ealg_kl == "auto" ) {
+ $key_hi = $p2_ealgos[$ealg_id]['keysel']['hi'];
+ $key_lo = $p2_ealgos[$ealg_id]['keysel']['lo'];
+ $key_step = $p2_ealgos[$ealg_id]['keysel']['step'];
- if (isset ($tunnel['p1']['myident']['myaddress'])) {
- $myidentt = "address";
- $myident = $curwanip;
- } else
- if (isset ($tunnel['p1']['myident']['address'])) {
- $myidentt = "address";
- $myident = $tunnel['p1']['myident']['address'];
- } else
- if (isset ($tunnel['p1']['myident']['fqdn'])) {
- $myidentt = "fqdn";
- $myident = $tunnel['p1']['myident']['fqdn'];
- } else
- if (isset ($tunnel['p1']['myident']['ufqdn'])) {
- $myidentt = "user_fqdn";
- $myident = $tunnel['p1']['myident']['ufqdn'];
+ for ($keylen = $key_hi; $keylen >= $key_lo; $keylen -= $key_step) {
+ if( $ealgos )
+ $ealgos = $ealgos.", ";
+ $ealgos = $ealgos.$ealg_id." ".$keylen;
+ }
+ } else {
+ if ($ealgos)
+ $ealgos = $ealgos.", ";
+ $ealgos = $ealgos.$ealg_id." ".$ealg_kl;
}
-
- if (isset ($tunnel['p1']['authentication_method'])) {
- $authmethod = $tunnel['p1']['authentication_method'];
- } else {
- $authmethod = 'pre_shared_key';
- }
-
- $certline = '';
- if ($authmethod == 'rsasig') {
- if ($tunnel['p1']['cert'] && $tunnel['p1']['private-key']) {
- $cert = base64_decode($tunnel['p1']['cert']);
- $private_key = base64_decode($tunnel['p1']['private-key']);
- } else {
- /* null certificate/key */
- $cert = '';
- $private_key = '';
- }
-
- if ($tunnel['p1']['peercert'])
- $peercert = base64_decode($tunnel['p1']['peercert']);
- else
- $peercert = '';
-
- $fd1 = fopen("{$g['varetc_path']}/server-mobile{$tunnelnumber}-signed.pem", "w");
- if (!$fd1) {
- printf("Error: cannot open server-mobile{$tunnelnumber}-signed.pem in vpn.\n");
- return 1;
- }
- chmod("{$g['varetc_path']}/server-mobile{$tunnelnumber}-signed.pem", 0600);
- fwrite($fd1, $cert);
- fclose($fd1);
-
- $fd1 = fopen("{$g['varetc_path']}/server-mobile{$tunnelnumber}-key.pem", "w");
- if (!$fd1) {
- printf("Error: cannot open server-mobile{$tunnelnumber}-key.pem in vpn.\n");
- return 1;
+ } else {
+ if ($ealgos)
+ $ealgos = $ealgos.", ";
+ $ealgos = $ealgos.$ealg_id;
+ }
}
- chmod("{$g['varetc_path']}/server-mobile{$tunnelnumber}-key.pem", 0600);
- fwrite($fd1, $private_key);
- fclose($fd1);
-
- $certline = "certificate_type x509 \"server-mobile{$tunnelnumber}-signed.pem\" \"server-mobile{$tunnelnumber}-key.pem\";";
- }
- $racoonconf .=<<<EOD
-remote anonymous \{
- exchange_mode {$tunnel['p1']['mode']};
- my_identifier {$myidentt}{$myident};
- {$certline}
- initial_contact on;
- dpd_delay 120; # DPD poll every 120 seconds
- ike_frag on;
- passive on;
- generate_policy on;
- support_proxy on;
- proposal_check obey;
-
- proposal \{
- encryption_algorithm {$tunnel['p1']['encryption-algorithm']};
- hash_algorithm {$tunnel['p1']['hash-algorithm']};
- authentication_method {$authmethod};
- dh_group {$tunnel['p1']['dhgroup']};
-
-EOD;
- if ($tunnel['p1']['lifetime'])
- $racoonconf .= " lifetime time {$tunnel['p1']['lifetime']} secs;\n";
-
- $racoonconf .= " }\n";
- if ($tunnel['p1']['lifetime'])
- $racoonconf .= " lifetime time {$tunnel['p1']['lifetime']} secs;\n";
-
- $racoonconf .= "}\n\n";
-
- $p2ealgos = join(",", $tunnel['p2']['encryption-algorithm-option']);
- $p2halgos = join(",", $tunnel['p2']['hash-algorithm-option']);
-
- $racoonconf .=<<<EOD
-sainfo anonymous \{
- encryption_algorithm {$p2ealgos};
- authentication_algorithm {$p2halgos};
+ /* add sainfo section to configuration */
+
+ $racoonconf .=<<<EOD
+
+sainfo {$localid_type} {$localid_data} any {$remoteid_type} {$remoteid_data} any
+{
+ remoteid {$ikeid};
+ encryption_algorithm {$ealgos};
+ authentication_algorithm {$halgos};
compression_algorithm deflate;
+ ${pfsline}
+ ${lifeline}
+}
EOD;
-
- if ($tunnel['p2']['pfsgroup'])
- $racoonconf .= " pfs_group {$tunnel['p2']['pfsgroup']};\n";
-
- if ($tunnel['p2']['lifetime'])
- $racoonconf .= " lifetime time {$tunnel['p2']['lifetime']} secs;\n";
-
- $racoonconf .= "}\n\n";
+ }
+ /* end sainfo */
}
+ /* end sainfo sections */
fwrite($fd, $racoonconf);
fclose($fd);
+ }
+ /* end racoon.conf */
- /* generate psk.txt */
- $fd = fopen("{$g['varetc_path']}/psk.txt", "w");
+ /* generate IPsec policies */
+ if (is_array($a_phase2) && count($a_phase2)) {
+ /* generate spd.conf */
+ $fd = fopen("{$g['varetc_path']}/spd.conf", "w");
if (!$fd) {
- printf("Error: cannot open psk.txt in vpn_ipsec_configure().\n");
+ printf("Error: cannot open spd.conf in vpn_ipsec_configure().\n");
return 1;
}
- $pskconf = "";
+ $spdconf = "";
- if (is_array($ipseccfg['tunnel'])) {
- foreach ($ipseccfg['tunnel'] as $tunnel) {
- if (isset ($tunnel['disabled']))
- continue;
- $rgip = $rgmap[$tunnel['remote-gateway']];
- if (!$rgip)
- continue;
- $pskconf .= "{$rgip} {$tunnel['p1']['pre-shared-key']}\n";
- }
- }
+ /* What are these SPD entries for?
+ * -mgrooms 07/10/2008
+ */
+ $spdconf .= "spdadd {$lanip}/32 {$lansa}/{$lansn} any -P out none;\n";
+ $spdconf .= "spdadd {$lansa}/{$lansn} {$lanip}/32 any -P in none;\n";
- /* add PSKs for mobile clients */
- if (is_array($ipseccfg['mobilekey'])) {
- foreach ($ipseccfg['mobilekey'] as $key) {
- $pskconf .= "{$key['ident']} {$key['pre-shared-key']}\n";
- }
- }
+ foreach ($a_phase2 as $ph2ent) {
+ if( !ipsec_lookup_phase1($ph2ent,$ph1ent))
+ continue;
- fwrite($fd, $pskconf);
- fclose($fd);
- chmod("{$g['varetc_path']}/psk.txt", 0600);
-
-
- if(is_process_running("racoon")) {
- /* We are already online, reload */
- mwexec("/usr/bin/killall -HUP racoon");
- /* flush SPD entries */
- mwexec("/usr/local/sbin/setkey -FP");
- mwexec("/usr/local/sbin/setkey -F");
- /* load SPD */
- mwexec("/usr/local/sbin/setkey -f {$g['varetc_path']}/spd.conf");
- sleep(1);
- /* We are already online, reload */
- mwexec("/usr/bin/killall -HUP racoon");
- sleep(1);
- mwexec("/usr/bin/killall -HUP racoon");
- } else {
- /* start racoon */
- mwexec("/usr/local/sbin/racoon -f {$g['varetc_path']}/racoon.conf");
- /* flush SA + SPD entries*/
- mwexec("/usr/local/sbin/setkey -FP");
- mwexec("/usr/local/sbin/setkey -F");
- /* load SPD */
- mwexec("/usr/local/sbin/setkey -f {$g['varetc_path']}/spd.conf");
- sleep(1);
- /* We are already online, reload */
- mwexec("/usr/bin/killall -HUP racoon");
- sleep(1);
- mwexec("/usr/bin/killall -HUP racoon");
-
- /* start dnswatch, if necessary */
- if (count($dnswatch_list) > 0) {
- $interval = 60;
- if ($ipseccfg['dns-interval']) {
- $interval = $ipseccfg['dns-interval'];
- }
-
- $hostnames = "";
- foreach ($dnswatch_list as $dns) {
- $hostnames .= " " . escapeshellarg($dns);
+ if (isset ($ph1ent['disabled']))
+ continue;
+
+ if (isset ($ph2ent['disabled']))
+ continue;
+
+ $ep = vpn_endpoint_determine($ph1ent, $curwanip);
+ if (!$ep)
+ continue;
+
+ $rgip = $rgmap[$ph1ent['remote-gateway']];
+
+ $localid = ipsec_idinfo_to_cidr($ph2ent['localid'],true);
+ $remoteid = ipsec_idinfo_to_cidr($ph2ent['remoteid'],true);
+
+ if (isset ($ph2ent['creategif'])) {
+ $number_of_gifs = find_last_gif_device();
+ $number_of_gifs++;
+ $curwanip = get_current_wan_address();
+ if ($config['installedpackages']['sasyncd']['config'] <> "") {
+ foreach ($config['installedpackages']['sasyncd']['config'] as $sasyncd) {
+ if ($sasyncd['ip'] <> "")
+ $curwanip = $sasyncd['ip'];
+ }
}
- mwexec("/usr/local/bin/dnswatch {$g['varrun_path']}/dnswatch-ipsec.pid $interval " .
- escapeshellarg("/etc/rc.newipsecdns") . $hostnames);
+ mwexec("/sbin/ifconfig gif" . $number_of_gifs . " tunnel" . $curwanip . " " . $rgip);
+ mwexec("/sbin/ifconfig gif" . $number_of_gifs . " {$lansa}/{$lansn} {$lanip}/32");
}
- }
- if (is_array($ipseccfg['tunnel'])) {
- foreach ($ipseccfg['tunnel'] as $tunnel) {
- if (isset ($tunnel['auto'])) {
- $remotehost = substr($tunnel['remote-subnet'], 0, strpos($tunnel['remote-subnet'], "/"));
- $srchost = vpn_endpoint_determine($tunnel, $curwanip);
- if ($srchost)
- mwexec_bg("/sbin/ping -c 10 -S {$srchost} {$remotehost}");
+ $spdconf .= "spdadd {$localid} {$remoteid} any -P out ipsec " .
+ "{$ph2ent['protocol']}/tunnel/{$ep}-{$rgip}/unique;\n";
+
+ $spdconf .= "spdadd {$remoteid} {$localid} any -P in ipsec " .
+ "{$ph2ent['protocol']}/tunnel/{$rgip}-{$ep}/unique;\n";
+
+ /* static route needed? */
+ if (preg_match("/^carp/i", $ph1ent['interface']))
+ $parentinterface = link_carp_interface_to_parent($ph1ent['interface']);
+ else
+ $parentinterface = $ph1ent['interface'];
+
+ if ($parentinterface <> "wan") {
+ /* add endpoint routes to correct gateway on interface */
+ if (interface_has_gateway($parentinterface)) {
+ $gatewayip = get_interface_gateway("$parentinterface");
+ $interfaceip = $config['interfaces'][$parentinterface]['ipaddr'];
+ $subnet_bits = $config['interfaces'][$parentinterface]['subnet'];
+ $subnet_ip = gen_subnet("{$interfaceip}", "{$subnet_bits}");
+ /* if the remote gateway is in the local subnet, then don't add a route */
+ if (! ip_in_subnet($rgip, "{$subnet_ip}/{$subnet_bits}")) {
+ if(is_ipaddr($gatewayip)) {
+ log_error("IPSEC interface is not WAN but {$parentinterface}, adding static route for VPN endpoint {$rgip} via {$gatewayip}");
+ mwexec("/sbin/route delete -host {$rgip};/sbin/route add -host {$rgip} {$gatewayip}");
+ }
+ }
}
}
+ else
+ mwexec("/sbin/route delete -host {$rgip}");
+ }
+
+ fwrite($fd, $spdconf);
+ fclose($fd);
+ }
+
+ /* mange racoon process */
+ if (is_process_running("racoon")) {
+ /* We are already online, reload */
+ mwexec("/usr/bin/killall -HUP racoon");
+ /* flush SPD entries */
+ mwexec("/usr/local/sbin/setkey -FP");
+ mwexec("/usr/local/sbin/setkey -F");
+ /* load SPD */
+ mwexec("/usr/local/sbin/setkey -f {$g['varetc_path']}/spd.conf");
+ sleep(1);
+ /* We are already online, reload */
+ mwexec("/usr/bin/killall -HUP racoon");
+ sleep(1);
+ mwexec("/usr/bin/killall -HUP racoon");
+ } else {
+ /* start racoon */
+ mwexec("/usr/local/sbin/racoon -f {$g['varetc_path']}/racoon.conf");
+ /* flush SA + SPD entries */
+ mwexec("/usr/local/sbin/setkey -FP");
+ mwexec("/usr/local/sbin/setkey -F");
+ /* load SPD */
+ mwexec("/usr/local/sbin/setkey -f {$g['varetc_path']}/spd.conf");
+ sleep(1);
+ /* We are already online, reload */
+ mwexec("/usr/bin/killall -HUP racoon");
+ sleep(1);
+ mwexec("/usr/bin/killall -HUP racoon");
+
+ /* start dnswatch, if necessary */
+ if (count($dnswatch_list) > 0) {
+ $interval = 60;
+ if ($ipseccfg['dns-interval'])
+ $interval = $ipseccfg['dns-interval'];
+
+ $hostnames = "";
+ foreach ($dnswatch_list as $dns)
+ $hostnames .= " " . escapeshellarg($dns);
+
+ mwexec("/usr/local/bin/dnswatch {$g['varrun_path']}/dnswatch-ipsec.pid $interval " .
+ escapeshellarg("/etc/rc.newipsecdns") . $hostname);
}
}
}
-
+
vpn_ipsec_failover_configure();
if (!$g['booting']) {
@@ -943,20 +985,20 @@ function vpn_localnet_determine($adr, & $sa, & $sn) {
}
}
-function vpn_endpoint_determine($tunnel, $curwanip) {
+function vpn_endpoint_determine($ph1ent, $curwanip) {
global $g, $config;
- if ((!$tunnel['interface']) || ($tunnel['interface'] == "wan")) {
+ if ((!$ph1ent['interface']) || ($ph1ent['interface'] == "wan")) {
if ($curwanip)
return $curwanip;
else
return null;
- } elseif ($tunnel['interface'] == "lan") {
+ } elseif ($ph1ent['interface'] == "lan") {
return $config['interfaces']['lan']['ipaddr'];
} else {
- $iface = $config['interfaces'][$tunnel['interface']]['if'];
- $oc = $config['interfaces'][$tunnel['interface']];
+ $iface = $config['interfaces'][$ph1ent['interface']]['if'];
+ $oc = $config['interfaces'][$ph1ent['interface']];
/* carp ips, etc */
$ip = find_interface_ip($iface);
if($ip)
diff --git a/etc/inc/xmlparse.inc b/etc/inc/xmlparse.inc
index 6eabbe1..64179d7 100644
--- a/etc/inc/xmlparse.inc
+++ b/etc/inc/xmlparse.inc
@@ -34,7 +34,7 @@
function listtags() {
$ret = explode(" ", "element alias aliasurl allowedip cacert config columnitem disk dnsserver domainoverrides " .
"earlyshellcmd encryption-algorithm-option field fieldname hash-algorithm-option " .
- "hosts group interface_array item key lbpool menu mobilekey mount onetoone option ppp package passthrumac priv proxyarpnet " .
+ "hosts group interface_array item key lbpool menu mobilekey mount onetoone option ppp package passthrumac phase1 phase2 priv proxyarpnet " .
"queue pages pipe route row rule schedule service servernat servers serversdisabled earlyshellcmd shellcmd staticmap subqueue " .
"timerange tunnel user vip virtual_server vlan winsserver ntpserver wolentry widget depends_on_package gateway_item gateway_group");
return $ret;
OpenPOWER on IntegriCloud