diff options
author | Saurabh Mohan <saurabh@vyatta.com> | 2012-05-16 17:44:36 -0700 |
---|---|---|
committer | Saurabh Mohan <saurabh@vyatta.com> | 2012-05-16 17:44:36 -0700 |
commit | 2403afbb9b6b58877b6b8a8ae932ff06827be026 (patch) | |
tree | 30c974d191f20041eb952a7460ec278c9fc7ae4f | |
parent | e46d2937711e4fec4c09191cbdbbd9149206eb6d (diff) | |
download | vyatta-cfg-vpn-2403afbb9b6b58877b6b8a8ae932ff06827be026.tar.gz vyatta-cfg-vpn-2403afbb9b6b58877b6b8a8ae932ff06827be026.zip |
Vti config support.
-rw-r--r-- | Makefile.am | 1 | ||||
-rwxr-xr-x | scripts/vpn-config.pl | 103 | ||||
-rwxr-xr-x | scripts/vyatta-vti-config.pl | 146 | ||||
-rw-r--r-- | templates/vpn/ipsec/site-to-site/peer/node.tag/vti/bind/node.def | 3 | ||||
-rw-r--r-- | templates/vpn/ipsec/site-to-site/peer/node.tag/vti/disable/node.def | 1 | ||||
-rw-r--r-- | templates/vpn/ipsec/site-to-site/peer/node.tag/vti/esp-group/node.def | 3 | ||||
-rw-r--r-- | templates/vpn/ipsec/site-to-site/peer/node.tag/vti/mark/node.def | 2 | ||||
-rw-r--r-- | templates/vpn/ipsec/site-to-site/peer/node.tag/vti/node.def | 1 | ||||
-rw-r--r-- | templates/vpn/node.def | 1 |
9 files changed, 236 insertions, 25 deletions
diff --git a/Makefile.am b/Makefile.am index ca5db1a..f3c732d 100644 --- a/Makefile.am +++ b/Makefile.am @@ -12,6 +12,7 @@ sbin_SCRIPTS = sbin_SCRIPTS += scripts/vpn-config.pl sbin_SCRIPTS += scripts/vyatta-vpn-ppp-updown.pl sbin_SCRIPTS += scripts/is_valid_address.pl +sbin_SCRIPTS += scripts/vyatta-vti-config.pl bin_sudo_users_SCRIPTS = scripts/vyatta-ipsec-dhcp.pl share_perl5_DATA = lib/Vyatta/VPN/Util.pm diff --git a/scripts/vpn-config.pl b/scripts/vpn-config.pl index e91d1cd..8f35e7e 100755 --- a/scripts/vpn-config.pl +++ b/scripts/vpn-config.pl @@ -394,6 +394,7 @@ if ( $vcVPN->exists('ipsec') ) { . " remote-users configured\n"; } my $prev_peer = ""; + my %marks = (); foreach my $peer (@peers) { my $peer_ike_group = $vcVPN->returnValue("ipsec site-to-site peer $peer ike-group"); @@ -487,37 +488,53 @@ if ( $vcVPN->exists('ipsec') ) { # # Name connection by peer and tunnel # + my $isVti = 0; my @tunnels = $vcVPN->listNodes("ipsec site-to-site peer $peer tunnel"); if ( @tunnels == 0 ) { - vpn_die(["vpn", "ipsec", "site-to-site","peer",$peer,"tunnel"], - "$vpn_cfg_err No tunnels configured for peer \"$peer\". At least" - . " one tunnel required per peer.\n"); + # + # Check if this is VTI + # + if ($vcVPN->exists("ipsec site-to-site peer $peer vti") ) { + $isVti = 1; + @tunnels = (@tunnels, "vti"); + } + if (@tunnels == 0) { + vpn_die(["vpn", "ipsec", "site-to-site","peer",$peer,"tunnel"], + "$vpn_cfg_err No tunnels configured for peer \"$peer\". At least" + . " one tunnel required per peer.\n"); + } } foreach my $tunnel (@tunnels) { my $needs_passthrough = 'false'; + my $tunKeyword; + if ($isVti == 1) { + $tunKeyword = 'vti'; + } else { + $tunKeyword = 'tunnel '."$tunnel"; + } # # Add support for tunnel disable. # if ( - $vcVPN->exists("ipsec site-to-site peer $peer tunnel $tunnel disable") ) + $vcVPN->exists("ipsec site-to-site peer $peer $tunKeyword disable") ) { next; } my $peer_tunnel_esp_group = $vcVPN->returnValue( - "ipsec site-to-site peer $peer tunnel $tunnel esp-group"); + "ipsec site-to-site peer $peer $tunKeyword esp-group"); $peer_tunnel_esp_group = '' if (!defined($peer_tunnel_esp_group)); if ( (!defined($peer_tunnel_esp_group) || $peer_tunnel_esp_group eq '') && (!defined($def_esp_group) || $def_esp_group eq '')) { - vpn_die(["vpn","ipsec","site-to-site","peer",$peer,"tunnel",$tunnel,"esp-group"], + vpn_die(["vpn","ipsec","site-to-site","peer",$peer,$tunKeyword,"esp-group"], "$vpn_cfg_err No ESP group specified for peer \"$peer\" " - . "tunnel $tunnel.\n"); + . "$tunKeyword.\n"); } elsif ( !$vcVPN->exists("ipsec esp-group $peer_tunnel_esp_group") ) { - vpn_die(["vpn","ipsec","site-to-site","peer",$peer,"tunnel",$tunnel,"esp-group"], + vpn_die(["vpn","ipsec","site-to-site","peer",$peer,$tunKeyword,"esp-group"], "$vpn_cfg_err The ESP group \"$peer_tunnel_esp_group\" specified " - . "for peer \"$peer\" tunnel $tunnel has not been configured.\n"); + . "for peer \"$peer\" $tunKeyword has not been configured.\n"); } my $conn_head = "\nconn peer-$peer-tunnel-$tunnel\n"; @@ -546,6 +563,11 @@ if ( $vcVPN->exists('ipsec') ) { # if ( defined($lip) ) { if ( $lip eq 'any' ) { + if ($isVti) { + vpn_die(["vpn","ipsec","site-to-site","peer",$peer,$tunKeyword,"local-address"], + "$vpn_cfg_err The local interface must be specified " + . "for peer \"$peer\" $tunKeyword.\n"); + } $genout .= "\tleft=%defaultroute\n"; # no need for leftsourceip as a defaultroute is must for this to work } else { @@ -555,6 +577,7 @@ if ( $vcVPN->exists('ipsec') ) { $genout .= "\tleftid=$authid\n" if defined $authid; } + # @SM Todo: must have explicit settings for VTI. my $any_peer = 0; my $right; my $rightid = undef; @@ -570,6 +593,11 @@ if ( $vcVPN->exists('ipsec') ) { or ( $peer eq '0.0.0.0' ) or $any_peer == 1 ) { + if ($isVti) { + vpn_die(["vpn","ipsec","site-to-site","peer",$peer], + "$vpn_cfg_err The \"$peer\" is invalid " + . "ip address must be specified for $tunKeyword.\n"); + } $right = '%any'; $any_peer = 1; } else { @@ -585,8 +613,8 @@ if ( $vcVPN->exists('ipsec') ) { # Write tunnel configuration # my $leftsubnet = $vcVPN->returnValue( - "ipsec site-to-site peer $peer tunnel $tunnel local prefix"); - if ( defined($leftsubnet) && $leftsubnet eq 'any' ) { + "ipsec site-to-site peer $peer $tunKeyword local prefix"); + if ( (defined($leftsubnet) && $leftsubnet eq 'any') || $isVti == 1 ) { $leftsubnet = '0.0.0.0/0'; } @@ -613,12 +641,15 @@ if ( $vcVPN->exists('ipsec') ) { } my $remotesubnet = $vcVPN->returnValue( - "ipsec site-to-site peer $peer tunnel $tunnel remote prefix"); + "ipsec site-to-site peer $peer $tunKeyword remote prefix"); + if ($isVti) { + $remotesubnet = 'any'; + } # Check local and remote prefix protocol consistency my $leftsubnet_proto = is_ip_v4_or_v6($leftsubnet); my $remotesubnet_proto = is_ip_v4_or_v6($remotesubnet); - if ($leftsubnet_proto != $remotesubnet_proto) { + if ( !$isVti && ($leftsubnet_proto != $remotesubnet_proto) ) { vpn_die(["vpn", "ipsec", "site-to-site", "peer", $peer, "tunnel", $tunnel], "$vpn_cfg_err The 'remote prefix' and 'local prefix' protocols ". "do not match"); @@ -636,9 +667,9 @@ if ( $vcVPN->exists('ipsec') ) { my $rightsubnet; my $allow_nat_networks = $vcVPN->returnValue( - "ipsec site-to-site peer $peer tunnel $tunnel allow-nat-networks"); + "ipsec site-to-site peer $peer $tunKeyword allow-nat-networks"); my $allow_public_networks = $vcVPN->returnValue( - "ipsec site-to-site peer $peer tunnel $tunnel allow-public-networks"); + "ipsec site-to-site peer $peer $tunKeyword allow-public-networks"); if ( defined($allow_nat_networks) && $allow_nat_networks eq 'enable' ) { if ( defined($remotesubnet) && $remotesubnet ne "" ) { @@ -653,7 +684,7 @@ if ( $vcVPN->exists('ipsec') ) { if ( @allowed_network == 0 ) { vpn_die(["vpn","ipsec","site-to-site","peer",$peer,"tunnel", $tunnel], "$vpn_cfg_err While 'allow-nat-networks' has been enabled for peer" - . " \"$peer\" tunnel $tunnel, no global allowed NAT networks have" + . " \"$peer\" $tunKeyword, no global allowed NAT networks have" . " been configured.\n"); } @@ -665,7 +696,7 @@ if ( $vcVPN->exists('ipsec') ) { vpn_die(["vpn","ipsec","site-to-site","peer",$peer,"tunnel", $tunnel], "$vpn_cfg_err The 'remote-subnet' has been specified while " . "'allow-public-networks' has been enabled for peer \"$peer\" " - . "tunnel $tunnel. Both not allowed at once.\n"); + . "$tunKeyword. Both not allowed at once.\n"); } $rightsubnet .= ",%no"; } @@ -696,13 +727,13 @@ if ( $vcVPN->exists('ipsec') ) { # Protocol/port # my $protocol = $vcVPN->returnValue( - "ipsec site-to-site peer $peer tunnel $tunnel protocol"); + "ipsec site-to-site peer $peer $tunKeyword protocol"); my $lprotoport = ''; if (defined($protocol)){ $lprotoport .= $protocol; } my $lport = $vcVPN->returnValue( - "ipsec site-to-site peer $peer tunnel $tunnel local port"); + "ipsec site-to-site peer $peer $tunKeyword local port"); if (defined($lport)){ if (!defined($protocol)){ $lprotoport .= "0/$lport"; @@ -722,7 +753,7 @@ if ( $vcVPN->exists('ipsec') ) { $rprotoport .= $protocol; } my $rport = $vcVPN->returnValue( - "ipsec site-to-site peer $peer tunnel $tunnel remote port"); + "ipsec site-to-site peer $peer $tunKeyword remote port"); if (defined($rport)){ if (!defined($protocol)){ $rprotoport .= "0/$rport"; @@ -742,7 +773,7 @@ if ( $vcVPN->exists('ipsec') ) { # check if passthrough connection is needed # needed when remote-subnet encompasses local-subnet # - if (defined $leftsubnet && defined $rightsubnet) { + if (!$isVti && defined $leftsubnet && defined $rightsubnet) { # validate that these values are ipv4net my $valid_leftsubnet = 'false'; my $valid_rightsubnet = 'false'; @@ -810,7 +841,7 @@ if ( $vcVPN->exists('ipsec') ) { } elsif ( $dh_group ne '' ) { vpn_die(["vpn","ipsec","site-to-site","peer",$peer,"tunnel", $tunnel], "$vpn_cfg_err Invalid 'dh-group' $dh_group specified for " - . "peer \"$peer\" tunnel $tunnel. Only 2 or 5 accepted.\n"); + . "peer \"$peer\" $tunKeyword. Only 2 or 5 accepted.\n"); } } } @@ -852,7 +883,7 @@ if ( $vcVPN->exists('ipsec') ) { my $esplifetime = ESPLIFETIME_DEFAULT; $genout .= "\tesp="; my $esp_group = $vcVPN->returnValue( - "ipsec site-to-site peer $peer tunnel $tunnel esp-group"); + "ipsec site-to-site peer $peer $tunKeyword esp-group"); if (!defined($esp_group) || $esp_group eq ''){ $esp_group = $vcVPN->returnValue( "ipsec site-to-site peer $peer default-esp-group"); @@ -920,10 +951,14 @@ if ( $vcVPN->exists('ipsec') ) { } if ( $espmode eq "transport" ) { if ( defined $leftsubnet or defined $rightsubnet ) { - vpn_die(["vpn","ipsec","site-to-site","peer",$peer,"tunnel", $tunnel], + vpn_die(["vpn","ipsec","site-to-site","peer",$peer,"$tunKeyword"], "$vpn_cfg_err Can not use local-subnet or remote-subnet when " . "using transport mode\n"); } + if ( $isVti == 1) { + vpn_die(["vpn","ipsec","site-to-site","peer",$peer,"$tunKeyword"], + "$vpn_cfg_err Can not use transport mode for \"$peer\" with vti\n"); + } } $genout .= "\ttype=$espmode\n"; @@ -1094,6 +1129,25 @@ if ( $vcVPN->exists('ipsec') ) { } # + # Mark setting for vti. + # + if ($isVti) { + my $mark = $vcVPN->returnValue("ipsec site-to-site peer $peer vti mark"); + if (!defined($mark) || $mark eq '' || $mark eq "0") { + vpn_die(["vpn","ipsec","site-to-site","peer",$peer,"vti","mark"], + "$vpn_cfg_err No mark specified for peer \"$peer\" vti\n"); + } else { + if (defined($marks{ $mark })) { + vpn_die(["vpn","ipsec","site-to-site","peer",$peer,"vti","mark"], + "$vpn_cfg_err vti mark $mark already used.\n"); + } else { + $marks{ $mark } = 1; + $genout .= "\tmark=$mark\n"; + } + } + } + + # # Start automatically # if ($any_peer) { @@ -1136,7 +1190,6 @@ if ( $vcVPN->exists('ipsec') ) { $genout .= "#$passthrough_conn_head"; } - } } } else { diff --git a/scripts/vyatta-vti-config.pl b/scripts/vyatta-vti-config.pl new file mode 100755 index 0000000..94c2edf --- /dev/null +++ b/scripts/vyatta-vti-config.pl @@ -0,0 +1,146 @@ +#!/usr/bin/perl -w +# +# Module: vpn-config.pl +# +# **** License **** +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# This code was originally developed by Vyatta, Inc. +# Portions created by Vyatta are Copyright (C) 2006, 2007, 2008, 2009 Vyatta, Inc. +# All Rights Reserved. +# +# Authors: Justin Fletcher, Marat Nepomnyashy +# Date: 2012 +# Description: setup the vti tunnel +# +# **** End License **** +# +# +# For each VTI tunnel (vpn ipsec site-to-site peer ip-address sti); find the vti tunnel, local address, mark. +# Find the corresponding tunnel (interfaces vti vtiXXX), tunnel address, disable, mtu +# if not configured: ip tunnel add vtiXXX mode esp local $local remote $remote i_key $mark +# if (mtu): configure mtu +# if (tunnel-addres): configur ip link vtiXXX address +# if (!disable): enable the interface. +# + +use strict; +use lib "/opt/vyatta/share/perl5"; + +use Vyatta::TypeChecker; +use Vyatta::VPN::Util; +use Getopt::Long; +use Vyatta::Misc; +use NetAddr::IP; + + +my $vti_cfg_err = "VPN VTI configuration error:"; +my $gencmds = ""; +my $result = 0; + +# +# Prepare Vyatta::Config object +# +use Vyatta::Config; +my $vcIntf = new Vyatta::Config(); +my $vcVPN = new Vyatta::Config(); +$vcVPN->setLevel('vpn'); +$vcIntf->setLevel('interfaces'); + +if (!$vcVPN->exists('ipsec') ) { + exit $result; +} +if (!$vcVPN->exists('ipsec site-to-site') ) { + exit $result; +} + +my @peers = $vcVPN->listNodes('ipsec site-to-site peer'); +if (@peers == 0) { + exit $result; +} + foreach my $peer (@peers) { + if (! $vcVPN->exists("ipsec site-to-site peer $peer vti")) { + next; + } + # + # we have the vti configured. + # + my $lip = $vcVPN->returnValue("ipsec site-to-site peer $peer local-address"); + my $mark = $vcVPN->returnValue("ipsec site-to-site peer $peer vti mark"); + my $tunName = $vcVPN->returnValue("ipsec site-to-site peer $peer vti bind"); + + # Check local address is valid. + if (!defined($lip)) { + print STDERR "$vti_cfg_err local-address not defined.\n"; + exit -1; + } + + if ($lip eq "" || $lip eq "0.0.0.0") { + print STDERR "$vti_cfg_err Invalid local-address \"$lip\".\n"; + exit -1; + } + # Check mark is valid. + if (!defined($mark) || $mark eq "" || $mark eq "0") { + print STDERR "$vti_cfg_err Invalid mark \"$mark\".\n"; + exit -1; + } + # Check tunName is valid. + if (!defined($tunName) || $tunName eq "" || ! $vcIntf->exists("vti $tunName") ) { + print STDERR "$vti_cfg_err Invalid tunnel name vti \"$tunName\".\n"; + exit -1; + } + # + # Get the tunnel parameters. + # + # ip address's + my @tunIPs = $vcIntf->returnValues("vti $tunName address"); + # mtu + my $mtu = $vcIntf->returnValue("vti $tunName mtu"); + if (!defined($mtu) || $mtu eq "") { + $mtu = 1500; + } + # disabled or not. + my $disabled = $vcIntf->exists("vti $tunName disabled"); + #my $exists = `ls -l /sys/class/net/$tunName &> /dev/null`; + + # description. + my $description = $vcIntf->returnValue("vti $tunName description"); + + # + # Set the configuration into the output string. + # + # By default we delete the tunnel... + $gencmds .= "sudo /sbin/ip tunnel del $tunName &> /dev/null\n"; + $gencmds .= "sudo /sbin/ip tunnel add $tunName mode esp remote $peer local $lip ikey $mark\n"; + foreach my $tunIP (@tunIPs) { + $gencmds .= "sudo /sbin/ip addr add $tunIP dev $tunName\n"; + } + $gencmds .= "sudo /sbin/ip link set $tunName mtu $mtu\n"; + + if (! $disabled) { + # @SM TODO: Don not bring the tunnel link-state up till strongswan does it. + $gencmds .= "sudo /sbin/ip link set $tunName up\n"; + # @SM TODO: Add the static routes over this tunnel... + } + if (defined($description)) { + $gencmds .= "sudo /sbin/ip tunnel show $tunName || sudo echo \"$description\" > /sys/class/net/$tunName/ifalias\n"; + } + } + +if ($gencmds ne "") { + open my $output_config, '>', '/tmp/vti_config' or die "Can't open /tmp/vti_config $!"; + print ${output_config} "#!/bin/sh\n"; + print ${output_config} $gencmds; + close $output_config; + `chmod 755 /tmp/vti_config`; + #$result=`/tmp/vti_config`; + #@SM TODO: remove /tmp/vti_config; +} +exit $result; diff --git a/templates/vpn/ipsec/site-to-site/peer/node.tag/vti/bind/node.def b/templates/vpn/ipsec/site-to-site/peer/node.tag/vti/bind/node.def new file mode 100644 index 0000000..01bb112 --- /dev/null +++ b/templates/vpn/ipsec/site-to-site/peer/node.tag/vti/bind/node.def @@ -0,0 +1,3 @@ +type: txt +help: VTI tunnel interface associated with this configuration [REQUIRED] +allowed: cli-shell-api listActiveNodes interfaces vti diff --git a/templates/vpn/ipsec/site-to-site/peer/node.tag/vti/disable/node.def b/templates/vpn/ipsec/site-to-site/peer/node.tag/vti/disable/node.def new file mode 100644 index 0000000..b797d44 --- /dev/null +++ b/templates/vpn/ipsec/site-to-site/peer/node.tag/vti/disable/node.def @@ -0,0 +1 @@ +help: Option to disable vpn tunnel diff --git a/templates/vpn/ipsec/site-to-site/peer/node.tag/vti/esp-group/node.def b/templates/vpn/ipsec/site-to-site/peer/node.tag/vti/esp-group/node.def new file mode 100644 index 0000000..700d0ee --- /dev/null +++ b/templates/vpn/ipsec/site-to-site/peer/node.tag/vti/esp-group/node.def @@ -0,0 +1,3 @@ +help: ESP group name [REQUIRED] +type: txt +allowed: cli-shell-api listActiveNodes vpn ipsec esp-group diff --git a/templates/vpn/ipsec/site-to-site/peer/node.tag/vti/mark/node.def b/templates/vpn/ipsec/site-to-site/peer/node.tag/vti/mark/node.def new file mode 100644 index 0000000..1d29970 --- /dev/null +++ b/templates/vpn/ipsec/site-to-site/peer/node.tag/vti/mark/node.def @@ -0,0 +1,2 @@ +type: u32 +help: Mark associated with the secure tunnel interface [REQUIRED] diff --git a/templates/vpn/ipsec/site-to-site/peer/node.tag/vti/node.def b/templates/vpn/ipsec/site-to-site/peer/node.tag/vti/node.def new file mode 100644 index 0000000..2915f9e --- /dev/null +++ b/templates/vpn/ipsec/site-to-site/peer/node.tag/vti/node.def @@ -0,0 +1 @@ +help: Virtual tunnel interface [REQUIRED] diff --git a/templates/vpn/node.def b/templates/vpn/node.def index f16f39a..8adc512 100644 --- a/templates/vpn/node.def +++ b/templates/vpn/node.def @@ -6,3 +6,4 @@ end:sudo /opt/vyatta/sbin/vpn-config.pl \ --init_script='/etc/init.d/ipsec' || exit 1 sudo /opt/vyatta/sbin/vyatta-update-l2tp.pl || exit 1 sudo /opt/vyatta/sbin/vyatta-update-pptp.pl || exit 1 + sudo /opt/vyatta/sbin/vyatta-vti-config.pl || exit 1 |