summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStig Thormodsrud <stig@vyatta.com>2007-12-19 18:09:06 -0800
committerStig Thormodsrud <stig@vyatta.com>2007-12-19 18:09:06 -0800
commit2b188e0c9ca392a7c54f4169378e523c355873c1 (patch)
tree0ac0524531ab4033af0da006cf39f8736b52beed
downloadvyatta-cfg-vpn-2b188e0c9ca392a7c54f4169378e523c355873c1.tar.gz
vyatta-cfg-vpn-2b188e0c9ca392a7c54f4169378e523c355873c1.zip
Port vpn cfg from fairfield to glendale.
-rw-r--r--AUTHORS1
-rw-r--r--COPYING27
-rw-r--r--ChangeLog0
-rw-r--r--Makefile.am22
-rw-r--r--NEWS1
-rw-r--r--README1
-rw-r--r--configure.ac30
-rw-r--r--debian/README6
-rwxr-xr-xdebian/autogen.sh37
-rw-r--r--debian/changelog6
-rw-r--r--debian/compat1
-rw-r--r--debian/control12
-rw-r--r--debian/copyright34
-rw-r--r--debian/docs2
-rw-r--r--debian/linda1
-rw-r--r--debian/lintian2
-rwxr-xr-xdebian/rules101
-rw-r--r--debian/vyatta-cfg-vpn.postinst.in17
-rwxr-xr-xscripts/VyattaVPNUtil.pm132
-rwxr-xr-xscripts/vpn-config.pl1059
-rw-r--r--templates/vpn/ipsec/copy-tos/node.def4
-rw-r--r--templates/vpn/ipsec/esp-group/node.def4
-rw-r--r--templates/vpn/ipsec/esp-group/node.tag/compression/node.def4
-rw-r--r--templates/vpn/ipsec/esp-group/node.tag/lifetime/node.def4
-rw-r--r--templates/vpn/ipsec/esp-group/node.tag/mode/node.def4
-rw-r--r--templates/vpn/ipsec/esp-group/node.tag/node.tag/encryption/node.def2
-rw-r--r--templates/vpn/ipsec/esp-group/node.tag/node.tag/hash/node.def2
-rw-r--r--templates/vpn/ipsec/esp-group/node.tag/pfs/node.def4
-rw-r--r--templates/vpn/ipsec/esp-group/node.tag/proposal/node.def4
-rw-r--r--templates/vpn/ipsec/esp-group/node.tag/proposal/node.tag/encryption/node.def4
-rw-r--r--templates/vpn/ipsec/esp-group/node.tag/proposal/node.tag/hash/node.def4
-rw-r--r--templates/vpn/ipsec/ike-group/node.def4
-rw-r--r--templates/vpn/ipsec/ike-group/node.tag/aggressive-mode/node.def4
-rw-r--r--templates/vpn/ipsec/ike-group/node.tag/dead-peer-detection/action/node.def4
-rw-r--r--templates/vpn/ipsec/ike-group/node.tag/dead-peer-detection/interval/node.def4
-rw-r--r--templates/vpn/ipsec/ike-group/node.tag/dead-peer-detection/node.def1
-rw-r--r--templates/vpn/ipsec/ike-group/node.tag/dead-peer-detection/timeout/node.def4
-rw-r--r--templates/vpn/ipsec/ike-group/node.tag/lifetime/node.def4
-rw-r--r--templates/vpn/ipsec/ike-group/node.tag/proposal/node.def4
-rw-r--r--templates/vpn/ipsec/ike-group/node.tag/proposal/node.tag/dh-group/node.def3
-rw-r--r--templates/vpn/ipsec/ike-group/node.tag/proposal/node.tag/encryption/node.def4
-rw-r--r--templates/vpn/ipsec/ike-group/node.tag/proposal/node.tag/hash/node.def4
-rw-r--r--templates/vpn/ipsec/ipsec-interfaces/interface/node.def3
-rw-r--r--templates/vpn/ipsec/ipsec-interfaces/node.def1
-rw-r--r--templates/vpn/ipsec/logging/facility/node.def6
-rw-r--r--templates/vpn/ipsec/logging/level/node.def3
-rw-r--r--templates/vpn/ipsec/logging/log-modes/node.def4
-rw-r--r--templates/vpn/ipsec/logging/node.def1
-rw-r--r--templates/vpn/ipsec/nat-networks/allowed-network/node.def3
-rw-r--r--templates/vpn/ipsec/nat-networks/allowed-network/node.tag/exclude/node.def3
-rw-r--r--templates/vpn/ipsec/nat-networks/node.def1
-rw-r--r--templates/vpn/ipsec/nat-traversal/node.def3
-rw-r--r--templates/vpn/ipsec/node.def1
-rw-r--r--templates/vpn/ipsec/site-to-site/node.def1
-rw-r--r--templates/vpn/ipsec/site-to-site/peer/node.def3
-rw-r--r--templates/vpn/ipsec/site-to-site/peer/node.tag/authentication/mode/node.def4
-rw-r--r--templates/vpn/ipsec/site-to-site/peer/node.tag/authentication/node.def1
-rw-r--r--templates/vpn/ipsec/site-to-site/peer/node.tag/authentication/pre-shared-secret/node.def3
-rw-r--r--templates/vpn/ipsec/site-to-site/peer/node.tag/authentication/rsa-key-name/node.def3
-rw-r--r--templates/vpn/ipsec/site-to-site/peer/node.tag/ike-group/node.def2
-rw-r--r--templates/vpn/ipsec/site-to-site/peer/node.tag/local-ip/node.def2
-rw-r--r--templates/vpn/ipsec/site-to-site/peer/node.tag/tunnel/node.def3
-rw-r--r--templates/vpn/ipsec/site-to-site/peer/node.tag/tunnel/node.tag/allow-nat-networks/node.def4
-rw-r--r--templates/vpn/ipsec/site-to-site/peer/node.tag/tunnel/node.tag/allow-public-networks/node.def4
-rw-r--r--templates/vpn/ipsec/site-to-site/peer/node.tag/tunnel/node.tag/esp-group/node.def2
-rw-r--r--templates/vpn/ipsec/site-to-site/peer/node.tag/tunnel/node.tag/local-subnet/node.def2
-rw-r--r--templates/vpn/ipsec/site-to-site/peer/node.tag/tunnel/node.tag/remote-subnet/node.def2
-rw-r--r--templates/vpn/node.def1
-rw-r--r--templates/vpn/rsa-keys/local-key/file/node.def3
-rw-r--r--templates/vpn/rsa-keys/local-key/node.def1
-rw-r--r--templates/vpn/rsa-keys/node.def1
-rw-r--r--templates/vpn/rsa-keys/rsa-key-name/node.def3
-rw-r--r--templates/vpn/rsa-keys/rsa-key-name/node.tag/rsa-key/node.def2
73 files changed, 1648 insertions, 0 deletions
diff --git a/AUTHORS b/AUTHORS
new file mode 100644
index 0000000..ee635b2
--- /dev/null
+++ b/AUTHORS
@@ -0,0 +1 @@
+eng@vyatta.com
diff --git a/COPYING b/COPYING
new file mode 100644
index 0000000..1d65a21
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,27 @@
+/*
+ * Package: vyatt-cfg-vpn
+ *
+ * **** License ****
+ * Version: VPL 1.0
+ *
+ * The contents of this file are subject to the Vyatta Public License
+ * Version 1.0 ("License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.vyatta.com/vpl
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * This code was originally developed by Vyatta, Inc.
+ * Portions created by Vyatta are Copyright (C) "YEAR" Vyatta, Inc.
+ * All Rights Reserved.
+ *
+ * Author: eng@vyatta.com
+ * Date: 2007
+ * Description: Vyatta VPN configuration templates/scripts
+ *
+ * **** End License ****
+ *
+ */
diff --git a/ChangeLog b/ChangeLog
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/ChangeLog
diff --git a/Makefile.am b/Makefile.am
new file mode 100644
index 0000000..b2e9fd6
--- /dev/null
+++ b/Makefile.am
@@ -0,0 +1,22 @@
+cfgdir = $(datadir)/vyatta-cfg/templates
+share_perl5dir = $(datarootdir)/perl5
+libudevdir = /lib/udev
+etcudevdir = /etc/udev
+initddir = /etc/init.d
+
+bin_SCRIPTS =
+sbin_SCRIPTS =
+sysconf_DATA =
+
+sbin_SCRIPTS += scripts/vpn-config.pl
+
+share_perl5_DATA = scripts/VyattaVPNUtil.pm
+
+
+cpiop = find . ! -regex '\(.*~\|.*\.bak\|.*\.swp\|.*\#.*\#\)' -print0 | \
+ cpio -0pd
+
+install-exec-hook:
+ mkdir -p $(DESTDIR)$(cfgdir)
+ cd templates; $(cpiop) $(DESTDIR)$(cfgdir)
+
diff --git a/NEWS b/NEWS
new file mode 100644
index 0000000..78fdaa6
--- /dev/null
+++ b/NEWS
@@ -0,0 +1 @@
+see http://www.vyatta.com/news/
diff --git a/README b/README
new file mode 100644
index 0000000..e34e593
--- /dev/null
+++ b/README
@@ -0,0 +1 @@
+This package has the Vyatta VPN configuration templates and scripts.
diff --git a/configure.ac b/configure.ac
new file mode 100644
index 0000000..7492451
--- /dev/null
+++ b/configure.ac
@@ -0,0 +1,30 @@
+# Process this file with autoconf to produce a configure script.
+AC_PREREQ(2.59)
+
+m4_define([VERSION_ID], [m4_esyscmd([
+ if test -f .version ; then
+ head -n 1 .version | tr -d \\n
+ else
+ echo -n 2.4
+ fi])])
+AC_INIT([vyatta-cfg-vpn], VERSION_ID, [vyatta-support@vyatta.com])
+
+test -n "$VYATTA_VERSION" || VYATTA_VERSION=$PACKAGE_VERSION
+
+AC_CONFIG_AUX_DIR([config])
+AM_INIT_AUTOMAKE([gnu no-dist-gzip dist-bzip2 subdir-objects])
+AC_PREFIX_DEFAULT([/opt/vyatta])
+
+AC_ARG_ENABLE([nostrip],
+ AC_HELP_STRING([--enable-nostrip],
+ [include -nostrip option during packaging]),
+ [NOSTRIP=-nostrip], [NOSTRIP=])
+
+AC_CONFIG_FILES(
+ [Makefile]
+ [debian/vyatta-cfg-vpn.postinst])
+
+AC_SUBST(NOSTRIP)
+
+AC_OUTPUT
+
diff --git a/debian/README b/debian/README
new file mode 100644
index 0000000..07672fd
--- /dev/null
+++ b/debian/README
@@ -0,0 +1,6 @@
+The Debian Package vyatta-cfg-vpn
+---------------------------------
+
+This package has the Vyatta VPN configuration templates and scripts.
+
+ -- Stig Thormodsrud <stig@vyatta.com> Wed, 19 Dec 2007
diff --git a/debian/autogen.sh b/debian/autogen.sh
new file mode 100755
index 0000000..ff125d1
--- /dev/null
+++ b/debian/autogen.sh
@@ -0,0 +1,37 @@
+#!/bin/sh
+
+
+if [ -d .git ] ; then
+# generate GNU/Debian format ChangeLog from git log
+
+ rm -f ChangeLog
+
+ if which git2cl >/dev/null ; then
+ git-log --pretty --numstat --summary | git2cl >> ChangeLog
+ else
+ git-log --pretty=short >> ChangeLog
+ fi
+
+# append repository reference
+
+ url=` git repo-config --get remote.origin.url`
+ test "x$url" = "x" && url=`pwd`
+
+ branch=`git-branch --no-color | sed '/^\* /!d; s/^\* //'`
+ test "x$branch" = "x" && branch=master
+
+ sha=`git log --pretty=oneline --no-color -n 1 | cut -c-8`
+ test "x$sha" = "x" && sha=00000000
+
+ echo "$url#$branch-$sha" >> ChangeLog
+
+fi
+
+rm -rf config
+rm -f aclocal.m4 config.guess config.statusconfig.sub configure INSTALL
+
+autoreconf --force --install
+
+rm -f config.sub config.guess
+ln -s /usr/share/misc/config.sub .
+ln -s /usr/share/misc/config.guess .
diff --git a/debian/changelog b/debian/changelog
new file mode 100644
index 0000000..f28246b
--- /dev/null
+++ b/debian/changelog
@@ -0,0 +1,6 @@
+vyatta-cfg-vpn (0.1) unstable; urgency=low
+
+ * Initial Release.
+
+ -- Stig Thormodsrud <stig@vyatta.com> Wed, 19 Dec 2007 14:09:00 -0700
+
diff --git a/debian/compat b/debian/compat
new file mode 100644
index 0000000..7ed6ff8
--- /dev/null
+++ b/debian/compat
@@ -0,0 +1 @@
+5
diff --git a/debian/control b/debian/control
new file mode 100644
index 0000000..d691405
--- /dev/null
+++ b/debian/control
@@ -0,0 +1,12 @@
+Source: vyatta-cfg-vpn
+Section: contrib/net
+Priority: extra
+Maintainer: Stig Thormodsrud <stig@vyatta.com>
+Build-Depends: debhelper (>= 5), autotools-dev
+Standards-Version: 3.7.2
+
+Package: vyatta-cfg-vpn
+Architecture: all
+Depends: perl, vyatta-cfg, openswan
+Description: Vyatta VPN configuration templates/scripts
+ Vyatta VPN configuration templates and scripts.
diff --git a/debian/copyright b/debian/copyright
new file mode 100644
index 0000000..38b2ea7
--- /dev/null
+++ b/debian/copyright
@@ -0,0 +1,34 @@
+This package was debianized by Stig Thormodsrud <stig@vyatta.com> on
+Wed Dec 19 14:00:24 PST 2007.
+
+It's original content from the GIT repository <http://vyatt.com/git/vyatta-cfg-vpn>
+
+Upstream Author:
+
+ <eng@vyatta.com>
+
+Copyright:
+
+ Copyright (C) 2007 Vyatta, Inc.
+ All Rights Reserved.
+
+License:
+
+ The contents of this package are subject to the Vyatta Public License
+ Version 1.0 ("License"); you may not use this file except in
+ compliance with the License. You may obtain a copy of the License at
+ http://www.vyatta.com/vpl
+
+ Software distributed under the License is distributed on an "AS IS"
+ basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ the License for the specific language governing rights and limitations
+ under the License.
+
+ This code was originally developed by Vyatta, Inc.
+ Portions created by Vyatta are Copyright (C) 2007 Vyatta, Inc.
+
+On Debian systems, the complete text of the GNU General
+Public License can be found in `/usr/share/common-licenses/GPL'.
+
+The Debian packaging is (C) 2007, An-Cheng Huang <ancheng@vyatta.com> and
+is licensed under the GPL, see above.
diff --git a/debian/docs b/debian/docs
new file mode 100644
index 0000000..50bd824
--- /dev/null
+++ b/debian/docs
@@ -0,0 +1,2 @@
+NEWS
+README
diff --git a/debian/linda b/debian/linda
new file mode 100644
index 0000000..0381d9d
--- /dev/null
+++ b/debian/linda
@@ -0,0 +1 @@
+Tag: file-in-opt
diff --git a/debian/lintian b/debian/lintian
new file mode 100644
index 0000000..cfd9d6e
--- /dev/null
+++ b/debian/lintian
@@ -0,0 +1,2 @@
+vyatta-cfg-vpn: file-in-unusual-dir
+vyatta-cfg-vpn: dir-or-file-in-opt
diff --git a/debian/rules b/debian/rules
new file mode 100755
index 0000000..f088c27
--- /dev/null
+++ b/debian/rules
@@ -0,0 +1,101 @@
+#!/usr/bin/make -f
+# -*- makefile -*-
+# Sample debian/rules that uses debhelper.
+# This file was originally written by Joey Hess and Craig Small.
+# As a special exception, when this file is copied by dh-make into a
+# dh-make output file, you may use that output file without restriction.
+# This special exception was added by Craig Small in version 0.37 of dh-make.
+
+# Uncomment this to turn on verbose mode.
+#export DH_VERBOSE=1
+
+
+# These are used for cross-compiling and for saving the configure script
+# from having to guess our platform (since we know it already)
+DEB_HOST_GNU_TYPE ?= $(shell dpkg-architecture -qDEB_HOST_GNU_TYPE)
+DEB_BUILD_GNU_TYPE ?= $(shell dpkg-architecture -qDEB_BUILD_GNU_TYPE)
+PACKAGE=vyatta-cfg-vpn
+PKGDIR=$(CURDIR)/debian/$(PACKAGE)
+
+CFLAGS = -Wall -g
+
+configure = ./configure
+configure += --host=$(DEB_HOST_GNU_TYPE)
+configure += --build=$(DEB_BUILD_GNU_TYPE)
+configure += --prefix=/opt/vyatta
+configure += --mandir=\$${prefix}/share/man
+configure += --infodir=\$${prefix}/share/info
+configure += CFLAGS="$(CFLAGS)"
+configure += LDFLAGS="-Wl,-z,defs"
+
+ifneq (,$(findstring noopt,$(DEB_BUILD_OPTIONS)))
+ CFLAGS += -O0
+else
+ CFLAGS += -O2
+endif
+
+configure: configure.ac Makefile.am
+ chmod +x debian/autogen.sh
+ debian/autogen.sh
+
+config.status: configure
+ dh_testdir
+ rm -f config.cache
+ $(configure)
+
+build: build-stamp
+
+build-stamp: config.status
+ dh_testdir
+ $(MAKE)
+ touch $@
+
+clean: clean-patched
+
+# Clean everything up, including everything auto-generated
+# at build time that needs not to be kept around in the Debian diff
+clean-patched:
+ dh_testdir
+ dh_testroot
+ if test -f Makefile ; then $(MAKE) clean distclean ; fi
+ rm -f build-stamp
+ rm -f config.status config.sub config.guess config.log
+ rm -f aclocal.m4 configure Makefile.in Makefile INSTALL
+ rm -rf config
+ dh_clean
+
+install: build
+ dh_testdir
+ dh_testroot
+ dh_clean -k
+ dh_installdirs
+
+ $(MAKE) DESTDIR=$(PKGDIR) install
+
+ install -D --mode=0644 debian/lintian $(PKGDIR)/usr/share/lintian/overrides/$(PACKAGE)
+ install -D --mode=0644 debian/linda $(PKGDIR)/usr/share/linda/overrides/$(PACKAGE)
+
+# Build architecture-independent files here.
+binary-indep: build install
+ dh_testdir
+ dh_testroot
+ dh_installchangelogs ChangeLog
+ dh_installdocs
+ dh_install
+ dh_installdebconf
+ dh_link
+ dh_strip
+ dh_compress
+ dh_fixperms
+ dh_installdeb
+ dh_gencontrol
+ dh_md5sums
+ dh_builddeb
+
+# Build architecture-dependent files here.
+binary-arch: build install
+# This is an architecture independent package
+# so; we have nothing to do by default.
+
+binary: binary-indep binary-arch
+.PHONY: build clean binary-indep binary-arch binary install
diff --git a/debian/vyatta-cfg-vpn.postinst.in b/debian/vyatta-cfg-vpn.postinst.in
new file mode 100644
index 0000000..e56e2e8
--- /dev/null
+++ b/debian/vyatta-cfg-vpn.postinst.in
@@ -0,0 +1,17 @@
+#!/bin/bash
+
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+sysconfdir=@sysconfdir@
+bindir=@bindir@
+sbindir=@sbindir@
+
+# remove init of daemons that we start/stop
+for init in openswan; do
+ update-rc.d -f ${init} remove >/dev/null
+done
+
+# Local Variables:
+# mode: shell-script
+# sh-indentation: 4
+# End:
diff --git a/scripts/VyattaVPNUtil.pm b/scripts/VyattaVPNUtil.pm
new file mode 100755
index 0000000..b31c0e5
--- /dev/null
+++ b/scripts/VyattaVPNUtil.pm
@@ -0,0 +1,132 @@
+#
+# Module: VyattaVPNUtil.pm
+#
+# **** License ****
+# Version: VPL 1.0
+#
+# The contents of this file are subject to the Vyatta Public License
+# Version 1.0 ("License"); you may not use this file except in
+# compliance with the License. You may obtain a copy of the License at
+# http://www.vyatta.com/vpl
+#
+# Software distributed under the License is distributed on an "AS IS"
+# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+# the License for the specific language governing rights and limitations
+# under the License.
+#
+# This code was originally developed by Vyatta, Inc.
+# Portions created by Vyatta are Copyright (C) 2005, 2006, 2007 Vyatta, Inc.
+# All Rights Reserved.
+#
+# Author: Marat
+# Date: 2007
+# Description:
+#
+# **** End License ****
+#
+
+package VyattaVPNUtil;
+
+use strict;
+use warnings;
+
+use VyattaConfig;
+
+
+use constant LOCAL_KEY_FILE_DEFAULT => '/opt/vyatta/etc/config/ipsec.d/rsa-keys/localhost.key';
+
+sub is_vpn_running {
+ return ( -e '/var/run/pluto/pluto.ctl');
+}
+
+sub rsa_get_local_key_file {
+ my $file = LOCAL_KEY_FILE_DEFAULT;
+
+ #
+ # Read configuration tree
+ #
+ my $vc = new VyattaConfig();
+ $vc->setLevel('vpn');
+ my $key_file_override = $vc->returnValue('rsa-keys local-key file');
+
+ #
+ # We'll assume validation for valid path/file was handled in the
+ # commit.
+ #
+ $file = $key_file_override if defined($key_file_override);
+
+ return $file
+}
+
+sub rsa_get_local_pubkey {
+ my ($file) = @_;
+
+ unless ( -r $file) {
+ return 0;
+ }
+
+ open(DAT, $file) || die("Could not open file $file!");
+ my @raw_data=<DAT>;
+ close(DAT);
+
+ foreach my $line (@raw_data) {
+ my $file_pubkey;
+ if (($file_pubkey) = ($line =~ m/\s+\#pubkey=(\S+)/)) {
+ return $file_pubkey;
+ }
+ }
+ return 0;
+}
+
+sub vpn_debug {
+ use POSIX;
+ my $timestamp = strftime("%Y%m%d-%H:%M.%S", localtime);
+ open LOG, ">>", "/var/log/vpn-debug.log";
+ print LOG "$timestamp: ", @_ , "\n";
+ close LOG;
+}
+
+sub vpn_log {
+ my ($msg) = @_;
+
+ open LOG, ">> /tmp/ipsec.log";
+
+ use POSIX;
+ my $timestamp = strftime("%Y-%m-%d %H:%M.%S", localtime);
+
+ print LOG "$timestamp\nLog: $msg\n";
+ close LOG;
+}
+
+sub vpn_system {
+ my ($cmdline) = @_;
+ vpn_debug("START $cmdline");
+ my $ret = system($cmdline);
+ if ($ret) {
+ vpn_debug("END ERROR $cmdline");
+ } else {
+ vpn_debug("END OK $cmdline");
+ }
+}
+
+sub enableICMP {
+ my ($enable) = @_;
+
+ opendir DIR, '/proc/sys/net/ipv4/conf/' or return undef;
+ my @nodes = grep !/^\./, readdir DIR;
+ closedir DIR;
+
+ foreach my $node (@nodes) {
+ my $OUT;
+ open OUT, ">/proc/sys/net/ipv4/conf/$node/accept_redirects" or return undef;
+ print OUT $enable;
+ close OUT;
+ open OUT, ">/proc/sys/net/ipv4/conf/$node/send_redirects" or return undef;
+ print OUT $enable;
+ close OUT;
+ }
+ return 1;
+}
+
+1;
+
diff --git a/scripts/vpn-config.pl b/scripts/vpn-config.pl
new file mode 100755
index 0000000..0e8f5fa
--- /dev/null
+++ b/scripts/vpn-config.pl
@@ -0,0 +1,1059 @@
+#!/usr/bin/perl -w
+#
+# Module: vpn-config.pl
+#
+# **** License ****
+# Version: VPL 1.0
+#
+# The contents of this file are subject to the Vyatta Public License
+# Version 1.0 ("License"); you may not use this file except in
+# compliance with the License. You may obtain a copy of the License at
+# http://www.vyatta.com/vpl
+#
+# Software distributed under the License is distributed on an "AS IS"
+# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+# the License for the specific language governing rights and limitations
+# under the License.
+#
+# This code was originally developed by Vyatta, Inc.
+# Portions created by Vyatta are Copyright (C) 2006, 2007 Vyatta, Inc.
+# All Rights Reserved.
+#
+# Authors: Justin Fletcher, Marat Nepomnyashy
+# Date: 2007
+# Description: Start Openswan VPN based on verified configuration
+#
+# **** End License ****
+#
+
+use strict;
+use lib "/opt/vyatta/share/perl5/";
+
+use constant IKELIFETIME_DEFAULT => 28800; # 8 hours
+use constant ESPLIFETIME_DEFAULT => 3600; # 1 hour
+use constant REKEYMARGIN_DEFAULT => 540; # 9 minutes
+use constant REKEYFUZZ_DEFAULT => 100;
+use constant INVALID_LOCAL_IP => 254;
+use constant VPN_MAX_PROPOSALS => 10;
+
+use VyattaVPNUtil;
+use Getopt::Long;
+
+my $changes_dir;
+my $newconfig_dir;
+my $config_file;
+my $secrets_file;
+my $init_script;
+GetOptions("changes_dir=s" => \$changes_dir, "newconfig_dir=s" => \$newconfig_dir, "config_file=s" => \$config_file, "secrets_file=s" => \$secrets_file, "init_script=s" => \$init_script);
+
+my $clustering_ip = 0;
+my $error = 0;
+my $genout;
+my $genout_secrets;
+
+$genout .= "# generated by $0\n\n";
+$genout_secrets .= "# generated by $0\n\n";
+
+
+#
+# Prepare VyattaConfig object
+#
+use VyattaConfig;
+my $vc = new VyattaConfig();
+my $vcVPN = new VyattaConfig();
+
+if (defined($changes_dir) && $changes_dir ne '') {
+ $vc->{_changes_only_dir_base} = $changes_dir;
+ $vcVPN->{_changes_only_dir_base} = $changes_dir;
+}
+if (defined($newconfig_dir) && $newconfig_dir ne '') {
+ $vc->{_new_config_dir_base} = $newconfig_dir;
+ $vcVPN->{_new_config_dir_base} = $newconfig_dir;
+}
+
+$genout .= "# using 'changes only' directory: $vcVPN->{_changes_only_dir_base}\n";
+$genout .= "# using 'new config' directory: $vcVPN->{_new_config_dir_base}\n\n";
+
+$genout_secrets .= "# using 'changes only' directory: $vcVPN->{_changes_only_dir_base}\n";
+$genout_secrets .= "# using 'new config' directory: $vcVPN->{_new_config_dir_base}\n\n";
+
+
+
+$vcVPN->setLevel('vpn');
+
+if ($vcVPN->exists('.')) {
+
+ #
+ # Check that ESP groups have been specified
+ #
+ my @esp_groups = $vcVPN->listNodes('ipsec esp-group');
+ if (@esp_groups == 0) {
+ $error = 1;
+ print STDERR "VPN configuration error. No ESP groups configured. At least one ESP group required.\n";
+ } else {
+ foreach my $esp_group (@esp_groups) {
+ my @esp_group_proposals = $vcVPN->listNodes("ipsec esp-group $esp_group proposal");
+ if (@esp_group_proposals == 0) {
+ $error = 1;
+ print STDERR "VPN configuration error. No proposals configured for ESP group \"$esp_group\". At least one proposal required.\n";
+ } elsif (@esp_group_proposals > VPN_MAX_PROPOSALS) {
+ $error = 1;
+ print STDERR 'VPN configuration error. A total of ' . @esp_group_proposals . " proposals have been configured for ESP group \"$esp_group\". The maximum proposals allowed for an ESP group is " . VPN_MAX_PROPOSALS . "\n";
+ } else {
+ foreach my $esp_group_proposal (@esp_group_proposals) {
+ my $esp_group_proposal_encryption = $vcVPN->returnValue("ipsec esp-group $esp_group proposal $esp_group_proposal encryption");
+ if (!defined($esp_group_proposal_encryption) || $esp_group_proposal_encryption eq "") {
+ $error = 1;
+ print STDERR "VPN configuration error. No encryption specified for ESP group \"$esp_group\" proposal $esp_group_proposal.\n";
+ }
+ my $esp_group_proposal_hash = $vcVPN->returnValue("ipsec esp-group $esp_group proposal $esp_group_proposal hash");
+ if (!defined($esp_group_proposal_hash) || $esp_group_proposal_hash eq "") {
+ $error = 1;
+ print STDERR "VPN configuration error. No hash specified for ESP group \"$esp_group\" proposal $esp_group_proposal.\n";
+ }
+ }
+ }
+ }
+ }
+
+
+ #
+ # Check that IKE groups have been specified
+ #
+ my @ike_groups = $vcVPN->listNodes('ipsec ike-group');
+ if (@ike_groups == 0) {
+ $error = 1;
+ print STDERR "VPN configuration error. No IKE groups configured. At least one IKE group required.\n";
+ } else {
+ foreach my $ike_group (@ike_groups) {
+ my @ike_group_proposals = $vcVPN->listNodes("ipsec ike-group $ike_group proposal");
+ if (@ike_group_proposals == 0) {
+ $error = 1;
+ print STDERR "VPN configuration error. No proposals configured for IKE group \"$ike_group\". At least one proposal required.\n";
+ } elsif (@ike_group_proposals > VPN_MAX_PROPOSALS) {
+ $error = 1;
+ print STDERR 'VPN configuration error. A total of ' . @ike_group_proposals . " proposals have been configured for IKE group \"$ike_group\". The maximum proposals allowed for an IKE group is " . VPN_MAX_PROPOSALS . "\n";
+ } else {
+ foreach my $ike_group_proposal (@ike_group_proposals) {
+ my $ike_group_proposal_encryption = $vcVPN->returnValue("ipsec ike-group $ike_group proposal $ike_group_proposal encryption");
+ if (!defined($ike_group_proposal_encryption) || $ike_group_proposal_encryption eq "") {
+ $error = 1;
+ print STDERR "VPN configuration error. No encryption specified for IKE group \"$ike_group\" proposal $ike_group_proposal.\n";
+ }
+ my $ike_group_proposal_hash = $vcVPN->returnValue("ipsec ike-group $ike_group proposal $ike_group_proposal hash");
+ if (!defined($ike_group_proposal_hash) || $ike_group_proposal_hash eq "") {
+ $error = 1;
+ print STDERR "VPN configuration error. No hash specified for IKE group \"$ike_group\" proposal $ike_group_proposal.\n";
+ }
+ }
+ }
+ }
+ }
+
+ {
+ #
+ # Check the local key file
+ #
+ my $local_key_file = $vcVPN->returnValue('rsa-keys local-key file');
+ if (defined($local_key_file) && $local_key_file ne '') {
+
+ # Sanity check the usr specified local_key_file
+ #
+ # 1). Must start with "/"
+ # 2). Only allow alpha-numeric, ".", "-", "_", or "/".
+ # 3). Don't allow "//"
+ # 4). Verify that it's not a directory
+ #
+ if ($local_key_file !~ /^\//) {
+ $error = 1;
+ print STDERR "VPN configuration error. Invalid local RSA key file path \"$local_key_file\". Does not start with a '/'.\n";
+ }
+ if ($local_key_file =~ /[^a-zA-Z0-9\.\-\_\/]/g) {
+ $error = 1;
+ print STDERR "VPN configuration error. Invalid local RSA key file path \"$local_key_file\". Contains a character that is not alpha-numeric and not '.', '-', '_', '/'.\n";
+ }
+ if ($local_key_file =~ /\/\//g) {
+ $error = 1;
+ print STDERR "VPN configuration error. Invalid local RSA key file path \"$local_key_file\". Contains string \"//\".\n";
+ }
+ if (-d $local_key_file) {
+ $error = 1;
+ print STDERR "VPN configuration error. Invalid local RSA key file path \"$local_key_file\". Path is a directory rather than a file.\n";
+ }
+
+ if ($error == 0) {
+ my $prev_local_key_file = $vcVPN->returnOrigValue('rsa-keys local-key file');
+ if (!defined($prev_local_key_file) || $prev_local_key_file eq '') {
+ $prev_local_key_file = VyattaVPNUtil::LOCAL_KEY_FILE_DEFAULT;
+ }
+ if ($local_key_file ne $prev_local_key_file) {
+ if (-r $prev_local_key_file && !(-e $local_key_file)) {
+ VyattaVPNUtil::vpn_debug "cp $prev_local_key_file $local_key_file";
+ my ($dirpath) = ($local_key_file =~ m#^(.*/)?.*#s);
+ my $rc = system("mkdir -p $dirpath");
+ if ($rc != 0) {
+ $error = 1;
+ print STDERR "VPN configuration error. Could not copy previous local RSA key file \"$prev_local_key_file\" to new local RSA key file \"$local_key_file\". Could not mkdir [$dirpath] $!\n";
+ } else {
+ $rc = system("cp $prev_local_key_file $local_key_file");
+ if ($rc != 0) {
+ $error = 1;
+ print STDERR "VPN configuration error. Could not copy previous local RSA key file \"$prev_local_key_file\" to new local RSA key file \"$local_key_file\". $!\n";
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ #
+ # Version 2
+ #
+ $genout .= "version 2.0\n";
+ $genout .= "\n";
+ $genout .= "config setup\n";
+
+ #
+ # Interfaces
+ #
+ my @interfaces = $vcVPN->returnValues('ipsec ipsec-interfaces interface');
+ my %vpn_interfaces = map { $_ => 1 } @interfaces;
+ if (@interfaces == 0) {
+ $error = 1;
+ print STDERR "VPN configuration error. No IPSEC interfaces specified.\n";
+ } else {
+ $genout .= "\tinterfaces=\"";
+ my $counter = 0;
+ foreach my $interface (@interfaces) {
+ if ($counter > 0) {
+ $genout .= ' ';
+ }
+ $genout .= "ipsec$counter=$interface";
+ ++$counter;
+ }
+ $genout .= "\"\n";
+ }
+
+ #
+ # NAT traversal
+ #
+ my $nat_traversal = $vcVPN->returnValue('ipsec nat-traversal');
+ if (defined($nat_traversal)) {
+ if ($nat_traversal eq 'enable') {
+ $genout .= "\tnat_traversal=yes\n";
+ } elsif ($nat_traversal eq 'disable') {
+ $genout .= "\tnat_traversal=no\n";
+ } elsif ($nat_traversal ne '') {
+ $error = 1;
+ print STDERR "VPN configuration error. Invalid value \"$nat_traversal\" specified for 'nat-traversal'. Only \"enable\" or \"disable\" accepted.\n";
+ }
+ }
+
+ #
+ # NAT networks
+ #
+ my @nat_networks = $vcVPN->listNodes('ipsec nat-networks allowed-network');
+ if (@nat_networks > 0) {
+ my $first_nat_net = 1;
+ foreach my $nat_network (@nat_networks) {
+ if ($first_nat_net) {
+ $genout .= "\tvirtual_private=\"\%v4:$nat_network";
+ $first_nat_net = 0;
+ } else {
+ $genout .= ",\%v4:$nat_network";
+ }
+
+ my @nat_network_excludes = $vcVPN->returnValues("ipsec nat-networks allowed-network $nat_network exclude");
+ foreach my $nat_network_exclude (@nat_network_excludes) {
+ $genout .= ",\%v4:\!$nat_network_exclude";
+ }
+ }
+ $genout .= "\"\n";
+ }
+
+ #
+ # copy-tos
+ #
+ my $copy_tos = $vcVPN->returnValue('ipsec copy-tos');
+ if (defined($copy_tos) && $copy_tos eq 'enable') {
+ $genout .= "\thidetos=no\n";
+ } else {
+ $genout .= "\thidetos=yes\n";
+ }
+
+ #
+ # Logging
+ #
+ my $facility = $vcVPN->returnValue('ipsec logging facility');
+ my $level = $vcVPN->returnValue('ipsec logging level');
+ if ((defined($facility) && $facility ne '') && (!defined($level) || $level eq '')) {
+ $error = 1;
+ print STDERR "VPN configuration error. VPN logging facility has been specified without the VPN logging level. One may not be specified without the other.\n";
+ } elsif ((!defined($facility) || $facility eq '') && (defined($level) && $level ne '')) {
+ $error = 1;
+ print STDERR "VPN configuration error. VPN logging level has been specified without the VPN logging facility. One may not be specified without the other.\n";
+ }
+
+ if (defined($level) and ($level eq "err")) {
+ $level = "error"; # This allows the cli to be consistent with syslog.
+ }
+ if (defined($facility) and defined($level)) {
+ $genout .= "\tsyslog=$facility.$level\n";
+ }
+
+ my @logmodes = $vcVPN->returnValues('ipsec logging log-modes');
+ if (@logmodes > 0) {
+ my $debugmode = '';
+ foreach my $mode (@logmodes) {
+ if ($mode eq "all") {
+ $debugmode = "all";
+ last;
+ }
+ if ($debugmode eq '') {
+ $debugmode = "$mode";
+ } else {
+ $debugmode .= " $mode";
+ }
+ }
+ $genout .= "\tplutodebug=\"$debugmode\"\n";
+ }
+
+ #
+ # Disable implicit connections
+ #
+ foreach my $conn (qw/clear clear-or-private private-or-clear private block packetdefault/) {
+ $genout .= "\n";
+ $genout .= "conn $conn\n";
+ $genout .= "\tauto=ignore\n";
+ }
+
+ #
+ # Connection configurations
+ #
+ my @peers = $vcVPN->listNodes('ipsec site-to-site peer');
+ if (@peers == 0) {
+ $error = 1;
+ print STDERR "VPN configuration error. No peers configured. At least one peer required.\n";
+ }
+ foreach my $peer (@peers) {
+ my $peer_ike_group = $vcVPN->returnValue("ipsec site-to-site peer $peer ike-group");
+ if (!defined($peer_ike_group) || $peer_ike_group eq '') {
+ $error = 1;
+ print STDERR "VPN configuration error. No IKE group specified for peer \"$peer\".\n";
+ } elsif (!$vcVPN->exists("ipsec ike-group $peer_ike_group")) {
+ $error = 1;
+ print STDERR "VPN configuration error. The IKE group \"$peer_ike_group\" specified for peer \"$peer\" has not been configured.\n";
+ }
+
+ my $lip = $vcVPN->returnValue("ipsec site-to-site peer $peer local-ip");
+ if (!defined($lip) || $lip eq "") {
+ $error = 1;
+ print STDERR "VPN configuration error. No local IP specified for peer \"$peer\"\n";
+ } else {
+ use VyattaMisc;
+ if (!VyattaMisc::isIPinInterfaces($vc, \%vpn_interfaces, $lip)) {
+
+ # Due to Bug 2411, the quick short-term fix
+ # as described in comment #4, is to assume
+ # that a peer local-ip not found in any of
+ # the interfaces on the system must then be
+ # a cluster IP. The commit then proceeds
+ # without errors, but the ipsec daemons are
+ # not started either. This will cause a
+ # silent failure if the IP mismatch is only
+ # due to a user error, but allows VPN/cluster
+ # interoperability.
+
+ vpn_log("The local-ip address $lip of peer \"$peer\" has not been configured in any of the local interfaces. Assuming it is configured in clustering.\n");
+ $clustering_ip = 1;
+
+# if (VyattaMisc::isClusterIP($vc, $lip)) {
+# # Verified that dealing with a cluster IP.
+# $clustering_ip = 1;
+# } else {
+# $error = 1;
+# print STDERR "VPN configuration error. Local IP $lip specified for peer \"$peer\" has not been configured in any of the ipsec interfaces or clustering.\n";
+# }
+
+ }
+ }
+
+ #
+ # Name connection by peer and tunnel
+ #
+ my @tunnels = $vcVPN->listNodes("ipsec site-to-site peer $peer tunnel");
+ if (@tunnels == 0) {
+ $error = 1;
+ print STDERR "VPN configuration error. No tunnels configured for peer \"$peer\". At least one tunnel required per peer.\n";
+ }
+ foreach my $tunnel (@tunnels) {
+
+ my $peer_tunnel_esp_group = $vcVPN->returnValue("ipsec site-to-site peer $peer tunnel $tunnel esp-group");
+ if (!defined($peer_tunnel_esp_group) || $peer_tunnel_esp_group eq '') {
+ $error = 1;
+ print STDERR "VPN configuration error. No ESP group specified for peer \"$peer\" tunnel $tunnel.\n";
+ } elsif (!$vcVPN->exists("ipsec esp-group $peer_tunnel_esp_group")) {
+ $error = 1;
+ print STDERR "VPN configuration error. The ESP group \"$peer_tunnel_esp_group\" specified for peer \"$peer\" tunnel $tunnel has not been configured.\n";
+ }
+
+ $genout .= "\nconn peer-$peer-tunnel-$tunnel\n";
+
+ #
+ # Assign left and right to local and remote interfaces
+ #
+ if (defined($lip)) {
+ my $left = $lip;
+ $genout .= "\tleft=$left\n";
+ }
+
+ my $any_peer = 0;
+ my $right;
+ if (($peer eq 'any') or ($peer eq '0.0.0.0')) {
+ $right = '%any';
+ $any_peer = 1;
+ } else {
+ $right = $peer;
+ }
+ $genout .= "\tright=$right\n";
+ if ($any_peer) {
+ $genout .= "\trekey=no\n";
+ }
+
+ #
+ # Write tunnel configuration
+ #
+ my $leftsubnet = $vcVPN->returnValue("ipsec site-to-site peer $peer tunnel $tunnel local-subnet");
+ if (!defined($leftsubnet) || $leftsubnet eq "") {
+ $error = 1;
+ print STDERR "VPN configuration error. No 'local-subnet' specified for peer \"$peer\" tunnel $tunnel.\n";
+ }
+ if (defined($leftsubnet) && $leftsubnet eq 'any') {
+ $leftsubnet = '0.0.0.0/0';
+ }
+ if (defined($leftsubnet)) {
+ $genout .= "\tleftsubnet=$leftsubnet\n";
+ }
+
+ my $remotesubnet = $vcVPN->returnValue("ipsec site-to-site peer $peer tunnel $tunnel remote-subnet");
+
+ my $rightsubnet;
+ my $allow_nat_networks = $vcVPN->returnValue("ipsec site-to-site peer $peer tunnel $tunnel allow-nat-networks");
+ my $allow_public_networks = $vcVPN->returnValue("ipsec site-to-site peer $peer tunnel $tunnel allow-public-networks");
+
+ if (defined($allow_nat_networks) && $allow_nat_networks eq 'enable') {
+ if (defined($remotesubnet) && $remotesubnet ne "") {
+ $error = 1;
+ print STDERR "VPN configuration error. The 'remote-subnet' has been specified while 'allow-nat-networks' has been enabled for peer \"$peer\" tunnel $tunnel. Both not allowed at once.\n";
+ }
+
+ my @allowed_network = $vcVPN->listNodes('ipsec nat-networks allowed-network');
+ if (@allowed_network == 0) {
+ $error = 1;
+ print STDERR "VPN configuration error. While 'allow-nat-networks' has been enabled for peer \"$peer\" tunnel $tunnel, no global allowed NAT networks have been configured.\n";
+ }
+
+ $rightsubnet = "%priv";
+ if (defined($allow_public_networks) && $allow_public_networks eq "enable") {
+ if (defined($remotesubnet) && $remotesubnet ne "") {
+ $error = 1;
+ print STDERR "VPN configuration error. The 'remote-subnet' has been specified while 'allow-public-networks' has been enabled for peer \"$peer\" tunnel $tunnel. Both not allowed at once.\n";
+ }
+ $rightsubnet .= ",%no";
+ }
+ } else {
+ if (!defined($remotesubnet) || $remotesubnet eq '') {
+ $error = 1;
+ print STDERR "VPN configuration error. The 'remote-subnet' has not been specified while 'allow-nat-networks' has not been enabled for peer \"$peer\" tunnel $tunnel. Either one required.\n";
+ }
+ $rightsubnet = $remotesubnet;
+ if (defined($rightsubnet) && $rightsubnet eq 'any') {
+ $rightsubnet = '0.0.0.0/0';
+ }
+ }
+ if (defined($rightsubnet)) {
+ $genout .= "\trightsubnet=$rightsubnet\n";
+ }
+
+ #
+ # Write IKE configuration from group
+ #
+ $genout .= "\tike=";
+ my $ike_group = $vcVPN->returnValue("ipsec site-to-site peer $peer ike-group");
+ my @ike_proposals = $vcVPN->listNodes("ipsec ike-group $ike_group proposal");
+
+ my $first_ike_proposal = 1;
+ foreach my $ike_proposal (@ike_proposals) {
+ #
+ # Get encryption, hash & Diffie-Hellman key size
+ #
+ my $encryption = $vcVPN->returnValue("ipsec ike-group $ike_group proposal $ike_proposal encryption");
+ my $hash = $vcVPN->returnValue("ipsec ike-group $ike_group proposal $ike_proposal hash");
+ my $dh_group = $vcVPN->returnValue("ipsec ike-group $ike_group proposal $ike_proposal dh-group");
+
+ #
+ # Write separator if not first proposal
+ #
+ if ($first_ike_proposal) {
+ $first_ike_proposal = 0;
+ } else {
+ $genout .= ",";
+ }
+
+ #
+ # Write values
+ #
+ if (defined($encryption) && defined($hash)) {
+ $genout .= "$encryption-$hash";
+ if (defined($dh_group)) {
+ if ($dh_group eq '2') {
+ $genout .= '-modp1024';
+ } elsif ($dh_group eq '5') {
+ $genout .= '-modp1536';
+ } elsif ($dh_group ne '') {
+ $error = 1;
+ print STDERR "VPN configuration error. Invalid 'dh-group' $dh_group specified for peer \"$peer\" tunnel $tunnel. Only 2 or 5 accepted.\n";
+ }
+ }
+ }
+ }
+ $genout .= "\n";
+
+ my $ikelifetime = $vcVPN->returnValue("ipsec ike-group $ike_group lifetime");
+ if (!defined($ikelifetime) || $ikelifetime eq '') {
+ $ikelifetime = IKELIFETIME_DEFAULT;
+ }
+ $genout .= "\tikelifetime=$ikelifetime" . "s\n";
+
+ #
+ # Check for agressive-mode
+ #
+ my $aggressive_mode = $vcVPN->returnValue("ipsec ike-group $ike_group aggressive-mode");
+ if (defined($aggressive_mode)) {
+ if ($aggressive_mode eq 'enable') {
+ $genout .= "\taggrmode=yes\n";
+ } else {
+ $genout .= "\taggrmode=no\n";
+ }
+ }
+
+
+ #
+ # Check for Dead Peer Detection DPD
+ #
+ my $dpd_interval = $vcVPN->returnValue("ipsec ike-group $ike_group dead-peer-detection interval");
+ my $dpd_timeout = $vcVPN->returnValue("ipsec ike-group $ike_group dead-peer-detection timeout");
+ my $dpd_action = $vcVPN->returnValue("ipsec ike-group $ike_group dead-peer-detection action");
+ if (defined($dpd_interval) && defined($dpd_timeout) && defined($dpd_action)) {
+ $genout .= "\tdpddelay=$dpd_interval" . "s\n";
+ $genout .= "\tdpdtimeout=$dpd_timeout" . "s\n";
+ $genout .= "\tdpdaction=$dpd_action\n";
+ }
+
+ #
+ # Write ESP configuration from group
+ #
+ $genout .= "\tesp=";
+ my $esp_group = $vcVPN->returnValue("ipsec site-to-site peer $peer tunnel $tunnel esp-group");
+ my @esp_proposals = $vcVPN->listNodes("ipsec esp-group $esp_group proposal");
+ my $first_esp_proposal = 1;
+ foreach my $esp_proposal (@esp_proposals) {
+ #
+ # Get encryption, hash
+ #
+ my $encryption = $vcVPN->returnValue("ipsec esp-group $esp_group proposal $esp_proposal encryption");
+ my $hash = $vcVPN->returnValue("ipsec esp-group $esp_group proposal $esp_proposal hash");
+
+ #
+ # Write separator if not first proposal
+ #
+ if ($first_esp_proposal) {
+ $first_esp_proposal = 0;
+ } else {
+ $genout .= ",";
+ }
+
+ #
+ # Write values
+ #
+ if (defined($encryption) && defined($hash)) {
+ $genout .= "$encryption-$hash";
+ }
+ }
+ $genout .= "\n";
+
+ my $esplifetime = $vcVPN->returnValue("ipsec esp-group $esp_group lifetime");
+ if (!defined($esplifetime) || $esplifetime eq '') {
+ $esplifetime = ESPLIFETIME_DEFAULT;
+ }
+ $genout .= "\tkeylife=$esplifetime" . "s\n";
+
+ my $lower_lifetime = $ikelifetime;
+ if ($esplifetime < $ikelifetime) {
+ $lower_lifetime = $esplifetime;
+ }
+
+ #
+ # The lifetime values need to be greater than:
+ # rekeymargin*(100+rekeyfuzz)/100
+ #
+ my $rekeymargin = REKEYMARGIN_DEFAULT;
+ if ($lower_lifetime <= (2 * $rekeymargin)) {
+ $rekeymargin = int($lower_lifetime / 2) - 1;
+ }
+ $genout .= "\trekeymargin=$rekeymargin" . "s\n";
+
+ #
+ # Mode (tunnel or transport)
+ #
+ my $espmode = $vcVPN->returnValue("ipsec esp-group $esp_group mode");
+ if (!defined($espmode) || $espmode eq '') {
+ $espmode = "tunnel";
+ }
+ $genout .= "\ttype=$espmode\n";
+
+ #
+ # Perfect Forward Secrecy
+ #
+ my $pfs = $vcVPN->returnValue("ipsec esp-group $esp_group pfs");
+ if (defined($pfs)) {
+ if ($pfs eq 'enable') {
+ $genout .= "\tpfs=yes\n";
+ } else {
+ $genout .= "\tpfs=no\n";
+ }
+ }
+
+ #
+ # Compression
+ #
+ my $compression = $vcVPN->returnValue("ipsec esp-group $esp_group compression");
+ if (defined($compression)) {
+ if ($compression eq 'enable') {
+ $genout .= "\tcompress=yes\n";
+ } else {
+ $genout .= "\tcompress=no\n";
+ }
+ }
+
+ #
+ # Authentication mode
+ #
+ #
+ # Write shared secrets to ipsec.secrets
+ #
+ my $auth_mode = $vcVPN->returnValue("ipsec site-to-site peer $peer authentication mode");
+ if (defined($auth_mode) && ($auth_mode eq 'pre-shared-secret')) {
+
+ my $psk = $vcVPN->returnValue("ipsec site-to-site peer $peer authentication pre-shared-secret");
+ if (!defined($psk) || $psk eq '') {
+ $error = 1;
+ print STDERR "VPN configuration error. No 'pre-shared-secret' specified for peer \"$peer\" while 'pre-shared-secret' authentication mode is specified.\n";
+ }
+
+ my $right;
+ if (($peer eq 'any') or ($peer eq '0.0.0.0')) {
+ $right = '%any';
+ } else {
+ $right = $peer;
+ }
+ $genout_secrets .= "$lip $right : PSK \"$psk\"\n";
+ $genout .= "\tauthby=secret\n";
+ } elsif (defined($auth_mode) && $auth_mode eq 'rsa') {
+
+ my $local_key_file = VyattaVPNUtil::rsa_get_local_key_file();
+ unless (-r $local_key_file) {
+ $error = 1;
+ if (-e $local_key_file) {
+ print STDERR "VPN configuration error. Invalid local RSA key file path \"$local_key_file\". Filesystem read permission absent.\n";
+ } else {
+ print STDERR "VPN configuration error. Invalid local RSA key file path \"$local_key_file\". File absent. Use the 'vpn rsa-key generate' command to create.\n";
+ }
+ }
+
+ $genout .= "\tauthby=rsasig\n";
+ my $local_key = VyattaVPNUtil::rsa_get_local_pubkey($local_key_file);
+ if (!defined($local_key) || $local_key eq "") {
+ $error = 1;
+ print STDERR "VPN configuration error. Unable to determine local public key from local key file \"$local_key_file\" for peer \"$peer\".\n";
+ } else {
+ $genout .= "\tleftrsasigkey=$local_key\n";
+ }
+
+ my $rsa_key_name = $vcVPN->returnValue("ipsec site-to-site peer $peer authentication rsa-key-name");
+ if (!defined($rsa_key_name) || $rsa_key_name eq "") {
+ $error = 1;
+ print STDERR "VPN configuration error. No 'rsa-key-name' specified for peer \"$peer\" while 'rsa' authentication mode is specified.\n";
+ } else {
+ my $remote_key = $vcVPN->returnValue("rsa-keys rsa-key-name $rsa_key_name rsa-key");
+ if (!defined($remote_key) || $remote_key eq "") {
+ $error = 1;
+ print STDERR "VPN configuration error. No remote key configured for rsa key name \"$rsa_key_name\" that is specified for peer \"$peer\".\n";
+ } else {
+ $genout .= "\trightrsasigkey=$remote_key\n";
+ }
+ }
+ $genout_secrets .= "include $local_key_file\n";
+ } else {
+ $error = 1;
+ print STDERR "VPN configuration error. Unknown authentication mode \"$auth_mode\" for peer \"$peer\" specified.\n";
+ }
+
+ #
+ # Start automatically
+ #
+ if ($any_peer) {
+ $genout .= "\tauto=add\n";
+ } else {
+ $genout .= "\tauto=start\n";
+ }
+ }
+ }
+} else {
+ $genout .= "# No VPN configuration exists.\n";
+ $genout_secrets .= "# No VPN configuration exists.\n";
+}
+
+if (!(defined($config_file) && ($config_file ne '') && defined($secrets_file) && ($secrets_file ne ''))) {
+ print "Regular config file output would be:\n\n$genout\n\n";
+ print "Secrets config file output would be:\n\n$genout_secrets\n\n";
+ exit (0);
+}
+
+
+if ($error == 0) {
+ if ($vcVPN->isDeleted('.') || !$vcVPN->exists('.')) {
+ if (VyattaVPNUtil::is_vpn_running()) {
+ vpn_exec('ipsec setup --stop', 'stop ipsec');
+ }
+ if (!VyattaVPNUtil::enableICMP('1')) {
+ $error = 1;
+ print STDERR "VPN commit error. Unable to re-enable ICMP redirects.\n";
+ }
+ write_config($genout, $config_file, $genout_secrets, $secrets_file);
+ } else {
+ if (!VyattaVPNUtil::enableICMP('0')) {
+ $error = 1;
+ print STDERR "VPN commit error. Unable to disable ICMP redirects.\n";
+ }
+ # Assumming that if there was a local IP missmatch and clustering is enabled,
+ # then the clustering scripts will take care of starting the VPN daemon.
+ if ($clustering_ip) {
+ # If the local-ip is provided by clustering, then just write out the configuration,
+ # but do not start the VPN daemon
+
+ write_config($genout, $config_file, $genout_secrets, $secrets_file);
+
+ vpn_log("Wrote out configuration to files '$config_file' and '$secrets_file'. VPN/ipsec daemons not started due to clustering.\n");
+
+ } else {
+ if (VyattaVPNUtil::is_vpn_running()) {
+ if (isFullRestartRequired($vcVPN)) {
+ #
+ # Full restart required
+ #
+ write_config($genout, $config_file, $genout_secrets, $secrets_file);
+ vpn_exec('ipsec setup --restart', 'restart ipsec');
+ } else {
+ my @conn_down;
+ my @conn_delete;
+ my @conn_replace;
+ my @conn_add;
+ my @conn_up;
+ partial_restart($vcVPN, \@conn_down, \@conn_delete, \@conn_replace, \@conn_add, \@conn_up);
+
+ foreach my $conn (@conn_down) {
+ vpn_exec("ipsec auto --down $conn", "bring down ipsec connection $conn");
+ }
+ foreach my $conn (@conn_delete) {
+ vpn_exec("ipsec auto --delete $conn", "delete ipsec connection $conn");
+ }
+
+ write_config($genout, $config_file, $genout_secrets, $secrets_file);
+ vpn_exec('ipsec auto --rereadall', 're-read ipsec configuration');
+
+ foreach my $conn (@conn_replace) {
+ vpn_exec("ipsec auto --replace $conn", "replace ipsec connection $conn");
+ }
+ foreach my $conn (@conn_add) {
+ vpn_exec("ipsec auto --add $conn", "add ipsec connection $conn");
+ }
+ foreach my $conn (@conn_up) {
+ vpn_exec("ipsec auto --asynchronous --up $conn", "bring up replaced ipsec connection $conn");
+ }
+
+ }
+ } else {
+ write_config($genout, $config_file, $genout_secrets, $secrets_file);
+ vpn_exec('ipsec setup --start', 'start ipsec');
+ }
+ }
+ }
+}
+
+
+#
+# If error return error
+#
+if ($error) {
+ print STDERR "VPN configuration commit aborted due to error(s).\n";
+ exit(1);
+}
+
+
+#
+# Return success
+#
+exit 0;
+
+
+sub write_config {
+ my ($genout, $config_file, $genout_secrets, $secrets_file) = @_;
+
+ open OUTPUT_CONFIG, ">$config_file";
+ print OUTPUT_CONFIG $genout;
+ close OUTPUT_CONFIG;
+
+ open OUTPUT_SECRETS, ">$secrets_file";
+ print OUTPUT_SECRETS $genout_secrets;
+ close OUTPUT_SECRETS;
+}
+
+sub partial_restart {
+ my ($vcVPN, $conn_down, $conn_delete, $conn_replace, $conn_add, $conn_up) = @_;
+
+ my $debug = 0;
+
+ #
+ #
+ # Print configuration trees if debug enabled
+ #
+
+ if ($debug) {
+ print "Modified configuration:\n";
+ printTree();
+ print "\n";
+ print "\nUnmodified configuration:\n";
+ printTreeOrig();
+ print "\n";
+ }
+
+ #
+ # Add and modify connections individually
+ #
+ my %peers = $vcVPN->listNodeStatus('ipsec site-to-site peer');
+ while (my ($peer, $peer_status) = each %peers) {
+
+ if ($peer_status eq 'added') {
+ my @tunnels = $vcVPN->listNodes("ipsec site-to-site peer $peer tunnel");
+ foreach my $tunnel (@tunnels) {
+ addConnection($peer, $tunnel, $conn_add, $conn_up);
+ }
+ } elsif ($peer_status eq 'changed') {
+ my $restart_all_tunnels = 0;
+ if ($vcVPN->isChangedOrDeleted("ipsec site-to-site peer $peer authentication")) {
+ $restart_all_tunnels = 1;
+ } elsif ($vcVPN->isChangedOrDeleted("ipsec site-to-site peer $peer ike-group")) {
+ $restart_all_tunnels = 1;
+ } elsif ($vcVPN->isChangedOrDeleted("ipsec site-to-site peer $peer local-ip")) {
+ $restart_all_tunnels = 1;
+ }
+ my %tunnels = $vcVPN->listNodeStatus("ipsec site-to-site peer $peer tunnel");
+ while (my ($tunnel, $tunnel_status) = each %tunnels) {
+ my $conn = "peer-$peer-tunnel-$tunnel";
+ if ($tunnel_status eq 'added') {
+ addConnection($peer, $tunnel, $conn_add, $conn_up);
+ } elsif ($tunnel_status eq 'changed') {
+ replaceConnection($peer, $tunnel, $conn_down, $conn_replace, $conn_up);
+ } elsif ($tunnel_status eq 'deleted') {
+ deleteConnection($conn, $conn_down, $conn_delete);
+ } elsif ($tunnel_status eq 'static') {
+ if ($restart_all_tunnels || dependenciesChanged($vcVPN, $peer, $tunnel)) {
+ replaceConnection($peer, $tunnel, $conn_down, $conn_replace, $conn_up);
+ }
+ }
+ }
+ } elsif ($peer_status eq 'deleted') {
+ my @tunnels = $vcVPN->listOrigNodes("ipsec site-to-site peer $peer tunnel");
+ foreach my $tunnel (@tunnels) {
+ my $conn = "peer-$peer-tunnel-$tunnel";
+ deleteConnection($conn, $conn_down, $conn_delete);
+ }
+ } elsif ($peer_status eq 'static') {
+ my @tunnels = $vcVPN->listNodes("ipsec site-to-site peer $peer tunnel");
+ foreach my $tunnel (@tunnels) {
+ if (dependenciesChanged($vcVPN, $peer, $tunnel)) {
+ replaceConnection($peer, $tunnel, $conn_down, $conn_replace, $conn_up);
+ }
+ }
+ }
+ }
+}
+
+sub vpn_exec {
+ my ($command, $desc) = @_;
+
+ if ($error != 0) {
+ return;
+ }
+
+ open LOG, ">> /tmp/ipsec.log";
+
+ use POSIX;
+ my $timestamp = strftime("%Y-%m-%d %H:%M.%S", localtime);
+
+ print LOG "$timestamp\nExecuting: $command\nDescription: $desc\n";
+
+ if ($error == 0) {
+ my $cmd_out = qx($command);
+ print LOG "Output:\n$cmd_out\n---\n";
+ print LOG "Return code: $?\n";
+ if ($?) {
+# $error = 1; ignore execution errors for now
+ print LOG "VPN commit error. Unable to $desc, received error code $?\n";
+ print STDERR "VPN commit error. Unable to $desc, received error code $?\n";
+ print STDERR "$cmd_out\n";
+ }
+ } else {
+ print LOG "Execution not performed due to previous error.\n";
+ }
+
+ print LOG "---\n\n";
+ close LOG;
+}
+
+sub vpn_log {
+ my ($log) = @_;
+
+ open LOG, ">> /tmp/ipsec.log";
+
+ use POSIX;
+ my $timestamp = strftime("%Y-%m-%d %H:%M.%S", localtime);
+
+ print LOG "$timestamp\n$log\n";
+ print LOG "---\n\n";
+ close LOG;
+}
+
+sub addConnection {
+ my ($peer, $tunnel, $conn_add, $conn_up) = @_;
+ my $conn = "peer-$peer-tunnel-$tunnel";
+ push(@$conn_add, $conn);
+ if ($peer ne '0.0.0.0') {
+ push(@$conn_up, $conn);
+ }
+}
+
+sub replaceConnection {
+ my ($peer, $tunnel, $conn_down, $conn_replace, $conn_up) = @_;
+ my $conn = "peer-$peer-tunnel-$tunnel";
+ push(@$conn_down, $conn);
+ push(@$conn_replace, $conn);
+ if ($peer ne '0.0.0.0') {
+ push(@$conn_up, $conn);
+ }
+}
+
+sub deleteConnection {
+ my ($conn, $conn_down, $conn_delete) = @_;
+ push(@$conn_down, $conn);
+ push(@$conn_delete, $conn);
+}
+
+sub isFullRestartRequired {
+ my ($vcVPN) = @_;
+
+ my $restartf = 0;
+
+ #
+ # Check for configuration differences
+ #
+ #
+ # See what has been changed
+ #
+ if ($vcVPN->isChangedOrDeleted('ipsec copy-tos')) {
+ #
+ # Top level system parameter modified; full restart required
+ #
+
+ $restartf = 1;
+ } elsif ($vcVPN->isChangedOrDeleted('ipsec logging')) {
+ #
+ # Top level system parameter modified; full restart required
+ #
+
+ $restartf = 1;
+ } elsif ($vcVPN->isChangedOrDeleted('ipsec ipsec-interfaces')) {
+ #
+ # Top level system parameter modified; full restart required
+ #
+
+ $restartf = 1;
+ } elsif ($vcVPN->isChangedOrDeleted('ipsec nat-traversal')) {
+ #
+ # Top level system parameter modified; full restart required
+ #
+
+ $restartf = 1;
+ } elsif ($vcVPN->isChangedOrDeleted('ipsec nat-networks')) {
+ #
+ # Top level system parameter modified; full restart required
+ #
+ # FIXME: in reality this global doesn't affect every tunnel
+
+ $restartf = 1;
+ }
+
+ return $restartf;
+}
+
+sub dependenciesChanged {
+ my ($vcVPN, $peer, $tunnel) = @_;
+ my $auth_mode = $vcVPN->returnValue("ipsec site-to-site peer $peer authentication mode");
+ if (defined($auth_mode) && $auth_mode eq 'rsa') {
+ if ($vcVPN->isChangedOrDeleted('rsa-keys local-key')) {
+ return 1;
+ }
+ my $rsa_key_name = $vcVPN->returnValue("ipsec site-to-site peer $peer authentication rsa-key-name");
+ if ($vcVPN->isChangedOrDeleted("rsa-keys rsa-key-name $rsa_key_name")) {
+ return 1;
+ }
+ }
+
+ my $ike_group = $vcVPN->returnValue("ipsec site-to-site peer $peer ike-group");
+ if ($vcVPN->isChangedOrDeleted("ipsec ike-group $ike_group")) {
+ return 1;
+ }
+
+ my $esp_group = $vcVPN->returnValue("ipsec site-to-site peer $peer tunnel $tunnel esp-group");
+ if ($vcVPN->isChangedOrDeleted("ipsec esp-group $esp_group")) {
+ return 1;
+ }
+
+ return 0;
+}
+
+sub printTree {
+ my ($vc, $path, $depth) = @_;
+
+ my @children = $vc->listNodes($path);
+ foreach my $child (@children) {
+ print ' ' x $depth;
+ print $child . "\n";
+ printTree($vc, "$path $child", $depth + 1);
+ }
+}
+
+sub printTreeOrig {
+ my ($vc, $path, $depth) = @_;
+
+ my @children = $vc->listOrigNodes($path);
+ foreach my $child (@children) {
+ print ' ' x $depth;
+ print $child . "\n";
+ printTreeOrig($vc, "$path $child", $depth + 1);
+ }
+}
+
+# end of file
diff --git a/templates/vpn/ipsec/copy-tos/node.def b/templates/vpn/ipsec/copy-tos/node.def
new file mode 100644
index 0000000..cf675c6
--- /dev/null
+++ b/templates/vpn/ipsec/copy-tos/node.def
@@ -0,0 +1,4 @@
+help: "copy TOS configuration"
+type: txt
+default: "disable"
+syntax: $(@) in "enable", "disable"; "must be enable or disable"
diff --git a/templates/vpn/ipsec/esp-group/node.def b/templates/vpn/ipsec/esp-group/node.def
new file mode 100644
index 0000000..4aae745
--- /dev/null
+++ b/templates/vpn/ipsec/esp-group/node.def
@@ -0,0 +1,4 @@
+tag:
+type: txt
+help: "Encapsulating Security Payload configuration"
+syntax: pattern $(@) "^[-_a-zA-Z0-9.]+$" ; "invalid ESP group name \"$(@)\""
diff --git a/templates/vpn/ipsec/esp-group/node.tag/compression/node.def b/templates/vpn/ipsec/esp-group/node.tag/compression/node.def
new file mode 100644
index 0000000..81409ba
--- /dev/null
+++ b/templates/vpn/ipsec/esp-group/node.tag/compression/node.def
@@ -0,0 +1,4 @@
+help: "ESP compression configuration"
+type: txt
+default: "disable"
+syntax: $(@) in "enable", "disable"; "must be enable or disable"
diff --git a/templates/vpn/ipsec/esp-group/node.tag/lifetime/node.def b/templates/vpn/ipsec/esp-group/node.tag/lifetime/node.def
new file mode 100644
index 0000000..43bf9d3
--- /dev/null
+++ b/templates/vpn/ipsec/esp-group/node.tag/lifetime/node.def
@@ -0,0 +1,4 @@
+help: "ESP lifetime configuration"
+type: u32
+default: 3600
+syntax: ($(@) >= 30 && $(@) <= 86400) ; "must be in the range 30 to 86400 seconds inclusive"
diff --git a/templates/vpn/ipsec/esp-group/node.tag/mode/node.def b/templates/vpn/ipsec/esp-group/node.tag/mode/node.def
new file mode 100644
index 0000000..e288d81
--- /dev/null
+++ b/templates/vpn/ipsec/esp-group/node.tag/mode/node.def
@@ -0,0 +1,4 @@
+help: "ESP mode configuration"
+type: txt
+default: "tunnel"
+syntax: $(@) in "tunnel", "transport"; "must be tunnel or transport"
diff --git a/templates/vpn/ipsec/esp-group/node.tag/node.tag/encryption/node.def b/templates/vpn/ipsec/esp-group/node.tag/node.tag/encryption/node.def
new file mode 100644
index 0000000..66f7ebf
--- /dev/null
+++ b/templates/vpn/ipsec/esp-group/node.tag/node.tag/encryption/node.def
@@ -0,0 +1,2 @@
+type: txt
+default:"aes128"
diff --git a/templates/vpn/ipsec/esp-group/node.tag/node.tag/hash/node.def b/templates/vpn/ipsec/esp-group/node.tag/node.tag/hash/node.def
new file mode 100644
index 0000000..a4187e6
--- /dev/null
+++ b/templates/vpn/ipsec/esp-group/node.tag/node.tag/hash/node.def
@@ -0,0 +1,2 @@
+type: txt
+default:"sha1"
diff --git a/templates/vpn/ipsec/esp-group/node.tag/pfs/node.def b/templates/vpn/ipsec/esp-group/node.tag/pfs/node.def
new file mode 100644
index 0000000..f180a61
--- /dev/null
+++ b/templates/vpn/ipsec/esp-group/node.tag/pfs/node.def
@@ -0,0 +1,4 @@
+help: "ESP PFS configuration"
+type: txt
+default: "enable"
+syntax: $(@) in "enable", "disable"; "must be enable or disable"
diff --git a/templates/vpn/ipsec/esp-group/node.tag/proposal/node.def b/templates/vpn/ipsec/esp-group/node.tag/proposal/node.def
new file mode 100644
index 0000000..7fa4bdf
--- /dev/null
+++ b/templates/vpn/ipsec/esp-group/node.tag/proposal/node.def
@@ -0,0 +1,4 @@
+tag:
+type: u32
+help: "Configure a esp-group proposal"
+syntax: ($(@) >= 1 && $(@) <= 65535) ; "must be in the range 1 to 65535 inclusive"
diff --git a/templates/vpn/ipsec/esp-group/node.tag/proposal/node.tag/encryption/node.def b/templates/vpn/ipsec/esp-group/node.tag/proposal/node.tag/encryption/node.def
new file mode 100644
index 0000000..f345008
--- /dev/null
+++ b/templates/vpn/ipsec/esp-group/node.tag/proposal/node.tag/encryption/node.def
@@ -0,0 +1,4 @@
+help: "Set encryption"
+type: txt
+default: "aes128"
+syntax: $(@) in "aes128", "aes256", "3des"; "must be aes128, or aes256, or 3des"
diff --git a/templates/vpn/ipsec/esp-group/node.tag/proposal/node.tag/hash/node.def b/templates/vpn/ipsec/esp-group/node.tag/proposal/node.tag/hash/node.def
new file mode 100644
index 0000000..7cdd3f4
--- /dev/null
+++ b/templates/vpn/ipsec/esp-group/node.tag/proposal/node.tag/hash/node.def
@@ -0,0 +1,4 @@
+help: "Set hash algorithm"
+type: txt
+default: "sha1"
+syntax: $(@) in "md5", "sha1"; "must be md5 or sha1"
diff --git a/templates/vpn/ipsec/ike-group/node.def b/templates/vpn/ipsec/ike-group/node.def
new file mode 100644
index 0000000..19dfb49
--- /dev/null
+++ b/templates/vpn/ipsec/ike-group/node.def
@@ -0,0 +1,4 @@
+tag:
+type: txt
+help: "Internet Key Exchange configuration"
+syntax: pattern $(@) "^[-_a-zA-Z0-9.]+$" ; "invalid IKE group name \"$(@)\""
diff --git a/templates/vpn/ipsec/ike-group/node.tag/aggressive-mode/node.def b/templates/vpn/ipsec/ike-group/node.tag/aggressive-mode/node.def
new file mode 100644
index 0000000..b462e61
--- /dev/null
+++ b/templates/vpn/ipsec/ike-group/node.tag/aggressive-mode/node.def
@@ -0,0 +1,4 @@
+help: "IKE aggressive-mode configuration"
+type: txt
+default: "disable"
+syntax: $(@) in "enable", "disable"; "enable or disable"
diff --git a/templates/vpn/ipsec/ike-group/node.tag/dead-peer-detection/action/node.def b/templates/vpn/ipsec/ike-group/node.tag/dead-peer-detection/action/node.def
new file mode 100644
index 0000000..fbc1aef
--- /dev/null
+++ b/templates/vpn/ipsec/ike-group/node.tag/dead-peer-detection/action/node.def
@@ -0,0 +1,4 @@
+help: "Set keep-alive failure action"
+type: txt
+default: "hold"
+syntax: $(@) in "hold", "clear", "restart"; "must be hold, or clear, or restart"
diff --git a/templates/vpn/ipsec/ike-group/node.tag/dead-peer-detection/interval/node.def b/templates/vpn/ipsec/ike-group/node.tag/dead-peer-detection/interval/node.def
new file mode 100644
index 0000000..241edf0
--- /dev/null
+++ b/templates/vpn/ipsec/ike-group/node.tag/dead-peer-detection/interval/node.def
@@ -0,0 +1,4 @@
+help: "Set keep-alive interval"
+type: u32
+default: 30
+syntax: ($(@) >= 15 && $(@) <= 86400) ; "must be in the range 15 to 86400 seconds inclusive"
diff --git a/templates/vpn/ipsec/ike-group/node.tag/dead-peer-detection/node.def b/templates/vpn/ipsec/ike-group/node.tag/dead-peer-detection/node.def
new file mode 100644
index 0000000..a326d23
--- /dev/null
+++ b/templates/vpn/ipsec/ike-group/node.tag/dead-peer-detection/node.def
@@ -0,0 +1 @@
+help: "Configure DPD"
diff --git a/templates/vpn/ipsec/ike-group/node.tag/dead-peer-detection/timeout/node.def b/templates/vpn/ipsec/ike-group/node.tag/dead-peer-detection/timeout/node.def
new file mode 100644
index 0000000..8b46cbb
--- /dev/null
+++ b/templates/vpn/ipsec/ike-group/node.tag/dead-peer-detection/timeout/node.def
@@ -0,0 +1,4 @@
+help: "Set keep-alive timeout"
+type: u32
+default: 120
+syntax: ($(@) >= 30 && $(@) <= 86400) ; "must be in the range 30 to 86400 seconds inclusive"
diff --git a/templates/vpn/ipsec/ike-group/node.tag/lifetime/node.def b/templates/vpn/ipsec/ike-group/node.tag/lifetime/node.def
new file mode 100644
index 0000000..2a1500a
--- /dev/null
+++ b/templates/vpn/ipsec/ike-group/node.tag/lifetime/node.def
@@ -0,0 +1,4 @@
+help: "IKE lifetime configuration"
+type: u32
+default: 28800
+syntax: ($(@) >= 30 && $(@) <= 86400) ; "must be in the range 30 to 86400 seconds inclusive"
diff --git a/templates/vpn/ipsec/ike-group/node.tag/proposal/node.def b/templates/vpn/ipsec/ike-group/node.tag/proposal/node.def
new file mode 100644
index 0000000..b61a016
--- /dev/null
+++ b/templates/vpn/ipsec/ike-group/node.tag/proposal/node.def
@@ -0,0 +1,4 @@
+tag:
+help: "Configure a ike-group proposal"
+type: u32
+syntax: ($(@) >= 1 && $(@) <= 65535) ; "must be in the range 1 to 65535 inclusive"
diff --git a/templates/vpn/ipsec/ike-group/node.tag/proposal/node.tag/dh-group/node.def b/templates/vpn/ipsec/ike-group/node.tag/proposal/node.tag/dh-group/node.def
new file mode 100644
index 0000000..58c800b
--- /dev/null
+++ b/templates/vpn/ipsec/ike-group/node.tag/proposal/node.tag/dh-group/node.def
@@ -0,0 +1,3 @@
+help: "Set Diffie-Hellman key exchange"
+type: u32
+syntax: ($(@) == 2 || $(@) == 5); "must be 2 or 5"
diff --git a/templates/vpn/ipsec/ike-group/node.tag/proposal/node.tag/encryption/node.def b/templates/vpn/ipsec/ike-group/node.tag/proposal/node.tag/encryption/node.def
new file mode 100644
index 0000000..f345008
--- /dev/null
+++ b/templates/vpn/ipsec/ike-group/node.tag/proposal/node.tag/encryption/node.def
@@ -0,0 +1,4 @@
+help: "Set encryption"
+type: txt
+default: "aes128"
+syntax: $(@) in "aes128", "aes256", "3des"; "must be aes128, or aes256, or 3des"
diff --git a/templates/vpn/ipsec/ike-group/node.tag/proposal/node.tag/hash/node.def b/templates/vpn/ipsec/ike-group/node.tag/proposal/node.tag/hash/node.def
new file mode 100644
index 0000000..7cdd3f4
--- /dev/null
+++ b/templates/vpn/ipsec/ike-group/node.tag/proposal/node.tag/hash/node.def
@@ -0,0 +1,4 @@
+help: "Set hash algorithm"
+type: txt
+default: "sha1"
+syntax: $(@) in "md5", "sha1"; "must be md5 or sha1"
diff --git a/templates/vpn/ipsec/ipsec-interfaces/interface/node.def b/templates/vpn/ipsec/ipsec-interfaces/interface/node.def
new file mode 100644
index 0000000..c1c8d56
--- /dev/null
+++ b/templates/vpn/ipsec/ipsec-interfaces/interface/node.def
@@ -0,0 +1,3 @@
+multi:
+type: txt
+help: "ipsec interfaces"
diff --git a/templates/vpn/ipsec/ipsec-interfaces/node.def b/templates/vpn/ipsec/ipsec-interfaces/node.def
new file mode 100644
index 0000000..2fc83b8
--- /dev/null
+++ b/templates/vpn/ipsec/ipsec-interfaces/node.def
@@ -0,0 +1 @@
+help: "VPN interface configuration"
diff --git a/templates/vpn/ipsec/logging/facility/node.def b/templates/vpn/ipsec/logging/facility/node.def
new file mode 100644
index 0000000..7b12da1
--- /dev/null
+++ b/templates/vpn/ipsec/logging/facility/node.def
@@ -0,0 +1,6 @@
+type:txt
+syntax: $(@)in "daemon", "local0", "local1", "local2", "local3",\
+ "local4", "local5", "local6", "local7" ;"Value \"$(@)\" not in the list: daemon, local0, local1, local2, local3,\
+ local4, local5, local6, local7"
+help:"IKE lifetime configuration"
+
diff --git a/templates/vpn/ipsec/logging/level/node.def b/templates/vpn/ipsec/logging/level/node.def
new file mode 100644
index 0000000..287d9cc
--- /dev/null
+++ b/templates/vpn/ipsec/logging/level/node.def
@@ -0,0 +1,3 @@
+help: "Set log level"
+type:txt
+syntax: $(@) in "alert", "crit", "debug", "emerg", "err", "info", "notice", "warning"; "must be one of the following: crit, debug, emerg, err, info, notice, warning"
diff --git a/templates/vpn/ipsec/logging/log-modes/node.def b/templates/vpn/ipsec/logging/log-modes/node.def
new file mode 100644
index 0000000..4b89387
--- /dev/null
+++ b/templates/vpn/ipsec/logging/log-modes/node.def
@@ -0,0 +1,4 @@
+multi:
+help: "Set log mode"
+type:txt
+syntax: $(@) in "raw", "crypt", "parsing", "emitting", "control", "all", "private"; "must be one of the following: raw, crypt, parsing, emitting, control, all, private"
diff --git a/templates/vpn/ipsec/logging/node.def b/templates/vpn/ipsec/logging/node.def
new file mode 100644
index 0000000..1ca0fd3
--- /dev/null
+++ b/templates/vpn/ipsec/logging/node.def
@@ -0,0 +1 @@
+activate: "echo activating logging"
diff --git a/templates/vpn/ipsec/nat-networks/allowed-network/node.def b/templates/vpn/ipsec/nat-networks/allowed-network/node.def
new file mode 100644
index 0000000..3bc97e6
--- /dev/null
+++ b/templates/vpn/ipsec/nat-networks/allowed-network/node.def
@@ -0,0 +1,3 @@
+tag:
+type: ipv4net
+help: "NAT networks configuration"
diff --git a/templates/vpn/ipsec/nat-networks/allowed-network/node.tag/exclude/node.def b/templates/vpn/ipsec/nat-networks/allowed-network/node.tag/exclude/node.def
new file mode 100644
index 0000000..a20d924
--- /dev/null
+++ b/templates/vpn/ipsec/nat-networks/allowed-network/node.tag/exclude/node.def
@@ -0,0 +1,3 @@
+multi:
+type: ipv4net
+help: "NAT networks configuration"
diff --git a/templates/vpn/ipsec/nat-networks/node.def b/templates/vpn/ipsec/nat-networks/node.def
new file mode 100644
index 0000000..1d16a9c
--- /dev/null
+++ b/templates/vpn/ipsec/nat-networks/node.def
@@ -0,0 +1 @@
+help: "NAT networks configuration"
diff --git a/templates/vpn/ipsec/nat-traversal/node.def b/templates/vpn/ipsec/nat-traversal/node.def
new file mode 100644
index 0000000..ec08aa6
--- /dev/null
+++ b/templates/vpn/ipsec/nat-traversal/node.def
@@ -0,0 +1,3 @@
+help: "NAT traversal configuration"
+type: txt
+syntax: $(@) in "enable", "disable"; "must be enable or disable"
diff --git a/templates/vpn/ipsec/node.def b/templates/vpn/ipsec/node.def
new file mode 100644
index 0000000..5e1bd73
--- /dev/null
+++ b/templates/vpn/ipsec/node.def
@@ -0,0 +1 @@
+help: "VPN IP security configuration"
diff --git a/templates/vpn/ipsec/site-to-site/node.def b/templates/vpn/ipsec/site-to-site/node.def
new file mode 100644
index 0000000..a36d2ae
--- /dev/null
+++ b/templates/vpn/ipsec/site-to-site/node.def
@@ -0,0 +1 @@
+help: "Configure site to site VPN"
diff --git a/templates/vpn/ipsec/site-to-site/peer/node.def b/templates/vpn/ipsec/site-to-site/peer/node.def
new file mode 100644
index 0000000..ae179bd
--- /dev/null
+++ b/templates/vpn/ipsec/site-to-site/peer/node.def
@@ -0,0 +1,3 @@
+tag:
+type: ipv4
+help: "Configure VPN peers"
diff --git a/templates/vpn/ipsec/site-to-site/peer/node.tag/authentication/mode/node.def b/templates/vpn/ipsec/site-to-site/peer/node.tag/authentication/mode/node.def
new file mode 100644
index 0000000..5412926
--- /dev/null
+++ b/templates/vpn/ipsec/site-to-site/peer/node.tag/authentication/mode/node.def
@@ -0,0 +1,4 @@
+help: "Configure authentication mode"
+type: txt
+default: "pre-shared-secret"
+syntax: $(@) in "pre-shared-secret", "rsa"; "must be pre-shared-secret or rsa"
diff --git a/templates/vpn/ipsec/site-to-site/peer/node.tag/authentication/node.def b/templates/vpn/ipsec/site-to-site/peer/node.tag/authentication/node.def
new file mode 100644
index 0000000..78540d6
--- /dev/null
+++ b/templates/vpn/ipsec/site-to-site/peer/node.tag/authentication/node.def
@@ -0,0 +1 @@
+help: "Configure peer authentication"
diff --git a/templates/vpn/ipsec/site-to-site/peer/node.tag/authentication/pre-shared-secret/node.def b/templates/vpn/ipsec/site-to-site/peer/node.tag/authentication/pre-shared-secret/node.def
new file mode 100644
index 0000000..db096e4
--- /dev/null
+++ b/templates/vpn/ipsec/site-to-site/peer/node.tag/authentication/pre-shared-secret/node.def
@@ -0,0 +1,3 @@
+help: "Set pre-shared secret key"
+type: txt
+syntax: pattern $(@) "^[-_a-zA-Z0-9.]+$" ; "invalid pre-shared secret key \"$(@)\""
diff --git a/templates/vpn/ipsec/site-to-site/peer/node.tag/authentication/rsa-key-name/node.def b/templates/vpn/ipsec/site-to-site/peer/node.tag/authentication/rsa-key-name/node.def
new file mode 100644
index 0000000..c048fe8
--- /dev/null
+++ b/templates/vpn/ipsec/site-to-site/peer/node.tag/authentication/rsa-key-name/node.def
@@ -0,0 +1,3 @@
+help: "Set RSA key name"
+type: txt
+syntax: pattern $(@) "^[-_a-zA-Z0-9.]+$" ; "invalid RSA key name \"$(@)\""
diff --git a/templates/vpn/ipsec/site-to-site/peer/node.tag/ike-group/node.def b/templates/vpn/ipsec/site-to-site/peer/node.tag/ike-group/node.def
new file mode 100644
index 0000000..d70c5ca
--- /dev/null
+++ b/templates/vpn/ipsec/site-to-site/peer/node.tag/ike-group/node.def
@@ -0,0 +1,2 @@
+help: "Set IKE group name"
+type: txt
diff --git a/templates/vpn/ipsec/site-to-site/peer/node.tag/local-ip/node.def b/templates/vpn/ipsec/site-to-site/peer/node.tag/local-ip/node.def
new file mode 100644
index 0000000..967cf73
--- /dev/null
+++ b/templates/vpn/ipsec/site-to-site/peer/node.tag/local-ip/node.def
@@ -0,0 +1,2 @@
+help: "Set local interface address"
+type: ipv4
diff --git a/templates/vpn/ipsec/site-to-site/peer/node.tag/tunnel/node.def b/templates/vpn/ipsec/site-to-site/peer/node.tag/tunnel/node.def
new file mode 100644
index 0000000..943122f
--- /dev/null
+++ b/templates/vpn/ipsec/site-to-site/peer/node.tag/tunnel/node.def
@@ -0,0 +1,3 @@
+tag:
+type: u32
+help: "Configure peer tunnel"
diff --git a/templates/vpn/ipsec/site-to-site/peer/node.tag/tunnel/node.tag/allow-nat-networks/node.def b/templates/vpn/ipsec/site-to-site/peer/node.tag/tunnel/node.tag/allow-nat-networks/node.def
new file mode 100644
index 0000000..b8e6454
--- /dev/null
+++ b/templates/vpn/ipsec/site-to-site/peer/node.tag/tunnel/node.tag/allow-nat-networks/node.def
@@ -0,0 +1,4 @@
+help: "Set NAT networks"
+type: txt
+default: "disable"
+syntax: $(@) in "enable", "disable"; "must be enable or disable"
diff --git a/templates/vpn/ipsec/site-to-site/peer/node.tag/tunnel/node.tag/allow-public-networks/node.def b/templates/vpn/ipsec/site-to-site/peer/node.tag/tunnel/node.tag/allow-public-networks/node.def
new file mode 100644
index 0000000..7c18e68
--- /dev/null
+++ b/templates/vpn/ipsec/site-to-site/peer/node.tag/tunnel/node.tag/allow-public-networks/node.def
@@ -0,0 +1,4 @@
+help: "Set public networks"
+type: txt
+default: "disable"
+syntax: $(@) in "enable", "disable"; "must be enable or disable"
diff --git a/templates/vpn/ipsec/site-to-site/peer/node.tag/tunnel/node.tag/esp-group/node.def b/templates/vpn/ipsec/site-to-site/peer/node.tag/tunnel/node.tag/esp-group/node.def
new file mode 100644
index 0000000..478139e
--- /dev/null
+++ b/templates/vpn/ipsec/site-to-site/peer/node.tag/tunnel/node.tag/esp-group/node.def
@@ -0,0 +1,2 @@
+help: "Set ESP group name"
+type: txt
diff --git a/templates/vpn/ipsec/site-to-site/peer/node.tag/tunnel/node.tag/local-subnet/node.def b/templates/vpn/ipsec/site-to-site/peer/node.tag/tunnel/node.tag/local-subnet/node.def
new file mode 100644
index 0000000..3e9d176
--- /dev/null
+++ b/templates/vpn/ipsec/site-to-site/peer/node.tag/tunnel/node.tag/local-subnet/node.def
@@ -0,0 +1,2 @@
+help: "Set local subnet"
+type: ipv4net
diff --git a/templates/vpn/ipsec/site-to-site/peer/node.tag/tunnel/node.tag/remote-subnet/node.def b/templates/vpn/ipsec/site-to-site/peer/node.tag/tunnel/node.tag/remote-subnet/node.def
new file mode 100644
index 0000000..b3653e7
--- /dev/null
+++ b/templates/vpn/ipsec/site-to-site/peer/node.tag/tunnel/node.tag/remote-subnet/node.def
@@ -0,0 +1,2 @@
+help: "Set remote subnet"
+type: ipv4net
diff --git a/templates/vpn/node.def b/templates/vpn/node.def
new file mode 100644
index 0000000..cef282e
--- /dev/null
+++ b/templates/vpn/node.def
@@ -0,0 +1 @@
+end: "/opt/vyatta/sbin/vpn-config.pl --config_file='/etc/ipsec.conf' --secrets_file='/etc/ipsec.secrets' --init_script='/etc/init.d/ipsec' >> /tmp/ipsec.log"
diff --git a/templates/vpn/rsa-keys/local-key/file/node.def b/templates/vpn/rsa-keys/local-key/file/node.def
new file mode 100644
index 0000000..a95e3c5
--- /dev/null
+++ b/templates/vpn/rsa-keys/local-key/file/node.def
@@ -0,0 +1,3 @@
+help: "Set local RSA key file location"
+type: txt
+default: "/opt/vyatta/etc/config/ipsec.d/rsa-keys/localhost.key"
diff --git a/templates/vpn/rsa-keys/local-key/node.def b/templates/vpn/rsa-keys/local-key/node.def
new file mode 100644
index 0000000..2898967
--- /dev/null
+++ b/templates/vpn/rsa-keys/local-key/node.def
@@ -0,0 +1 @@
+help: "Set local RSA key"
diff --git a/templates/vpn/rsa-keys/node.def b/templates/vpn/rsa-keys/node.def
new file mode 100644
index 0000000..fa3d43d
--- /dev/null
+++ b/templates/vpn/rsa-keys/node.def
@@ -0,0 +1 @@
+help: "Set RSA keys"
diff --git a/templates/vpn/rsa-keys/rsa-key-name/node.def b/templates/vpn/rsa-keys/rsa-key-name/node.def
new file mode 100644
index 0000000..af47ad3
--- /dev/null
+++ b/templates/vpn/rsa-keys/rsa-key-name/node.def
@@ -0,0 +1,3 @@
+tag:
+type: txt
+help: "Set remote RSA key"
diff --git a/templates/vpn/rsa-keys/rsa-key-name/node.tag/rsa-key/node.def b/templates/vpn/rsa-keys/rsa-key-name/node.tag/rsa-key/node.def
new file mode 100644
index 0000000..0098ccc
--- /dev/null
+++ b/templates/vpn/rsa-keys/rsa-key-name/node.tag/rsa-key/node.def
@@ -0,0 +1,2 @@
+help: "Set remote RSA key"
+type: txt