X-Git-Url: https://git.proxmox.com/?p=pve-firewall.git;a=blobdiff_plain;f=src%2FPVE%2FFirewall.pm;h=5168093d9fca75ff0cd42d9d46865ff984449fa7;hp=1b83334c170ea293402a3364e866f31d04b3ff4e;hb=6e299ae385402df8019ecf34db56f05a0e9ffeae;hpb=9a2745a07ef3912afa42415c639c2069a1d08c7d diff --git a/src/PVE/Firewall.pm b/src/PVE/Firewall.pm index 1b83334..5168093 100644 --- a/src/PVE/Firewall.pm +++ b/src/PVE/Firewall.pm @@ -694,6 +694,8 @@ sub parse_port_name_number_or_range { my $services = PVE::Firewall::get_etc_services(); my $count = 0; + my $icmp_port = 0; + foreach my $item (split(/,/, $str)) { $count++; if ($item =~ m/^(\d+):(\d+)$/) { @@ -704,10 +706,16 @@ sub parse_port_name_number_or_range { my $port = $1; die "invalid port '$port'\n" if $port > 65535; } else { - die "invalid port '$item'\n" if !$services->{byname}->{$item}; + if ($icmp_type_names->{$item}) { + $icmp_port = 1; + } else { + die "invalid port '$item'\n" if !$services->{byname}->{$item}; + } } } + die "ICPM ports not allowed in port range\n" if $icmp_port && $count > 1; + return $count; } @@ -1997,29 +2005,26 @@ sub parse_cluster_fw_rules { } push @{$res->{$section}->{$group}}, $rule; } elsif ($section eq 'ipset') { - chomp $line; - $line =~ m/^(\!)?\s*((\d+)\.(\d+)\.(\d+)\.(\d+)(\/(\d+))?)/; + # we can add single line comments to the end of the rule + my $comment = decode('utf8', $1) if $line =~ s/#\s*(.*?)\s*$//; + + $line =~ m/^(\!)?\s*((?:\d+)\.(?:\d+)\.(?:\d+)\.(?:\d+))(?:\/(\d+))?\s*$/; my $nomatch = $1; - my $ip = $2; + my $cidr = $2; - if(!$ip){ - warn "$prefix: $line is not an valid ip address\n"; - next; - } - if (!Net::IP->new($ip)) { - warn "$prefix: $line is not an valid ip address\n"; + $cidr .= "/$3" if defined($3) && $3 != 32; + + if (!Net::IP->new($cidr)) { + my $err = Net::IP::Error(); + warn "$prefix: $cidr - $err\n"; next; } - if ($nomatch) { - if ($feature_ipset_nomatch) { - push @{$res->{$section}->{$group}}, "$ip nomatch"; - } else { - warn "$prefix: ignore $line - nomatch not supported by kernel\n"; - } - } else { - push @{$res->{$section}->{$group}}, $ip; - } + my $entry = { cidr => $cidr }; + $entry->{nomatch} = 1 if $nomatch; + $entry->{comment} = $comment if $comment; + + push @{$res->{$section}->{$group}}, $entry; } } @@ -2133,6 +2138,28 @@ my $format_options = sub { return $raw; }; +my $format_ipset = sub { + my ($options) = @_; + + my $raw = ''; + + my $nethash = {}; + foreach my $entry (@$options) { + $nethash->{$entry->{cidr}} = $entry; + } + + foreach my $cidr (sort keys %$nethash) { + my $entry = $nethash->{$cidr}; + my $line = $entry->{nomatch} ? '!' : ''; + $line .= $entry->{cidr}; + $line .= " # " . encode('utf8', $entry->{comment}) + if $entry->{comment} && $entry->{comment} !~ m/^\s*$/; + $raw .= "$line\n"; + } + + return $raw; +}; + sub save_vmfw_conf { my ($vmid, $vmfw_conf) = @_; @@ -2232,8 +2259,18 @@ sub generate_ipset { push @{$ipset_ruleset->{$name}}, "create $name hash:net family inet hashsize $hashsize maxelem $hashsize"; - foreach my $ip (@$options) { - push @{$ipset_ruleset->{$name}}, "add $name $ip"; + foreach my $entry (@$options) { + my $cidr = $entry->{cidr}; + my $cmd = "add $name $cidr"; + if ($entry->{nomatch}) { + if ($feature_ipset_nomatch) { + push @{$ipset_ruleset->{$name}}, "$cmd nomatch"; + } else { + warn "ignore !$cidr - nomatch not supported by kernel\n"; + } + } else { + push @{$ipset_ruleset->{$name}}, $cmd; + } } } @@ -2315,7 +2352,12 @@ sub save_clusterfw_conf { my $options = $cluster_conf->{options}; $raw .= &$format_options($options) if scalar(keys %$options); - # fixme: save ipset + foreach my $ipset (sort keys %{$cluster_conf->{ipset}}) { + $raw .= "[IPSET $ipset]\n\n"; + my $options = $cluster_conf->{ipset}->{$ipset}; + $raw .= &$format_ipset($options); + $raw .= "\n"; + } my $rules = $cluster_conf->{rules}; if (scalar(@$rules)) {