- Add proper support for using hostnames for the remote IPsec gateway.

- Make IPsec reloading granular, this resolves the long standing issue
that a IPsec reload will cause all tunnels to drop.
- Change IPsec edit screen description for remote gateway that a IP
address or hostname is allowed here. We already accepted hostnames
before.
- Add /etc/rc.newipsecdns, when a hostname changes IP we invoke this
script to remove the old tunnel and setup the new one.
This commit is contained in:
Seth Mos 2009-01-15 09:00:30 +00:00
parent e07ff7c0a5
commit bf92bc791d
9 changed files with 501 additions and 162 deletions

View File

@ -1434,7 +1434,7 @@ function find_interface_ip($interface, $flush = false) {
}
function guess_interface_from_ip($ipaddress) {
$ret = exec_command("/usr/bin/netstat -rn | /usr/bin/awk '/^{$ipaddress}/ {print \$6}'");
$ret = exec_command("/usr/bin/netstat -rn | /usr/bin/awk '/^{$ipaddress}/ {print $6}'");
if(empty($ret)) {
return false;
}
@ -3740,4 +3740,97 @@ function safe_write_file($file, $content, $force_binary) {
return true;
}
/* Write out all the found IP addresses to a file
* so we can compare it on change */
function add_hostname_to_watch($hostname) {
if(!is_dir("/var/db/dnscache")) {
mkdir("/var/db/dnscache");
}
if((is_fqdn($hostname)) && (!is_ipaddr($hostname))) {
$domrecords = array();
$domips = array();
exec("host -t A $hostname", $domrecords, $rethost);
if($rethost == 0) {
foreach($domrecords as $domr) {
$doml = explode(" ", $domr);
$domip = $doml[3];
/* fill array with domain ip addresses */
if(is_ipaddr($domip)) {
$domips[] = $domip;
}
}
}
sort($domips);
$contents = "";
if(! empty($domips)) {
foreach($domips as $ip) {
$contents .= "$ip\n";
}
}
file_put_contents("/var/db/dnscache/$hostname", $contents);
}
}
/* Compare the current hostname DNS to the DNS cache we made
* if it has changed we return the old records
* if no change we return true */
function compare_hostname_to_dnscache($hostname) {
if(!is_dir("/var/db/dnscache")) {
mkdir("/var/db/dnscache");
}
$hostname = trim($hostname);
if(is_readable("/var/db/dnscache/{$hostname}")) {
$oldcontents = file_get_contents("/var/db/dnscache/{$hostname}");
} else {
$oldcontents = "";
}
if((is_fqdn($hostname)) && (!is_ipaddr($hostname))) {
$domrecords = array();
$domips = array();
exec("host -t A $hostname", $domrecords, $rethost);
if($rethost == 0) {
foreach($domrecords as $domr) {
$doml = explode(" ", $domr);
$domip = $doml[3];
/* fill array with domain ip addresses */
if(is_ipaddr($domip)) {
$domips[] = $domip;
}
}
}
sort($domips);
$contents = "";
if(! empty($domips)) {
foreach($domips as $ip) {
$contents .= "$ip\n";
}
}
}
if(trim($oldcontents) != trim($contents)) {
log_error("DNSCACHE: Found old IP {$oldcontents} and new IP {$contents}");
return ($oldcontents);
} else {
return false;
}
}
function is_fqdn($fqdn) {
$hostname = false;
if(preg_match("/[-A-Z0-9\.]+\.[-A-Z0-9\.]+/i", $fqdn)) {
$hostname = true;
}
if(preg_match("/\.\./", $fqdn)) {
$hostname = false;
}
if(preg_match("/^\./i", $fqdn)) {
$hostname = false;
}
if(preg_match("/\//i", $fqdn)) {
$hostname = false;
}
return($hostname);
}
?>

View File

@ -566,4 +566,24 @@ function mac_format($clientmac) {
}
}
?>
function resolve_retry($hostname, $retries = 5) {
if (is_ipaddr($hostname))
return $hostname;
for ($i = 0; $i < $retries; $i++) {
$ip = gethostbyname($hostname);
if ($ip && $ip != $hostname) {
/* success */
return $ip;
}
sleep(1);
}
return false;
}
?>

