From b74c5a0fa1d2be30f3f35de5a8c8ce71fc3c25f7 Mon Sep 17 00:00:00 2001 From: Xuhan Peng Date: Tue, 6 May 2014 18:05:00 +0800 Subject: [PATCH] Allow DHCPv6 solicit from VM DHCPv6 solicit UDP package is currently dropped because there is no security group rule to allow it like IPv4. This fix allows UDP DHCPv6 solicit from client port 546 to server port 547. This fix also drops DHCP reply from VM. Change-Id: I4941d401576e2c8bad37859d2cba227afde9e764 Closes-Bug: 1316515 --- neutron/agent/linux/iptables_firewall.py | 8 +++++--- neutron/tests/unit/test_iptables_firewall.py | 20 +++++++++++++------ .../tests/unit/test_security_groups_rpc.py | 6 ++++++ 3 files changed, 25 insertions(+), 9 deletions(-) diff --git a/neutron/agent/linux/iptables_firewall.py b/neutron/agent/linux/iptables_firewall.py index ad11abe4994..8d112e819ee 100644 --- a/neutron/agent/linux/iptables_firewall.py +++ b/neutron/agent/linux/iptables_firewall.py @@ -214,6 +214,7 @@ class IptablesFirewallDriver(firewall.FirewallDriver): #Note(nati) allow dhcp or RA packet ipv4_rules += ['-p udp -m udp --sport 68 --dport 67 -j RETURN'] ipv6_rules += ['-p icmpv6 -j RETURN'] + ipv6_rules += ['-p udp -m udp --sport 546 --dport 547 -j RETURN'] mac_ipv4_pairs = [] mac_ipv6_pairs = [] @@ -236,9 +237,10 @@ class IptablesFirewallDriver(firewall.FirewallDriver): self._setup_spoof_filter_chain(port, self.iptables.ipv6['filter'], mac_ipv6_pairs, ipv6_rules) - def _drop_dhcp_rule(self): + def _drop_dhcp_rule(self, ipv4_rules, ipv6_rules): #Note(nati) Drop dhcp packet from VM - return ['-p udp -m udp --sport 67 --dport 68 -j DROP'] + ipv4_rules += ['-p udp -m udp --sport 67 --dport 68 -j DROP'] + ipv6_rules += ['-p udp -m udp --sport 547 --dport 546 -j DROP'] def _accept_inbound_icmpv6(self): # Allow multicast listener, neighbor solicitation and @@ -264,7 +266,7 @@ class IptablesFirewallDriver(firewall.FirewallDriver): self._spoofing_rule(port, ipv4_iptables_rule, ipv6_iptables_rule) - ipv4_iptables_rule += self._drop_dhcp_rule() + self._drop_dhcp_rule(ipv4_iptables_rule, ipv6_iptables_rule) if direction == INGRESS_DIRECTION: ipv6_iptables_rule += self._accept_inbound_icmpv6() ipv4_iptables_rule += self._convert_sgr_to_iptables_rules( diff --git a/neutron/tests/unit/test_iptables_firewall.py b/neutron/tests/unit/test_iptables_firewall.py index 18c4fe4db36..06f490d554d 100644 --- a/neutron/tests/unit/test_iptables_firewall.py +++ b/neutron/tests/unit/test_iptables_firewall.py @@ -801,14 +801,18 @@ class IptablesFirewallTestCase(base.BaseTestCase): ethertype = rule['ethertype'] prefix = FAKE_IP[ethertype] filter_inst = self.v4filter_inst - dhcp_rule = mock.call.add_rule( + dhcp_rule = [mock.call.add_rule( 'ofake_dev', - '-p udp -m udp --sport 68 --dport 67 -j RETURN') + '-p udp -m udp --sport 68 --dport 67 -j RETURN')] if ethertype == 'IPv6': filter_inst = self.v6filter_inst - dhcp_rule = mock.call.add_rule('ofake_dev', '-p icmpv6 -j RETURN') + dhcp_rule = [mock.call.add_rule('ofake_dev', + '-p icmpv6 -j RETURN'), + mock.call.add_rule('ofake_dev', '-p udp -m udp ' + '--sport 546 --dport 547 ' + '-j RETURN')] sg = [rule] port['security_group_rules'] = sg self.firewall.prepare_port_filter(port) @@ -860,13 +864,17 @@ class IptablesFirewallTestCase(base.BaseTestCase): 'sfake_dev', '-m mac --mac-source ff:ff:ff:ff:ff:ff -s %s -j RETURN' % prefix), - mock.call.add_rule('sfake_dev', '-j DROP'), - dhcp_rule, - mock.call.add_rule('ofake_dev', '-j $sfake_dev')] + mock.call.add_rule('sfake_dev', '-j DROP')] + calls += dhcp_rule + calls.append(mock.call.add_rule('ofake_dev', '-j $sfake_dev')) if ethertype == 'IPv4': calls.append(mock.call.add_rule( 'ofake_dev', '-p udp -m udp --sport 67 --dport 68 -j DROP')) + if ethertype == 'IPv6': + calls.append(mock.call.add_rule( + 'ofake_dev', + '-p udp -m udp --sport 547 --dport 546 -j DROP')) calls += [mock.call.add_rule( 'ofake_dev', '-m state --state INVALID -j DROP'), diff --git a/neutron/tests/unit/test_security_groups_rpc.py b/neutron/tests/unit/test_security_groups_rpc.py index 1a32051e490..5c72b2ccb4d 100644 --- a/neutron/tests/unit/test_security_groups_rpc.py +++ b/neutron/tests/unit/test_security_groups_rpc.py @@ -1593,6 +1593,8 @@ IPTABLES_FILTER_V6_1 = """# Generated by iptables_manager [0:0] -A %(bn)s-INPUT %(physdev_mod)s --physdev-EGRESS tap_port1 \ %(physdev_is_bridged)s -j %(bn)s-o_port1 [0:0] -A %(bn)s-o_port1 -p icmpv6 -j RETURN +[0:0] -A %(bn)s-o_port1 -p udp -m udp --sport 546 --dport 547 -j RETURN +[0:0] -A %(bn)s-o_port1 -p udp -m udp --sport 547 --dport 546 -j DROP [0:0] -A %(bn)s-o_port1 -m state --state INVALID -j DROP [0:0] -A %(bn)s-o_port1 -m state --state RELATED,ESTABLISHED -j RETURN [0:0] -A %(bn)s-o_port1 -j %(bn)s-sg-fallback @@ -1643,6 +1645,8 @@ IPTABLES_FILTER_V6_2 = """# Generated by iptables_manager [0:0] -A %(bn)s-INPUT %(physdev_mod)s --physdev-EGRESS tap_port1 \ %(physdev_is_bridged)s -j %(bn)s-o_port1 [0:0] -A %(bn)s-o_port1 -p icmpv6 -j RETURN +[0:0] -A %(bn)s-o_port1 -p udp -m udp --sport 546 --dport 547 -j RETURN +[0:0] -A %(bn)s-o_port1 -p udp -m udp --sport 547 --dport 546 -j DROP [0:0] -A %(bn)s-o_port1 -m state --state INVALID -j DROP [0:0] -A %(bn)s-o_port1 -m state --state RELATED,ESTABLISHED -j RETURN [0:0] -A %(bn)s-o_port1 -j %(bn)s-sg-fallback @@ -1665,6 +1669,8 @@ IPTABLES_FILTER_V6_2 = """# Generated by iptables_manager [0:0] -A %(bn)s-INPUT %(physdev_mod)s --physdev-EGRESS tap_port2 \ %(physdev_is_bridged)s -j %(bn)s-o_port2 [0:0] -A %(bn)s-o_port2 -p icmpv6 -j RETURN +[0:0] -A %(bn)s-o_port2 -p udp -m udp --sport 546 --dport 547 -j RETURN +[0:0] -A %(bn)s-o_port2 -p udp -m udp --sport 547 --dport 546 -j DROP [0:0] -A %(bn)s-o_port2 -m state --state INVALID -j DROP [0:0] -A %(bn)s-o_port2 -m state --state RELATED,ESTABLISHED -j RETURN [0:0] -A %(bn)s-o_port2 -j %(bn)s-sg-fallback