[pve-devel] [PATCH 2/2] apply ebtables_ruleset
Alexandre Derumier
aderumier at odiso.com
Tue Jul 15 17:45:22 CEST 2014
need ebtables-save && ebtables-restore, ebtables debian package don't include them.
ebtables-restore need to restore the full ruleset (atomicaly),
so we can't update only 1 chain
Signed-off-by: Alexandre Derumier <aderumier at odiso.com>
---
src/PVE/Firewall.pm | 103 +++++++++++++++++++++++++++++++++++++++++++++++++--
src/pve-firewall | 7 +++-
2 files changed, 105 insertions(+), 5 deletions(-)
diff --git a/src/PVE/Firewall.pm b/src/PVE/Firewall.pm
index fed9e12..d092018 100644
--- a/src/PVE/Firewall.pm
+++ b/src/PVE/Firewall.pm
@@ -1395,6 +1395,12 @@ sub ipset_restore_cmdlist {
run_command("/usr/sbin/ipset restore", input => $cmdlist);
}
+sub ebtables_restore_cmdlist {
+ my ($cmdlist) = @_;
+
+ run_command("/sbin/ebtables-restore", input => $cmdlist);
+}
+
sub iptables_get_chains {
my ($iptablescmd) = @_;
@@ -1507,6 +1513,43 @@ sub ipset_get_chains {
return $res;
}
+sub ebtables_get_chains {
+
+ my $res = {};
+ my $chains = {};
+
+ my $parser = sub {
+ my $line = shift;
+ return if $line =~ m/^#/;
+ return if $line =~ m/^\s*$/;
+ if ($line =~ m/^(?:\S+)\s(PVEFW-\S+)\s(?:\S+).*/) {
+ my $chain = $1;
+ $line =~ s/\s+$//;
+ push @{$chains->{$chain}}, $line;
+ }elsif ($line =~ m/^(?:\S+)\s(tap\d+i\d+-(:?IN|OUT))\s(?:\S+).*/) {
+ my $chain = $1;
+ $line =~ s/\s+$//;
+ push @{$chains->{$chain}}, $line;
+ }elsif ($line =~ m/^(?:\S+)\s(veth\d+.\d+-(:?IN|OUT))\s(?:\S+).*/) {
+ my $chain = $1;
+ $line =~ s/\s+$//;
+ push @{$chains->{$chain}}, $line;
+
+ }else {
+ # simply ignore the rest
+ return;
+ }
+ };
+
+ run_command("/sbin/ebtables-save", outfunc => $parser);
+
+ # compute digest for each chain
+ foreach my $chain (keys %$chains) {
+ $res->{$chain} = iptables_chain_digest($chains->{$chain});
+ }
+ return $res;
+}
+
sub ruleset_generate_cmdstr {
my ($ruleset, $chain, $rule, $actions, $goto, $cluster_conf, $fw_conf) = @_;
@@ -3311,7 +3354,6 @@ sub get_ruleset_cmdlist {
my $stat = $statushash->{$chain};
die "internal error" if !$stat;
next if $stat->{action} ne 'create';
-
$cmdlist .= ":$chain - [0:0]\n";
}
@@ -3360,6 +3402,42 @@ sub get_ruleset_cmdlist {
return wantarray ? ($cmdlist, $changes) : $cmdlist;
}
+sub get_ebtables_cmdlist {
+ my ($ruleset, $verbose) = @_;
+
+ my $changes = 0;
+ my $cmdlist = "*filter\n";
+
+ my ($active_chains, $hooks) = ebtables_get_chains();
+ my $statushash = get_ruleset_status($ruleset, $active_chains, \&iptables_chain_digest, $verbose);
+
+ # create chains first
+ foreach my $chain (sort keys %$ruleset) {
+ my $stat = $statushash->{$chain};
+ die "internal error" if !$stat;
+ $cmdlist .= ":$chain ACCEPT\n";
+ }
+
+ foreach my $h (qw(FORWARD)) {
+ my $chain = "PVEFW-$h";
+ if ($ruleset->{$chain}) {
+ $cmdlist .= "-A $h -j $chain\n";
+ }
+ }
+
+ foreach my $chain (sort keys %$ruleset) {
+ my $stat = $statushash->{$chain};
+ die "internal error" if !$stat;
+ $changes = 1 if ($stat->{action} ne 'exists');
+
+ foreach my $cmd (@{$ruleset->{$chain}}) {
+ $cmdlist .= "$cmd\n";
+ }
+ }
+
+ return wantarray ? ($cmdlist, $changes) : $cmdlist;
+}
+
sub get_ipset_cmdlist {
my ($ruleset, $verbose) = @_;
@@ -3420,7 +3498,7 @@ sub get_ipset_cmdlist {
}
sub apply_ruleset {
- my ($ruleset, $hostfw_conf, $ipset_ruleset, $rulesetv6, $verbose) = @_;
+ my ($ruleset, $hostfw_conf, $ipset_ruleset, $rulesetv6, $ebtables_ruleset, $verbose) = @_;
enable_bridge_firewall();
@@ -3429,6 +3507,7 @@ sub apply_ruleset {
my ($cmdlist, $changes) = get_ruleset_cmdlist($ruleset, $verbose);
my ($cmdlistv6, $changesv6) = get_ruleset_cmdlist($rulesetv6, $verbose, "ip6tables");
+ my ($ebtables_cmdlist, $ebtables_changes) = get_ebtables_cmdlist($ebtables_ruleset, $verbose);
if ($verbose) {
if ($ipset_changes) {
@@ -3446,6 +3525,11 @@ sub apply_ruleset {
print "ip6tables changes:\n";
print $cmdlistv6;
}
+
+ if ($ebtables_changes) {
+ print "ebtables changes:\n";
+ print $ebtables_cmdlist;
+ }
}
ipset_restore_cmdlist($ipset_create_cmdlist);
@@ -3455,6 +3539,8 @@ sub apply_ruleset {
ipset_restore_cmdlist($ipset_delete_cmdlist) if $ipset_delete_cmdlist;
+ ebtables_restore_cmdlist($ebtables_cmdlist);
+
# test: re-read status and check if everything is up to date
my $active_chains = iptables_get_chains();
my $statushash = get_ruleset_status($ruleset, $active_chains, \&iptables_chain_digest, 0);
@@ -3479,6 +3565,17 @@ sub apply_ruleset {
}
}
+ my $active_ebtables_chains = ebtables_get_chains();
+ my $ebtables_statushash = get_ruleset_status($ebtables_ruleset, $active_ebtables_chains, \&iptables_chain_digest, 0);
+
+ foreach my $chain (sort keys %$ebtables_ruleset) {
+ my $stat = $ebtables_statushash->{$chain};
+ if ($stat->{action} ne 'exists') {
+ warn "ebtables : unable to update chain '$chain'\n";
+ $errors = 1;
+ }
+ }
+
die "unable to apply firewall changes\n" if $errors;
update_nf_conntrack_max($hostfw_conf);
@@ -3580,7 +3677,7 @@ sub update {
my ($ruleset, $ipset_ruleset, $rulesetv6, $ebtables_ruleset) = compile($cluster_conf, $hostfw_conf);
- apply_ruleset($ruleset, $hostfw_conf, $ipset_ruleset, $rulesetv6);
+ apply_ruleset($ruleset, $hostfw_conf, $ipset_ruleset, $rulesetv6, $ebtables_ruleset);
};
run_locked($code);
diff --git a/src/pve-firewall b/src/pve-firewall
index 8e4c68d..b239c8f 100755
--- a/src/pve-firewall
+++ b/src/pve-firewall
@@ -350,8 +350,9 @@ __PACKAGE__->register_method ({
my (undef, undef, $ipset_changes) = PVE::Firewall::get_ipset_cmdlist($ipset_ruleset, $verbose);
my ($test, $ruleset_changes) = PVE::Firewall::get_ruleset_cmdlist($ruleset, $verbose);
my (undef, $ruleset_changesv6) = PVE::Firewall::get_ruleset_cmdlist($rulesetv6, $verbose, "ip6tables");
+ my (undef, $ebtables_changes) = PVE::Firewall::get_ebtables_cmdlist($ebtables_ruleset, $verbose);
- $res->{changes} = ($ipset_changes || $ruleset_changes || $ruleset_changesv6) ? 1 : 0;
+ $res->{changes} = ($ipset_changes || $ruleset_changes || $ruleset_changesv6 || $ebtables_changes) ? 1 : 0;
}
return $res;
@@ -386,8 +387,10 @@ __PACKAGE__->register_method ({
my (undef, undef, $ipset_changes) = PVE::Firewall::get_ipset_cmdlist($ipset_ruleset, $verbose);
my (undef, $ruleset_changes) = PVE::Firewall::get_ruleset_cmdlist($ruleset, $verbose);
my (undef, $ruleset_changesv6) = PVE::Firewall::get_ruleset_cmdlist($rulesetv6, $verbose, "ip6tables");
+ my (undef, $ebtables_changes) = PVE::Firewall::get_ebtables_cmdlist($ebtables_ruleset, $verbose);
- if ($ipset_changes || $ruleset_changes || $ruleset_changesv6) {
+
+ if ($ipset_changes || $ruleset_changes || $ruleset_changesv6 || $ebtables_changes) {
print "detected changes\n";
} else {
print "no changes\n";
--
1.7.10.4
More information about the pve-devel
mailing list