summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Southworth <john.southworth@vyatta.com>2011-02-16 19:16:25 -0600
committerJohn Southworth <john.southworth@vyatta.com>2011-02-16 19:16:25 -0600
commiteca11479b369dc04894da775f394e306b452d5b4 (patch)
tree7c9e50c5c4cf420e6083faa5d18d6da11918b415
parent241734ed6dc0c63411c78b82b8a85254fc311809 (diff)
downloadvyatta-cfg-vpn-eca11479b369dc04894da775f394e306b452d5b4.tar.gz
vyatta-cfg-vpn-eca11479b369dc04894da775f394e306b452d5b4.zip
Initial support for configuring dhcp-interfaces for IPSEC, needs testing
-rw-r--r--Makefile.am3
-rwxr-xr-xscripts/vpn-config.pl66
-rwxr-xr-xscripts/vyatta-ipsec-dhcp.pl92
-rw-r--r--templates/vpn/ipsec/site-to-site/peer/node.tag/dhcp-interface/node.def7
4 files changed, 159 insertions, 9 deletions
diff --git a/Makefile.am b/Makefile.am
index a9ca91a..eb1336a 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -4,12 +4,13 @@ libudevdir = /lib/udev
etcudevdir = /etc/udev
initddir = /etc/init.d
curverdir = $(sysconfdir)/config-migrate/current
+bin_sudo_usersdir = $(bindir)/sudo-users
sbin_SCRIPTS =
sbin_SCRIPTS += scripts/vpn-config.pl
sbin_SCRIPTS += scripts/vyatta-vpn-ppp-updown.pl
-
+bin_sudo_users_SCRIPTS = scripts/vyatta-ipsec-dhcp.pl
share_perl5_DATA = lib/Vyatta/VPN/Util.pm
curver_DATA = cfg-version/ipsec@3
diff --git a/scripts/vpn-config.pl b/scripts/vpn-config.pl
index f265f55..a9b9bf8 100755
--- a/scripts/vpn-config.pl
+++ b/scripts/vpn-config.pl
@@ -54,6 +54,7 @@ my $SERVER_KEY_PATH = '/etc/ipsec.d/private';
my $vpn_cfg_err = "VPN configuration error:";
my $clustering_ip = 0;
+my $dhcp_if = 0;
my $genout;
my $genout_secrets;
@@ -398,12 +399,22 @@ if ( $vcVPN->exists('ipsec') ) {
}
my $lip = $vcVPN->returnValue("ipsec site-to-site peer $peer local-ip");
+ my $dhcp_iface = $vcVPN->returnValue("ipsec site-to-site peer $peer dhcp-interface");
+ if (defined($lip) && defined($dhcp_iface)){
+ vpn_die(["vpn","ipsec","site-to-site","peer",$peer],
+ "$vpn_cfg_err Only one of local-ip or dhcp-interface may be defined");
+ }
+ if (defined($dhcp_iface)){
+ $dhcp_if = $dhcp_if + 1;
+ $lip = get_dhcp_addr($dhcp_iface);
+ }
my $authid =
$vcVPN->returnValue("ipsec site-to-site peer $peer authentication id");
my $authremoteid = $vcVPN->returnValue(
"ipsec site-to-site peer $peer authentication remote-id");
- if ( !defined($lip) || $lip eq "" ) {
- vpn_die(["vpn","ipsec","site-to-site","peer",$peer,"local-ip"],"$vpn_cfg_err No local-ip specified for peer \"$peer\"\n");
+ if ( (!defined($lip) || $lip eq "") && (!defined($dhcp_iface) || $dhcp_iface eq "") ) {
+ vpn_die(["vpn","ipsec","site-to-site","peer",$peer,"local-ip"],
+ "$vpn_cfg_err No local-ip specified for peer \"$peer\"\n");
} elsif ( $lip ne '0.0.0.0' ) {
# not '0.0.0.0' special case.
@@ -478,6 +489,13 @@ if ( $vcVPN->exists('ipsec') ) {
my $conn_head = "\nconn peer-$peer-tunnel-$tunnel\n";
$conn_head =~ s/ peer-@/ peer-/;
$genout .= $conn_head;
+
+ # Support for dhcp-interfaces
+ # The comment dhcp-interface will be used by the dhclient hook to do connection updates.
+ if (defined($dhcp_iface)){
+ $genout .= "\t\#dhcp-interface=$dhcp_iface\n";
+ $lip = get_dhcp_addr($dhcp_iface);
+ }
# -> leftsourceip is the internal source IP to use in a tunnel
# -> we use leftsourceip to add a route to the rightsubnet
@@ -945,11 +963,16 @@ if ( $vcVPN->exists('ipsec') ) {
# tag the secrets lines with 3 entries so the op mode command can
# deal with them properly. (LEFT means localid, RIGHT means remoteid)
if ((!defined($authid)) && (defined($authremoteid))) {
- $genout_secrets .= ": PSK \"$psk\" #RIGHT#\n";
+ $genout_secrets .= ": PSK \"$psk\" #RIGHT# ";
} elsif ((defined($authid)) && (!defined($authremoteid))) {
- $genout_secrets .= ": PSK \"$psk\" #LEFT#\n";
+ $genout_secrets .= ": PSK \"$psk\" #LEFT# ";
+ } else {
+ $genout_secrets .= ": PSK \"$psk\" ";
+ }
+ if (defined($dhcp_iface)){
+ $genout_secrets .= "#dhcp-interface=$dhcp_iface#\n";
} else {
- $genout_secrets .= ": PSK \"$psk\"\n";
+ $genout_secrets .= "\n";
}
}
$prev_peer = $peer;
@@ -1094,14 +1117,14 @@ if ( $vcVPN->isDeleted('.')
vpn_die(["vpn","ipsec"],
"VPN commit error. Unable to re-enable ICMP redirects.\n");
}
- write_config( $genout, $config_file, $genout_secrets, $secrets_file );
+ write_config( $genout, $config_file, $genout_secrets, $secrets_file, $dhcp_if);
} else {
if ( !enableICMP('0') ) {
vpn_die(["vpn","ipsec"],
"VPN commit error. Unable to disable ICMP redirects.\n");
}
- write_config( $genout, $config_file, $genout_secrets, $secrets_file );
+ write_config( $genout, $config_file, $genout_secrets, $secrets_file, $dhcp_if );
# 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.
@@ -1153,7 +1176,7 @@ sub vpn_die {
exit 1;
}
sub write_config {
- my ( $genout, $config_file, $genout_secrets, $secrets_file ) = @_;
+ my ( $genout, $config_file, $genout_secrets, $secrets_file, $dhcp_if ) = @_;
open my $output_config, '>', $config_file
or die "Can't open $config_file: $!";
@@ -1164,6 +1187,7 @@ sub write_config {
or die "Can't open $secrets_file: $!";
print ${output_secrets} $genout_secrets;
close $output_secrets;
+ dhcp_hook($dhcp_if);
}
sub vpn_exec {
@@ -1348,5 +1372,31 @@ sub get_x509_secret {
return $str;
}
+sub get_dhcp_addr {
+ my $dhcp_iface = pop(@_);
+ my @dhcp_addr = Vyatta::Misc::getIP($dhcp_iface,4);
+ my $addr = pop(@dhcp_addr);
+ @dhcp_addr = split(/\//, $addr);
+ $addr = $dhcp_addr[0];
+ $addr = '0.0.0.0' if ($addr eq '');
+ return $addr;
+}
+
+sub dhcp_hook {
+ my $dhcp_iface = pop(@_);
+ my $str = '';
+ if ($dhcp_iface > 0){
+ $str =<<EOS;
+#!/bin/sh
+/opt/vyatta/bin/sudo-users/vyatta-ipsec-dhcp.pl --interface=\"\$interface\" --new_ip=\"\$new_ip_address\" --reason=\"\$reason\" --old_ip=\"\$old_ip_address\"
+EOS
+ }
+ my $hook = "/etc/dhcp3/dhclient-exit-hooks.d/ipsecd";
+ open my $dhcp_hook, '>', $hook
+ or die "cannot open $hook";
+ print ${dhcp_hook} $str;
+ close $dhcp_hook;
+}
+
# end of file
diff --git a/scripts/vyatta-ipsec-dhcp.pl b/scripts/vyatta-ipsec-dhcp.pl
new file mode 100755
index 0000000..f20a65f
--- /dev/null
+++ b/scripts/vyatta-ipsec-dhcp.pl
@@ -0,0 +1,92 @@
+#!/usr/bin/perl
+use Getopt::Long;
+use strict;
+
+my $config_file = "/etc/ipsec.conf";
+my $secrets_file = "/etc/ipsec.secrets";
+my ($iface, $config_iface, $nip, $oip, $reason);
+GetOptions("interface=s" => \$iface,
+ "new_ip=s" => \$nip,
+ "old_ip=s" => \$oip,
+ "reason=s" => \$reason);
+
+# check if an update is needed
+exit(0) if (($oip eq $nip) && ($reason ne "BOUND"));
+
+# open ipsec config
+open (my $FD, '<', $config_file);
+my $header = '';
+my $footer = '';
+my $finheader = 0;
+my %connhash = ();
+my $curconn = '';
+foreach my $line (<$FD>){
+ next if (($line =~/^\s*$/) && $finheader);
+ if ($line =~ /\#conn.*/){
+ $curconn = '';
+ next;
+ }
+ if ($line =~ /(peer-.*-tunnel.*)/){
+ $finheader = 1;
+ my $connid = $1;
+ $curconn = $connid;
+ if (not exists $connhash{$connid}){
+ $connhash{$connid} = {
+ _dhcp_iface => undef,
+ _lip => undef,
+ _lines => []
+ };
+ }
+ } elsif (($line =~ /dhcp-interface=(.*)/) && ($curconn ne '') ){
+ $connhash{$curconn}->{_dhcp_iface}=$1;
+ } elsif (($line =~ /left=(.*)/) && ($curconn ne '') ){
+ $connhash{$curconn}->{_lip}=$1;
+ } elsif (!$finheader){
+ $header .= $line;
+ } elsif ($curconn ne ''){
+ push (@{$connhash{"$curconn"}->{_lines}}, $line);
+ } elsif ($curconn eq ''){
+ $footer .= $line;
+ }
+}
+close($FD);
+
+# output new ipsec.conf
+open my $output_config, '>', $config_file
+ or die "Can't open $config_file: $!";
+
+print ${output_config} "$header\n";
+foreach my $connid ( keys (%connhash)){
+ print ${output_config} "conn $connid\n";
+ if (defined($connhash{$connid}->{_dhcp_iface})){
+ if ($connhash{$connid}->{_dhcp_iface} eq $iface){
+ $connhash{$connid}->{_lip} = $nip;
+ }
+ print ${output_config} "\t\#dhcp-interface=$connhash{$connid}->{_dhcp_iface}\n";
+ }
+ print ${output_config} "\tleft=$connhash{$connid}->{_lip}\n";
+ foreach my $line (@{$connhash{$connid}->{_lines}}){
+ print ${output_config} $line;
+ }
+ print ${output_config} "\#conn $connid\n\n";
+}
+print ${output_config} "$footer\n";
+close $output_config;
+
+# change ipsec.secrets
+open (my $FD, '<', $secrets_file);
+my @lines = <$FD>;
+close FD;
+open my $output_secrets, '>', $secrets_file
+ or die "Can't open $secrets_file";
+foreach my $line (@lines){
+ if (($line =~ /\#dhcp-interface=(.*)\#/) && ($1 eq $iface)){
+ $line =~ s/^$oip /$nip /;
+ if (!($line =~ /^oip/)){
+ $line =~ s/^/$nip /;
+ }
+ }
+ print ${output_secrets} $line;
+}
+close $output_secrets;
+system ("/usr/sbin/ipsec update");
diff --git a/templates/vpn/ipsec/site-to-site/peer/node.tag/dhcp-interface/node.def b/templates/vpn/ipsec/site-to-site/peer/node.tag/dhcp-interface/node.def
new file mode 100644
index 0000000..5297f5a
--- /dev/null
+++ b/templates/vpn/ipsec/site-to-site/peer/node.tag/dhcp-interface/node.def
@@ -0,0 +1,7 @@
+type: txt
+help: DHCP interface to listen on
+allowed:
+ local -a array ;
+ array=( /var/lib/dhcp3/eth* /var/lib/dhcp3/br* ) ;
+ echo -n ${array[@]##*/}
+