X-Git-Url: https://git.proxmox.com/?p=pve-firewall.git;a=blobdiff_plain;f=src%2FPVE%2FFirewall.pm;h=be5354c780799f02dfe184937481e921f1d7f6fb;hp=8d0e187938db44a9ba9de1dfbf6805345b77fb2c;hb=e2beb7aa9900c650ec69594a2f26cc2889908134;hpb=e2943485a64595b65d24ef68b9036ad1f9ec9652 diff --git a/src/PVE/Firewall.pm b/src/PVE/Firewall.pm index 8d0e187..be5354c 100644 --- a/src/PVE/Firewall.pm +++ b/src/PVE/Firewall.pm @@ -40,7 +40,7 @@ sub pve_verify_ipv4_or_cidr { my ($cidr, $noerr) = @_; if ($cidr =~ m!^(?:$IPV4RE)(/(\d+))?$!) { - return $cidr if Net::IP->new($cidr); + return $cidr if Net::IP->new($cidr); return undef if $noerr; die Net::IP::Error() . "\n"; } @@ -53,7 +53,7 @@ PVE::JSONSchema::register_standard_option('ipset-name', { type => 'string', pattern => '[A-Za-z][A-Za-z0-9\-\_]+', minLength => 2, - maxLength => 20, + maxLength => 20, }); PVE::JSONSchema::register_standard_option('pve-fw-alias', { @@ -61,12 +61,12 @@ PVE::JSONSchema::register_standard_option('pve-fw-alias', { type => 'string', pattern => '[A-Za-z][A-Za-z0-9\-\_]+', minLength => 2, - maxLength => 20, + maxLength => 20, }); PVE::JSONSchema::register_standard_option('pve-fw-loglevel' => { description => "Log level.", - type => 'string', + type => 'string', enum => ['emerg', 'alert', 'crit', 'err', 'warning', 'notice', 'info', 'debug', 'nolog'], optional => 1, }); @@ -79,7 +79,7 @@ PVE::JSONSchema::register_standard_option('pve-security-group-name', { type => 'string', pattern => $security_group_name_pattern, minLength => 2, - maxLength => 20, + maxLength => 20, }); my $feature_ipset_nomatch = 0; @@ -98,7 +98,6 @@ use Data::Dumper; my $nodename = PVE::INotify::nodename(); my $pve_fw_lock_filename = "/var/lock/pvefw.lck"; -my $pve_fw_status_filename = "/var/lib/pve-firewall/pvefw.status"; my $default_log_level = 'info'; @@ -733,7 +732,7 @@ sub parse_address_list { } $iprange = 1 if $elem =~ m/-/; } - + die "you can use a range in a list\n" if $iprange && $count > 1; } @@ -757,7 +756,7 @@ sub parse_port_name_number_or_range { if ($icmp_type_names->{$item}) { $icmp_port = 1; } else { - die "invalid port '$item'\n" if !$services->{byname}->{$item}; + die "invalid port '$item'\n" if !$services->{byname}->{$item}; } } } @@ -918,7 +917,7 @@ sub add_rule_properties { sub delete_rule_properties { my ($rule, $delete_str) = @_; - + foreach my $opt (PVE::Tools::split_list($delete_str)) { raise_param_exc({ 'delete' => "no such property ('$opt')"}) if !defined($rule_properties->{$opt}); @@ -956,7 +955,7 @@ my $apply_macro = sub { if (!defined($v)) { my $msg = "missing parameter '$k' in macro '$macro_name'"; - raise_param_exc({ macro => $msg }) if $verify; + raise_param_exc({ macro => $msg }) if $verify; die "$msg\n"; } $rule->{$k} = $v; @@ -968,7 +967,7 @@ my $apply_macro = sub { if (defined($rule->{$k})) { if ($rule->{$k} ne $param->{$k}) { my $msg = "parameter '$k' already define in macro (value = '$rule->{$k}')"; - raise_param_exc({ $k => $msg }) if $verify; + raise_param_exc({ $k => $msg }) if $verify; die "$msg\n"; } } else { @@ -988,19 +987,19 @@ sub verify_rule { raise_param_exc({ type => "missing property"}) if !$type; raise_param_exc({ action => "missing property"}) if !$rule->{action}; - + if ($type eq 'in' || $type eq 'out') { raise_param_exc({ action => "unknown action '$rule->{action}'"}) if $rule->{action} !~ m/^(ACCEPT|DROP|REJECT)$/; } elsif ($type eq 'group') { - raise_param_exc({ type => "security groups not allowed"}) + raise_param_exc({ type => "security groups not allowed"}) if !$allow_groups; - raise_param_exc({ action => "invalid characters in security group name"}) + raise_param_exc({ action => "invalid characters in security group name"}) if $rule->{action} !~ m/^${security_group_name_pattern}$/; } else { raise_param_exc({ type => "unknown rule type '$type'"}); } - + # fixme: verify $rule->{iface}? if ($rule->{macro}) { @@ -1243,7 +1242,7 @@ sub ruleset_generate_cmdstr { die "invalid security group name '$dest'\n"; } } elsif ($dest =~ m/^${ip_alias_pattern}$/){ - my $alias = lc($source); + my $alias = lc($dest); my $e = $cluster_conf->{aliases}->{$alias}; die "no such alias $dest" if !$e; push @cmd, "-d $e->{cidr}"; @@ -1436,7 +1435,12 @@ sub ruleset_chain_add_conn_filters { } sub ruleset_chain_add_input_filters { - my ($ruleset, $chain, $options) = @_; + my ($ruleset, $chain, $options, $cluster_conf, $loglevel) = @_; + + if ($cluster_conf->{ipset}->{blacklist}){ + ruleset_addlog($ruleset, $chain, 0, "DROP: ", $loglevel, "-m set --match-set PVEFW-blacklist src"); + ruleset_addrule($ruleset, $chain, "-m set --match-set PVEFW-blacklist src -j DROP"); + } if (!(defined($options->{nosmurfs}) && $options->{nosmurfs} == 0)) { ruleset_addrule($ruleset, $chain, "-m conntrack --ctstate INVALID,NEW -j PVEFW-smurfs"); @@ -1471,6 +1475,26 @@ sub ruleset_create_vm_chain { } } +sub ruleset_add_group_rule { + my ($ruleset, $cluster_conf, $chain, $rule, $direction, $action) = @_; + + my $group = $rule->{action}; + my $group_chain = "GROUP-$group-$direction"; + if(!ruleset_chain_exist($ruleset, $group_chain)){ + generate_group_rules($ruleset, $cluster_conf, $group); + } + + if ($direction eq 'OUT' && $rule->{iface_out}) { + ruleset_addrule($ruleset, $chain, "-o $rule->{iface_out} -j $group_chain"); + } elsif ($direction eq 'IN' && $rule->{iface_in}) { + ruleset_addrule($ruleset, $chain, "-i $rule->{iface_in} -j $group_chain"); + } else { + ruleset_addrule($ruleset, $chain, "-j $group_chain"); + } + + ruleset_addrule($ruleset, $chain, "-m mark --mark 1 -j $action"); +} + sub ruleset_generate_vm_rules { my ($ruleset, $rules, $cluster_conf, $chain, $netid, $direction, $options) = @_; @@ -1482,28 +1506,18 @@ sub ruleset_generate_vm_rules { next if $rule->{iface} && $rule->{iface} ne $netid; next if !$rule->{enable}; if ($rule->{type} eq 'group') { - my $group_chain = "GROUP-$rule->{action}-$direction"; - if(!ruleset_chain_exist($ruleset, $group_chain)){ - generate_group_rules($ruleset, $cluster_conf, $rule->{action}); - } - ruleset_addrule($ruleset, $chain, "-j $group_chain"); - if ($direction eq 'OUT'){ - ruleset_addrule($ruleset, $chain, "-m mark --mark 1 -j RETURN"); - }else{ - my $accept = generate_nfqueue($options); - ruleset_addrule($ruleset, $chain, "-m mark --mark 1 -j $accept"); - } - + ruleset_add_group_rule($ruleset, $cluster_conf, $chain, $rule, $direction, + $direction eq 'OUT' ? 'RETURN' : $in_accept); } else { next if $rule->{type} ne $lc_direction; eval { if ($direction eq 'OUT') { ruleset_generate_rule($ruleset, $chain, $rule, - { ACCEPT => "PVEFW-SET-ACCEPT-MARK", REJECT => "PVEFW-reject" }, + { ACCEPT => "PVEFW-SET-ACCEPT-MARK", REJECT => "PVEFW-reject" }, undef, $cluster_conf); } else { - ruleset_generate_rule($ruleset, $chain, $rule, - { ACCEPT => $in_accept , REJECT => "PVEFW-reject" }, + ruleset_generate_rule($ruleset, $chain, $rule, + { ACCEPT => $in_accept , REJECT => "PVEFW-reject" }, undef, $cluster_conf); } }; @@ -1548,8 +1562,6 @@ sub ruleset_generate_vm_ipsrules { sub generate_venet_rules_direction { my ($ruleset, $cluster_conf, $hostfw_conf, $vmfw_conf, $vmid, $ip, $direction) = @_; - parse_address_list($ip); # make sure we have a valid $ip list - my $lc_direction = lc($direction); my $rules = $vmfw_conf->{rules}; @@ -1577,27 +1589,16 @@ sub generate_venet_rules_direction { my $accept_action = $direction eq 'OUT' ? "PVEFW-SET-ACCEPT-MARK" : $accept; ruleset_add_chain_policy($ruleset, $chain, $vmid, $policy, $loglevel, $accept_action); - # plug into FORWARD, INPUT and OUTPUT chain if ($direction eq 'OUT') { ruleset_generate_rule_insert($ruleset, "PVEFW-VENET-OUT", { action => $chain, source => $ip, iface_in => 'venet0'}); - - ruleset_generate_rule_insert($ruleset, "PVEFW-INPUT", { - action => $chain, - source => $ip, - iface_in => 'venet0'}); } else { ruleset_generate_rule($ruleset, "PVEFW-VENET-IN", { action => $chain, dest => $ip, iface_out => 'venet0'}); - - ruleset_generate_rule($ruleset, "PVEFW-OUTPUT", { - action => $chain, - dest => $ip, - iface_out => 'venet0'}); } } @@ -1660,7 +1661,7 @@ sub enable_host_firewall { ruleset_addrule($ruleset, $chain, "-i lo -j ACCEPT"); ruleset_chain_add_conn_filters($ruleset, $chain, 'ACCEPT'); - ruleset_chain_add_input_filters($ruleset, $chain, $options); + ruleset_chain_add_input_filters($ruleset, $chain, $options, $cluster_conf, $loglevel); ruleset_addrule($ruleset, $chain, "-m addrtype --dst-type MULTICAST -j ACCEPT"); ruleset_addrule($ruleset, $chain, "-p udp -m conntrack --ctstate NEW --dport 5404:5405 -j ACCEPT"); @@ -1671,8 +1672,14 @@ sub enable_host_firewall { # add host rules first, so that cluster wide rules can be overwritten foreach my $rule (@$rules, @$cluster_rules) { - next if $rule->{type} ne 'in'; - ruleset_generate_rule($ruleset, $chain, $rule, { ACCEPT => $accept_action, REJECT => "PVEFW-reject" }, undef, $cluster_conf); + $rule->{iface_in} = $rule->{iface} if $rule->{iface}; + if ($rule->{type} eq 'group') { + ruleset_add_group_rule($ruleset, $cluster_conf, $chain, $rule, 'IN', $accept_action); + } elsif ($rule->{type} eq 'in') { + ruleset_generate_rule($ruleset, $chain, $rule, { ACCEPT => $accept_action, REJECT => "PVEFW-reject" }, + undef, $cluster_conf); + } + delete $rule->{iface_in}; } # implement input policy @@ -1698,8 +1705,14 @@ sub enable_host_firewall { # add host rules first, so that cluster wide rules can be overwritten foreach my $rule (@$rules, @$cluster_rules) { - next if $rule->{type} ne 'out'; - ruleset_generate_rule($ruleset, $chain, $rule, { ACCEPT => $accept_action, REJECT => "PVEFW-reject" }, undef, $cluster_conf); + $rule->{iface_out} = $rule->{iface} if $rule->{iface}; + if ($rule->{type} eq 'group') { + ruleset_add_group_rule($ruleset, $cluster_conf, $chain, $rule, 'OUT', $accept_action); + } elsif ($rule->{type} eq 'out') { + ruleset_generate_rule($ruleset, $chain, $rule, { ACCEPT => $accept_action, REJECT => "PVEFW-reject" }, + undef, $cluster_conf); + } + delete $rule->{iface_out}; } # implement output policy @@ -1712,10 +1725,14 @@ sub enable_host_firewall { sub generate_group_rules { my ($ruleset, $cluster_conf, $group) = @_; - die "no such security group '$group'\n" if !$cluster_conf->{groups}->{$group}; my $rules = $cluster_conf->{groups}->{$group}; + if (!$rules) { + warn "no such security group '$group'\n"; + $rules = []; # create empty chain + } + my $chain = "GROUP-${group}-IN"; ruleset_create_chain($ruleset, $chain); @@ -1788,7 +1805,7 @@ sub parse_fw_rule { die "unknown action '$action'\n"; } } elsif ($type eq 'group') { - die "wrong number of rule elements\n" if scalar(@data) != 3; + die "wrong number of rule elements\n" if scalar(@data) > 3; die "groups disabled\n" if !$allow_groups; die "invalid characters in group name\n" if $action !~ m/^${security_group_name_pattern}$/; @@ -1864,7 +1881,7 @@ sub parse_hostfw_option { my $loglevels = "emerg|alert|crit|err|warning|notice|info|debug|nolog"; - if ($line =~ m/^(enable|nosmurfs|tcpflags|optimize):\s*(0|1)\s*$/i) { + if ($line =~ m/^(enable|nosmurfs|tcpflags):\s*(0|1)\s*$/i) { $opt = lc($1); $value = int($2); } elsif ($line =~ m/^(log_level_in|log_level_out|tcp_flags_log_level|smurf_log_level):\s*(($loglevels)\s*)?$/i) { @@ -2023,14 +2040,14 @@ sub parse_cluster_fw_rules { my $section; my $group; - my $res = { - rules => [], - options => {}, - aliases => {}, - groups => {}, - group_comments => {}, + my $res = { + rules => [], + options => {}, + aliases => {}, + groups => {}, + group_comments => {}, ipset => {} , - ipset_comments => {}, + ipset_comments => {}, }; while (defined(my $line = <$fh>)) { @@ -2070,7 +2087,7 @@ sub parse_cluster_fw_rules { $group = lc($1); my $comment = $2; $res->{$section}->{$group} = []; - $res->{ipset_comments}->{$group} = decode('utf8', $comment) + $res->{ipset_comments}->{$group} = decode('utf8', $comment) if $comment; next; } @@ -2118,7 +2135,7 @@ sub parse_cluster_fw_rules { if($cidr !~ m/^${ip_alias_pattern}$/) { $cidr =~ s|/32$||; - + eval { pve_verify_ipv4_or_cidr($cidr); }; if (my $err = $@) { warn "$prefix: $cidr - $err"; @@ -2126,10 +2143,10 @@ sub parse_cluster_fw_rules { } } - my $entry = { cidr => $cidr }; + my $entry = { cidr => $cidr }; $entry->{nomatch} = 1 if $nomatch; $entry->{comment} = $comment if $comment; - + push @{$res->{$section}->{$group}}, $entry; } } @@ -2186,11 +2203,13 @@ sub read_local_vm_config { }; sub load_vmfw_conf { - my ($vmid) = @_; + my ($vmid, $dir) = @_; my $vmfw_conf = {}; - my $filename = "/etc/pve/firewall/$vmid.fw"; + $dir = "/etc/pve/firewall" if !defined($dir); + + my $filename = "$dir/$vmid.fw"; if (my $fh = IO::File->new($filename, O_RDONLY)) { $vmfw_conf = parse_vm_fw_rules($filename, $fh); } @@ -2283,7 +2302,7 @@ my $format_ipset = sub { if $entry->{comment} && $entry->{comment} !~ m/^\s*$/; $raw .= "$line\n"; } - + return $raw; }; @@ -2307,11 +2326,12 @@ sub save_vmfw_conf { } sub read_vm_firewall_configs { - my ($vmdata) = @_; + my ($vmdata, $dir) = @_; + my $vmfw_configs = {}; foreach my $vmid (keys %{$vmdata->{qemu}}, keys %{$vmdata->{openvz}}) { - my $vmfw_conf = load_vmfw_conf($vmid); + my $vmfw_conf = load_vmfw_conf($vmid, $dir); next if !$vmfw_conf->{options}; # skip if file does not exists $vmfw_configs->{$vmid} = $vmfw_conf; } @@ -2430,35 +2450,14 @@ sub round_powerof2 { return ++$int; } -sub save_pvefw_status { - my ($status) = @_; - - die "unknown status '$status' - internal error" - if $status !~ m/^(stopped|active)$/; - - mkdir dirname($pve_fw_status_filename); - PVE::Tools::file_set_contents($pve_fw_status_filename, $status); -} - -sub read_pvefw_status { - - my $status = 'unknown'; - - return 'stopped' if ! -f $pve_fw_status_filename; - - eval { - $status = PVE::Tools::file_get_contents($pve_fw_status_filename); - }; - warn $@ if $@; - - return $status; -} - sub load_clusterfw_conf { + my ($filename) = @_; + + $filename = $clusterfw_conf_filename if !defined($filename); my $cluster_conf = {}; - if (my $fh = IO::File->new($clusterfw_conf_filename, O_RDONLY)) { - $cluster_conf = parse_cluster_fw_rules($clusterfw_conf_filename, $fh); + if (my $fh = IO::File->new($filename, O_RDONLY)) { + $cluster_conf = parse_cluster_fw_rules($filename, $fh); } return $cluster_conf; @@ -2474,7 +2473,7 @@ sub save_clusterfw_conf { my $aliases = $cluster_conf->{aliases}; $raw .= &$format_aliases($aliases) if scalar(keys %$aliases); - + foreach my $ipset (sort keys %{$cluster_conf->{ipset}}) { if (my $comment = $cluster_conf->{ipset_comments}->{$ipset}) { my $utf8comment = encode('utf8', $comment); @@ -2511,10 +2510,13 @@ sub save_clusterfw_conf { } sub load_hostfw_conf { + my ($filename) = @_; + + $filename = $hostfw_conf_filename if !defined($filename); my $hostfw_conf = {}; - if (my $fh = IO::File->new($hostfw_conf_filename, O_RDONLY)) { - $hostfw_conf = parse_host_fw_rules($hostfw_conf_filename, $fh); + if (my $fh = IO::File->new($filename, O_RDONLY)) { + $hostfw_conf = parse_host_fw_rules($filename, $fh); } return $hostfw_conf; } @@ -2538,16 +2540,32 @@ sub save_hostfw_conf { } sub compile { - my ($cluster_conf, $hostfw_conf) = @_; + my ($cluster_conf, $hostfw_conf, $vmdata) = @_; - $cluster_conf = load_clusterfw_conf() if !$cluster_conf; - $hostfw_conf = load_hostfw_conf() if !$hostfw_conf; + my $vmfw_configs; - my $vmdata = read_local_vm_config(); - my $vmfw_configs = read_vm_firewall_configs($vmdata); + if ($vmdata) { # test mode + my $testdir = $vmdata->{testdir} || die "no test directory specified"; + my $filename = "$testdir/cluster.fw"; + die "missing test file '$filename'\n" if ! -f $filename; + $cluster_conf = load_clusterfw_conf($filename); + + $filename = "$testdir/host.fw"; + die "missing test file '$filename'\n" if ! -f $filename; + $hostfw_conf = load_hostfw_conf($filename); + + $vmfw_configs = read_vm_firewall_configs($vmdata, $testdir); + } else { # normal operation + $cluster_conf = load_clusterfw_conf() if !$cluster_conf; + + $hostfw_conf = load_hostfw_conf() if !$hostfw_conf; + + $vmdata = read_local_vm_config(); + $vmfw_configs = read_vm_firewall_configs($vmdata); + } - my $ipset_ruleset = {}; - generate_ipset_chains($ipset_ruleset, $cluster_conf); + + $cluster_conf->{ipset}->{venet0} = []; my $ruleset = {}; @@ -2555,37 +2573,30 @@ sub compile { ruleset_create_chain($ruleset, "PVEFW-OUTPUT"); ruleset_create_chain($ruleset, "PVEFW-FORWARD"); - + my $hostfw_options = $hostfw_conf->{options} || {}; # fixme: what log level should we use here? my $loglevel = get_option_log_level($hostfw_options, "log_level_out"); - my $accept = ruleset_chain_exist($ruleset, "PVEFW-IPS") ? "PVEFW-IPS" : "ACCEPT"; - ruleset_chain_add_conn_filters($ruleset, "PVEFW-FORWARD", $accept); - - #ruleset_chain_add_conn_filters($ruleset, "PVEFW-FORWARD", $hostfw_options, $accept); - - if ($cluster_conf->{ipset}->{blacklist}){ - ruleset_addlog($ruleset, "PVEFW-FORWARD", 0, "DROP: ", $loglevel, "-m set --match-set PVEFW-blacklist src"); - ruleset_addrule($ruleset, "PVEFW-FORWARD", "-m set --match-set PVEFW-blacklist src -j DROP"); - } + ruleset_chain_add_conn_filters($ruleset, "PVEFW-FORWARD", "ACCEPT"); ruleset_create_chain($ruleset, "PVEFW-VENET-OUT"); - ruleset_addrule($ruleset, "PVEFW-FORWARD", "-i venet0 -j PVEFW-VENET-OUT"); + ruleset_addrule($ruleset, "PVEFW-FORWARD", "-i venet0 -m set --match-set PVEFW-venet0 src -j PVEFW-VENET-OUT"); + ruleset_addrule($ruleset, "PVEFW-INPUT", "-i venet0 -m set --match-set PVEFW-venet0 src -j PVEFW-VENET-OUT"); ruleset_create_chain($ruleset, "PVEFW-FWBR-IN"); - ruleset_chain_add_input_filters($ruleset, "PVEFW-FWBR-IN", $hostfw_options); + ruleset_chain_add_input_filters($ruleset, "PVEFW-FWBR-IN", $hostfw_options, $cluster_conf, $loglevel); - ruleset_addrule($ruleset, "PVEFW-FORWARD", "-m physdev --physdev-is-bridged --physdev-in link+ -j PVEFW-FWBR-IN"); + ruleset_addrule($ruleset, "PVEFW-FORWARD", "-m physdev --physdev-is-bridged --physdev-in fwln+ -j PVEFW-FWBR-IN"); ruleset_create_chain($ruleset, "PVEFW-FWBR-OUT"); - ruleset_addrule($ruleset, "PVEFW-FORWARD", "-m physdev --physdev-is-bridged --physdev-out link+ -j PVEFW-FWBR-OUT"); + ruleset_addrule($ruleset, "PVEFW-FORWARD", "-m physdev --physdev-is-bridged --physdev-out fwln+ -j PVEFW-FWBR-OUT"); ruleset_create_chain($ruleset, "PVEFW-VENET-IN"); - ruleset_chain_add_input_filters($ruleset, "PVEFW-VENET-IN", $hostfw_options); + ruleset_chain_add_input_filters($ruleset, "PVEFW-VENET-IN", $hostfw_options, $cluster_conf, $loglevel); - ruleset_addrule($ruleset, "PVEFW-FORWARD", "-o venet0 -j PVEFW-VENET-IN"); + ruleset_addrule($ruleset, "PVEFW-FORWARD", "-o venet0 -m set --match-set PVEFW-venet0 dst -j PVEFW-VENET-IN"); generate_std_chains($ruleset, $hostfw_options); @@ -2593,6 +2604,8 @@ sub compile { enable_host_firewall($ruleset, $hostfw_conf, $cluster_conf) if $hostfw_enable; + ruleset_addrule($ruleset, "PVEFW-OUTPUT", "-o venet0 -m set --match-set PVEFW-venet0 dst -j PVEFW-VENET-IN"); + # generate firewall rules for QEMU VMs foreach my $vmid (keys %{$vmdata->{qemu}}) { my $conf = $vmdata->{qemu}->{$vmid}; @@ -2603,7 +2616,7 @@ sub compile { foreach my $netid (keys %$conf) { next if $netid !~ m/^net(\d+)$/; my $net = PVE::QemuServer::parse_net($conf->{$netid}); - next if !$net; + next if !$net->{firewall}; my $iface = "tap${vmid}i$1"; my $macaddr = $net->{macaddr}; @@ -2624,6 +2637,17 @@ sub compile { if ($conf->{ip_address} && $conf->{ip_address}->{value}) { my $ip = $conf->{ip_address}->{value}; + $ip =~ s/\s+/,/g; + parse_address_list($ip); # make sure we have a valid $ip list + + my @ips = split(',', $ip); + + foreach my $singleip (@ips) { + my $venet0ipset = {}; + $venet0ipset->{cidr} = $singleip; + push @{$cluster_conf->{ipset}->{venet0}}, $venet0ipset; + } + generate_venet_rules_direction($ruleset, $cluster_conf, $hostfw_conf, $vmfw_conf, $vmid, $ip, 'IN'); generate_venet_rules_direction($ruleset, $cluster_conf, $hostfw_conf, $vmfw_conf, $vmid, $ip, 'OUT'); } @@ -2643,6 +2667,13 @@ sub compile { } } + if(ruleset_chain_exist($ruleset, "PVEFW-IPS")){ + ruleset_insertrule($ruleset, "PVEFW-FORWARD", "-m conntrack --ctstate RELATED,ESTABLISHED -j PVEFW-IPS"); + } + + my $ipset_ruleset = {}; + generate_ipset_chains($ipset_ruleset, $cluster_conf); + return ($ruleset, $ipset_ruleset); } @@ -2762,7 +2793,7 @@ sub get_ipset_cmdlist { my $active_chains = ipset_get_chains(); my $statushash = get_ruleset_status($ruleset, $active_chains, \&ipset_chain_digest, $verbose); - # remove stale _swap chains + # remove stale _swap chains foreach my $chain (keys %$active_chains) { if ($chain =~ m/^PVEFW-\S+_swap$/) { $cmdlist .= "destroy $chain\n"; @@ -2913,7 +2944,7 @@ sub remove_pvefw_chains { } sub update { - my ($start, $verbose) = @_; + my ($verbose) = @_; my $code = sub { @@ -2922,9 +2953,7 @@ sub update { my $enable = $cluster_options->{enable}; - my $status = read_pvefw_status(); - - die "Firewall is disabled - cannot start\n" if !$enable && $start; + die "Firewall is disabled - cannot start\n" if !$enable; if (!$enable) { PVE::Firewall::remove_pvefw_chains(); @@ -2936,14 +2965,7 @@ sub update { my ($ruleset, $ipset_ruleset) = compile($cluster_conf, $hostfw_conf); - if ($start || $status eq 'active') { - - save_pvefw_status('active') if ($status ne 'active'); - - apply_ruleset($ruleset, $hostfw_conf, $ipset_ruleset, $verbose); - } else { - print "Firewall not active (status = $status)\n" if $verbose; - } + apply_ruleset($ruleset, $hostfw_conf, $ipset_ruleset, $verbose); }; run_locked($code);