From: Michael Tremer Date: Thu, 25 Apr 2024 17:15:53 +0000 (+0200) Subject: wireguard.cgi: Dynamically allocate a pool address for clients X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=ff9ccfa8d75871f96d43501f4536590c680429d7;p=ipfire-2.x.git wireguard.cgi: Dynamically allocate a pool address for clients Signed-off-by: Michael Tremer --- diff --git a/doc/language_issues.de b/doc/language_issues.de index c57603fc6..1dc31d6e7 100644 --- a/doc/language_issues.de +++ b/doc/language_issues.de @@ -1051,6 +1051,7 @@ WARNING: untranslated string: wg invalid remote subnet = Invalid remote subnet WARNING: untranslated string: wg keepalive interval = Keepalive Interval WARNING: untranslated string: wg name is already used = The name is already in use WARNING: untranslated string: wg no local subnets = No local subnets given +WARNING: untranslated string: wg no more free addresses in pool = No more free addresses in pool WARNING: untranslated string: wg no remote subnets = No remote subnets given WARNING: untranslated string: wg peer configuration = Peer Configuration WARNING: untranslated string: wg peer does not exist = Peer does not exist diff --git a/doc/language_issues.en b/doc/language_issues.en index 5ddce9b81..49d51e046 100644 --- a/doc/language_issues.en +++ b/doc/language_issues.en @@ -2158,6 +2158,7 @@ WARNING: untranslated string: wg invalid remote subnet = Invalid remote subnet WARNING: untranslated string: wg keepalive interval = Keepalive Interval WARNING: untranslated string: wg name is already used = The name is already in use WARNING: untranslated string: wg no local subnets = No local subnets given +WARNING: untranslated string: wg no more free addresses in pool = No more free addresses in pool WARNING: untranslated string: wg no remote subnets = No remote subnets given WARNING: untranslated string: wg peer configuration = Peer Configuration WARNING: untranslated string: wg peer does not exist = Peer does not exist diff --git a/doc/language_issues.es b/doc/language_issues.es index 9d2d5d0dd..9e6ce3b90 100644 --- a/doc/language_issues.es +++ b/doc/language_issues.es @@ -1118,6 +1118,7 @@ WARNING: untranslated string: wg invalid remote subnet = Invalid remote subnet WARNING: untranslated string: wg keepalive interval = Keepalive Interval WARNING: untranslated string: wg name is already used = The name is already in use WARNING: untranslated string: wg no local subnets = No local subnets given +WARNING: untranslated string: wg no more free addresses in pool = No more free addresses in pool WARNING: untranslated string: wg no remote subnets = No remote subnets given WARNING: untranslated string: wg peer configuration = Peer Configuration WARNING: untranslated string: wg peer does not exist = Peer does not exist diff --git a/doc/language_issues.fr b/doc/language_issues.fr index a7af2c1d0..f87f98eb7 100644 --- a/doc/language_issues.fr +++ b/doc/language_issues.fr @@ -1058,6 +1058,7 @@ WARNING: untranslated string: wg invalid remote subnet = Invalid remote subnet WARNING: untranslated string: wg keepalive interval = Keepalive Interval WARNING: untranslated string: wg name is already used = The name is already in use WARNING: untranslated string: wg no local subnets = No local subnets given +WARNING: untranslated string: wg no more free addresses in pool = No more free addresses in pool WARNING: untranslated string: wg no remote subnets = No remote subnets given WARNING: untranslated string: wg peer configuration = Peer Configuration WARNING: untranslated string: wg peer does not exist = Peer does not exist diff --git a/doc/language_issues.it b/doc/language_issues.it index 069cf7f27..e47ac4624 100644 --- a/doc/language_issues.it +++ b/doc/language_issues.it @@ -1404,6 +1404,7 @@ WARNING: untranslated string: wg invalid remote subnet = Invalid remote subnet WARNING: untranslated string: wg keepalive interval = Keepalive Interval WARNING: untranslated string: wg name is already used = The name is already in use WARNING: untranslated string: wg no local subnets = No local subnets given +WARNING: untranslated string: wg no more free addresses in pool = No more free addresses in pool WARNING: untranslated string: wg no remote subnets = No remote subnets given WARNING: untranslated string: wg peer configuration = Peer Configuration WARNING: untranslated string: wg peer does not exist = Peer does not exist diff --git a/doc/language_issues.nl b/doc/language_issues.nl index c49c7ad9a..832bb3805 100644 --- a/doc/language_issues.nl +++ b/doc/language_issues.nl @@ -1425,6 +1425,7 @@ WARNING: untranslated string: wg invalid remote subnet = Invalid remote subnet WARNING: untranslated string: wg keepalive interval = Keepalive Interval WARNING: untranslated string: wg name is already used = The name is already in use WARNING: untranslated string: wg no local subnets = No local subnets given +WARNING: untranslated string: wg no more free addresses in pool = No more free addresses in pool WARNING: untranslated string: wg no remote subnets = No remote subnets given WARNING: untranslated string: wg peer configuration = Peer Configuration WARNING: untranslated string: wg peer does not exist = Peer does not exist diff --git a/doc/language_issues.pl b/doc/language_issues.pl index 5a599ff50..b60fc6e4f 100644 --- a/doc/language_issues.pl +++ b/doc/language_issues.pl @@ -1667,6 +1667,7 @@ WARNING: untranslated string: wg invalid remote subnet = Invalid remote subnet WARNING: untranslated string: wg keepalive interval = Keepalive Interval WARNING: untranslated string: wg name is already used = The name is already in use WARNING: untranslated string: wg no local subnets = No local subnets given +WARNING: untranslated string: wg no more free addresses in pool = No more free addresses in pool WARNING: untranslated string: wg no remote subnets = No remote subnets given WARNING: untranslated string: wg peer configuration = Peer Configuration WARNING: untranslated string: wg peer does not exist = Peer does not exist diff --git a/doc/language_issues.ru b/doc/language_issues.ru index f70efde44..28e43001a 100644 --- a/doc/language_issues.ru +++ b/doc/language_issues.ru @@ -1660,6 +1660,7 @@ WARNING: untranslated string: wg invalid remote subnet = Invalid remote subnet WARNING: untranslated string: wg keepalive interval = Keepalive Interval WARNING: untranslated string: wg name is already used = The name is already in use WARNING: untranslated string: wg no local subnets = No local subnets given +WARNING: untranslated string: wg no more free addresses in pool = No more free addresses in pool WARNING: untranslated string: wg no remote subnets = No remote subnets given WARNING: untranslated string: wg peer configuration = Peer Configuration WARNING: untranslated string: wg peer does not exist = Peer does not exist diff --git a/doc/language_issues.tr b/doc/language_issues.tr index ba2f4871c..e1c8027ce 100644 --- a/doc/language_issues.tr +++ b/doc/language_issues.tr @@ -1287,6 +1287,7 @@ WARNING: untranslated string: wg invalid remote subnet = Invalid remote subnet WARNING: untranslated string: wg keepalive interval = Keepalive Interval WARNING: untranslated string: wg name is already used = The name is already in use WARNING: untranslated string: wg no local subnets = No local subnets given +WARNING: untranslated string: wg no more free addresses in pool = No more free addresses in pool WARNING: untranslated string: wg no remote subnets = No remote subnets given WARNING: untranslated string: wg peer configuration = Peer Configuration WARNING: untranslated string: wg peer does not exist = Peer does not exist diff --git a/doc/language_missings b/doc/language_missings index 10013f2f2..5d363fe71 100644 --- a/doc/language_missings +++ b/doc/language_missings @@ -132,6 +132,7 @@ < wg keepalive interval < wg name is already used < wg no local subnets +< wg no more free addresses in pool < wg no remote subnets < wg peer configuration < wg peer does not exist @@ -224,6 +225,7 @@ < wg keepalive interval < wg name is already used < wg no local subnets +< wg no more free addresses in pool < wg no remote subnets < wg peer configuration < wg peer does not exist @@ -294,6 +296,7 @@ < wg keepalive interval < wg name is already used < wg no local subnets +< wg no more free addresses in pool < wg no remote subnets < wg peer configuration < wg peer does not exist @@ -818,6 +821,7 @@ < wg keepalive interval < wg name is already used < wg no local subnets +< wg no more free addresses in pool < wg no remote subnets < wg peer configuration < wg peer does not exist @@ -1418,6 +1422,7 @@ < wg keepalive interval < wg name is already used < wg no local subnets +< wg no more free addresses in pool < wg no remote subnets < wg peer configuration < wg peer does not exist @@ -2434,6 +2439,7 @@ < wg keepalive interval < wg name is already used < wg no local subnets +< wg no more free addresses in pool < wg no remote subnets < wg peer configuration < wg peer does not exist @@ -3487,6 +3493,7 @@ < wg keepalive interval < wg name is already used < wg no local subnets +< wg no more free addresses in pool < wg no remote subnets < wg peer configuration < wg peer does not exist @@ -3917,6 +3924,7 @@ < wg keepalive interval < wg name is already used < wg no local subnets +< wg no more free addresses in pool < wg no remote subnets < wg peer configuration < wg peer does not exist diff --git a/html/cgi-bin/wireguard.cgi b/html/cgi-bin/wireguard.cgi index 8f5cababe..5f84c7a20 100644 --- a/html/cgi-bin/wireguard.cgi +++ b/html/cgi-bin/wireguard.cgi @@ -272,12 +272,16 @@ if ($cgiparams{"ACTION"} eq $Lang::tr{'save'}) { } } elsif ($cgiparams{"ACTION"} eq "SAVE-PEER-HOST") { + my @free_addresses = (); my @local_subnets = (); my $private_key; # Fetch or allocate a new key my $key = $cgiparams{'KEY'} || &General::findhasharraykey(\%peers); + # Is this a new connection? + my $is_new = !exists $peers{$key}; + # Check if the name is valid unless (&name_is_valid($cgiparams{"NAME"})) { push(@errormessages, $Lang::tr{'wg invalid name'}); @@ -304,12 +308,20 @@ if ($cgiparams{"ACTION"} eq $Lang::tr{'save'}) { push(@errormessages, $Lang::tr{'wg no local subnets'}); } + # Check if we have address space left in the pool + if ($is_new) { + # Fetch the next free address + @free_addresses = &free_pool_addresses($settings{'CLIENT_POOL'}, 1); + + # Fail if we ran out of addresses + if (scalar @free_addresses == 0) { + push(@errormessages, $Lang::tr{'wg no more free addresses in pool'}); + } + } + # If there are any errors, we go back to the editor goto EDITHOST if (scalar @errormessages); - # Is this a new connection? - my $is_new = !exists $peers{$key}; - # Generate things for a new peer if ($is_new) { # Generate a new private key @@ -321,10 +333,17 @@ if ($cgiparams{"ACTION"} eq $Lang::tr{'save'}) { # Generate a new PSK $cgiparams{"PSK"} = &generate_private_key(); + # Fetch a free address from the pool + foreach (@free_addresses) { + $cgiparams{'CLIENT_ADDRESS'} = $_; + last; + } + # Fetch some configuration parts } else { - $cgiparams{"PUBLIC_KEY"} = $peers{$key}[3]; - $cgiparams{"PSK"} = $peers{$key}[9]; + $cgiparams{"PUBLIC_KEY"} = $peers{$key}[3]; + $cgiparams{'CLIENT_ADDRESS'} = $peers{$key}[6]; + $cgiparams{"PSK"} = $peers{$key}[9]; } # Save the connection @@ -342,7 +361,7 @@ if ($cgiparams{"ACTION"} eq $Lang::tr{'save'}) { # 5 = Endpoint Port "", # 6 = Remote Subnets - "", #&encode_subnets(@remote_subnets), + $cgiparams{'CLIENT_ADDRESS'}, # 7 = Remark &encode_remarks($cgiparams{"REMARKS"}), # 8 = Local Subnets @@ -1167,6 +1186,49 @@ sub pool_is_in_use($) { return 0; } +# Takes the pool and an optional limit of up to how many addresses to return +sub free_pool_addresses($$) { + my $pool = shift; + my $limit = shift || 0; + + my @used_addresses = (); + my @free_addresses = (); + + # Collect all used addresses + foreach my $key (keys %peers) { + my $type = $peers{$key}[1]; + my $address = $peers{$key}[6]; + + # Only check hosts + next if ($type ne "host"); + + push(@used_addresses, &Network::ip2bin($address)); + } + + # Fetch the first address + my $address = &Network::get_netaddress($pool); + + # Fetch the last address + my $broadcast = &Network::get_broadcast($pool); + $broadcast = &Network::ip2bin($broadcast); + + # Walk through all addresses excluding the first and last address. + # No technical reason, we just don't want to confuse people. + OUTER: for (my $i = &Network::ip2bin($address) + 1; $i < $broadcast; $i++) { + # Skip any addresses that already in use + foreach my $used_address (@used_addresses) { + next OUTER if ($i == $used_address); + } + + push(@free_addresses, &Network::bin2ip($i)); + + # Check limit + last if ($limit > 0 && scalar @free_addresses >= $limit); + } + + return @free_addresses; +} + sub generate_client_configuration($) { my $peer = shift; diff --git a/langs/en/cgi-bin/en.pl b/langs/en/cgi-bin/en.pl index feee700f4..754a4ddb7 100644 --- a/langs/en/cgi-bin/en.pl +++ b/langs/en/cgi-bin/en.pl @@ -3055,6 +3055,7 @@ 'wg keepalive interval' => 'Keepalive Interval', 'wg name is already used' => 'The name is already in use', 'wg no local subnets' => 'No local subnets given', +'wg no more free addresses in pool' => 'No more free addresses in pool', 'wg no remote subnets' => 'No remote subnets given', 'wg peer configuration' => 'Peer Configuration', 'wg peer does not exist' => 'Peer does not exist',