From 558a977902c9e83aabaefe67333aee544aa86585 Mon Sep 17 00:00:00 2001 From: Doug Wiegley Date: Sat, 2 Mar 2019 22:35:52 -0700 Subject: [PATCH] When converting sg rules to iptables, do not emit dport if not supported Since iptables-restore doesn't support --dport with protocol vrrp, it errors out setting the security groups on the hypervisor. Marking this a partial fix, since we need a change to prevent adding those incompatible rules in the first place, but this patch will stop the bleeding. Change-Id: If5e557a8e61c3aa364ba1e2c60be4cbe74c1ec8f Partial-Bug: #1818385 (cherry picked from commit 8c213e45902e21d2fe00639ef7d92b35304bde82) --- neutron/agent/linux/iptables_firewall.py | 20 ++++++++++++++----- .../agent/linux/test_iptables_firewall.py | 14 +++++++++++++ 2 files changed, 29 insertions(+), 5 deletions(-) diff --git a/neutron/agent/linux/iptables_firewall.py b/neutron/agent/linux/iptables_firewall.py index 496376dacf1..5fb9740df56 100644 --- a/neutron/agent/linux/iptables_firewall.py +++ b/neutron/agent/linux/iptables_firewall.py @@ -46,6 +46,15 @@ IPSET_DIRECTION = {constants.INGRESS_DIRECTION: 'src', comment_rule = iptables_manager.comment_rule libc = ctypes.CDLL(util.find_library('libc.so.6')) +# iptables protocols that support --dport and --sport +IPTABLES_PORT_PROTOCOLS = [ + constants.PROTO_NAME_DCCP, + constants.PROTO_NAME_SCTP, + constants.PROTO_NAME_TCP, + constants.PROTO_NAME_UDP, + constants.PROTO_NAME_UDPLITE +] + def get_hybrid_port_name(port_name): return (constants.TAP_DEVICE_PREFIX + port_name)[:n_const.LINUX_DEV_LEN] @@ -731,11 +740,12 @@ class IptablesFirewallDriver(firewall.FirewallDriver): # icmp code can be 0 so we cannot use "if port_range_max" here if port_range_max is not None: args[-1] += '/%s' % port_range_max - elif port_range_min == port_range_max: - args += ['--%s' % direction, '%s' % (port_range_min,)] - else: - args += ['-m', 'multiport', '--%ss' % direction, - '%s:%s' % (port_range_min, port_range_max)] + elif protocol in IPTABLES_PORT_PROTOCOLS: + if port_range_min == port_range_max: + args += ['--%s' % direction, '%s' % (port_range_min,)] + else: + args += ['-m', 'multiport', '--%ss' % direction, + '%s:%s' % (port_range_min, port_range_max)] return args def _ip_prefix_arg(self, direction, ip_prefix): diff --git a/neutron/tests/unit/agent/linux/test_iptables_firewall.py b/neutron/tests/unit/agent/linux/test_iptables_firewall.py index d7268bcdfd7..7ab8a0ae01d 100644 --- a/neutron/tests/unit/agent/linux/test_iptables_firewall.py +++ b/neutron/tests/unit/agent/linux/test_iptables_firewall.py @@ -276,6 +276,20 @@ class IptablesFirewallTestCase(BaseIptablesFirewallTestCase): egress = None self._test_prepare_port_filter(rule, ingress, egress) + def test_filter_bad_vrrp_with_dport(self): + rule = {'ethertype': 'IPv4', + 'direction': 'ingress', + 'protocol': 'vrrp', + 'port_range_min': 10, + 'port_range_max': 10} + # Dest port isn't support with VRRP, so don't send it + # down to iptables. + ingress = mock.call.add_rule('ifake_dev', + '-p vrrp -j RETURN', + top=False, comment=None) + egress = None + self._test_prepare_port_filter(rule, ingress, egress) + def test_filter_ipv4_ingress_tcp_port_by_num(self): rule = {'ethertype': 'IPv4', 'direction': 'ingress',