From: Yalei Wang Date: Fri, 7 Aug 2015 14:43:30 +0000 (+0800) Subject: Add support for unaddressed port X-Git-Url: https://review.fuel-infra.org/gitweb?a=commitdiff_plain;h=d4c52b7f5a36a103a92bf9dcda7f371959112292;p=openstack-build%2Fneutron-build.git Add support for unaddressed port Neutron could create a port without the IP address when the network doesn't have a subnet. In this case, neutron will have no L3 knowledgee and we need remove the L3 filter on it but reserve the L2 filter if there is. This patch will make L2 agent verify the fixed_ips before converting the security-group-rules into firewall rules, L3 rules in it will be removed. And filter like arp-spoofing will be disabled for this port. Partially Implements: blueprint vm-without-l3-address Change-Id: I5cd1fdfa13a7e57258be7251768eaa8ba64d486e --- diff --git a/neutron/agent/linux/iptables_firewall.py b/neutron/agent/linux/iptables_firewall.py index a080e6ef2..6b6ffe1f1 100644 --- a/neutron/agent/linux/iptables_firewall.py +++ b/neutron/agent/linux/iptables_firewall.py @@ -45,6 +45,13 @@ LINUX_DEV_LEN = 14 comment_rule = iptables_manager.comment_rule +def port_needs_l3_security(port): + if port['fixed_ips'] or port.get('allowed_address_pairs'): + return True + else: + return False + + class IptablesFirewallDriver(firewall.FirewallDriver): """Driver which enforces security groups through iptables rules.""" IPTABLES_DIRECTION = {firewall.INGRESS_DIRECTION: 'physdev-out', @@ -367,17 +374,20 @@ class IptablesFirewallDriver(firewall.FirewallDriver): mac_ipv6_pairs.append((mac, ip_address)) def _spoofing_rule(self, port, ipv4_rules, ipv6_rules): - # Allow dhcp client packets - ipv4_rules += [comment_rule('-p udp -m udp --sport 68 --dport 67 ' - '-j RETURN', comment=ic.DHCP_CLIENT)] - # Drop Router Advts from the port. - ipv6_rules += [comment_rule('-p icmpv6 --icmpv6-type %s ' - '-j DROP' % constants.ICMPV6_TYPE_RA, - comment=ic.IPV6_RA_DROP)] - ipv6_rules += [comment_rule('-p icmpv6 -j RETURN', - comment=ic.IPV6_ICMP_ALLOW)] - ipv6_rules += [comment_rule('-p udp -m udp --sport 546 --dport 547 ' - '-j RETURN', comment=ic.DHCP_CLIENT)] + if port_needs_l3_security(port): + # Allow dhcp client packets + ipv4_rules += [comment_rule('-p udp -m udp --sport 68 --dport 67 ' + '-j RETURN', comment=ic.DHCP_CLIENT)] + # Drop Router Advts from the port. + ipv6_rules += [comment_rule('-p icmpv6 --icmpv6-type %s ' + '-j DROP' % constants.ICMPV6_TYPE_RA, + comment=ic.IPV6_RA_DROP)] + ipv6_rules += [comment_rule('-p icmpv6 -j RETURN', + comment=ic.IPV6_ICMP_ALLOW)] + ipv6_rules += [comment_rule('-p udp -m udp --sport 546 --dport ' + '547 -j RETURN', + comment=ic.DHCP_CLIENT)] + mac_ipv4_pairs = [] mac_ipv6_pairs = [] @@ -483,11 +493,14 @@ class IptablesFirewallDriver(firewall.FirewallDriver): ipv6_iptables_rules) elif direction == firewall.INGRESS_DIRECTION: ipv6_iptables_rules += self._accept_inbound_icmpv6() - # include IPv4 and IPv6 iptable rules from security group - ipv4_iptables_rules += self._convert_sgr_to_iptables_rules( - ipv4_sg_rules) - ipv6_iptables_rules += self._convert_sgr_to_iptables_rules( - ipv6_sg_rules) + + if port_needs_l3_security(port): + # include IPv4 and IPv6 iptable rules from security group + ipv4_iptables_rules += self._convert_sgr_to_iptables_rules( + ipv4_sg_rules) + ipv6_iptables_rules += self._convert_sgr_to_iptables_rules( + ipv6_sg_rules) + # finally add the rules to the port chain for a given direction self._add_rules_to_chain_v4v6(self._port_chain_name(port, direction), ipv4_iptables_rules, @@ -498,7 +511,8 @@ class IptablesFirewallDriver(firewall.FirewallDriver): self._spoofing_rule(port, ipv4_iptables_rules, ipv6_iptables_rules) - self._drop_dhcp_rule(ipv4_iptables_rules, ipv6_iptables_rules) + if port_needs_l3_security(port): + self._drop_dhcp_rule(ipv4_iptables_rules, ipv6_iptables_rules) def _update_ipset_members(self, security_group_ids): for ip_version, sg_ids in security_group_ids.items(): diff --git a/neutron/plugins/ml2/drivers/openvswitch/agent/ovs_neutron_agent.py b/neutron/plugins/ml2/drivers/openvswitch/agent/ovs_neutron_agent.py index 28d4735a6..ea5ac9c2b 100644 --- a/neutron/plugins/ml2/drivers/openvswitch/agent/ovs_neutron_agent.py +++ b/neutron/plugins/ml2/drivers/openvswitch/agent/ovs_neutron_agent.py @@ -30,6 +30,7 @@ from neutron.agent.common import ovs_lib from neutron.agent.common import polling from neutron.agent.common import utils from neutron.agent.linux import ip_lib +from neutron.agent.linux.iptables_firewall import port_needs_l3_security from neutron.agent import rpc as agent_rpc from neutron.agent import securitygroups_rpc as sg_rpc from neutron.api.rpc.handlers import dvr_rpc @@ -807,6 +808,9 @@ class OVSNeutronAgent(sg_rpc.SecurityGroupAgentRpcCallbackMixin, addresses |= {p['ip_address'] for p in port_details['allowed_address_pairs']} + if not port_needs_l3_security(port_details): + return + addresses = {ip for ip in addresses if netaddr.IPNetwork(ip).version == 4} if any(netaddr.IPNetwork(ip).prefixlen == 0 for ip in addresses): diff --git a/neutron/tests/unit/agent/linux/test_iptables_firewall.py b/neutron/tests/unit/agent/linux/test_iptables_firewall.py index 3f878ecb1..dd458029c 100644 --- a/neutron/tests/unit/agent/linux/test_iptables_firewall.py +++ b/neutron/tests/unit/agent/linux/test_iptables_firewall.py @@ -1453,15 +1453,6 @@ class IptablesFirewallTestCase(BaseIptablesFirewallTestCase): '--physdev-is-bridged ' '-j $ifake_dev', comment=ic.SG_TO_VM_SG), - mock.call.add_rule( - 'ifake_dev', - '-m state --state INVALID -j DROP', comment=None), - mock.call.add_rule( - 'ifake_dev', - '-m state --state RELATED,ESTABLISHED -j RETURN', - comment=None), - mock.call.add_rule('ifake_dev', '-j $sg-fallback', - comment=None), mock.call.add_chain('ofake_dev'), mock.call.add_rule('FORWARD', '-m physdev --physdev-in tapfake_dev ' @@ -1483,26 +1474,8 @@ class IptablesFirewallTestCase(BaseIptablesFirewallTestCase): mock.call.add_rule( 'sfake_dev', '-j DROP', comment=ic.PAIR_DROP), - mock.call.add_rule( - 'ofake_dev', - '-p udp -m udp --sport 68 --dport 67 -j RETURN', - comment=None), mock.call.add_rule('ofake_dev', '-j $sfake_dev', comment=None), - mock.call.add_rule( - 'ofake_dev', - '-p udp -m udp --sport 67 --dport 68 -j DROP', - comment=None), - mock.call.add_rule( - 'ofake_dev', - '-m state --state INVALID -j DROP', - comment=None), - mock.call.add_rule( - 'ofake_dev', - '-m state --state RELATED,ESTABLISHED -j RETURN', - comment=None), - mock.call.add_rule('ofake_dev', '-j $sg-fallback', - comment=None), mock.call.add_rule('sg-chain', '-j ACCEPT')] self.v4filter_inst.assert_has_calls(calls) diff --git a/neutron/tests/unit/plugins/ml2/drivers/openvswitch/agent/test_ovs_neutron_agent.py b/neutron/tests/unit/plugins/ml2/drivers/openvswitch/agent/test_ovs_neutron_agent.py index 527f8ab39..eae21aa23 100644 --- a/neutron/tests/unit/plugins/ml2/drivers/openvswitch/agent/test_ovs_neutron_agent.py +++ b/neutron/tests/unit/plugins/ml2/drivers/openvswitch/agent/test_ovs_neutron_agent.py @@ -1102,7 +1102,7 @@ class TestOvsNeutronAgent(object): self.assertTrue(int_br.delete_arp_spoofing_protection.called) self.assertFalse(int_br.install_arp_spoofing_protection.called) - def test_arp_spoofing_basic_rule_setup(self): + def test_arp_spoofing_basic_rule_setup_without_ip(self): vif = FakeVif() fake_details = {'fixed_ips': []} self.agent.prevent_arp_spoofing = True @@ -1111,9 +1111,18 @@ class TestOvsNeutronAgent(object): self.assertEqual( [mock.call(port=vif.ofport)], int_br.delete_arp_spoofing_protection.mock_calls) + self.assertFalse(int_br.install_arp_spoofing_protection.called) + + def test_arp_spoofing_basic_rule_setup_fixed_ip(self): + vif = FakeVif() + fake_details = {'fixed_ips': [{'ip_address': '192.168.44.100'}]} + self.agent.prevent_arp_spoofing = True + int_br = mock.create_autospec(self.agent.int_br) + self.agent.setup_arp_spoofing_protection(int_br, vif, fake_details) self.assertEqual( - [mock.call(ip_addresses=set(), port=vif.ofport)], - int_br.install_arp_spoofing_protection.mock_calls) + [mock.call(port=vif.ofport)], + int_br.delete_arp_spoofing_protection.mock_calls) + self.assertTrue(int_br.install_arp_spoofing_protection.called) def test_arp_spoofing_fixed_and_allowed_addresses(self): vif = FakeVif()