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
return ($nbports);
}
+# helper function for API
+sub cleanup_fw_rule {
+ my ($rule, $digest, $pos) = @_;
+
+ my $r = {};
+
+ foreach my $k (keys %$rule) {
+ next if $k eq 'nbdport';
+ next if $k eq 'nbsport';
+ my $v = $rule->{$k};
+ next if !defined($v);
+ $r->{$k} = $v;
+ $r->{digest} = $digest;
+ $r->{pos} = $pos;
+ }
+
+ return $r;
+}
+
my $bridge_firewall_enabled = 0;
sub enable_bridge_firewall {
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/^\|//;
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*$/;
push @{$res->{$section}}, @$rules;
}
+ $res->{digest} = $digest->b64digest;
+
return $res;
}
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*$/;
push @{$res->{$section}}, @$rules;
}
+ $res->{digest} = $digest->b64digest;
+
return $res;
}
my $res = { rules => {} };
+ my $digest = Digest::SHA->new('sha1');
+
while (defined(my $line = <$fh>)) {
+ $digest->add($line);
+
next if $line =~ m/^#/;
next if $line =~ m/^\s*$/;
push @{$res->{$section}->{$group}}, @$rules;
}
+ $res->{digest} = $digest->b64digest;
+
return $res;
}
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;
return $groups_conf;
}
+sub load_hostfw_conf {
+
+ my $hostfw_conf = {};
+ my $filename = "/etc/pve/local/host.fw";
+ if (my $fh = IO::File->new($filename, O_RDONLY)) {
+ $hostfw_conf = parse_host_fw_rules($filename, $fh);
+ }
+ return $hostfw_conf;
+}
+
sub compile {
my $vmdata = read_local_vm_config();
my $vmfw_configs = read_vm_firewall_configs($vmdata);
ruleset_create_chain($ruleset, "PVEFW-FORWARD");
- my $hostfw_options = {};
- my $hostfw_conf = {};
-
- my $filename = "/etc/pve/local/host.fw";
- if (my $fh = IO::File->new($filename, O_RDONLY)) {
- $hostfw_conf = parse_host_fw_rules($filename, $fh);
- $hostfw_options = $hostfw_conf->{options};
- }
+ my $hostfw_conf = load_hostfw_conf();
+ my $hostfw_options = $hostfw_conf->{options} || {};
generate_std_chains($ruleset, $hostfw_options);
}
}
- # 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");