diff --git a/neutron/agent/linux/iptables_firewall.py b/neutron/agent/linux/iptables_firewall.py index 027298de5..d12e214b3 100644 --- a/neutron/agent/linux/iptables_firewall.py +++ b/neutron/agent/linux/iptables_firewall.py @@ -243,6 +243,15 @@ class IptablesFirewallDriver(firewall.FirewallDriver): #Note(nati) Drop dhcp packet from VM return ['-p udp -m udp --sport 67 --dport 68 -j DROP'] + def _accept_inbound_icmpv6(self): + # Allow router advertisements, multicast listener + # and neighbor advertisement into the instance + icmpv6_rules = [] + for icmp6_type in constants.ICMPV6_ALLOWED_TYPES: + icmpv6_rules += ['-p icmpv6 --icmpv6-type %s -j RETURN' % + icmp6_type] + return icmpv6_rules + def _add_rule_by_security_group(self, port, direction): chain_name = self._port_chain_name(port, direction) # select rules for current direction @@ -259,6 +268,8 @@ class IptablesFirewallDriver(firewall.FirewallDriver): ipv4_iptables_rule, ipv6_iptables_rule) ipv4_iptables_rule += self._drop_dhcp_rule() + if direction == INGRESS_DIRECTION: + ipv6_iptables_rule += self._accept_inbound_icmpv6() ipv4_iptables_rule += self._convert_sgr_to_iptables_rules( ipv4_sg_rules) ipv6_iptables_rule += self._convert_sgr_to_iptables_rules( diff --git a/neutron/common/constants.py b/neutron/common/constants.py index a55e1bfb7..754d25220 100644 --- a/neutron/common/constants.py +++ b/neutron/common/constants.py @@ -93,3 +93,12 @@ PROTO_NUM_TCP = 6 PROTO_NUM_ICMP = 1 PROTO_NUM_ICMP_V6 = 58 PROTO_NUM_UDP = 17 + +# List of ICMPv6 types that should be allowed by default: +# Multicast Listener Query (130), +# Multicast Listener Report (131), +# Multicast Listener Done (132), +# Router Advertisement (134), +# Neighbor Solicitation (135), +# Neighbor Advertisement (136) +ICMPV6_ALLOWED_TYPES = [130, 131, 132, 134, 135, 136] diff --git a/neutron/tests/unit/test_iptables_firewall.py b/neutron/tests/unit/test_iptables_firewall.py index e03119278..b65ee780f 100644 --- a/neutron/tests/unit/test_iptables_firewall.py +++ b/neutron/tests/unit/test_iptables_firewall.py @@ -23,6 +23,7 @@ from oslo.config import cfg from neutron.agent.common import config as a_cfg from neutron.agent.linux.iptables_firewall import IptablesFirewallDriver +from neutron.common import constants from neutron.tests import base from neutron.tests.unit import test_api_v2 @@ -747,11 +748,18 @@ class IptablesFirewallTestCase(base.BaseTestCase): '-m physdev --physdev-out tapfake_dev ' '--physdev-is-bridged ' '-j $ifake_dev'), - call.add_rule( - 'ifake_dev', '-m state --state INVALID -j DROP'), - call.add_rule( - 'ifake_dev', - '-m state --state RELATED,ESTABLISHED -j RETURN')] + ] + if ethertype == 'IPv6': + for icmp6_type in constants.ICMPV6_ALLOWED_TYPES: + calls.append( + call.add_rule('ifake_dev', + '-p icmpv6 --icmpv6-type %s -j RETURN' % + icmp6_type)) + calls += [call.add_rule('ifake_dev', + '-m state --state INVALID -j DROP'), + call.add_rule( + 'ifake_dev', + '-m state --state RELATED,ESTABLISHED -j RETURN')] if ingress_expected_call: calls.append(ingress_expected_call) diff --git a/neutron/tests/unit/test_security_groups_rpc.py b/neutron/tests/unit/test_security_groups_rpc.py index ecbeb6d9f..a0a386c55 100644 --- a/neutron/tests/unit/test_security_groups_rpc.py +++ b/neutron/tests/unit/test_security_groups_rpc.py @@ -1092,6 +1092,12 @@ IPTABLES_FILTER_V6_1 = """# Generated by iptables_manager %(physdev_is_bridged)s -j %(bn)s-sg-chain [0:0] -A %(bn)s-sg-chain %(physdev_mod)s --physdev-INGRESS tap_port1 \ %(physdev_is_bridged)s -j %(bn)s-i_port1 +[0:0] -A %(bn)s-i_port1 -p icmpv6 --icmpv6-type 130 -j RETURN +[0:0] -A %(bn)s-i_port1 -p icmpv6 --icmpv6-type 131 -j RETURN +[0:0] -A %(bn)s-i_port1 -p icmpv6 --icmpv6-type 132 -j RETURN +[0:0] -A %(bn)s-i_port1 -p icmpv6 --icmpv6-type 134 -j RETURN +[0:0] -A %(bn)s-i_port1 -p icmpv6 --icmpv6-type 135 -j RETURN +[0:0] -A %(bn)s-i_port1 -p icmpv6 --icmpv6-type 136 -j RETURN [0:0] -A %(bn)s-i_port1 -m state --state INVALID -j DROP [0:0] -A %(bn)s-i_port1 -m state --state RELATED,ESTABLISHED -j RETURN [0:0] -A %(bn)s-i_port1 -j %(bn)s-sg-fallback @@ -1137,6 +1143,12 @@ IPTABLES_FILTER_V6_2 = """# Generated by iptables_manager %(physdev_is_bridged)s -j %(bn)s-sg-chain [0:0] -A %(bn)s-sg-chain %(physdev_mod)s --physdev-INGRESS tap_port1 \ %(physdev_is_bridged)s -j %(bn)s-i_port1 +[0:0] -A %(bn)s-i_port1 -p icmpv6 --icmpv6-type 130 -j RETURN +[0:0] -A %(bn)s-i_port1 -p icmpv6 --icmpv6-type 131 -j RETURN +[0:0] -A %(bn)s-i_port1 -p icmpv6 --icmpv6-type 132 -j RETURN +[0:0] -A %(bn)s-i_port1 -p icmpv6 --icmpv6-type 134 -j RETURN +[0:0] -A %(bn)s-i_port1 -p icmpv6 --icmpv6-type 135 -j RETURN +[0:0] -A %(bn)s-i_port1 -p icmpv6 --icmpv6-type 136 -j RETURN [0:0] -A %(bn)s-i_port1 -m state --state INVALID -j DROP [0:0] -A %(bn)s-i_port1 -m state --state RELATED,ESTABLISHED -j RETURN [0:0] -A %(bn)s-i_port1 -j %(bn)s-sg-fallback @@ -1154,6 +1166,12 @@ IPTABLES_FILTER_V6_2 = """# Generated by iptables_manager %(physdev_is_bridged)s -j %(bn)s-sg-chain [0:0] -A %(bn)s-sg-chain %(physdev_mod)s --physdev-INGRESS tap_port2 \ %(physdev_is_bridged)s -j %(bn)s-i_port2 +[0:0] -A %(bn)s-i_port2 -p icmpv6 --icmpv6-type 130 -j RETURN +[0:0] -A %(bn)s-i_port2 -p icmpv6 --icmpv6-type 131 -j RETURN +[0:0] -A %(bn)s-i_port2 -p icmpv6 --icmpv6-type 132 -j RETURN +[0:0] -A %(bn)s-i_port2 -p icmpv6 --icmpv6-type 134 -j RETURN +[0:0] -A %(bn)s-i_port2 -p icmpv6 --icmpv6-type 135 -j RETURN +[0:0] -A %(bn)s-i_port2 -p icmpv6 --icmpv6-type 136 -j RETURN [0:0] -A %(bn)s-i_port2 -m state --state INVALID -j DROP [0:0] -A %(bn)s-i_port2 -m state --state RELATED,ESTABLISHED -j RETURN [0:0] -A %(bn)s-i_port2 -j %(bn)s-sg-fallback