mirror of
https://git.proxmox.com/git/pve-http-server
synced 2025-05-02 16:20:13 +00:00

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 <s.ivanov@proxmox.com>
72 lines
2.0 KiB
Perl
72 lines
2.0 KiB
Perl
package PVE::APIServer::Utils;
|
|
|
|
use strict;
|
|
use warnings;
|
|
|
|
use Net::IP;
|
|
|
|
# all settings are used for pveproxy and pmgproxy
|
|
# the ALLOW/DENY/POLICY is also used by spiceproxy
|
|
sub read_proxy_config {
|
|
my ($proxy_name) = @_;
|
|
|
|
my $conffile = "/etc/default/$proxy_name";
|
|
|
|
# Note: evaluate with bash
|
|
my $shcmd = ". $conffile;\n";
|
|
$shcmd .= 'echo \"LISTEN_IP:\$LISTEN_IP\";';
|
|
$shcmd .= 'echo \"ALLOW_FROM:\$ALLOW_FROM\";';
|
|
$shcmd .= 'echo \"DENY_FROM:\$DENY_FROM\";';
|
|
$shcmd .= 'echo \"POLICY:\$POLICY\";';
|
|
$shcmd .= 'echo \"CIPHERS:\$CIPHERS\";';
|
|
$shcmd .= 'echo \"DHPARAMS:\$DHPARAMS\";';
|
|
$shcmd .= 'echo \"HONOR_CIPHER_ORDER:\$HONOR_CIPHER_ORDER\";';
|
|
$shcmd .= 'echo \"COMPRESSION:\$COMPRESSION\";';
|
|
|
|
my $data = -f $conffile ? `bash -c "$shcmd"` : '';
|
|
|
|
my $res = {};
|
|
|
|
while ($data =~ s/^(.*)\n//) {
|
|
my ($key, $value) = split(/:/, $1, 2);
|
|
next if !defined($value) || $value eq '';
|
|
if ($key eq 'ALLOW_FROM' || $key eq 'DENY_FROM') {
|
|
my $ips = [];
|
|
foreach my $ip (split(/,/, $value)) {
|
|
$ip = "0/0" if $ip eq 'all';
|
|
push @$ips, Net::IP->new(normalize_v4_in_v6($ip)) || die Net::IP::Error() . "\n";
|
|
}
|
|
$res->{$key} = $ips;
|
|
} elsif ($key eq 'LISTEN_IP') {
|
|
$res->{$key} = $value;
|
|
} elsif ($key eq 'POLICY') {
|
|
die "unknown policy '$value'\n" if $value !~ m/^(allow|deny)$/;
|
|
$res->{$key} = $value;
|
|
} elsif ($key eq 'CIPHERS') {
|
|
$res->{$key} = $value;
|
|
} elsif ($key eq 'DHPARAMS') {
|
|
$res->{$key} = $value;
|
|
} elsif ($key eq 'HONOR_CIPHER_ORDER' || $key eq 'COMPRESSION') {
|
|
die "unknown value '$value' - use 0 or 1\n" if $value !~ m/^(0|1)$/;
|
|
$res->{$key} = $value;
|
|
} else {
|
|
# silently skip everythin else?
|
|
}
|
|
}
|
|
|
|
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;
|