return 1;
}
-sub ruleset_generate_rule {
+sub ruleset_generate_cmdstr {
my ($ruleset, $chain, $rule, $actions, $goto) = @_;
return if $rule->{disable};
my @cmd = ();
+ push @cmd, "-i $rule->{iface_in}" if $rule->{iface_in};
+ push @cmd, "-o $rule->{iface_out}" if $rule->{iface_out};
+
push @cmd, "-m iprange --src-range" if $rule->{nbsource} && $rule->{nbsource} > 1;
push @cmd, "-s $rule->{source}" if $rule->{source};
push @cmd, "-m iprange --dst-range" if $rule->{nbdest} && $rule->{nbdest} > 1;
push @cmd, $goto ? "-g $action" : "-j $action";
}
- if (scalar(@cmd)) {
- my $cmdstr = join(' ', @cmd);
+ return scalar(@cmd) ? join(' ', @cmd) : undef;
+}
+
+sub ruleset_generate_rule {
+ my ($ruleset, $chain, $rule, $actions, $goto) = @_;
+
+ if (my $cmdstr = ruleset_generate_cmdstr($ruleset, $chain, $rule, $actions, $goto)) {
ruleset_addrule($ruleset, $chain, $cmdstr);
}
}
+sub ruleset_generate_rule_insert {
+ my ($ruleset, $chain, $rule, $actions, $goto) = @_;
+
+ if (my $cmdstr = ruleset_generate_cmdstr($ruleset, $chain, $rule, $actions, $goto)) {
+ ruleset_insertrule($ruleset, $chain, $cmdstr);
+ }
+}
sub ruleset_create_chain {
my ($ruleset, $chain) = @_;
sub generate_bridge_chains {
my ($ruleset, $hostfw_conf, $bridge) = @_;
- my $options = $hostfw_conf->{options} || {};
-
- # fixme: what log level should we use here?
- my $loglevel = get_option_log_level($options, "log_level_out");
-
if (!ruleset_chain_exist($ruleset, "$bridge-FW")) {
ruleset_create_chain($ruleset, "$bridge-FW");
ruleset_addrule($ruleset, "PVEFW-FORWARD", "-o $bridge -m physdev --physdev-is-bridged -j $bridge-FW");
ruleset_addrule($ruleset, "PVEFW-FORWARD", "-i $bridge -m physdev --physdev-is-bridged -j $bridge-FW");
- # disable interbridge routing
- ruleset_addrule($ruleset, "PVEFW-FORWARD", "-o $bridge -j PVEFW-Drop");
- ruleset_addrule($ruleset, "PVEFW-FORWARD", "-i $bridge -j PVEFW-Drop");
- ruleset_addrule($ruleset, "PVEFW-FORWARD", "-o $bridge -j LOG --log-prefix \"PVEFW-FORWARD-dropped \" --log-level $loglevel");
- ruleset_addrule($ruleset, "PVEFW-FORWARD", "-i $bridge -j LOG --log-prefix \"PVEFW-FORWARD-dropped \" --log-level $loglevel");
- ruleset_addrule($ruleset, "PVEFW-FORWARD", "-o $bridge -j DROP");
- ruleset_addrule($ruleset, "PVEFW-FORWARD", "-i $bridge -j DROP");
}
if (!ruleset_chain_exist($ruleset, "$bridge-OUT")) {
ruleset_create_chain($ruleset, "$bridge-OUT");
ruleset_addrule($ruleset, "$bridge-FW", "-m physdev --physdev-is-bridged --physdev-is-in -j $bridge-OUT");
- ruleset_addrule($ruleset, "PVEFW-INPUT", "-i $bridge -m physdev --physdev-is-bridged --physdev-is-in -j $bridge-OUT");
+ ruleset_insertrule($ruleset, "PVEFW-INPUT", "-i $bridge -m physdev --physdev-is-bridged --physdev-is-in -j $bridge-OUT");
}
if (!ruleset_chain_exist($ruleset, "$bridge-IN")) {
my $accept_action = $direction eq 'OUT' ? "PVEFW-SET-ACCEPT-MARK" : "ACCEPT";
ruleset_add_chain_policy($ruleset, $chain, $policy, $loglevel, $accept_action);
-
+ # plug into FORWARD, INPUT and OUTPUT chain
+ if ($direction eq 'OUT') {
+ ruleset_generate_rule_insert($ruleset, "PVEFW-FORWARD", {
+ 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-FORWARD", {
+ action => $chain,
+ dest => $ip,
+ iface_out => 'venet0'});
+
+ ruleset_generate_rule($ruleset, "PVEFW-OUTPUT", {
+ action => $chain,
+ dest => $ip,
+ iface_out => 'venet0'});
+ }
}
sub generate_tap_rules_direction {
ruleset_create_chain($ruleset, "PVEFW-OUTPUT");
ruleset_create_chain($ruleset, "PVEFW-FORWARD");
- ruleset_addrule($ruleset, "PVEFW-FORWARD", "-m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT");
my $hostfw_options = {};
my $hostfw_conf = {};
}
}
+ # 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");
+
+ # fixme: should we really block inter-bridge traffic?
+
+ # always allow traffic from containers?
+ ruleset_addrule($ruleset, "PVEFW-FORWARD", "-i venet0 -j RETURN");
+
+ # disable interbridge routing
+ ruleset_addrule($ruleset, "PVEFW-FORWARD", "-o vmbr+ -j PVEFW-Drop");
+ ruleset_addrule($ruleset, "PVEFW-FORWARD", "-i vmbr+ -j PVEFW-Drop");
+ ruleset_addrule($ruleset, "PVEFW-FORWARD", "-o vmbr+ -j LOG --log-prefix \"PVEFW-FORWARD-dropped \" --log-level $loglevel");
+ ruleset_addrule($ruleset, "PVEFW-FORWARD", "-i vmbr+ -j LOG --log-prefix \"PVEFW-FORWARD-dropped \" --log-level $loglevel");
+ ruleset_addrule($ruleset, "PVEFW-FORWARD", "-o vmbr+ -j DROP");
+ ruleset_addrule($ruleset, "PVEFW-FORWARD", "-i vmbr+ -j DROP");
+
return wantarray ? ($ruleset, $hostfw_conf) : $ruleset;
}
}
sub apply_ruleset {
- my ($ruleset, $verbose) = @_;
+ my ($ruleset, $hostfw_conf, $verbose) = @_;
enable_bridge_firewall();
+ update_nf_conntrack_max($hostfw_conf);
+
my $cmdlist = get_rulset_cmdlist($ruleset, $verbose);
print $cmdlist if $verbose;
my ($ruleset, $hostfw_conf) = PVE::Firewall::compile();
- update_nf_conntrack_max($hostfw_conf);
-
if ($start || $status eq 'active') {
save_pvefw_status('active') if ($status ne 'active');
- PVE::Firewall::apply_ruleset($ruleset, $verbose);
+ apply_ruleset($ruleset, $hostfw_conf, $verbose);
} else {
print "Firewall not active (status = $status)\n" if $verbose;
}