View File

@ -104,19 +104,6 @@ function vpn_ipsec_configure($ipchg = false) {
unlink_if_exists("/var/db/ipsecpinghosts");
touch("/var/db/ipsecpinghosts");
if($g['booting'] == true) {
/* determine if we should load the via padlock module */
$dmesg_boot = `cat /var/log/dmesg.boot | grep CPU`;
if(stristr($dmesg_boot, "ACE") == true) {
//echo "Enabling [VIA Padlock] ...";
//mwexec("/sbin/kldload padlock");
//mwexec("/sbin/sysctl net.inet.ipsec.crypto_support=1");
//mwexec("/usr/local/sbin/setkey -F");
//mwexec("/usr/local/sbin/setkey -FP");
//echo " done.\n";
}
}
if(isset($config['ipsec']['preferredoldsa'])) {
mwexec("/sbin/sysctl net.key.preferred_oldsa=0");
} else {
@ -143,6 +130,8 @@ function vpn_ipsec_configure($ipchg = false) {
/* kill racoon */
mwexec("/usr/bin/killall racoon", true);
killbypid("{$g['varrun_path']}/dnswatch-ipsec.pid");
/* wait for process to die */
sleep(2);
@ -164,7 +153,7 @@ function vpn_ipsec_configure($ipchg = false) {
if (isset($ipseccfg['enable'])) {
/* fastforwarding is not compatible with ipsec tunnels */
system("/sbin/sysctl net.inet.ip.fastforwarding=0 >/dev/null 2>&1");
mwexec("/sbin/sysctl net.inet.ip.fastforwarding=0");
if (!$curwanip) {
/* IP address not configured yet, exit */
@ -180,6 +169,9 @@ function vpn_ipsec_configure($ipchg = false) {
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 */
@ -200,30 +192,47 @@ function vpn_ipsec_configure($ipchg = false) {
continue;
$ep = vpn_endpoint_determine($tunnel, $curwanip);
/* 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']);
add_hostname_to_watch($tunnel['remote-gateway']);
if (!$rgip) {
log_error("Could not deterimine VPN endpoint for {$tunnel['descr']}");
continue;
}
} else {
$rgip = $tunnel['remote-gateway'];
}
$rgmap[$tunnel['remote-gateway']] = $rgip;
if (!$ep) {
log_error("Could not deterimine VPN endpoint for {$tunnel['descr']}");
continue;
}
vpn_localnet_determine($tunnel['local-subnet'], $sa, $sn);
if(is_domain($tunnel['remote-gateway'])) {
$tmp = gethostbyname($tunnel['remote-gateway']);
if($tmp)
if($tmp) {
$tunnel['remote-gateway'] = $tmp;
}
}
/* add entry to host pinger */
if ($tunnel['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']);
}
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 = $tunnel['pinghost'];
fwrite($pfd, "$srcip|$dstip|3\n");
fclose($pfd);
@ -287,7 +296,10 @@ function vpn_ipsec_configure($ipchg = false) {
return 1;
}
$racoonconf = "";
$racoonconf = "# This file is automatically generated. Do not edit\n";
$racoonconf .= "listen {\n";
$racoonconf .= " adminsock \"/var/run/racoon.sock\" \"root\" \"wheel\" 0660;\n";
$racoonconf .= "}\n";
$racoonconf .= "path pre_shared_key \"{$g['varetc_path']}/psk.txt\";\n\n";
$racoonconf .= "path certificate \"{$g['varetc_path']}\";\n\n";
@ -322,6 +334,10 @@ function vpn_ipsec_configure($ipchg = false) {
if (isset($tunnel['disabled']))
continue;
$rgip = $rgmap[$tunnel['remote-gateway']];
if (!$rgip)
continue;
$ep = vpn_endpoint_determine($tunnel, $curwanip);
if (!$ep)
continue;
@ -411,11 +427,11 @@ EOD;
}
}
$racoonconf .= <<<EOD
remote {$tunnel['remote-gateway']} \{
remote {$rgmap[$tunnel['remote-gateway']]} \{
exchange_mode {$tunnel['p1']['mode']};
my_identifier {$myidentt}{$myident};
{$certline}
peers_identifier address {$tunnel['remote-gateway']};
peers_identifier address {$rgmap[$tunnel['remote-gateway']]};
initial_contact on;
#dpd_delay 120; # DPD poll every 120 seconds
ike_frag on;
@ -585,7 +601,12 @@ EOD;
foreach ($ipseccfg['tunnel'] as $tunnel) {
if (isset($tunnel['disabled']))
continue;
$pskconf .= "{$tunnel['remote-gateway']} {$tunnel['p1']['pre-shared-key']}\n";
$rgip = $rgmap[$tunnel['remote-gateway']];
if (!$rgip)
continue;
$pskconf .= "{$rgip} {$tunnel['p1']['pre-shared-key']}\n";
}
}
@ -601,31 +622,41 @@ EOD;
chmod("{$g['varetc_path']}/psk.txt", 0600);
if(is_process_running("racoon")) {
/* flush SPD entries */
mwexec("/usr/local/sbin/setkey -FP");
log_error("IPSEC: Send a reload signal to the IPsec process");
sleep("0.1");
mwexec("/usr/local/sbin/setkey -F");
/* load SPD */
sleep("0.1");
mwexec("/usr/local/sbin/setkey -f {$g['varetc_path']}/spd.conf");
/* We are already online, reload */
sleep("0.1");
mwexec("/usr/bin/killall -HUP racoon", true);
mwexec("/usr/local/sbin/racoonctl -s /var/run/racoon.sock reload-config", false);
// mwexec("/usr/bin/killall -HUP racoon", false);
} else {
/* flush SA + SPD entries */
mwexec("/usr/local/sbin/setkey -FP");
mwexec("/usr/local/sbin/setkey -FP", false);
sleep("0.1");
mwexec("/usr/local/sbin/setkey -F");
mwexec("/usr/local/sbin/setkey -F", false);
sleep("0.1");
/* start racoon */
mwexec("/usr/local/sbin/racoon -f {$g['varetc_path']}/racoon.conf");
mwexec("/usr/local/sbin/racoon -f {$g['varetc_path']}/racoon.conf", false);
sleep("0.1");
/* load SPD */
mwexec("/usr/local/sbin/setkey -f {$g['varetc_path']}/spd.conf");
mwexec("/usr/local/sbin/setkey -f {$g['varetc_path']}/spd.conf", false);
/* We are already online, reload */
sleep("0.1");
mwexec("/usr/bin/killall -HUP racoon", true);
mwexec("/usr/bin/killall -HUP racoon", false);
}
/* 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);
killbypid("{$g['varrun_path']}/dnswatch-ipsec.pid");
mwexec("/usr/local/sbin/dnswatch {$g['varrun_path']}/dnswatch-ipsec.pid $interval " .
escapeshellarg("/etc/rc.newipsecdns") . $hostnames, false);
}
}
}
@ -1086,9 +1117,6 @@ function vpn_ipsec_force_reload() {
$ipseccfg = $config['ipsec'];
/* kill any ipsec communications regardless when we are invoked */
mwexec("/sbin/ifconfig enc0 down");
/* kill racoon */
mwexec("/usr/bin/killall racoon", true);
@ -1109,4 +1137,190 @@ function vpn_ipsec_force_reload() {
}
/* Walk the tunnels for hostname endpoints. If the hostnames
* resolve to a different IP now compared to the DNS cache
* we reload the policies if the endpoint has changed */
function vpn_ipsec_refresh_policies() {
global $config;
global $g;
$ipseccfg = $config['ipsec'];
if (! isset($ipseccfg['enable'])) {
return true;
}
/* Walk the Ipsec tunnel array */
if (is_array($ipseccfg['tunnel']) && count($ipseccfg['tunnel'])) {
foreach ($ipseccfg['tunnel'] as $tunnel) {
if (isset($tunnel['disabled'])) {
continue;
}
if (is_ipaddr($tunnel['remote-gateway'])) {
continue;
}
if (!is_ipaddr($tunnel['remote-gateway'])) {
$dnscache = compare_hostname_to_dnscache($tunnel['remote-gateway']);
$dnscache = trim($dnscache);
/* we should have the old IP addresses in the dnscache now */
if($dnscache <> "") {
$oldtunnel = $tunnel;
$oldtunnel['remote-gateway'] = trim($dnscache);
reload_tunnel_spd_policy ($tunnel, $oldtunnel);
}
}
}
}
/* process all generated spd.conf files from tmp which are left behind
* behind by either changes of dynamic tunnels or manual edits
* scandir() is only available in PHP5 */
$tmpfiles = array();
$dh = opendir($g['tmp_path']);
while (false !== ($filename = readdir($dh))) {
$tmpfiles[] = $filename;
}
sort($tmpfiles);
foreach($tmpfiles as $tmpfile) {
if(preg_match("/^spd.conf./", $tmpfile)) {
$ret = mwexec("/usr/local/sbin/setkey -f {$g['tmp_path']}/{$tmpfile} 2>&1", false);
if($ret == 0) {
unlink("{$g['tmp_path']}/{$tmpfile}");
} else {
rename("{$g['tmp_path']}/{$tmpfile}", ("{$g['tmp_path']}/failed.{$tmpfile}"));
}
unlink("{$g['tmp_path']}/{$tmpfile}");
}
}
}
function reload_tunnel_spd_policy($tunnel, $oldtunnel) {
global $config;
global $g;
/* if we are not passed a old tunnel array we create one */
if(empty($oldtunnel)) {
$oldtunnel = $tunnel;
}
$curwanip = get_current_wan_address();
$sad_arr = return_ipsec_sad_array();
$ep = vpn_endpoint_determine($tunnel, $curwanip);
vpn_localnet_determine($tunnel['local-subnet'], $sa, $sn);
/* make sure we pass the oldtunnel array with a IP for the remote gw */
$oldgw = trim($oldtunnel['remote-gateway']);
$oldep = vpn_endpoint_determine($oldtunnel, $curwanip);
vpn_localnet_determine($oldtunnel['local-subnet'], $oldsa, $oldsn);
/* 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'])) {
$rgip = resolve_retry($tunnel['remote-gateway']);
add_hostname_to_watch($tunnel['remote-gateway']);
if (!$rgip) {
log_error("Could not determine VPN endpoint for {$tunnel['descr']}");
return false;
}
} else {
$rgip = $tunnel['remote-gateway'];
}
if (!$ep) {
log_error("Could not determine VPN endpoint for {$tunnel['descr']}");
return false;
}
$spdconf = "";
/* Delete old SPD policies if there are changes between the old and new */
if(($tunnel != $oldtunnel) && (is_ipaddr($oldgw))) {
$spdconf .= "spddelete {$oldsa}/{$oldsn} " .
"{$oldtunnel['remote-subnet']} any -P out ipsec " .
"{$oldtunnel['p2']['protocol']}/tunnel/{$oldep}-" .
"{$oldgw}/unique;\n";
$spdconf .= "spddelete {$oldtunnel['remote-subnet']} " .
"{$oldsa}/{$oldsn} any -P in ipsec " .
"{$oldtunnel['p2']['protocol']}/tunnel/{$oldgw}-" .
"{$oldep}/unique;\n";
/* zap any existing SA entries */
foreach($sad_arr as $sad) {
if(($sad['dst'] == $oldep) && ($sad['src'] == $oldgw)) {
$spdconf .= "delete {$oldep} {$oldgw} {$tunnel['p2']['protocol']} 0x{$sad['spi']};\n";
}
if(($sad['src'] == $oldep) && ($sad['dst'] == $oldgw)) {
$spdconf .= "delete {$oldgw} {$oldep} {$tunnel['p2']['protocol']} 0x{$sad['spi']};\n";
}
}
}
/* Create new SPD entries for the new configuration */
/* zap any existing SA entries beforehand */
foreach($sad_arr as $sad) {
if(($sad['dst'] == $ep) && ($sad['src'] == $rgip)) {
$spdconf .= "delete {$ep} {$rgip} {$tunnel['p2']['protocol']} 0x{$sad['spi']};\n";
}
if(($sad['src'] == $ep) && ($sad['dst'] == $rgip)) {
$spdconf .= "delete {$rgip} {$ep} {$tunnel['p2']['protocol']} 0x{$sad['spi']};\n";
}
}
/* add new SPD policies to replace them */
$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";
log_error("IPSEC: Tunnel '{$tunnel['descr']}' has changed IP from '{$oldgw}' to '{$rgip}', reloading policy");
$now = time();
$spdfile = tempnam("{$g['tmp_path']}", "spd.conf.reload.{$now}.");
/* generate temporary spd.conf */
file_put_contents($spdfile, $spdconf);
return true;
}
/* Dump SAD database to array */
function return_ipsec_sad_array() {
/* query 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));
if ($i == 1) {
$cursa['proto'] = $linea[0];
$cursa['spi'] = substr($linea[2], strpos($linea[2], "x")+1, -1);
} else if ($i == 2) {
$cursa['ealgo'] = $linea[1];
} else if ($i == 3) {
$cursa['aalgo'] = $linea[1];
}
}
$i++;
}
if (is_array($cursa) && count($cursa))
$sad[] = $cursa;
pclose($fd);
}
return($sad);
}
?>

52
etc/rc.newipsecdns Executable file
View File

@ -0,0 +1,52 @@
#!/usr/local/bin/php -f
<?php
/*
$Id$
part of m0n0wall (http://m0n0.ch/wall)
Copyright (C) 2007 Manuel Kasper <mk@neon1.net>.
All rights reserved.
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.
*/
/* parse the configuration and include all functions used below */
require_once("config.inc");
require_once("functions.inc");
/* make sure to wait until the boot scripts have finished */
while (file_exists("{$g['varrun_path']}/booting")) {
sleep(1);
}
log_error("IPSEC: One or more IPSEC tunnel endpoints has changed IP. Refreshing.");
/* We will walk the list of hostnames found in the ipsec tunnel
* configuration. Since we are already triggered by dnswatch
* that a hostname has changed we can proceed to compare the
* new IP address with the old address from the DNS cache.
*/
vpn_ipsec_refresh_policies();
vpn_ipsec_configure();
?>

View File

@ -34,6 +34,50 @@ $pgtitle = "Status: IPsec";
require("guiconfig.inc");
include("head.inc");
function get_ipsec_tunnel_src($tunnel) {
global $g, $config, $sad;
$if = "WAN";
if ($tunnel['interface']) {
$if = $tunnel['interface'];
$realinterface = convert_friendly_interface_to_real_interface_name($if);
$interfaceip = find_interface_ip($realinterface);
}
return $interfaceip;
}
function output_ipsec_tunnel_status($tunnel) {
global $g, $config, $sad;
$if = "WAN";
$interfaceip = get_ipsec_tunnel_src($tunnel);
$foundsrc = false;
$founddst = false;
if(!is_ipaddr($tunnel['remote-gateway']))
$tunnel['remote-gateway'] = resolve_retry($tunnel['remote-gateway']);
foreach($sad as $sa) {
if($sa['src'] == $interfaceip)
$foundsrc = true;
if($sa['dst'] == $tunnel['remote-gateway'])
$founddst = true;
}
if($foundsrc && $founddst) {
/* tunnel is up */
$iconfn = "pass";
} else {
/* tunnel is down */
$iconfn = "reject";
}
echo "<img src ='/themes/{$g['theme']}/images/icons/icon_{$iconfn}.gif'>";
}
/* query SAD */
$sad = return_ipsec_sad_array();
if (!is_array($config['ipsec']['tunnel'])) {
$config['ipsec']['tunnel'] = array();
}
?>
<body link="#0000CC" vlink="#0000CC" alink="#0000CC" onload="<?= $jsevents["body"]["onload"] ?>">
@ -54,47 +98,6 @@ include("head.inc");
</tr>
<tr>
<td>
<?php
/* query 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));
if ($i == 1) {
$cursa['proto'] = $linea[0];
$cursa['spi'] = substr($linea[2], strpos($linea[2], "x")+1, -1);
} else if ($i == 2) {
$cursa['ealgo'] = $linea[1];
} else if ($i == 3) {
$cursa['aalgo'] = $linea[1];
}
}
$i++;
}
if (is_array($cursa) && count($cursa))
$sad[] = $cursa;
pclose($fd);
}
if (!is_array($config['ipsec']['tunnel'])) {
$config['ipsec']['tunnel'] = array();
}
?>
<div id="mainarea">
<table class="tabcont" width="100%" border="0" cellpadding="6" cellspacing="0">
<?php if (count($sad)): ?>
@ -162,40 +165,3 @@ foreach ($config['ipsec']['tunnel'] as $ipsec) {
<?php include("fend.inc"); ?>
</body>
</html>
<?php
function get_ipsec_tunnel_src($tunnel) {
global $g, $config, $sad;
$if = "WAN";
if ($tunnel['interface']) {
$if = $tunnel['interface'];
$realinterface = convert_friendly_interface_to_real_interface_name($if);
$interfaceip = find_interface_ip($realinterface);
}
return $interfaceip;
}
function output_ipsec_tunnel_status($tunnel) {
global $g, $config, $sad;
$if = "WAN";
$interfaceip = get_ipsec_tunnel_src($tunnel);
$foundsrc = false;
$founddst = false;
foreach($sad as $sa) {
if($sa['src'] == $interfaceip)
$foundsrc = true;
if($sa['dst'] == $tunnel['remote-gateway'])
$founddst = true;
}
if($foundsrc && $founddst) {
/* tunnel is up */
$iconfn = "pass";
} else {
/* tunnel is down */
$iconfn = "reject";
}
echo "<img src ='/themes/{$g['theme']}/images/icons/icon_{$iconfn}.gif'>";
}
?>

View File

@ -66,38 +66,8 @@ if ($_GET['act'] == "del") {
}
/* query 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));
if ($i == 1) {
$cursa['proto'] = $linea[0];
$cursa['spi'] = substr($linea[2], strpos($linea[2], "x")+1, -1);
} else if ($i == 2) {
$cursa['ealgo'] = $linea[1];
} else if ($i == 3) {
$cursa['aalgo'] = $linea[1];
}
}
$i++;
}
if (is_array($cursa) && count($cursa))
$sad[] = $cursa;
pclose($fd);
}
$sad = return_ipsec_sad_array();
?>
<div id="mainarea">
<table class="tabcont" width="100%" border="0" cellpadding="6" cellspacing="0">

View File

@ -40,6 +40,9 @@ $search = array();
$replace = array();
if(is_array($config['ipsec']['tunnel']))
foreach($config['ipsec']['tunnel'] as $tunnel) {
if(!is_ipaddr($tunnel['remote-gateway']))
$tunnel['remote-gateway'] = resolve_retry($tunnel['remote-gateway']);
$gateway = "{$tunnel['remote-gateway']}";
$search[] = "/(racoon: )([A-Z:].*?)({$gateway}\[[0-9].+\]|{$gateway})(.*)/i";
$replace[] = "$1<strong>[{$tunnel['descr']}]</strong>: $2$3$4";

View File

@ -43,7 +43,10 @@ if ($_POST) {
if ($_POST['apply']) {
$retval = 0;
$retval = vpn_ipsec_refresh_policies();
$retval = vpn_ipsec_configure();
/* reload the filter in the background */
filter_configure();
$savemsg = get_std_save_message($retval);
if ($retval == 0) {
if (file_exists($d_ipsecconfdirty_path))
@ -59,6 +62,7 @@ if ($_POST) {
$retval = 0;
config_lock();
$retval = vpn_ipsec_refresh_policies();
$retval = vpn_ipsec_configure();
config_unlock();
/* reload the filter in the background */
@ -76,9 +80,11 @@ if ($_GET['act'] == "del") {
if ($a_ipsec[$_GET['id']]) {
/* remove static route if interface is not WAN */
if($a_ipsec[$_GET['id']]['interface'] <> "wan") {
mwexec("/sbin/route delete -host {$$a_ipsec[$_GET['id']]['remote-gateway']}");
$oldgw = resolve_retry($a_ipsec[$_GET['id']]['remote-gateway']);
mwexec("/sbin/route delete -host {$oldgw}");
}
unset($a_ipsec[$_GET['id']]);
vpn_ipsec_configure();
filter_configure();
write_config();
header("Location: vpn_ipsec.php");
@ -99,7 +105,8 @@ include("head.inc");
<?php if ($savemsg) print_info_box($savemsg); ?>
<?php if (file_exists($d_ipsecconfdirty_path)): ?><p>
<?php if ($pconfig['enable'])
print_info_box_np("The IPsec tunnel configuration has been changed.<br>You must apply the changes in order for them to take effect.");?><br>
print_info_box_np("The IPsec tunnel configuration has been changed.<br>You must apply the changes
in order for them to take effect.");?><br>
<?php endif; ?>
<table width="100%" border="0" cellpadding="0" cellspacing="0">
<tr><td class="tabnavtbl">

View File

@ -46,6 +46,7 @@ if (isset($_GET['dup'])) {
}
if (isset($id) && $a_ipsec[$id]) {
$oldipsecent = $a_ipsec[$id];
$pconfig['disabled'] = isset($a_ipsec[$id]['disabled']);
$pconfig['auto'] = isset($a_ipsec[$id]['auto']);
@ -61,6 +62,7 @@ if (isset($id) && $a_ipsec[$id]) {
list($pconfig['remotenet'],$pconfig['remotebits']) = explode("/", $a_ipsec[$id]['remote-subnet']);
$pconfig['remotegw'] = $a_ipsec[$id]['remote-gateway'];
$pconfig['p1mode'] = $a_ipsec[$id]['p1']['mode'];
if (isset($a_ipsec[$id]['p1']['myident']['myaddress']))
@ -209,13 +211,24 @@ if ($_POST) {
$ipsecent['interface'] = $pconfig['interface'];
pconfig_to_address($ipsecent['local-subnet'], $_POST['localnet'], $_POST['localnetmask']);
$ipsecent['remote-subnet'] = $_POST['remotenet'] . "/" . $_POST['remotebits'];
/* if the remote gateway changed and the interface is not WAN then remove route */
/* the vpn_ipsec_configure() handles adding the route */
if($_POST['interface'] <> "wan") {
if($ipsecent['remote-gateway'] <> $_POST['remotegw']) {
/* if the old endpoint is different from the new one we make sure to purge
* the old policy and add a new one. If the old endpoint IP is empty we
* only add new SPD entries. */
if(!is_ipaddr($oldipsecent['remote-gateway'])) {
$oldipsecent['remote-gateway'] = resolve_retry($oldipsecent['remote-gateway']);
}
if($ipsecent['remote-gateway'] <> $_POST['remotegw']) {
if(!is_ipaddr($ipsecent['remote-gateway'])) {
$ipsecent['remote-gateway'] = resolve_retry($ipsecent['remote-gateway']);
}
/* if the remote gateway changed and the interface is not WAN then remove route */
/* the vpn_ipsec_configure() handles adding the route */
if($_POST['interface'] <> "wan") {
mwexec("/sbin/route delete -host {$ipsecent['remote-gateway']}");
}
}
$ipsecent['remote-gateway'] = $_POST['remotegw'];
$ipsecent['p1']['mode'] = $_POST['p1mode'];
@ -261,6 +274,7 @@ if ($_POST) {
$a_ipsec[] = $ipsecent;
write_config();
reload_tunnel_spd_policy($ipsecent, $oldipsecent);
touch($d_ipsecconfdirty_path);
header("Location: vpn_ipsec.php");
@ -401,7 +415,7 @@ function methodsel_change() {
<td width="78%" class="vtable">
<?=$mandfldhtml;?><input name="remotegw" type="text" class="formfld" id="remotegw" size="20" value="<?=$pconfig['remotegw'];?>">
<br>
Enter the public IP address of the remote gateway</td>
Enter the public IP address or hostname of the remote gateway</td>
</tr>
<tr>
<td width="22%" valign="top" class="vncell">Description</td>