From: Stoiko Ivanov Date: Wed, 5 May 2021 14:36:26 +0000 (+0200) Subject: access control: correctly match v4-mapped-v6 addresses X-Git-Url: https://git.proxmox.com/?a=commitdiff_plain;ds=sidebyside;h=c6de5b3f2d8e55e7aa582dbbf6f365202a3257d5;p=pve-http-server.git access control: correctly match v4-mapped-v6 addresses With recent changes to the listening socket code in pve-manager the proxy daemons now usually bind to '::' and ipv4 clients are read as v4-mapped-v6 addresses [0] from ::ffff:0:0/96. This caused the allow_from/deny_from matching to break. This patch addresses the issue by normalizing addresses from ::ffff:0:0/96 using Net::IP::ip_get_embedded_ipv4 (which roughly splits on ':' and checks if the last part looks like an ipv4 address). Issue was originally reported in our community forum [1] [0] https://en.wikipedia.org/wiki/IPv6_address [1] https://forum.proxmox.com/threads/my-pveproxy-file-doesnt-work.83228/ Signed-off-by: Stoiko Ivanov --- diff --git a/PVE/APIServer/AnyEvent.pm b/PVE/APIServer/AnyEvent.pm index 0654bd4..f0e2e68 100644 --- a/PVE/APIServer/AnyEvent.pm +++ b/PVE/APIServer/AnyEvent.pm @@ -34,6 +34,7 @@ use PVE::SafeSyslog; use PVE::INotify; use PVE::Tools; use PVE::APIServer::Formatter; +use PVE::APIServer::Utils; use Net::IP; use URI; @@ -1662,6 +1663,7 @@ sub wait_end_loop { sub check_host_access { my ($self, $clientip) = @_; + $clientip = PVE::APIServer::Utils::normalize_v4_in_v6($clientip); my $cip = Net::IP->new($clientip); if (!$cip) { diff --git a/PVE/APIServer/Utils.pm b/PVE/APIServer/Utils.pm index 36e3ae6..8470f80 100644 --- a/PVE/APIServer/Utils.pm +++ b/PVE/APIServer/Utils.pm @@ -34,7 +34,7 @@ sub read_proxy_config { my $ips = []; foreach my $ip (split(/,/, $value)) { $ip = "0/0" if $ip eq 'all'; - push @$ips, Net::IP->new($ip) || die Net::IP::Error() . "\n"; + push @$ips, Net::IP->new(normalize_v4_in_v6($ip)) || die Net::IP::Error() . "\n"; } $res->{$key} = $ips; } elsif ($key eq 'LISTEN_IP') { @@ -57,4 +57,15 @@ sub read_proxy_config { return $res; } +sub normalize_v4_in_v6 { + my ($ip_text) = @_; + + my $ip = Net::IP->new($ip_text) || die Net::IP::Error() . "\n"; + my $v4_mapped_v6_prefix = Net::IP->new('::ffff:0:0/96'); + if ($v4_mapped_v6_prefix->overlaps($ip)) { + return Net::IP::ip_get_embedded_ipv4($ip_text); + } + return $ip_text; +} + 1;