summaryrefslogtreecommitdiffstats
path: root/etc/inc/vpn.inc
diff options
context:
space:
mode:
authorScott Ullrich <sullrich@pfsense.org>2004-11-07 03:06:49 +0000
committerScott Ullrich <sullrich@pfsense.org>2004-11-07 03:06:49 +0000
commit5b237745003431d487de361ca0980a467ee2f5d5 (patch)
tree0a29f0237f9e8e536112f9fc816e7a52bbc19691 /etc/inc/vpn.inc
downloadpfsense-5b237745003431d487de361ca0980a467ee2f5d5.zip
pfsense-5b237745003431d487de361ca0980a467ee2f5d5.tar.gz
Initial revision
Diffstat (limited to 'etc/inc/vpn.inc')
-rw-r--r--etc/inc/vpn.inc559
1 files changed, 559 insertions, 0 deletions
diff --git a/etc/inc/vpn.inc b/etc/inc/vpn.inc
new file mode 100644
index 0000000..b73af46
--- /dev/null
+++ b/etc/inc/vpn.inc
@@ -0,0 +1,559 @@
+<?php
+/*
+ vpn.inc
+ part of m0n0wall (http://m0n0.ch/wall)
+
+ Copyright (C) 2003-2004 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.
+*/
+
+/* include all configuration functions */
+require_once("functions.inc");
+
+function vpn_ipsec_configure($ipchg = false) {
+ global $config, $g;
+
+ $curwanip = get_current_wan_address();
+
+ $syscfg = $config['system'];
+ $ipseccfg = $config['ipsec'];
+ $lancfg = $config['interfaces']['lan'];
+ $lanip = $lancfg['ipaddr'];
+ $lansa = gen_subnet($lancfg['ipaddr'], $lancfg['subnet']);
+ $lansn = $lancfg['subnet'];
+
+ if ($g['booting']) {
+ if (!isset($ipseccfg['enable']))
+ return 0;
+
+ echo "Configuring IPsec VPN... ";
+ } else {
+ /* kill racoon */
+ killbypid("{$g['varrun_path']}/racoon.pid");
+
+ /* wait for process to die */
+ sleep(2);
+
+ /* send a SIGKILL to be sure */
+ sigkillbypid("{$g['varrun_path']}/racoon.pid", "KILL");
+ }
+
+ /* flush SPD and SAD */
+ mwexec("/usr/sbin/setkey -FP");
+ mwexec("/usr/sbin/setkey -F");
+
+ /* prefer old SAs only for 30 seconds, then use the new one */
+ mwexec("/sbin/sysctl -w net.key.preferred_oldsa=-30");
+
+ if (isset($ipseccfg['enable'])) {
+
+ if (!$curwanip) {
+ /* IP address not configured yet, exit */
+ if ($g['booting'])
+ echo "done\n";
+ return 0;
+ }
+
+ if ((is_array($ipseccfg['tunnel']) && count($ipseccfg['tunnel'])) ||
+ isset($ipseccfg['mobileclients']['enable'])) {
+
+ 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;
+ }
+
+ $spdconf = "";
+
+ $spdconf .= "spdadd {$lansa}/{$lansn} {$lanip}/32 any -P in none;\n";
+ $spdconf .= "spdadd {$lanip}/32 {$lansa}/{$lansn} any -P out none;\n";
+
+ foreach ($ipseccfg['tunnel'] as $tunnel) {
+
+ if (isset($tunnel['disabled']))
+ continue;
+
+ $ep = vpn_endpoint_determine($tunnel, $curwanip);
+ if (!$ep)
+ continue;
+
+ vpn_localnet_determine($tunnel['local-subnet'], $sa, $sn);
+
+ $spdconf .= "spdadd {$sa}/{$sn} " .
+ "{$tunnel['remote-subnet']} any -P out ipsec " .
+ "{$tunnel['p2']['protocol']}/tunnel/{$ep}-" .
+ "{$tunnel['remote-gateway']}/unique;\n";
+
+ $spdconf .= "spdadd {$tunnel['remote-subnet']} " .
+ "{$sa}/{$sn} any -P in ipsec " .
+ "{$tunnel['p2']['protocol']}/tunnel/{$tunnel['remote-gateway']}-" .
+ "{$ep}/unique;\n";
+ }
+
+ fwrite($fd, $spdconf);
+ fclose($fd);
+
+ /* load SPD */
+ mwexec("/usr/sbin/setkey -c < {$g['varetc_path']}/spd.conf");
+ }
+
+ /* generate racoon.conf */
+ $fd = fopen("{$g['varetc_path']}/racoon.conf", "w");
+ if (!$fd) {
+ printf("Error: cannot open racoon.conf in vpn_ipsec_configure().\n");
+ return 1;
+ }
+
+ $racoonconf = "path pre_shared_key \"{$g['varetc_path']}/psk.txt\";\n\n";
+
+ if (is_array($ipseccfg['tunnel']) && count($ipseccfg['tunnel']))
+ foreach ($ipseccfg['tunnel'] as $tunnel) {
+
+ if (isset($tunnel['disabled']))
+ continue;
+
+ $ep = vpn_endpoint_determine($tunnel, $curwanip);
+ if (!$ep)
+ continue;
+
+ vpn_localnet_determine($tunnel['local-subnet'], $sa, $sn);
+
+ if (isset($tunnel['p1']['myident']['myaddress'])) {
+ $myidentt = "address";
+ $myident = $ep;
+ } 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'];
+ }
+
+ $racoonconf .= <<<EOD
+remote {$tunnel['remote-gateway']} \{
+ exchange_mode {$tunnel['p1']['mode']};
+ my_identifier {$myidentt} "{$myident}";
+ peers_identifier address {$tunnel['remote-gateway']};
+ initial_contact on;
+ support_proxy on;
+ proposal_check obey;
+
+ proposal \{
+ encryption_algorithm {$tunnel['p1']['encryption-algorithm']};
+ hash_algorithm {$tunnel['p1']['hash-algorithm']};
+ authentication_method pre_shared_key;
+ 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 address {$sa}/{$sn} any address {$tunnel['remote-subnet']} any \{
+ encryption_algorithm {$p2ealgos};
+ authentication_algorithm {$p2halgos};
+ compression_algorithm deflate;
+
+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";
+ }
+
+ /* mobile clients? */
+ if (isset($ipseccfg['mobileclients']['enable'])) {
+
+ $tunnel = $ipseccfg['mobileclients'];
+
+ 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'];
+ }
+
+ $racoonconf .= <<<EOD
+remote anonymous \{
+ exchange_mode {$tunnel['p1']['mode']};
+ my_identifier {$myidentt} "{$myident}";
+ initial_contact 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 pre_shared_key;
+ 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};
+ compression_algorithm deflate;
+
+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";
+ }
+
+ fwrite($fd, $racoonconf);
+ fclose($fd);
+
+ /* 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($ipseccfg['tunnel'])) {
+ foreach ($ipseccfg['tunnel'] as $tunnel) {
+ if (isset($tunnel['disabled']))
+ continue;
+ $pskconf .= "{$tunnel['remote-gateway']} {$tunnel['p1']['pre-shared-key']}\n";
+ }
+ }
+
+ /* add PSKs for mobile clients */
+ if (is_array($ipseccfg['mobilekey'])) {
+ foreach ($ipseccfg['mobilekey'] as $key) {
+ $pskconf .= "{$key['ident']} {$key['pre-shared-key']}\n";
+ }
+ }
+
+ fwrite($fd, $pskconf);
+ fclose($fd);
+ chmod("{$g['varetc_path']}/psk.txt", 0600);
+
+ /* start racoon */
+ mwexec("/usr/local/sbin/racoon -d -f {$g['varetc_path']}/racoon.conf");
+
+ 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 1 -S {$srchost} {$remotehost}");
+ }
+ }
+ }
+ }
+
+ if (!$g['booting']) {
+ /* reload the filter */
+ filter_configure();
+ }
+
+ if ($g['booting'])
+ echo "done\n";
+
+ return 0;
+}
+
+function vpn_pptpd_configure() {
+ global $config, $g;
+
+ $syscfg = $config['system'];
+ $pptpdcfg = $config['pptpd'];
+
+ if ($g['booting']) {
+ if (!$pptpdcfg['mode'] || ($pptpdcfg['mode'] == "off"))
+ return 0;
+
+ echo "Configuring PPTP VPN service... ";
+ } else {
+ /* kill mpd */
+ killbypid("{$g['varrun_path']}/mpd-vpn.pid");
+
+ /* wait for process to die */
+ sleep(2);
+
+ /* remove mpd.conf, if it exists */
+ unlink_if_exists("{$g['varetc_path']}/mpd-vpn/mpd.conf");
+ unlink_if_exists("{$g['varetc_path']}/mpd-vpn/mpd.links");
+ unlink_if_exists("{$g['varetc_path']}/mpd-vpn/mpd.secret");
+ }
+
+ /* make sure mpd-vpn directory exists */
+ if (!file_exists("{$g['varetc_path']}/mpd-vpn"))
+ mkdir("{$g['varetc_path']}/mpd-vpn");
+
+ switch ($pptpdcfg['mode']) {
+
+ case 'server':
+
+ /* write mpd.conf */
+ $fd = fopen("{$g['varetc_path']}/mpd-vpn/mpd.conf", "w");
+ if (!$fd) {
+ printf("Error: cannot open mpd.conf in vpn_pptpd_configure().\n");
+ return 1;
+ }
+
+ $mpdconf = <<<EOD
+pptpd:
+
+EOD;
+
+ for ($i = 0; $i < $g['n_pptp_units']; $i++) {
+ $mpdconf .= " load pt{$i}\n";
+ }
+
+ for ($i = 0; $i < $g['n_pptp_units']; $i++) {
+
+ $clientip = long2ip(ip2long($pptpdcfg['remoteip']) + $i);
+ $ngif = "ng" . ($i+1);
+
+ $mpdconf .= <<<EOD
+
+pt{$i}:
+ new -i {$ngif} pt{$i} pt{$i}
+ set ipcp ranges {$pptpdcfg['localip']}/32 {$clientip}/32
+ load pts
+
+EOD;
+ }
+
+ $mpdconf .= <<<EOD
+
+pts:
+ set iface disable on-demand
+ set iface enable proxy-arp
+ set iface enable tcpmssfix
+ set iface idle 1800
+ set iface up-script /usr/local/sbin/vpn-linkup
+ set iface down-script /usr/local/sbin/vpn-linkdown
+ set bundle enable multilink
+ set bundle enable crypt-reqd
+ set link yes acfcomp protocomp
+ set link no pap chap
+ set link enable chap-msv2
+ set link mtu 1460
+ set link keep-alive 10 60
+ set ipcp yes vjcomp
+ set bundle enable compression
+ set ccp yes mppc
+ set ccp yes mpp-e128
+ set ccp yes mpp-stateless
+
+EOD;
+
+ if (!isset($pptpdcfg['req128'])) {
+ $mpdconf .= <<<EOD
+ set ccp yes mpp-e40
+ set ccp yes mpp-e56
+
+EOD;
+ }
+
+ if (isset($config['dnsmasq']['enable'])) {
+ $mpdconf .= " set ipcp dns " . $config['interfaces']['lan']['ipaddr'];
+ if ($syscfg['dnsserver'][0])
+ $mpdconf .= " " . $syscfg['dnsserver'][0];
+ $mpdconf .= "\n";
+ } else if (is_array($syscfg['dnsserver']) && ($syscfg['dnsserver'][0])) {
+ $mpdconf .= " set ipcp dns " . join(" ", $syscfg['dnsserver']) . "\n";
+ }
+
+ if (isset($pptpdcfg['radius']['enable'])) {
+ $mpdconf .= <<<EOD
+ set radius server {$pptpdcfg['radius']['server']} "{$pptpdcfg['radius']['secret']}"
+ set radius retries 3
+ set radius timeout 10
+ set bundle enable radius-auth
+ set bundle disable radius-fallback
+
+EOD;
+
+ if (isset($pptpdcfg['radius']['accounting'])) {
+ $mpdconf .= <<<EOD
+ set bundle enable radius-acct
+
+EOD;
+ }
+ }
+
+ fwrite($fd, $mpdconf);
+ fclose($fd);
+
+ /* write mpd.links */
+ $fd = fopen("{$g['varetc_path']}/mpd-vpn/mpd.links", "w");
+ if (!$fd) {
+ printf("Error: cannot open mpd.links in vpn_pptpd_configure().\n");
+ return 1;
+ }
+
+ $mpdlinks = "";
+
+ for ($i = 0; $i < $g['n_pptp_units']; $i++) {
+ $mpdlinks .= <<<EOD
+
+pt{$i}:
+ set link type pptp
+ set pptp enable incoming
+ set pptp disable originate
+ set pptp disable windowing
+ set pptp self 127.0.0.1
+
+EOD;
+ }
+
+ fwrite($fd, $mpdlinks);
+ fclose($fd);
+
+ /* write mpd.secret */
+ $fd = fopen("{$g['varetc_path']}/mpd-vpn/mpd.secret", "w");
+ if (!$fd) {
+ printf("Error: cannot open mpd.secret in vpn_pptpd_configure().\n");
+ return 1;
+ }
+
+ $mpdsecret = "";
+
+ if (is_array($pptpdcfg['user'])) {
+ foreach ($pptpdcfg['user'] as $user)
+ $mpdsecret .= "{$user['name']} \"{$user['password']}\" {$user['ip']}\n";
+ }
+
+ fwrite($fd, $mpdsecret);
+ fclose($fd);
+ chmod("{$g['varetc_path']}/mpd-vpn/mpd.secret", 0600);
+
+ /* fire up mpd */
+ mwexec("/usr/local/sbin/mpd -b -d {$g['varetc_path']}/mpd-vpn -p {$g['varrun_path']}/mpd-vpn.pid pptpd");
+
+ break;
+
+ case 'redir':
+ break;
+ }
+
+ if (!$g['booting']) {
+ /* reload the filter */
+ filter_configure();
+ }
+
+ if ($g['booting'])
+ echo "done\n";
+
+ return 0;
+}
+
+function vpn_localnet_determine($adr, &$sa, &$sn) {
+ global $config, $g;
+
+ if (isset($adr)) {
+ if ($adr['network']) {
+ switch ($adr['network']) {
+ case 'lan':
+ $sn = $config['interfaces']['lan']['subnet'];
+ $sa = gen_subnet($config['interfaces']['lan']['ipaddr'], $sn);
+ break;
+ }
+ } else if ($adr['address']) {
+ list($sa,$sn) = explode("/", $adr['address']);
+ if (is_null($sn))
+ $sn = 32;
+ }
+ } else {
+ $sn = $config['interfaces']['lan']['subnet'];
+ $sa = gen_subnet($config['interfaces']['lan']['ipaddr'], $sn);
+ }
+}
+
+function vpn_endpoint_determine($tunnel, $curwanip) {
+
+ global $g, $config;
+
+ if ((!$tunnel['interface']) || ($tunnel['interface'] == "wan")) {
+ if ($curwanip)
+ return $curwanip;
+ else
+ return null;
+ } else if ($tunnel['interface'] == "lan") {
+ return $config['interfaces']['lan']['ipaddr'];
+ } else {
+ $oc = $config['interfaces'][$tunnel['interface']];
+
+ if (isset($oc['enable']) && $oc['if']) {
+ return $oc['ipaddr'];
+ }
+ }
+
+ return null;
+}
+
+?>
OpenPOWER on IntegriCloud