From 359b7c971a88f6dff64e8e4d558210a880f3ee0f Mon Sep 17 00:00:00 2001 From: Ian Wienand Date: Thu, 7 May 2015 14:59:38 +1000 Subject: [PATCH] Ensure netfilter is enabled for bridges Since security-groups use iptables rules on Linux bridges, we need to ensure that netfilter is enabled for bridges. Unfortunately, there seems to be a long history of distributions having differing defaults for this, best described in [1]. It seems at the moment everyone has to discover this for themselves; packstack found it in Ia8c86dcb31810a8d6b133a161388604fde9bead4, then fuel found the same thing in I8582c24706c3a7253e00569eef275f116d765bca and then finally someone else hit it and put it into documentation with I4ed3cec03a1b3a7d56dfe18394154ec1b2db6791. I just spent a long time figuring it out too when deploying with devstack. Rather than having yet another fix in devstack, I don't see why neutron shouldn't be ensuring the setting is correct when it starts up -- without these settings enabled, security-groups are silently broken. This does that, and modifies test-cases to check we make the calls. [1] http://wiki.libvirt.org/page/Net.bridge-nf-call_and_sysctl.conf Change-Id: If2d316eb8c422dc1e4f34b17a50b93dd72993a99 --- neutron/agent/linux/iptables_firewall.py | 29 ++++++++++++++++++- .../unit/agent/test_securitygroups_rpc.py | 10 +++++++ 2 files changed, 38 insertions(+), 1 deletion(-) diff --git a/neutron/agent/linux/iptables_firewall.py b/neutron/agent/linux/iptables_firewall.py index 840fba7f6..5cea8e39b 100644 --- a/neutron/agent/linux/iptables_firewall.py +++ b/neutron/agent/linux/iptables_firewall.py @@ -22,6 +22,7 @@ from neutron.agent import firewall from neutron.agent.linux import ipset_manager from neutron.agent.linux import iptables_comments as ic from neutron.agent.linux import iptables_manager +from neutron.agent.linux import utils from neutron.common import constants from neutron.common import ipv6_utils from neutron.extensions import portsecurity as psec @@ -71,6 +72,32 @@ class IptablesFirewallDriver(firewall.FirewallDriver): lambda: collections.defaultdict(list)) self.pre_sg_members = None self.enable_ipset = cfg.CONF.SECURITYGROUP.enable_ipset + self._enabled_netfilter_for_bridges = False + + def _enable_netfilter_for_bridges(self): + # we only need to set these values once, but it has to be when + # we create a bridge; before that the bridge module might not + # be loaded and the proc values aren't there. + if self._enabled_netfilter_for_bridges: + return + else: + self._enabled_netfilter_for_bridges = True + + # These proc values ensure that netfilter is enabled on + # bridges; essential for enforcing security groups rules with + # OVS Hybrid. Distributions can differ on whether this is + # enabled by default or not (Ubuntu - yes, Redhat - no, for + # example). + LOG.debug("Enabling netfilter for bridges") + utils.execute(['sysctl', '-w', + 'net.bridge.bridge-nf-call-arptables=1'], + run_as_root=True) + utils.execute(['sysctl', '-w', + 'net.bridge.bridge-nf-call-ip6tables=1'], + run_as_root=True) + utils.execute(['sysctl', '-w', + 'net.bridge.bridge-nf-call-iptables=1'], + run_as_root=True) @property def ports(self): @@ -103,7 +130,7 @@ class IptablesFirewallDriver(firewall.FirewallDriver): LOG.debug("Preparing device (%s) filter", port['device']) self._remove_chains() self._set_ports(port) - + self._enable_netfilter_for_bridges() # each security group has it own chains self._setup_chains() self.iptables.apply() diff --git a/neutron/tests/unit/agent/test_securitygroups_rpc.py b/neutron/tests/unit/agent/test_securitygroups_rpc.py index b732b6b5a..6d050e6cc 100644 --- a/neutron/tests/unit/agent/test_securitygroups_rpc.py +++ b/neutron/tests/unit/agent/test_securitygroups_rpc.py @@ -2483,6 +2483,9 @@ class TestSecurityGroupAgentWithIptables(base.BaseTestCase): cfg.CONF.set_override('enable_ipset', False, group='SECURITYGROUP') cfg.CONF.set_override('comment_iptables_rules', False, group='AGENT') + self.utils_exec = mock.patch( + 'neutron.agent.linux.utils.execute').start() + self.rpc = mock.Mock() self._init_agent(defer_refresh_firewall) @@ -2607,6 +2610,13 @@ class TestSecurityGroupAgentWithIptables(base.BaseTestCase): self.assertThat(kwargs['process_input'], matchers.MatchesRegex(expected_regex)) + expected = ['net.bridge.bridge-nf-call-arptables=1', + 'net.bridge.bridge-nf-call-ip6tables=1', + 'net.bridge.bridge-nf-call-iptables=1'] + for e in expected: + self.utils_exec.assert_any_call(['sysctl', '-w', e], + run_as_root=True) + def _replay_iptables(self, v4_filter, v6_filter, raw): self._register_mock_call( ['iptables-save', '-c'], -- 2.45.2