X-Git-Url: https://git.proxmox.com/?p=pve-firewall.git;a=blobdiff_plain;f=src%2FPVE%2FFirewall.pm;h=6d715c20f6348fd7fe745b1cff1f27824e34b0a8;hp=3c8d687bf008f4f43afcb53a8476ab8d14146832;hb=4ac863a6076f6d6d83efe940c4e52c75b450771b;hpb=8b27beb907eff6f132d6830739328781dcfb36cb diff --git a/src/PVE/Firewall.pm b/src/PVE/Firewall.pm index 3c8d687..6d715c2 100644 --- a/src/PVE/Firewall.pm +++ b/src/PVE/Firewall.pm @@ -13,6 +13,7 @@ use File::Path; use IO::File; use Net::IP; use PVE::Tools qw(run_command lock_file); +use Encode; # dynamically include PVE::QemuServer and PVE::OpenVZ # to avoid dependency problems @@ -968,7 +969,11 @@ sub ruleset_create_vm_chain { } if (!(defined($options->{dhcp}) && $options->{dhcp} == 0)) { - ruleset_addrule($ruleset, $chain, "-p udp -m udp --dport 67:68 -j ACCEPT"); + if ($direction eq 'OUT') { + ruleset_addrule($ruleset, $chain, "-p udp -m udp --sport 68 --dport 67 -j PVEFW-SET-ACCEPT-MARK"); + } else { + ruleset_addrule($ruleset, $chain, "-p udp -m udp --sport 67 --dport 68 -j ACCEPT"); + } } if ($options->{tcpflags}) { @@ -1120,6 +1125,14 @@ sub enable_host_firewall { my $loglevel = get_option_log_level($options, "log_level_in"); + if (!(defined($options->{nosmurfs}) && $options->{nosmurfs} == 0)) { + ruleset_addrule($ruleset, $chain, "-m conntrack --ctstate INVALID,NEW -j PVEFW-smurfs"); + } + + if ($options->{tcpflags}) { + ruleset_addrule($ruleset, $chain, "-p tcp -j PVEFW-tcpflags"); + } + ruleset_addrule($ruleset, $chain, "-m conntrack --ctstate INVALID -j DROP"); ruleset_addrule($ruleset, $chain, "-m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT"); ruleset_addrule($ruleset, $chain, "-i lo -j ACCEPT"); @@ -1170,8 +1183,7 @@ sub enable_host_firewall { sub generate_group_rules { my ($ruleset, $groups_conf, $group) = @_; - - die "no such security group '$group'\n" if !$groups_conf->{$group}; + die "no such security group '$group'\n" if !$groups_conf->{rules}->{$group}; my $rules = $groups_conf->{rules}->{$group}; @@ -1213,7 +1225,7 @@ sub parse_fw_rule { my ($type, $action, $iface, $source, $dest, $proto, $dport, $sport); # we can add single line comments to the end of the rule - my $comment = $1 if $line =~ s/#\s*(.*?)\s*$//; + my $comment = decode('utf8', $1) if $line =~ s/#\s*(.*?)\s*$//; # we can disable a rule when prefixed with '|' my $disable = 1 if $line =~ s/^\|//; @@ -1400,7 +1412,11 @@ sub parse_vm_fw_rules { my $section; + my $digest = Digest::SHA->new('sha1'); + while (defined(my $line = <$fh>)) { + $digest->add($line); + next if $line =~ m/^#/; next if $line =~ m/^\s*$/; @@ -1438,6 +1454,8 @@ sub parse_vm_fw_rules { push @{$res->{$section}}, @$rules; } + $res->{digest} = $digest->b64digest; + return $res; } @@ -1587,16 +1605,27 @@ sub read_local_vm_config { return $vmdata; }; +sub load_vmfw_conf { + my ($vmid) = @_; + + my $vmfw_conf = {}; + + my $filename = "/etc/pve/firewall/$vmid.fw"; + if (my $fh = IO::File->new($filename, O_RDONLY)) { + $vmfw_conf = parse_vm_fw_rules($filename, $fh); + } + + return $vmfw_conf; +} + sub read_vm_firewall_configs { my ($vmdata) = @_; my $vmfw_configs = {}; foreach my $vmid (keys %{$vmdata->{qemu}}, keys %{$vmdata->{openvz}}) { - my $filename = "/etc/pve/firewall/$vmid.fw"; - my $fh = IO::File->new($filename, O_RDONLY); - next if !$fh; - - $vmfw_configs->{$vmid} = parse_vm_fw_rules($filename, $fh); + my $vmfw_conf = load_vmfw_conf($vmid); + next if !$vmfw_conf->{options}; # skip if file does not exists + $vmfw_configs->{$vmid} = $vmfw_conf; } return $vmfw_configs; @@ -1810,9 +1839,6 @@ sub compile { } } - # fixme: this is an optimization? if so, we should also drop INVALID packages? - ruleset_insertrule($ruleset, "PVEFW-FORWARD", "-m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT"); - # fixme: what log level should we use here? my $loglevel = get_option_log_level($hostfw_options, "log_level_out");