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}";
}
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");
}
}
+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) = @_;
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 {
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");
# 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
# 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
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);
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}$/;
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) {
ruleset_chain_add_conn_filters($ruleset, "PVEFW-FORWARD", "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_create_chain($ruleset, "PVEFW-VENET-OUT");
ruleset_addrule($ruleset, "PVEFW-FORWARD", "-i venet0 -j PVEFW-VENET-OUT");
ruleset_addrule($ruleset, "PVEFW-INPUT", "-i venet0 -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 fwln+ -j PVEFW-FWBR-IN");
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");
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};