From 1edbec992e1bbf77932ce6fcd147a3522020d1dd Mon Sep 17 00:00:00 2001 From: Erik Kapfer Date: Sat, 28 Mar 2020 10:25:58 +0100 Subject: [PATCH] OpenVPN: Reorder ifconfig for N2N [Do not merge this] N2N currently reserves a /24 subnet for each connection. This patch should spare network space cause the P2P topology only needs a /30 subnet. Open Questions: - The firewalling of N2N needs to be adapted (and deeper checked in general) since openvpnctrl uses always a DROP for *.0/30 for OVPNBLOCK. - An overlaping of different N2N subnets should be prevented. - More testings needs to be done also with already existing connections. Signed-off-by: Erik Kapfer --- html/cgi-bin/ovpnmain.cgi | 92 +++++++++++++++++++++++++-------------- langs/en/cgi-bin/en.pl | 4 +- 2 files changed, 63 insertions(+), 33 deletions(-) diff --git a/html/cgi-bin/ovpnmain.cgi b/html/cgi-bin/ovpnmain.cgi index ce9524df79..f0e1752736 100644 --- a/html/cgi-bin/ovpnmain.cgi +++ b/html/cgi-bin/ovpnmain.cgi @@ -32,6 +32,7 @@ use strict; use Archive::Zip qw(:ERROR_CODES :CONSTANTS); use Sort::Naturally; require '/var/ipfire/general-functions.pl'; +require '/var/ipfire/network-functions.pl'; require "${General::swroot}/lang.pl"; require "${General::swroot}/header.pl"; require "${General::swroot}/countries.pl"; @@ -251,6 +252,27 @@ sub pkiconfigcheck CRYPTO_WARNING: } +# Prepare N2N ifconfig range +sub ifconfigip +{ + my $ip = $_[0]; + + if (!($ip =~ /^(\d+)\.(\d+)\.(\d+)\.(\d+)$/)) { + return 0; + } else { + my @octets = ($1, $2, $3, $4); + foreach $_ (@octets) + { + + if (/^0./) { + return 0; } + if ($_ < 1 || $_ > 253) { + return 0; } + } + return 1; + } +} + sub writeserverconf { my %sovpnsettings = (); my @temp = (); @@ -490,13 +512,6 @@ sub modccdnet my $oldname=$_[1]; my %ccdconfhash=(); my %ccdhash=(); - - # Check if the new name is valid. - if(!&General::validhostname($newname)) { - $errormessage=$Lang::tr{'ccd err invalidname'}; - return; - } - &General::readhasharray("${General::swroot}/ovpn/ccd.conf", \%ccdconfhash); foreach my $key (keys %ccdconfhash) { if ($ccdconfhash{$key}[0] eq $oldname) { @@ -917,8 +932,7 @@ if ($cgiparams{'ACTION'} eq $Lang::tr{'save'} && $cgiparams{'TYPE'} eq 'net' && { my @remsubnet = split(/\//,$cgiparams{'REMOTE_SUBNET'}); -my @ovsubnettemp = split(/\./,$cgiparams{'OVPN_SUBNET'}); -my $ovsubnet = "$ovsubnettemp[0].$ovsubnettemp[1].$ovsubnettemp[2]"; +my $remip = &General::NextIP($cgiparams{'OVPN_SUBNET'}); my $tunmtu = ''; unless(-d "${General::swroot}/ovpn/n2nconf/"){mkdir "${General::swroot}/ovpn/n2nconf", 0755 or die "Unable to create dir $!";} @@ -942,8 +956,8 @@ unless(-d "${General::swroot}/ovpn/n2nconf/$cgiparams{'NAME'}"){mkdir "${General } print SERVERCONF "float\n"; - print SERVERCONF "# IP adresses of the VPN Subnet\n"; - print SERVERCONF "ifconfig $ovsubnet.1 $ovsubnet.2\n"; + print SERVERCONF "# IP adresses of the VPN Subnet\n"; + print SERVERCONF "ifconfig $cgiparams{'OVPN_SUBNET'} $remip\n"; print SERVERCONF "# Client Gateway Network\n"; print SERVERCONF "route $remsubnet[0] $remsubnet[1]\n"; print SERVERCONF "up \"/etc/init.d/static-routes start\"\n"; @@ -1016,8 +1030,7 @@ unless(-d "${General::swroot}/ovpn/n2nconf/$cgiparams{'NAME'}"){mkdir "${General if ($cgiparams{'ACTION'} eq $Lang::tr{'save'} && $cgiparams{'TYPE'} eq 'net' && $cgiparams{'SIDE'} eq 'client') { - my @ovsubnettemp = split(/\./,$cgiparams{'OVPN_SUBNET'}); - my $ovsubnet = "$ovsubnettemp[0].$ovsubnettemp[1].$ovsubnettemp[2]"; + my $remip = &General::NextIP($cgiparams{'OVPN_SUBNET'}); my @remsubnet = split(/\//,$cgiparams{'REMOTE_SUBNET'}); my $tunmtu = ''; @@ -1038,8 +1051,8 @@ unless(-d "${General::swroot}/ovpn/n2nconf/$cgiparams{'NAME'}"){mkdir "${General print CLIENTCONF "# IP/DNS for remote Server Gateway\n"; print CLIENTCONF "remote $cgiparams{'REMOTE'}\n"; print CLIENTCONF "float\n"; - print CLIENTCONF "# IP adresses of the VPN Subnet\n"; - print CLIENTCONF "ifconfig $ovsubnet.2 $ovsubnet.1\n"; + print CLIENTCONF "# IP adresses of the VPN Subnet\n"; + print CLIENTCONF "ifconfig $remip $cgiparams{'OVPN_SUBNET'}\n"; print CLIENTCONF "# Server Gateway Network\n"; print CLIENTCONF "route $remsubnet[0] $remsubnet[1]\n"; print CLIENTCONF "up \"/etc/init.d/static-routes start\"\n"; @@ -2144,9 +2157,8 @@ if ($confighash{$cgiparams{'KEY'}}[3] eq 'net'){ my $zipname = "$confighash{$cgiparams{'KEY'}}[1]-Client.zip"; my $zippathname = "$zippath$zipname"; - $clientovpn = "$confighash{$cgiparams{'KEY'}}[1].conf"; - my @ovsubnettemp = split(/\./,$confighash{$cgiparams{'KEY'}}[27]); - my $ovsubnet = "$ovsubnettemp[0].$ovsubnettemp[1].$ovsubnettemp[2]"; + $clientovpn = "$confighash{$cgiparams{'KEY'}}[1].conf"; + my $remip = &General::NextIP($confighash{$cgiparams{'KEY'}}[27]); my $tunmtu = ''; my @remsubnet = split(/\//,$confighash{$cgiparams{'KEY'}}[8]); my $n2nfragment = ''; @@ -2166,8 +2178,8 @@ if ($confighash{$cgiparams{'KEY'}}[3] eq 'net'){ print CLIENTCONF "# IP/DNS for remote Server Gateway\n"; print CLIENTCONF "remote $vpnsettings{'VPN_IP'}\n"; print CLIENTCONF "float\n"; - print CLIENTCONF "# IP adresses of the VPN Subnet\n"; - print CLIENTCONF "ifconfig $ovsubnet.2 $ovsubnet.1\n"; + print CLIENTCONF "# IP adresses of the VPN Subnet\n"; + print CLIENTCONF "ifconfig $remip $confighash{$cgiparams{'KEY'}}[27]\n"; print CLIENTCONF "# Server Gateway Network\n"; print CLIENTCONF "route $remsubnet[0] $remsubnet[1]\n"; print CLIENTCONF "# tun Device\n"; @@ -2471,7 +2483,7 @@ else if ($confighash{$cgiparams{'KEY'}}[3] eq 'net') { # Stop the N2N connection before it is removed - system('/usr/local/bin/openvpnctrl', '-kn2n', $confighash{$cgiparams{'KEY'}}[1]); + system("/usr/local/bin/openvpnctrl -kn2n $confighash{$cgiparams{'KEY'}}[1] &>/dev/null"); my $conffile = glob("${General::swroot}/ovpn/n2nconf/$confighash{$cgiparams{'KEY'}}[1]/$confighash{$cgiparams{'KEY'}}[1].conf"); my $certfile = glob("${General::swroot}/ovpn/certs/$confighash{$cgiparams{'KEY'}}[1].p12"); @@ -3353,7 +3365,7 @@ if ($n2nmssfix[0] =~ /mssfix/){$mssfixactive = "on";} else {$mssfixactive = "off my @n2nfragment = split(/ /, (grep { /^fragment/ } @firen2nconf)[0]); my @n2nremote = split(/ /, (grep { /^remote/ } @firen2nconf)[0]); my @n2novpnsuball = split(/ /, (grep { /^ifconfig/ } @firen2nconf)[0]); -my @n2novpnsub = split(/\./,$n2novpnsuball[1]); +my @n2novpnsub = split(/ /,$n2novpnsuball[1]); my @n2nremsub = split(/ /, (grep { /^route/ } @firen2nconf)[0]); my @n2nmgmt = split(/ /, (grep { /^management/ } @firen2nconf)[0]); my @n2nlocalsub = split(/ /, (grep { /^# remsub/ } @firen2nconf)[0]); @@ -3367,7 +3379,6 @@ my @n2nauth = split(/ /, (grep { /^auth/ } @firen2nconf)[0]);; $n2nremote[1] =~ s/\n|\r//g; $n2novpnsub[0] =~ s/\n|\r//g; $n2novpnsub[1] =~ s/\n|\r//g; -$n2novpnsub[2] =~ s/\n|\r//g; $n2nproto[0] =~ s/\n|\r//g; $n2nport[1] =~ s/\n|\r//g; $n2ntunmtu[1] =~ s/\n|\r//g; @@ -3404,7 +3415,7 @@ chomp ($mssfixactive); ### foreach my $dkey (keys %confighash) { - if ($confighash{$dkey}[27] eq "$n2novpnsub[0].$n2novpnsub[1].$n2novpnsub[2].0/255.255.255.0") { + if ($confighash{$dkey}[27] eq "$n2novpnsub[0] $n2novpnsub[1]") { $errormessage = 'The OpenVPN Subnet is already in use'; unlink ("${General::swroot}/ovpn/n2nconf/$n2nname[0]/$n2nname[0].conf") or die "Removing Configfile fail: $!"; unlink ("${General::swroot}/ovpn/certs/$n2nname[0].p12") or die "Removing Certfile fail: $!"; @@ -3447,7 +3458,7 @@ foreach my $dkey (keys %confighash) { $confighash{$key}[24] = $n2nfragment[1]; $confighash{$key}[25] = 'IPFire n2n Client'; $confighash{$key}[26] = 'red'; - $confighash{$key}[27] = "$n2novpnsub[0].$n2novpnsub[1].$n2novpnsub[2].0/255.255.255.0"; + $confighash{$key}[27] = "$n2novpnsub[0] $n2novpnsub[1]"; $confighash{$key}[28] = $n2nproto[0]; $confighash{$key}[29] = $n2nport[1]; $confighash{$key}[30] = $complzoactive; @@ -3830,12 +3841,12 @@ if ($cgiparams{'TYPE'} eq 'net') { } # Check if the input for the transfer net is valid. - if (!&General::validipandmask($cgiparams{'OVPN_SUBNET'})){ - $errormessage = $Lang::tr{'ccd err invalidnet'}; - unlink ("${General::swroot}/ovpn/n2nconf/$cgiparams{'NAME'}/$cgiparams{'NAME'}.conf") or die "Removing Configfile fail: $!"; - rmdir ("${General::swroot}/ovpn/n2nconf/$cgiparams{'NAME'}") || die "Removing Directory fail: $!"; - goto VPNCONF_ERROR; - } + if (!&ifconfigip($cgiparams{'OVPN_SUBNET'})){ + $errormessage = $Lang::tr{'ovpn transportnet is invalid'}; + unlink ("${General::swroot}/ovpn/n2nconf/$cgiparams{'NAME'}/$cgiparams{'NAME'}.conf") or die "Removing Configfile fail: $!"; + rmdir ("${General::swroot}/ovpn/n2nconf/$cgiparams{'NAME'}") || die "Removing Directory fail: $!"; + goto VPNCONF_ERROR; + } if ($cgiparams{'OVPN_SUBNET'} eq $vpnsettings{'DOVPN_SUBNET'}) { $errormessage = $Lang::tr{'openvpn subnet is used'}; @@ -3870,7 +3881,24 @@ if ($cgiparams{'TYPE'} eq 'net') { unlink ("${General::swroot}/ovpn/n2nconf/$cgiparams{'NAME'}/$cgiparams{'NAME'}.conf") or die "Removing Configfile fail: $!"; rmdir ("${General::swroot}/ovpn/n2nconf/$cgiparams{'NAME'}") || die "Removing Directory fail: $!"; goto VPNCONF_ERROR; - } + } + + # Check if there is no other transportnet IP and +1 and -1 already there + if ($cgiparams{'TYPE'} eq 'net') { + foreach my $key (keys %confighash) { + my $transportip = $cgiparams{'OVPN_SUBNET'}; + my $nextip = &General::getnextip($transportip); + my $lastip = &General::getlastip($transportip); + if ($confighash{$key}[27] eq $transportip) { + $errormessage = $Lang::tr{'ovpn transportnet already exist'}; + if ($cgiparams{'TYPE'} eq 'net') { + unlink ("${General::swroot}/ovpn/n2nconf/$cgiparams{'NAME'}/$cgiparams{'NAME'}.conf") or die "Removing Configfile fail: $!"; + rmdir ("${General::swroot}/ovpn/n2nconf/$cgiparams{'NAME'}") || die "Removing Directory fail: $!"; + } + goto VPNCONF_ERROR; + } + } + } if ( &validdotmask ($cgiparams{'REMOTE_SUBNET'})) { $errormessage = $Lang::tr{'openvpn prefix remote subnet'}; diff --git a/langs/en/cgi-bin/en.pl b/langs/en/cgi-bin/en.pl index 1e1aed53cb..42a884d9b6 100644 --- a/langs/en/cgi-bin/en.pl +++ b/langs/en/cgi-bin/en.pl @@ -1547,7 +1547,6 @@ 'ipsec mode tunnel' => 'Tunnel', 'ipsec network' => 'IPsec network', 'ipsec no connections' => 'No active IPsec connections', -'ipsec routing table entries' => 'IPsec Routing Table Entries', 'ipsec settings' => 'IPsec Settings', 'iptable rules' => 'IPTable rules', 'iptmangles' => 'IPTable Mangles', @@ -1950,8 +1949,11 @@ 'ovpn routes push options' => 'Route push options', 'ovpn server status' => 'Current OpenVPN server status:', 'ovpn subnet' => 'OpenVPN subnet:', +'ovpn n2n subnet' => 'Transportnet IP:', 'ovpn subnet is invalid' => 'OpenVPN subnet is invalid.', 'ovpn subnet overlap' => 'OpenVPN Subnet overlaps with : ', +'ovpn transportnet is invalid' => 'Invalid Transportnet IP: Format: 10.1.2.1 or 10.1.1.123. Range: From 10.1.2.1 until 10.1.2.253', +'ovpn transportnet already exist' => 'This Transportnet IP already exists. Please choose another IP', 'ovpn tls auth' => 'TLS Channel Protection:', 'ovpn warning rfc3280' => 'Your host certificate is not RFC3280 compliant.
Please update to the latest IPFire version and generate as soon as possible a new root and host certificate.

All OpenVPN clients needs then to be renewed!
', 'ovpn_fastio' => 'Fast-IO', -- 2.47.2