X-Git-Url: https://git.proxmox.com/?p=pve-firewall.git;a=blobdiff_plain;f=src%2FPVE%2FFirewall.pm;h=76684f9676ddc5a49bfcd3ab61b4725d72e8bf75;hp=727204a733afd20fe7780456495ecbfd0f388a60;hb=d31689ee39ce7365231f02301ec8770dfc633eb8;hpb=9f6845cfa97dbe5e264c9d4e188a245ba3d7edf5 diff --git a/src/PVE/Firewall.pm b/src/PVE/Firewall.pm index 727204a..76684f9 100644 --- a/src/PVE/Firewall.pm +++ b/src/PVE/Firewall.pm @@ -489,7 +489,8 @@ my $pve_fw_parsed_macros; my $pve_fw_macro_descr; my $pve_fw_preferred_macro_names = {}; -my $pve_std_chains = { +my $pve_std_chains = {}; +$pve_std_chains->{4} = { 'PVEFW-SET-ACCEPT-MARK' => [ "-j MARK --set-mark 1", ], @@ -760,7 +761,10 @@ sub local_network { return $__local_network; } -my $max_iptables_ipset_name_length = 27; +# ipset names are limited to 31 characters, and we use '_swap' +# suffix for atomic update, for example PVEFW-${VMID}-${ipset_name}_swap + +my $max_iptables_ipset_name_length = 31 - length("_swap"); sub compute_ipset_chain_name { my ($vmid, $ipset_name) = @_; @@ -798,6 +802,8 @@ sub parse_address_list { my $count = 0; my $iprange = 0; + my $ipversion = undef; + foreach my $elem (split(/,/, $str)) { $count++; if (!Net::IP->new($elem)) { @@ -805,9 +811,11 @@ sub parse_address_list { die "invalid IP address: $err\n"; } $iprange = 1 if $elem =~ m/-/; + $ipversion = Net::IP::ip_get_version($elem); #fixme : don't work with range } die "you can use a range in a list\n" if $iprange && $count > 1; + return $ipversion; } sub parse_port_name_number_or_range { @@ -849,8 +857,8 @@ sub pve_fw_verify_port_spec { return $portstr; } -PVE::JSONSchema::register_format('pve-fw-v4addr-spec', \&pve_fw_verify_v4addr_spec); -sub pve_fw_verify_v4addr_spec { +PVE::JSONSchema::register_format('pve-fw-addr-spec', \&pve_fw_verify_addr_spec); +sub pve_fw_verify_addr_spec { my ($list) = @_; parse_address_list($list); @@ -949,11 +957,11 @@ my $rule_properties = { }, iface => get_standard_option('pve-iface', { optional => 1 }), source => { - type => 'string', format => 'pve-fw-v4addr-spec', + type => 'string', format => 'pve-fw-addr-spec', optional => 1, }, dest => { - type => 'string', format => 'pve-fw-v4addr-spec', + type => 'string', format => 'pve-fw-addr-spec', optional => 1, }, proto => { @@ -1067,6 +1075,7 @@ sub verify_rule { my ($rule, $cluster_conf, $fw_conf, $rule_env, $noerr) = @_; my $allow_groups = $rule_env eq 'group' ? 0 : 1; + my $ipversion = undef; my $allow_iface = $rule_env_iface_lookup->{$rule_env}; die "unknown rule_env '$rule_env'\n" if !defined($allow_iface); # should not happen @@ -1165,13 +1174,13 @@ sub verify_rule { } if ($rule->{source}) { - eval { parse_address_list($rule->{source}); }; + eval { $ipversion = parse_address_list($rule->{source}); }; &$add_error('source', $@) if $@; &$check_ipset_or_alias_property('source'); } if ($rule->{dest}) { - eval { parse_address_list($rule->{dest}); }; + eval { $ipversion = parse_address_list($rule->{dest}); }; &$add_error('dest', $@) if $@; &$check_ipset_or_alias_property('dest'); } @@ -1191,6 +1200,7 @@ sub verify_rule { } $rule->{errors} = $errors if $error_count; + $rule->{ipversion} = $ipversion if $ipversion; return $rule; } @@ -2638,29 +2648,35 @@ sub get_option_log_level { } sub generate_std_chains { - my ($ruleset, $options) = @_; + my ($ruleset, $options, $ipversion) = @_; + + my $std_chains = $pve_std_chains->{$ipversion} || die "internal error"; my $loglevel = get_option_log_level($options, 'smurf_log_level'); - # same as shorewall smurflog. - my $chain = 'PVEFW-smurflog'; - $pve_std_chains->{$chain} = []; + my $chain; - push @{$pve_std_chains->{$chain}}, get_log_rule_base($chain, 0, "DROP: ", $loglevel) if $loglevel; - push @{$pve_std_chains->{$chain}}, "-j DROP"; + if ($ipversion == 4) { + # same as shorewall smurflog. + $chain = 'PVEFW-smurflog'; + $std_chains->{$chain} = []; + + push @{$std_chains->{$chain}}, get_log_rule_base($chain, 0, "DROP: ", $loglevel) if $loglevel; + push @{$std_chains->{$chain}}, "-j DROP"; + } # same as shorewall logflags action. $loglevel = get_option_log_level($options, 'tcp_flags_log_level'); $chain = 'PVEFW-logflags'; - $pve_std_chains->{$chain} = []; + $std_chains->{$chain} = []; # fixme: is this correctly logged by pvewf-logger? (ther is no --log-ip-options for NFLOG) - push @{$pve_std_chains->{$chain}}, get_log_rule_base($chain, 0, "DROP: ", $loglevel) if $loglevel; - push @{$pve_std_chains->{$chain}}, "-j DROP"; + push @{$std_chains->{$chain}}, get_log_rule_base($chain, 0, "DROP: ", $loglevel) if $loglevel; + push @{$std_chains->{$chain}}, "-j DROP"; - foreach my $chain (keys %$pve_std_chains) { + foreach my $chain (keys %$std_chains) { ruleset_create_chain($ruleset, $chain); - foreach my $rule (@{$pve_std_chains->{$chain}}) { + foreach my $rule (@{$std_chains->{$chain}}) { if (ref($rule)) { ruleset_generate_rule($ruleset, $chain, $rule); } else { @@ -2833,6 +2849,13 @@ sub compile { $vmfw_configs = read_vm_firewall_configs($cluster_conf, $vmdata, undef, $verbose); } + my ($ruleset, $ipset_ruleset) = compile_iptables_filter($cluster_conf, $hostfw_conf, $vmfw_configs, $vmdata, 4, $verbose); + return ($ruleset, $ipset_ruleset); +} + +sub compile_iptables_filter { + my ($cluster_conf, $hostfw_conf, $vmfw_configs, $vmdata, $ipversion, $verbose) = @_; + $cluster_conf->{ipset}->{venet0} = []; my $venet0_ipset_chain = compute_ipset_chain_name(0, 'venet0'); @@ -2880,7 +2903,7 @@ sub compile { ruleset_addrule($ruleset, "PVEFW-FORWARD", "-o venet0 -m set --match-set ${venet0_ipset_chain} dst -j PVEFW-VENET-IN"); - generate_std_chains($ruleset, $hostfw_options); + generate_std_chains($ruleset, $hostfw_options, $ipversion); my $hostfw_enable = !(defined($hostfw_options->{enable}) && ($hostfw_options->{enable} == 0));