High severity8.2NVD Advisory· Published Jun 17, 2016· Updated May 6, 2026
CVE-2016-5363
CVE-2016-5363
Description
The IPTables firewall in OpenStack Neutron before 7.0.4 and 8.0.0 through 8.1.0 allows remote attackers to bypass an intended MAC-spoofing protection mechanism and consequently cause a denial of service or intercept network traffic via (1) a crafted DHCP discovery message or (2) crafted non-IP traffic.
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
neutronPyPI | < 7.1.0 | 7.1.0 |
neutronPyPI | >= 8.0.0, < 8.1.0 | 8.1.0 |
Affected products
7cpe:2.3:a:openstack:neutron:7.0.0:*:*:*:*:*:*:*+ 6 more
- cpe:2.3:a:openstack:neutron:7.0.0:*:*:*:*:*:*:*
- cpe:2.3:a:openstack:neutron:7.0.1:*:*:*:*:*:*:*
- cpe:2.3:a:openstack:neutron:7.0.2:*:*:*:*:*:*:*
- cpe:2.3:a:openstack:neutron:7.0.3:*:*:*:*:*:*:*
- cpe:2.3:a:openstack:neutron:7.0.4:*:*:*:*:*:*:*
- cpe:2.3:a:openstack:neutron:8.0.0:*:*:*:*:*:*:*
- cpe:2.3:a:openstack:neutron:8.1.0:*:*:*:*:*:*:*
Patches
4fd5fd259a021Iptables firewall prevent IP spoofed DHCP requests
3 files changed · +146 −92
neutron/agent/linux/iptables_firewall.py+6 −3 modified@@ -386,9 +386,9 @@ def _build_ipv4v6_mac_ip_list(self, mac, ip_address, mac_ipv4_pairs, 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 ' - '-m udp --dport 67 ' + # Allow dhcp client discovery and request + ipv4_rules += [comment_rule('-s 0.0.0.0/32 -d 255.255.255.255/32 ' + '-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 ipv6-icmp -m icmp6 --icmpv6-type %s ' @@ -420,6 +420,9 @@ def _spoofing_rule(self, port, ipv4_rules, ipv6_rules): mac_ipv4_pairs, ipv4_rules) self._setup_spoof_filter_chain(port, self.iptables.ipv6['filter'], mac_ipv6_pairs, ipv6_rules) + # Allow dhcp client renewal and rebinding + ipv4_rules += [comment_rule('-p udp -m udp --sport 68 --dport 67 ' + '-j RETURN', comment=ic.DHCP_CLIENT)] def _drop_dhcp_rule(self, ipv4_rules, ipv6_rules): #Note(nati) Drop dhcp packet from VM
neutron/tests/unit/agent/linux/test_iptables_firewall.py+36 −6 modified@@ -158,10 +158,15 @@ def test_prepare_port_filter_with_no_sg(self): comment=ic.PAIR_DROP), mock.call.add_rule( 'ofake_dev', - '-p udp -m udp --sport 68 -m udp --dport 67 -j RETURN', + '-s 0.0.0.0/32 -d 255.255.255.255/32 -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 68 --dport 67 -j RETURN', + comment=None), mock.call.add_rule( 'ofake_dev', '-p udp -m udp --sport 67 -m udp --dport 68 -j DROP', @@ -940,7 +945,8 @@ def _test_prepare_port_filter(self, filter_inst = self.v4filter_inst dhcp_rule = [mock.call.add_rule( 'ofake_dev', - '-p udp -m udp --sport 68 -m udp --dport 67 -j RETURN', + '-s 0.0.0.0/32 -d 255.255.255.255/32 -p udp -m udp ' + '--sport 68 --dport 67 -j RETURN', comment=None)] if ethertype == 'IPv6': @@ -1027,6 +1033,10 @@ def _test_prepare_port_filter(self, calls.append(mock.call.add_rule('ofake_dev', '-j $sfake_dev', comment=None)) if ethertype == 'IPv4': + calls.append(mock.call.add_rule( + 'ofake_dev', + '-p udp -m udp --sport 68 --dport 67 -j RETURN', + comment=None)) calls.append(mock.call.add_rule( 'ofake_dev', '-p udp -m udp --sport 67 -m udp --dport 68 -j DROP', @@ -1195,10 +1205,15 @@ def test_update_delete_port_filter(self): comment=ic.PAIR_DROP), mock.call.add_rule( 'ofake_dev', - '-p udp -m udp --sport 68 -m udp --dport 67 -j RETURN', + '-s 0.0.0.0/32 -d 255.255.255.255/32 -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 68 --dport 67 -j RETURN', + comment=None), mock.call.add_rule( 'ofake_dev', '-p udp -m udp --sport 67 -m udp --dport 68 -j DROP', @@ -1267,10 +1282,15 @@ def test_update_delete_port_filter(self): comment=ic.PAIR_DROP), mock.call.add_rule( 'ofake_dev', - '-p udp -m udp --sport 68 -m udp --dport 67 -j RETURN', + '-s 0.0.0.0/32 -d 255.255.255.255/32 -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 68 --dport 67 -j RETURN', + comment=None), mock.call.add_rule( 'ofake_dev', '-p udp -m udp --sport 67 -m udp --dport 68 -j DROP', @@ -1442,10 +1462,15 @@ def test_ip_spoofing_filter_with_multiple_ips(self): comment=ic.PAIR_DROP), mock.call.add_rule( 'ofake_dev', - '-p udp -m udp --sport 68 -m udp --dport 67 -j RETURN', + '-s 0.0.0.0/32 -d 255.255.255.255/32 -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 68 --dport 67 -j RETURN', + comment=None), mock.call.add_rule( 'ofake_dev', '-p udp -m udp --sport 67 -m udp --dport 68 -j DROP', @@ -1516,10 +1541,15 @@ def test_ip_spoofing_no_fixed_ips(self): comment=ic.PAIR_DROP), mock.call.add_rule( 'ofake_dev', - '-p udp -m udp --sport 68 -m udp --dport 67 -j RETURN', + '-s 0.0.0.0/32 -d 255.255.255.255/32 -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 68 --dport 67 -j RETURN', + comment=None), mock.call.add_rule( 'ofake_dev', '-p udp -m udp --sport 67 -m udp --dport 68 -j DROP',
neutron/tests/unit/agent/test_securitygroups_rpc.py+104 −83 modified@@ -1810,14 +1810,15 @@ def test_security_groups_member_not_updated(self): RETURN -I %(bn)s-i_port1 5 -m state --state INVALID -j DROP -I %(bn)s-i_port1 6 -j %(bn)s-sg-fallback --I %(bn)s-o_port1 1 -p udp -m udp --sport 68 -m udp --dport 67 \ --j RETURN +-I %(bn)s-o_port1 1 -s 0.0.0.0/32 -d 255.255.255.255/32 -p udp -m udp \ +--sport 68 --dport 67 -j RETURN -I %(bn)s-o_port1 2 -j %(bn)s-s_port1 --I %(bn)s-o_port1 3 -p udp -m udp --sport 67 -m udp --dport 68 -j DROP --I %(bn)s-o_port1 4 -m state --state RELATED,ESTABLISHED -j RETURN --I %(bn)s-o_port1 5 -j RETURN --I %(bn)s-o_port1 6 -m state --state INVALID -j DROP --I %(bn)s-o_port1 7 -j %(bn)s-sg-fallback +-I %(bn)s-o_port1 3 -p udp -m udp --sport 68 --dport 67 -j RETURN +-I %(bn)s-o_port1 4 -p udp -m udp --sport 67 -m udp --dport 68 -j DROP +-I %(bn)s-o_port1 5 -m state --state RELATED,ESTABLISHED -j RETURN +-I %(bn)s-o_port1 6 -j RETURN +-I %(bn)s-o_port1 7 -m state --state INVALID -j DROP +-I %(bn)s-o_port1 8 -j %(bn)s-sg-fallback -I %(bn)s-s_port1 1 -s 10.0.0.3/32 -m mac --mac-source 12:34:56:78:9A:BC \ -j RETURN -I %(bn)s-s_port1 2 -j DROP @@ -1864,14 +1865,15 @@ def test_security_groups_member_not_updated(self): -I %(bn)s-i_port1 3 -p tcp -m tcp --dport 22 -j RETURN -I %(bn)s-i_port1 4 -m state --state INVALID -j DROP -I %(bn)s-i_port1 5 -j %(bn)s-sg-fallback --I %(bn)s-o_port1 1 -p udp -m udp --sport 68 -m udp --dport 67 \ --j RETURN +-I %(bn)s-o_port1 1 -s 0.0.0.0/32 -d 255.255.255.255/32 -p udp -m udp \ +--sport 68 --dport 67 -j RETURN -I %(bn)s-o_port1 2 -j %(bn)s-s_port1 --I %(bn)s-o_port1 3 -p udp -m udp --sport 67 -m udp --dport 68 -j DROP --I %(bn)s-o_port1 4 -m state --state RELATED,ESTABLISHED -j RETURN --I %(bn)s-o_port1 5 -j RETURN --I %(bn)s-o_port1 6 -m state --state INVALID -j DROP --I %(bn)s-o_port1 7 -j %(bn)s-sg-fallback +-I %(bn)s-o_port1 3 -p udp -m udp --sport 68 --dport 67 -j RETURN +-I %(bn)s-o_port1 4 -p udp -m udp --sport 67 -m udp --dport 68 -j DROP +-I %(bn)s-o_port1 5 -m state --state RELATED,ESTABLISHED -j RETURN +-I %(bn)s-o_port1 6 -j RETURN +-I %(bn)s-o_port1 7 -m state --state INVALID -j DROP +-I %(bn)s-o_port1 8 -j %(bn)s-sg-fallback -I %(bn)s-s_port1 1 -s 10.0.0.3/32 -m mac --mac-source 12:34:56:78:9A:BC \ -j RETURN -I %(bn)s-s_port1 2 -j DROP @@ -1920,14 +1922,15 @@ def test_security_groups_member_not_updated(self): -I %(bn)s-i_port1 4 -s 10.0.0.4/32 -j RETURN -I %(bn)s-i_port1 5 -m state --state INVALID -j DROP -I %(bn)s-i_port1 6 -j %(bn)s-sg-fallback --I %(bn)s-o_port1 1 -p udp -m udp --sport 68 -m udp --dport 67 \ --j RETURN +-I %(bn)s-o_port1 1 -s 0.0.0.0/32 -d 255.255.255.255/32 -p udp -m udp \ +--sport 68 --dport 67 -j RETURN -I %(bn)s-o_port1 2 -j %(bn)s-s_port1 --I %(bn)s-o_port1 3 -p udp -m udp --sport 67 -m udp --dport 68 -j DROP --I %(bn)s-o_port1 4 -m state --state RELATED,ESTABLISHED -j RETURN --I %(bn)s-o_port1 5 -j RETURN --I %(bn)s-o_port1 6 -m state --state INVALID -j DROP --I %(bn)s-o_port1 7 -j %(bn)s-sg-fallback +-I %(bn)s-o_port1 3 -p udp -m udp --sport 68 --dport 67 -j RETURN +-I %(bn)s-o_port1 4 -p udp -m udp --sport 67 -m udp --dport 68 -j DROP +-I %(bn)s-o_port1 5 -m state --state RELATED,ESTABLISHED -j RETURN +-I %(bn)s-o_port1 6 -j RETURN +-I %(bn)s-o_port1 7 -m state --state INVALID -j DROP +-I %(bn)s-o_port1 8 -j %(bn)s-sg-fallback -I %(bn)s-s_port1 1 -s 10.0.0.3/32 -m mac --mac-source 12:34:56:78:9A:BC \ -j RETURN -I %(bn)s-s_port1 2 -j DROP @@ -1993,20 +1996,24 @@ def test_security_groups_member_not_updated(self): -I %(bn)s-i_%(port2)s 4 -m set --match-set NIPv4security_group1 src -j RETURN -I %(bn)s-i_%(port2)s 5 -m state --state INVALID -j DROP -I %(bn)s-i_%(port2)s 6 -j %(bn)s-sg-fallback --I %(bn)s-o_%(port1)s 1 -p udp -m udp --sport 68 -m udp --dport 67 -j RETURN +-I %(bn)s-o_%(port1)s 1 -s 0.0.0.0/32 -d 255.255.255.255/32 -p udp -m udp \ +--sport 68 --dport 67 -j RETURN -I %(bn)s-o_%(port1)s 2 -j %(bn)s-s_%(port1)s --I %(bn)s-o_%(port1)s 3 -p udp -m udp --sport 67 -m udp --dport 68 -j DROP --I %(bn)s-o_%(port1)s 4 -m state --state RELATED,ESTABLISHED -j RETURN --I %(bn)s-o_%(port1)s 5 -j RETURN --I %(bn)s-o_%(port1)s 6 -m state --state INVALID -j DROP --I %(bn)s-o_%(port1)s 7 -j %(bn)s-sg-fallback --I %(bn)s-o_%(port2)s 1 -p udp -m udp --sport 68 -m udp --dport 67 -j RETURN +-I %(bn)s-o_%(port1)s 3 -p udp -m udp --sport 68 --dport 67 -j RETURN +-I %(bn)s-o_%(port1)s 4 -p udp -m udp --sport 67 -m udp --dport 68 -j DROP +-I %(bn)s-o_%(port1)s 5 -m state --state RELATED,ESTABLISHED -j RETURN +-I %(bn)s-o_%(port1)s 6 -j RETURN +-I %(bn)s-o_%(port1)s 7 -m state --state INVALID -j DROP +-I %(bn)s-o_%(port1)s 8 -j %(bn)s-sg-fallback +-I %(bn)s-o_%(port2)s 1 -s 0.0.0.0/32 -d 255.255.255.255/32 -p udp -m udp \ +--sport 68 --dport 67 -j RETURN -I %(bn)s-o_%(port2)s 2 -j %(bn)s-s_%(port2)s --I %(bn)s-o_%(port2)s 3 -p udp -m udp --sport 67 -m udp --dport 68 -j DROP --I %(bn)s-o_%(port2)s 4 -m state --state RELATED,ESTABLISHED -j RETURN --I %(bn)s-o_%(port2)s 5 -j RETURN --I %(bn)s-o_%(port2)s 6 -m state --state INVALID -j DROP --I %(bn)s-o_%(port2)s 7 -j %(bn)s-sg-fallback +-I %(bn)s-o_%(port2)s 3 -p udp -m udp --sport 68 --dport 67 -j RETURN +-I %(bn)s-o_%(port2)s 4 -p udp -m udp --sport 67 -m udp --dport 68 -j DROP +-I %(bn)s-o_%(port2)s 5 -m state --state RELATED,ESTABLISHED -j RETURN +-I %(bn)s-o_%(port2)s 6 -j RETURN +-I %(bn)s-o_%(port2)s 7 -m state --state INVALID -j DROP +-I %(bn)s-o_%(port2)s 8 -j %(bn)s-sg-fallback -I %(bn)s-s_%(port1)s 1 -s %(ip1)s -m mac --mac-source %(mac1)s -j RETURN -I %(bn)s-s_%(port1)s 2 -j DROP -I %(bn)s-s_%(port2)s 1 -s %(ip2)s -m mac --mac-source %(mac2)s -j RETURN @@ -2077,20 +2084,24 @@ def test_security_groups_member_not_updated(self): -I %(bn)s-i_%(port2)s 5 -p icmp -j RETURN -I %(bn)s-i_%(port2)s 6 -m state --state INVALID -j DROP -I %(bn)s-i_%(port2)s 7 -j %(bn)s-sg-fallback --I %(bn)s-o_%(port1)s 1 -p udp -m udp --sport 68 -m udp --dport 67 -j RETURN +-I %(bn)s-o_%(port1)s 1 -s 0.0.0.0/32 -d 255.255.255.255/32 -p udp -m udp \ +--sport 68 --dport 67 -j RETURN -I %(bn)s-o_%(port1)s 2 -j %(bn)s-s_%(port1)s --I %(bn)s-o_%(port1)s 3 -p udp -m udp --sport 67 -m udp --dport 68 -j DROP --I %(bn)s-o_%(port1)s 4 -m state --state RELATED,ESTABLISHED -j RETURN --I %(bn)s-o_%(port1)s 5 -j RETURN --I %(bn)s-o_%(port1)s 6 -m state --state INVALID -j DROP --I %(bn)s-o_%(port1)s 7 -j %(bn)s-sg-fallback --I %(bn)s-o_%(port2)s 1 -p udp -m udp --sport 68 -m udp --dport 67 -j RETURN +-I %(bn)s-o_%(port1)s 3 -p udp -m udp --sport 68 --dport 67 -j RETURN +-I %(bn)s-o_%(port1)s 4 -p udp -m udp --sport 67 -m udp --dport 68 -j DROP +-I %(bn)s-o_%(port1)s 5 -m state --state RELATED,ESTABLISHED -j RETURN +-I %(bn)s-o_%(port1)s 6 -j RETURN +-I %(bn)s-o_%(port1)s 7 -m state --state INVALID -j DROP +-I %(bn)s-o_%(port1)s 8 -j %(bn)s-sg-fallback +-I %(bn)s-o_%(port2)s 1 -s 0.0.0.0/32 -d 255.255.255.255/32 -p udp -m udp \ +--sport 68 --dport 67 -j RETURN -I %(bn)s-o_%(port2)s 2 -j %(bn)s-s_%(port2)s --I %(bn)s-o_%(port2)s 3 -p udp -m udp --sport 67 -m udp --dport 68 -j DROP --I %(bn)s-o_%(port2)s 4 -m state --state RELATED,ESTABLISHED -j RETURN --I %(bn)s-o_%(port2)s 5 -j RETURN --I %(bn)s-o_%(port2)s 6 -m state --state INVALID -j DROP --I %(bn)s-o_%(port2)s 7 -j %(bn)s-sg-fallback +-I %(bn)s-o_%(port2)s 3 -p udp -m udp --sport 68 --dport 67 -j RETURN +-I %(bn)s-o_%(port2)s 4 -p udp -m udp --sport 67 -m udp --dport 68 -j DROP +-I %(bn)s-o_%(port2)s 5 -m state --state RELATED,ESTABLISHED -j RETURN +-I %(bn)s-o_%(port2)s 6 -j RETURN +-I %(bn)s-o_%(port2)s 7 -m state --state INVALID -j DROP +-I %(bn)s-o_%(port2)s 8 -j %(bn)s-sg-fallback -I %(bn)s-s_%(port1)s 1 -s %(ip1)s -m mac --mac-source %(mac1)s -j RETURN -I %(bn)s-s_%(port1)s 2 -j DROP -I %(bn)s-s_%(port2)s 1 -s %(ip2)s -m mac --mac-source %(mac2)s -j RETURN @@ -2159,22 +2170,24 @@ def test_security_groups_member_not_updated(self): -I %(bn)s-i_%(port2)s 4 -s %(ip1)s -j RETURN -I %(bn)s-i_%(port2)s 5 -m state --state INVALID -j DROP -I %(bn)s-i_%(port2)s 6 -j %(bn)s-sg-fallback --I %(bn)s-o_%(port1)s 1 -p udp -m udp --sport 68 -m udp --dport 67 \ --j RETURN +-I %(bn)s-o_%(port1)s 1 -s 0.0.0.0/32 -d 255.255.255.255/32 -p udp -m udp \ +--sport 68 --dport 67 -j RETURN -I %(bn)s-o_%(port1)s 2 -j %(bn)s-s_%(port1)s --I %(bn)s-o_%(port1)s 3 -p udp -m udp --sport 67 -m udp --dport 68 -j DROP --I %(bn)s-o_%(port1)s 4 -m state --state RELATED,ESTABLISHED -j RETURN --I %(bn)s-o_%(port1)s 5 -j RETURN --I %(bn)s-o_%(port1)s 6 -m state --state INVALID -j DROP --I %(bn)s-o_%(port1)s 7 -j %(bn)s-sg-fallback --I %(bn)s-o_%(port2)s 1 -p udp -m udp --sport 68 -m udp --dport 67 \ --j RETURN +-I %(bn)s-o_%(port1)s 3 -p udp -m udp --sport 68 --dport 67 -j RETURN +-I %(bn)s-o_%(port1)s 4 -p udp -m udp --sport 67 -m udp --dport 68 -j DROP +-I %(bn)s-o_%(port1)s 5 -m state --state RELATED,ESTABLISHED -j RETURN +-I %(bn)s-o_%(port1)s 6 -j RETURN +-I %(bn)s-o_%(port1)s 7 -m state --state INVALID -j DROP +-I %(bn)s-o_%(port1)s 8 -j %(bn)s-sg-fallback +-I %(bn)s-o_%(port2)s 1 -s 0.0.0.0/32 -d 255.255.255.255/32 -p udp -m udp \ +--sport 68 --dport 67 -j RETURN -I %(bn)s-o_%(port2)s 2 -j %(bn)s-s_%(port2)s --I %(bn)s-o_%(port2)s 3 -p udp -m udp --sport 67 -m udp --dport 68 -j DROP --I %(bn)s-o_%(port2)s 4 -m state --state RELATED,ESTABLISHED -j RETURN --I %(bn)s-o_%(port2)s 5 -j RETURN --I %(bn)s-o_%(port2)s 6 -m state --state INVALID -j DROP --I %(bn)s-o_%(port2)s 7 -j %(bn)s-sg-fallback +-I %(bn)s-o_%(port2)s 3 -p udp -m udp --sport 68 --dport 67 -j RETURN +-I %(bn)s-o_%(port2)s 4 -p udp -m udp --sport 67 -m udp --dport 68 -j DROP +-I %(bn)s-o_%(port2)s 5 -m state --state RELATED,ESTABLISHED -j RETURN +-I %(bn)s-o_%(port2)s 6 -j RETURN +-I %(bn)s-o_%(port2)s 7 -m state --state INVALID -j DROP +-I %(bn)s-o_%(port2)s 8 -j %(bn)s-sg-fallback -I %(bn)s-s_%(port1)s 1 -s %(ip1)s -m mac --mac-source %(mac1)s -j RETURN -I %(bn)s-s_%(port1)s 2 -j DROP -I %(bn)s-s_%(port2)s 1 -s %(ip2)s -m mac --mac-source %(mac2)s -j RETURN @@ -2242,20 +2255,24 @@ def test_security_groups_member_not_updated(self): -I %(bn)s-i_%(port2)s 4 -s %(ip1)s -j RETURN -I %(bn)s-i_%(port2)s 5 -m state --state INVALID -j DROP -I %(bn)s-i_%(port2)s 6 -j %(bn)s-sg-fallback --I %(bn)s-o_%(port1)s 1 -p udp -m udp --sport 68 -m udp --dport 67 -j RETURN +-I %(bn)s-o_%(port1)s 1 -s 0.0.0.0/32 -d 255.255.255.255/32 -p udp -m udp \ +--sport 68 --dport 67 -j RETURN -I %(bn)s-o_%(port1)s 2 -j %(bn)s-s_%(port1)s --I %(bn)s-o_%(port1)s 3 -p udp -m udp --sport 67 -m udp --dport 68 -j DROP --I %(bn)s-o_%(port1)s 4 -m state --state RELATED,ESTABLISHED -j RETURN --I %(bn)s-o_%(port1)s 5 -j RETURN --I %(bn)s-o_%(port1)s 6 -m state --state INVALID -j DROP --I %(bn)s-o_%(port1)s 7 -j %(bn)s-sg-fallback --I %(bn)s-o_%(port2)s 1 -p udp -m udp --sport 68 -m udp --dport 67 -j RETURN +-I %(bn)s-o_%(port1)s 3 -p udp -m udp --sport 68 --dport 67 -j RETURN +-I %(bn)s-o_%(port1)s 4 -p udp -m udp --sport 67 -m udp --dport 68 -j DROP +-I %(bn)s-o_%(port1)s 5 -m state --state RELATED,ESTABLISHED -j RETURN +-I %(bn)s-o_%(port1)s 6 -j RETURN +-I %(bn)s-o_%(port1)s 7 -m state --state INVALID -j DROP +-I %(bn)s-o_%(port1)s 8 -j %(bn)s-sg-fallback +-I %(bn)s-o_%(port2)s 1 -s 0.0.0.0/32 -d 255.255.255.255/32 -p udp -m udp \ +--sport 68 --dport 67 -j RETURN -I %(bn)s-o_%(port2)s 2 -j %(bn)s-s_%(port2)s --I %(bn)s-o_%(port2)s 3 -p udp -m udp --sport 67 -m udp --dport 68 -j DROP --I %(bn)s-o_%(port2)s 4 -m state --state RELATED,ESTABLISHED -j RETURN --I %(bn)s-o_%(port2)s 5 -j RETURN --I %(bn)s-o_%(port2)s 6 -m state --state INVALID -j DROP --I %(bn)s-o_%(port2)s 7 -j %(bn)s-sg-fallback +-I %(bn)s-o_%(port2)s 3 -p udp -m udp --sport 68 --dport 67 -j RETURN +-I %(bn)s-o_%(port2)s 4 -p udp -m udp --sport 67 -m udp --dport 68 -j DROP +-I %(bn)s-o_%(port2)s 5 -m state --state RELATED,ESTABLISHED -j RETURN +-I %(bn)s-o_%(port2)s 6 -j RETURN +-I %(bn)s-o_%(port2)s 7 -m state --state INVALID -j DROP +-I %(bn)s-o_%(port2)s 8 -j %(bn)s-sg-fallback -I %(bn)s-s_%(port1)s 1 -s %(ip1)s -m mac --mac-source %(mac1)s -j RETURN -I %(bn)s-s_%(port1)s 2 -j DROP -I %(bn)s-s_%(port2)s 1 -s %(ip2)s -m mac --mac-source %(mac2)s -j RETURN @@ -2326,20 +2343,24 @@ def test_security_groups_member_not_updated(self): -I %(bn)s-i_%(port2)s 5 -p icmp -j RETURN -I %(bn)s-i_%(port2)s 6 -m state --state INVALID -j DROP -I %(bn)s-i_%(port2)s 7 -j %(bn)s-sg-fallback --I %(bn)s-o_%(port1)s 1 -p udp -m udp --sport 68 -m udp --dport 67 -j RETURN +-I %(bn)s-o_%(port1)s 1 -s 0.0.0.0/32 -d 255.255.255.255/32 -p udp -m udp \ +--sport 68 --dport 67 -j RETURN -I %(bn)s-o_%(port1)s 2 -j %(bn)s-s_%(port1)s --I %(bn)s-o_%(port1)s 3 -p udp -m udp --sport 67 -m udp --dport 68 -j DROP --I %(bn)s-o_%(port1)s 4 -m state --state RELATED,ESTABLISHED -j RETURN --I %(bn)s-o_%(port1)s 5 -j RETURN --I %(bn)s-o_%(port1)s 6 -m state --state INVALID -j DROP --I %(bn)s-o_%(port1)s 7 -j %(bn)s-sg-fallback --I %(bn)s-o_%(port2)s 1 -p udp -m udp --sport 68 -m udp --dport 67 -j RETURN +-I %(bn)s-o_%(port1)s 3 -p udp -m udp --sport 68 --dport 67 -j RETURN +-I %(bn)s-o_%(port1)s 4 -p udp -m udp --sport 67 -m udp --dport 68 -j DROP +-I %(bn)s-o_%(port1)s 5 -m state --state RELATED,ESTABLISHED -j RETURN +-I %(bn)s-o_%(port1)s 6 -j RETURN +-I %(bn)s-o_%(port1)s 7 -m state --state INVALID -j DROP +-I %(bn)s-o_%(port1)s 8 -j %(bn)s-sg-fallback +-I %(bn)s-o_%(port2)s 1 -s 0.0.0.0/32 -d 255.255.255.255/32 -p udp -m udp \ +--sport 68 --dport 67 -j RETURN -I %(bn)s-o_%(port2)s 2 -j %(bn)s-s_%(port2)s --I %(bn)s-o_%(port2)s 3 -p udp -m udp --sport 67 -m udp --dport 68 -j DROP --I %(bn)s-o_%(port2)s 4 -m state --state RELATED,ESTABLISHED -j RETURN --I %(bn)s-o_%(port2)s 5 -j RETURN --I %(bn)s-o_%(port2)s 6 -m state --state INVALID -j DROP --I %(bn)s-o_%(port2)s 7 -j %(bn)s-sg-fallback +-I %(bn)s-o_%(port2)s 3 -p udp -m udp --sport 68 --dport 67 -j RETURN +-I %(bn)s-o_%(port2)s 4 -p udp -m udp --sport 67 -m udp --dport 68 -j DROP +-I %(bn)s-o_%(port2)s 5 -m state --state RELATED,ESTABLISHED -j RETURN +-I %(bn)s-o_%(port2)s 6 -j RETURN +-I %(bn)s-o_%(port2)s 7 -m state --state INVALID -j DROP +-I %(bn)s-o_%(port2)s 8 -j %(bn)s-sg-fallback -I %(bn)s-s_%(port1)s 1 -s %(ip1)s -m mac --mac-source %(mac1)s -j RETURN -I %(bn)s-s_%(port1)s 2 -j DROP -I %(bn)s-s_%(port2)s 1 -s %(ip2)s -m mac --mac-source %(mac2)s -j RETURN
5853af9cba67Iptables firewall prevent IP spoofed DHCP requests
4 files changed · +149 −92
neutron/agent/linux/iptables_firewall.py+6 −3 modified@@ -381,9 +381,9 @@ def _build_ipv4v6_mac_ip_list(self, mac, ip_address, mac_ipv4_pairs, 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 ' - '-m udp --dport 67 ' + # Allow dhcp client discovery and request + ipv4_rules += [comment_rule('-s 0.0.0.0/32 -d 255.255.255.255/32 ' + '-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 ipv6-icmp -m icmp6 --icmpv6-type %s ' @@ -415,6 +415,9 @@ def _spoofing_rule(self, port, ipv4_rules, ipv6_rules): mac_ipv4_pairs, ipv4_rules) self._setup_spoof_filter_chain(port, self.iptables.ipv6['filter'], mac_ipv6_pairs, ipv6_rules) + # Allow dhcp client renewal and rebinding + ipv4_rules += [comment_rule('-p udp -m udp --sport 68 --dport 67 ' + '-j RETURN', comment=ic.DHCP_CLIENT)] def _drop_dhcp_rule(self, ipv4_rules, ipv6_rules): #Note(nati) Drop dhcp packet from VM
neutron/tests/functional/agent/test_firewall.py+3 −0 modified@@ -355,6 +355,9 @@ def test_ip_spoofing(self): direction=self.tester.INGRESS) self.tester.assert_no_connection(protocol=self.tester.ICMP, direction=self.tester.EGRESS) + self.tester.assert_no_connection(protocol=self.tester.UDP, + src_port=68, dst_port=67, + direction=self.tester.EGRESS) @skip_if_firewall('openvswitch') def test_ip_spoofing_works_without_port_security_enabled(self):
neutron/tests/unit/agent/linux/test_iptables_firewall.py+36 −6 modified@@ -158,10 +158,15 @@ def test_prepare_port_filter_with_no_sg(self): comment=ic.PAIR_DROP), mock.call.add_rule( 'ofake_dev', - '-p udp -m udp --sport 68 -m udp --dport 67 -j RETURN', + '-s 0.0.0.0/32 -d 255.255.255.255/32 -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 68 --dport 67 -j RETURN', + comment=None), mock.call.add_rule( 'ofake_dev', '-p udp -m udp --sport 67 -m udp --dport 68 -j DROP', @@ -940,7 +945,8 @@ def _test_prepare_port_filter(self, filter_inst = self.v4filter_inst dhcp_rule = [mock.call.add_rule( 'ofake_dev', - '-p udp -m udp --sport 68 -m udp --dport 67 -j RETURN', + '-s 0.0.0.0/32 -d 255.255.255.255/32 -p udp -m udp ' + '--sport 68 --dport 67 -j RETURN', comment=None)] if ethertype == 'IPv6': @@ -1027,6 +1033,10 @@ def _test_prepare_port_filter(self, calls.append(mock.call.add_rule('ofake_dev', '-j $sfake_dev', comment=None)) if ethertype == 'IPv4': + calls.append(mock.call.add_rule( + 'ofake_dev', + '-p udp -m udp --sport 68 --dport 67 -j RETURN', + comment=None)) calls.append(mock.call.add_rule( 'ofake_dev', '-p udp -m udp --sport 67 -m udp --dport 68 -j DROP', @@ -1195,10 +1205,15 @@ def test_update_delete_port_filter(self): comment=ic.PAIR_DROP), mock.call.add_rule( 'ofake_dev', - '-p udp -m udp --sport 68 -m udp --dport 67 -j RETURN', + '-s 0.0.0.0/32 -d 255.255.255.255/32 -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 68 --dport 67 -j RETURN', + comment=None), mock.call.add_rule( 'ofake_dev', '-p udp -m udp --sport 67 -m udp --dport 68 -j DROP', @@ -1267,10 +1282,15 @@ def test_update_delete_port_filter(self): comment=ic.PAIR_DROP), mock.call.add_rule( 'ofake_dev', - '-p udp -m udp --sport 68 -m udp --dport 67 -j RETURN', + '-s 0.0.0.0/32 -d 255.255.255.255/32 -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 68 --dport 67 -j RETURN', + comment=None), mock.call.add_rule( 'ofake_dev', '-p udp -m udp --sport 67 -m udp --dport 68 -j DROP', @@ -1442,10 +1462,15 @@ def test_ip_spoofing_filter_with_multiple_ips(self): comment=ic.PAIR_DROP), mock.call.add_rule( 'ofake_dev', - '-p udp -m udp --sport 68 -m udp --dport 67 -j RETURN', + '-s 0.0.0.0/32 -d 255.255.255.255/32 -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 68 --dport 67 -j RETURN', + comment=None), mock.call.add_rule( 'ofake_dev', '-p udp -m udp --sport 67 -m udp --dport 68 -j DROP', @@ -1516,10 +1541,15 @@ def test_ip_spoofing_no_fixed_ips(self): comment=ic.PAIR_DROP), mock.call.add_rule( 'ofake_dev', - '-p udp -m udp --sport 68 -m udp --dport 67 -j RETURN', + '-s 0.0.0.0/32 -d 255.255.255.255/32 -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 68 --dport 67 -j RETURN', + comment=None), mock.call.add_rule( 'ofake_dev', '-p udp -m udp --sport 67 -m udp --dport 68 -j DROP',
neutron/tests/unit/agent/test_securitygroups_rpc.py+104 −83 modified@@ -1888,14 +1888,15 @@ def test_security_groups_member_not_updated(self): RETURN -I %(bn)s-i_port1 5 -m state --state INVALID -j DROP -I %(bn)s-i_port1 6 -j %(bn)s-sg-fallback --I %(bn)s-o_port1 1 -p udp -m udp --sport 68 -m udp --dport 67 \ --j RETURN +-I %(bn)s-o_port1 1 -s 0.0.0.0/32 -d 255.255.255.255/32 -p udp -m udp \ +--sport 68 --dport 67 -j RETURN -I %(bn)s-o_port1 2 -j %(bn)s-s_port1 --I %(bn)s-o_port1 3 -p udp -m udp --sport 67 -m udp --dport 68 -j DROP --I %(bn)s-o_port1 4 -m state --state RELATED,ESTABLISHED -j RETURN --I %(bn)s-o_port1 5 -j RETURN --I %(bn)s-o_port1 6 -m state --state INVALID -j DROP --I %(bn)s-o_port1 7 -j %(bn)s-sg-fallback +-I %(bn)s-o_port1 3 -p udp -m udp --sport 68 --dport 67 -j RETURN +-I %(bn)s-o_port1 4 -p udp -m udp --sport 67 -m udp --dport 68 -j DROP +-I %(bn)s-o_port1 5 -m state --state RELATED,ESTABLISHED -j RETURN +-I %(bn)s-o_port1 6 -j RETURN +-I %(bn)s-o_port1 7 -m state --state INVALID -j DROP +-I %(bn)s-o_port1 8 -j %(bn)s-sg-fallback -I %(bn)s-s_port1 1 -s 10.0.0.3/32 -m mac --mac-source 12:34:56:78:9A:BC \ -j RETURN -I %(bn)s-s_port1 2 -j DROP @@ -1944,14 +1945,15 @@ def test_security_groups_member_not_updated(self): -I %(bn)s-i_port1 3 -p tcp -m tcp --dport 22 -j RETURN -I %(bn)s-i_port1 4 -m state --state INVALID -j DROP -I %(bn)s-i_port1 5 -j %(bn)s-sg-fallback --I %(bn)s-o_port1 1 -p udp -m udp --sport 68 -m udp --dport 67 \ --j RETURN +-I %(bn)s-o_port1 1 -s 0.0.0.0/32 -d 255.255.255.255/32 -p udp -m udp \ +--sport 68 --dport 67 -j RETURN -I %(bn)s-o_port1 2 -j %(bn)s-s_port1 --I %(bn)s-o_port1 3 -p udp -m udp --sport 67 -m udp --dport 68 -j DROP --I %(bn)s-o_port1 4 -m state --state RELATED,ESTABLISHED -j RETURN --I %(bn)s-o_port1 5 -j RETURN --I %(bn)s-o_port1 6 -m state --state INVALID -j DROP --I %(bn)s-o_port1 7 -j %(bn)s-sg-fallback +-I %(bn)s-o_port1 3 -p udp -m udp --sport 68 --dport 67 -j RETURN +-I %(bn)s-o_port1 4 -p udp -m udp --sport 67 -m udp --dport 68 -j DROP +-I %(bn)s-o_port1 5 -m state --state RELATED,ESTABLISHED -j RETURN +-I %(bn)s-o_port1 6 -j RETURN +-I %(bn)s-o_port1 7 -m state --state INVALID -j DROP +-I %(bn)s-o_port1 8 -j %(bn)s-sg-fallback -I %(bn)s-s_port1 1 -s 10.0.0.3/32 -m mac --mac-source 12:34:56:78:9A:BC \ -j RETURN -I %(bn)s-s_port1 2 -j DROP @@ -2002,14 +2004,15 @@ def test_security_groups_member_not_updated(self): -I %(bn)s-i_port1 4 -s 10.0.0.4/32 -j RETURN -I %(bn)s-i_port1 5 -m state --state INVALID -j DROP -I %(bn)s-i_port1 6 -j %(bn)s-sg-fallback --I %(bn)s-o_port1 1 -p udp -m udp --sport 68 -m udp --dport 67 \ --j RETURN +-I %(bn)s-o_port1 1 -s 0.0.0.0/32 -d 255.255.255.255/32 -p udp -m udp \ +--sport 68 --dport 67 -j RETURN -I %(bn)s-o_port1 2 -j %(bn)s-s_port1 --I %(bn)s-o_port1 3 -p udp -m udp --sport 67 -m udp --dport 68 -j DROP --I %(bn)s-o_port1 4 -m state --state RELATED,ESTABLISHED -j RETURN --I %(bn)s-o_port1 5 -j RETURN --I %(bn)s-o_port1 6 -m state --state INVALID -j DROP --I %(bn)s-o_port1 7 -j %(bn)s-sg-fallback +-I %(bn)s-o_port1 3 -p udp -m udp --sport 68 --dport 67 -j RETURN +-I %(bn)s-o_port1 4 -p udp -m udp --sport 67 -m udp --dport 68 -j DROP +-I %(bn)s-o_port1 5 -m state --state RELATED,ESTABLISHED -j RETURN +-I %(bn)s-o_port1 6 -j RETURN +-I %(bn)s-o_port1 7 -m state --state INVALID -j DROP +-I %(bn)s-o_port1 8 -j %(bn)s-sg-fallback -I %(bn)s-s_port1 1 -s 10.0.0.3/32 -m mac --mac-source 12:34:56:78:9A:BC \ -j RETURN -I %(bn)s-s_port1 2 -j DROP @@ -2077,20 +2080,24 @@ def test_security_groups_member_not_updated(self): -I %(bn)s-i_%(port2)s 4 -m set --match-set NIPv4security_group1 src -j RETURN -I %(bn)s-i_%(port2)s 5 -m state --state INVALID -j DROP -I %(bn)s-i_%(port2)s 6 -j %(bn)s-sg-fallback --I %(bn)s-o_%(port1)s 1 -p udp -m udp --sport 68 -m udp --dport 67 -j RETURN +-I %(bn)s-o_%(port1)s 1 -s 0.0.0.0/32 -d 255.255.255.255/32 -p udp -m udp \ +--sport 68 --dport 67 -j RETURN -I %(bn)s-o_%(port1)s 2 -j %(bn)s-s_%(port1)s --I %(bn)s-o_%(port1)s 3 -p udp -m udp --sport 67 -m udp --dport 68 -j DROP --I %(bn)s-o_%(port1)s 4 -m state --state RELATED,ESTABLISHED -j RETURN --I %(bn)s-o_%(port1)s 5 -j RETURN --I %(bn)s-o_%(port1)s 6 -m state --state INVALID -j DROP --I %(bn)s-o_%(port1)s 7 -j %(bn)s-sg-fallback --I %(bn)s-o_%(port2)s 1 -p udp -m udp --sport 68 -m udp --dport 67 -j RETURN +-I %(bn)s-o_%(port1)s 3 -p udp -m udp --sport 68 --dport 67 -j RETURN +-I %(bn)s-o_%(port1)s 4 -p udp -m udp --sport 67 -m udp --dport 68 -j DROP +-I %(bn)s-o_%(port1)s 5 -m state --state RELATED,ESTABLISHED -j RETURN +-I %(bn)s-o_%(port1)s 6 -j RETURN +-I %(bn)s-o_%(port1)s 7 -m state --state INVALID -j DROP +-I %(bn)s-o_%(port1)s 8 -j %(bn)s-sg-fallback +-I %(bn)s-o_%(port2)s 1 -s 0.0.0.0/32 -d 255.255.255.255/32 -p udp -m udp \ +--sport 68 --dport 67 -j RETURN -I %(bn)s-o_%(port2)s 2 -j %(bn)s-s_%(port2)s --I %(bn)s-o_%(port2)s 3 -p udp -m udp --sport 67 -m udp --dport 68 -j DROP --I %(bn)s-o_%(port2)s 4 -m state --state RELATED,ESTABLISHED -j RETURN --I %(bn)s-o_%(port2)s 5 -j RETURN --I %(bn)s-o_%(port2)s 6 -m state --state INVALID -j DROP --I %(bn)s-o_%(port2)s 7 -j %(bn)s-sg-fallback +-I %(bn)s-o_%(port2)s 3 -p udp -m udp --sport 68 --dport 67 -j RETURN +-I %(bn)s-o_%(port2)s 4 -p udp -m udp --sport 67 -m udp --dport 68 -j DROP +-I %(bn)s-o_%(port2)s 5 -m state --state RELATED,ESTABLISHED -j RETURN +-I %(bn)s-o_%(port2)s 6 -j RETURN +-I %(bn)s-o_%(port2)s 7 -m state --state INVALID -j DROP +-I %(bn)s-o_%(port2)s 8 -j %(bn)s-sg-fallback -I %(bn)s-s_%(port1)s 1 -s %(ip1)s -m mac --mac-source %(mac1)s -j RETURN -I %(bn)s-s_%(port1)s 2 -j DROP -I %(bn)s-s_%(port2)s 1 -s %(ip2)s -m mac --mac-source %(mac2)s -j RETURN @@ -2163,20 +2170,24 @@ def test_security_groups_member_not_updated(self): -I %(bn)s-i_%(port2)s 5 -p icmp -j RETURN -I %(bn)s-i_%(port2)s 6 -m state --state INVALID -j DROP -I %(bn)s-i_%(port2)s 7 -j %(bn)s-sg-fallback --I %(bn)s-o_%(port1)s 1 -p udp -m udp --sport 68 -m udp --dport 67 -j RETURN +-I %(bn)s-o_%(port1)s 1 -s 0.0.0.0/32 -d 255.255.255.255/32 -p udp -m udp \ +--sport 68 --dport 67 -j RETURN -I %(bn)s-o_%(port1)s 2 -j %(bn)s-s_%(port1)s --I %(bn)s-o_%(port1)s 3 -p udp -m udp --sport 67 -m udp --dport 68 -j DROP --I %(bn)s-o_%(port1)s 4 -m state --state RELATED,ESTABLISHED -j RETURN --I %(bn)s-o_%(port1)s 5 -j RETURN --I %(bn)s-o_%(port1)s 6 -m state --state INVALID -j DROP --I %(bn)s-o_%(port1)s 7 -j %(bn)s-sg-fallback --I %(bn)s-o_%(port2)s 1 -p udp -m udp --sport 68 -m udp --dport 67 -j RETURN +-I %(bn)s-o_%(port1)s 3 -p udp -m udp --sport 68 --dport 67 -j RETURN +-I %(bn)s-o_%(port1)s 4 -p udp -m udp --sport 67 -m udp --dport 68 -j DROP +-I %(bn)s-o_%(port1)s 5 -m state --state RELATED,ESTABLISHED -j RETURN +-I %(bn)s-o_%(port1)s 6 -j RETURN +-I %(bn)s-o_%(port1)s 7 -m state --state INVALID -j DROP +-I %(bn)s-o_%(port1)s 8 -j %(bn)s-sg-fallback +-I %(bn)s-o_%(port2)s 1 -s 0.0.0.0/32 -d 255.255.255.255/32 -p udp -m udp \ +--sport 68 --dport 67 -j RETURN -I %(bn)s-o_%(port2)s 2 -j %(bn)s-s_%(port2)s --I %(bn)s-o_%(port2)s 3 -p udp -m udp --sport 67 -m udp --dport 68 -j DROP --I %(bn)s-o_%(port2)s 4 -m state --state RELATED,ESTABLISHED -j RETURN --I %(bn)s-o_%(port2)s 5 -j RETURN --I %(bn)s-o_%(port2)s 6 -m state --state INVALID -j DROP --I %(bn)s-o_%(port2)s 7 -j %(bn)s-sg-fallback +-I %(bn)s-o_%(port2)s 3 -p udp -m udp --sport 68 --dport 67 -j RETURN +-I %(bn)s-o_%(port2)s 4 -p udp -m udp --sport 67 -m udp --dport 68 -j DROP +-I %(bn)s-o_%(port2)s 5 -m state --state RELATED,ESTABLISHED -j RETURN +-I %(bn)s-o_%(port2)s 6 -j RETURN +-I %(bn)s-o_%(port2)s 7 -m state --state INVALID -j DROP +-I %(bn)s-o_%(port2)s 8 -j %(bn)s-sg-fallback -I %(bn)s-s_%(port1)s 1 -s %(ip1)s -m mac --mac-source %(mac1)s -j RETURN -I %(bn)s-s_%(port1)s 2 -j DROP -I %(bn)s-s_%(port2)s 1 -s %(ip2)s -m mac --mac-source %(mac2)s -j RETURN @@ -2247,22 +2258,24 @@ def test_security_groups_member_not_updated(self): -I %(bn)s-i_%(port2)s 4 -s %(ip1)s -j RETURN -I %(bn)s-i_%(port2)s 5 -m state --state INVALID -j DROP -I %(bn)s-i_%(port2)s 6 -j %(bn)s-sg-fallback --I %(bn)s-o_%(port1)s 1 -p udp -m udp --sport 68 -m udp --dport 67 \ --j RETURN +-I %(bn)s-o_%(port1)s 1 -s 0.0.0.0/32 -d 255.255.255.255/32 -p udp -m udp \ +--sport 68 --dport 67 -j RETURN -I %(bn)s-o_%(port1)s 2 -j %(bn)s-s_%(port1)s --I %(bn)s-o_%(port1)s 3 -p udp -m udp --sport 67 -m udp --dport 68 -j DROP --I %(bn)s-o_%(port1)s 4 -m state --state RELATED,ESTABLISHED -j RETURN --I %(bn)s-o_%(port1)s 5 -j RETURN --I %(bn)s-o_%(port1)s 6 -m state --state INVALID -j DROP --I %(bn)s-o_%(port1)s 7 -j %(bn)s-sg-fallback --I %(bn)s-o_%(port2)s 1 -p udp -m udp --sport 68 -m udp --dport 67 \ --j RETURN +-I %(bn)s-o_%(port1)s 3 -p udp -m udp --sport 68 --dport 67 -j RETURN +-I %(bn)s-o_%(port1)s 4 -p udp -m udp --sport 67 -m udp --dport 68 -j DROP +-I %(bn)s-o_%(port1)s 5 -m state --state RELATED,ESTABLISHED -j RETURN +-I %(bn)s-o_%(port1)s 6 -j RETURN +-I %(bn)s-o_%(port1)s 7 -m state --state INVALID -j DROP +-I %(bn)s-o_%(port1)s 8 -j %(bn)s-sg-fallback +-I %(bn)s-o_%(port2)s 1 -s 0.0.0.0/32 -d 255.255.255.255/32 -p udp -m udp \ +--sport 68 --dport 67 -j RETURN -I %(bn)s-o_%(port2)s 2 -j %(bn)s-s_%(port2)s --I %(bn)s-o_%(port2)s 3 -p udp -m udp --sport 67 -m udp --dport 68 -j DROP --I %(bn)s-o_%(port2)s 4 -m state --state RELATED,ESTABLISHED -j RETURN --I %(bn)s-o_%(port2)s 5 -j RETURN --I %(bn)s-o_%(port2)s 6 -m state --state INVALID -j DROP --I %(bn)s-o_%(port2)s 7 -j %(bn)s-sg-fallback +-I %(bn)s-o_%(port2)s 3 -p udp -m udp --sport 68 --dport 67 -j RETURN +-I %(bn)s-o_%(port2)s 4 -p udp -m udp --sport 67 -m udp --dport 68 -j DROP +-I %(bn)s-o_%(port2)s 5 -m state --state RELATED,ESTABLISHED -j RETURN +-I %(bn)s-o_%(port2)s 6 -j RETURN +-I %(bn)s-o_%(port2)s 7 -m state --state INVALID -j DROP +-I %(bn)s-o_%(port2)s 8 -j %(bn)s-sg-fallback -I %(bn)s-s_%(port1)s 1 -s %(ip1)s -m mac --mac-source %(mac1)s -j RETURN -I %(bn)s-s_%(port1)s 2 -j DROP -I %(bn)s-s_%(port2)s 1 -s %(ip2)s -m mac --mac-source %(mac2)s -j RETURN @@ -2332,20 +2345,24 @@ def test_security_groups_member_not_updated(self): -I %(bn)s-i_%(port2)s 4 -s %(ip1)s -j RETURN -I %(bn)s-i_%(port2)s 5 -m state --state INVALID -j DROP -I %(bn)s-i_%(port2)s 6 -j %(bn)s-sg-fallback --I %(bn)s-o_%(port1)s 1 -p udp -m udp --sport 68 -m udp --dport 67 -j RETURN +-I %(bn)s-o_%(port1)s 1 -s 0.0.0.0/32 -d 255.255.255.255/32 -p udp -m udp \ +--sport 68 --dport 67 -j RETURN -I %(bn)s-o_%(port1)s 2 -j %(bn)s-s_%(port1)s --I %(bn)s-o_%(port1)s 3 -p udp -m udp --sport 67 -m udp --dport 68 -j DROP --I %(bn)s-o_%(port1)s 4 -m state --state RELATED,ESTABLISHED -j RETURN --I %(bn)s-o_%(port1)s 5 -j RETURN --I %(bn)s-o_%(port1)s 6 -m state --state INVALID -j DROP --I %(bn)s-o_%(port1)s 7 -j %(bn)s-sg-fallback --I %(bn)s-o_%(port2)s 1 -p udp -m udp --sport 68 -m udp --dport 67 -j RETURN +-I %(bn)s-o_%(port1)s 3 -p udp -m udp --sport 68 --dport 67 -j RETURN +-I %(bn)s-o_%(port1)s 4 -p udp -m udp --sport 67 -m udp --dport 68 -j DROP +-I %(bn)s-o_%(port1)s 5 -m state --state RELATED,ESTABLISHED -j RETURN +-I %(bn)s-o_%(port1)s 6 -j RETURN +-I %(bn)s-o_%(port1)s 7 -m state --state INVALID -j DROP +-I %(bn)s-o_%(port1)s 8 -j %(bn)s-sg-fallback +-I %(bn)s-o_%(port2)s 1 -s 0.0.0.0/32 -d 255.255.255.255/32 -p udp -m udp \ +--sport 68 --dport 67 -j RETURN -I %(bn)s-o_%(port2)s 2 -j %(bn)s-s_%(port2)s --I %(bn)s-o_%(port2)s 3 -p udp -m udp --sport 67 -m udp --dport 68 -j DROP --I %(bn)s-o_%(port2)s 4 -m state --state RELATED,ESTABLISHED -j RETURN --I %(bn)s-o_%(port2)s 5 -j RETURN --I %(bn)s-o_%(port2)s 6 -m state --state INVALID -j DROP --I %(bn)s-o_%(port2)s 7 -j %(bn)s-sg-fallback +-I %(bn)s-o_%(port2)s 3 -p udp -m udp --sport 68 --dport 67 -j RETURN +-I %(bn)s-o_%(port2)s 4 -p udp -m udp --sport 67 -m udp --dport 68 -j DROP +-I %(bn)s-o_%(port2)s 5 -m state --state RELATED,ESTABLISHED -j RETURN +-I %(bn)s-o_%(port2)s 6 -j RETURN +-I %(bn)s-o_%(port2)s 7 -m state --state INVALID -j DROP +-I %(bn)s-o_%(port2)s 8 -j %(bn)s-sg-fallback -I %(bn)s-s_%(port1)s 1 -s %(ip1)s -m mac --mac-source %(mac1)s -j RETURN -I %(bn)s-s_%(port1)s 2 -j DROP -I %(bn)s-s_%(port2)s 1 -s %(ip2)s -m mac --mac-source %(mac2)s -j RETURN @@ -2418,20 +2435,24 @@ def test_security_groups_member_not_updated(self): -I %(bn)s-i_%(port2)s 5 -p icmp -j RETURN -I %(bn)s-i_%(port2)s 6 -m state --state INVALID -j DROP -I %(bn)s-i_%(port2)s 7 -j %(bn)s-sg-fallback --I %(bn)s-o_%(port1)s 1 -p udp -m udp --sport 68 -m udp --dport 67 -j RETURN +-I %(bn)s-o_%(port1)s 1 -s 0.0.0.0/32 -d 255.255.255.255/32 -p udp -m udp \ +--sport 68 --dport 67 -j RETURN -I %(bn)s-o_%(port1)s 2 -j %(bn)s-s_%(port1)s --I %(bn)s-o_%(port1)s 3 -p udp -m udp --sport 67 -m udp --dport 68 -j DROP --I %(bn)s-o_%(port1)s 4 -m state --state RELATED,ESTABLISHED -j RETURN --I %(bn)s-o_%(port1)s 5 -j RETURN --I %(bn)s-o_%(port1)s 6 -m state --state INVALID -j DROP --I %(bn)s-o_%(port1)s 7 -j %(bn)s-sg-fallback --I %(bn)s-o_%(port2)s 1 -p udp -m udp --sport 68 -m udp --dport 67 -j RETURN +-I %(bn)s-o_%(port1)s 3 -p udp -m udp --sport 68 --dport 67 -j RETURN +-I %(bn)s-o_%(port1)s 4 -p udp -m udp --sport 67 -m udp --dport 68 -j DROP +-I %(bn)s-o_%(port1)s 5 -m state --state RELATED,ESTABLISHED -j RETURN +-I %(bn)s-o_%(port1)s 6 -j RETURN +-I %(bn)s-o_%(port1)s 7 -m state --state INVALID -j DROP +-I %(bn)s-o_%(port1)s 8 -j %(bn)s-sg-fallback +-I %(bn)s-o_%(port2)s 1 -s 0.0.0.0/32 -d 255.255.255.255/32 -p udp -m udp \ +--sport 68 --dport 67 -j RETURN -I %(bn)s-o_%(port2)s 2 -j %(bn)s-s_%(port2)s --I %(bn)s-o_%(port2)s 3 -p udp -m udp --sport 67 -m udp --dport 68 -j DROP --I %(bn)s-o_%(port2)s 4 -m state --state RELATED,ESTABLISHED -j RETURN --I %(bn)s-o_%(port2)s 5 -j RETURN --I %(bn)s-o_%(port2)s 6 -m state --state INVALID -j DROP --I %(bn)s-o_%(port2)s 7 -j %(bn)s-sg-fallback +-I %(bn)s-o_%(port2)s 3 -p udp -m udp --sport 68 --dport 67 -j RETURN +-I %(bn)s-o_%(port2)s 4 -p udp -m udp --sport 67 -m udp --dport 68 -j DROP +-I %(bn)s-o_%(port2)s 5 -m state --state RELATED,ESTABLISHED -j RETURN +-I %(bn)s-o_%(port2)s 6 -j RETURN +-I %(bn)s-o_%(port2)s 7 -m state --state INVALID -j DROP +-I %(bn)s-o_%(port2)s 8 -j %(bn)s-sg-fallback -I %(bn)s-s_%(port1)s 1 -s %(ip1)s -m mac --mac-source %(mac1)s -j RETURN -I %(bn)s-s_%(port1)s 2 -j DROP -I %(bn)s-s_%(port2)s 1 -s %(ip2)s -m mac --mac-source %(mac2)s -j RETURN
6a93ee8ac1a9Iptables firewall prevent IP spoofed DHCP requests
4 files changed · +149 −92
neutron/agent/linux/iptables_firewall.py+6 −3 modified@@ -381,9 +381,9 @@ def _build_ipv4v6_mac_ip_list(self, mac, ip_address, mac_ipv4_pairs, 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 ' - '-m udp --dport 67 ' + # Allow dhcp client discovery and request + ipv4_rules += [comment_rule('-s 0.0.0.0/32 -d 255.255.255.255/32 ' + '-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 ipv6-icmp -m icmp6 --icmpv6-type %s ' @@ -415,6 +415,9 @@ def _spoofing_rule(self, port, ipv4_rules, ipv6_rules): mac_ipv4_pairs, ipv4_rules) self._setup_spoof_filter_chain(port, self.iptables.ipv6['filter'], mac_ipv6_pairs, ipv6_rules) + # Allow dhcp client renewal and rebinding + ipv4_rules += [comment_rule('-p udp -m udp --sport 68 --dport 67 ' + '-j RETURN', comment=ic.DHCP_CLIENT)] def _drop_dhcp_rule(self, ipv4_rules, ipv6_rules): #Note(nati) Drop dhcp packet from VM
neutron/tests/functional/agent/test_firewall.py+3 −0 modified@@ -355,6 +355,9 @@ def test_ip_spoofing(self): direction=self.tester.INGRESS) self.tester.assert_no_connection(protocol=self.tester.ICMP, direction=self.tester.EGRESS) + self.tester.assert_no_connection(protocol=self.tester.UDP, + src_port=68, dst_port=67, + direction=self.tester.EGRESS) @skip_if_firewall('openvswitch') def test_ip_spoofing_works_without_port_security_enabled(self):
neutron/tests/unit/agent/linux/test_iptables_firewall.py+36 −6 modified@@ -158,10 +158,15 @@ def test_prepare_port_filter_with_no_sg(self): comment=ic.PAIR_DROP), mock.call.add_rule( 'ofake_dev', - '-p udp -m udp --sport 68 -m udp --dport 67 -j RETURN', + '-s 0.0.0.0/32 -d 255.255.255.255/32 -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 68 --dport 67 -j RETURN', + comment=None), mock.call.add_rule( 'ofake_dev', '-p udp -m udp --sport 67 -m udp --dport 68 -j DROP', @@ -940,7 +945,8 @@ def _test_prepare_port_filter(self, filter_inst = self.v4filter_inst dhcp_rule = [mock.call.add_rule( 'ofake_dev', - '-p udp -m udp --sport 68 -m udp --dport 67 -j RETURN', + '-s 0.0.0.0/32 -d 255.255.255.255/32 -p udp -m udp ' + '--sport 68 --dport 67 -j RETURN', comment=None)] if ethertype == 'IPv6': @@ -1027,6 +1033,10 @@ def _test_prepare_port_filter(self, calls.append(mock.call.add_rule('ofake_dev', '-j $sfake_dev', comment=None)) if ethertype == 'IPv4': + calls.append(mock.call.add_rule( + 'ofake_dev', + '-p udp -m udp --sport 68 --dport 67 -j RETURN', + comment=None)) calls.append(mock.call.add_rule( 'ofake_dev', '-p udp -m udp --sport 67 -m udp --dport 68 -j DROP', @@ -1195,10 +1205,15 @@ def test_update_delete_port_filter(self): comment=ic.PAIR_DROP), mock.call.add_rule( 'ofake_dev', - '-p udp -m udp --sport 68 -m udp --dport 67 -j RETURN', + '-s 0.0.0.0/32 -d 255.255.255.255/32 -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 68 --dport 67 -j RETURN', + comment=None), mock.call.add_rule( 'ofake_dev', '-p udp -m udp --sport 67 -m udp --dport 68 -j DROP', @@ -1267,10 +1282,15 @@ def test_update_delete_port_filter(self): comment=ic.PAIR_DROP), mock.call.add_rule( 'ofake_dev', - '-p udp -m udp --sport 68 -m udp --dport 67 -j RETURN', + '-s 0.0.0.0/32 -d 255.255.255.255/32 -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 68 --dport 67 -j RETURN', + comment=None), mock.call.add_rule( 'ofake_dev', '-p udp -m udp --sport 67 -m udp --dport 68 -j DROP', @@ -1442,10 +1462,15 @@ def test_ip_spoofing_filter_with_multiple_ips(self): comment=ic.PAIR_DROP), mock.call.add_rule( 'ofake_dev', - '-p udp -m udp --sport 68 -m udp --dport 67 -j RETURN', + '-s 0.0.0.0/32 -d 255.255.255.255/32 -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 68 --dport 67 -j RETURN', + comment=None), mock.call.add_rule( 'ofake_dev', '-p udp -m udp --sport 67 -m udp --dport 68 -j DROP', @@ -1516,10 +1541,15 @@ def test_ip_spoofing_no_fixed_ips(self): comment=ic.PAIR_DROP), mock.call.add_rule( 'ofake_dev', - '-p udp -m udp --sport 68 -m udp --dport 67 -j RETURN', + '-s 0.0.0.0/32 -d 255.255.255.255/32 -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 68 --dport 67 -j RETURN', + comment=None), mock.call.add_rule( 'ofake_dev', '-p udp -m udp --sport 67 -m udp --dport 68 -j DROP',
neutron/tests/unit/agent/test_securitygroups_rpc.py+104 −83 modified@@ -1888,14 +1888,15 @@ def test_security_groups_member_not_updated(self): RETURN -I %(bn)s-i_port1 5 -m state --state INVALID -j DROP -I %(bn)s-i_port1 6 -j %(bn)s-sg-fallback --I %(bn)s-o_port1 1 -p udp -m udp --sport 68 -m udp --dport 67 \ --j RETURN +-I %(bn)s-o_port1 1 -s 0.0.0.0/32 -d 255.255.255.255/32 -p udp -m udp \ +--sport 68 --dport 67 -j RETURN -I %(bn)s-o_port1 2 -j %(bn)s-s_port1 --I %(bn)s-o_port1 3 -p udp -m udp --sport 67 -m udp --dport 68 -j DROP --I %(bn)s-o_port1 4 -m state --state RELATED,ESTABLISHED -j RETURN --I %(bn)s-o_port1 5 -j RETURN --I %(bn)s-o_port1 6 -m state --state INVALID -j DROP --I %(bn)s-o_port1 7 -j %(bn)s-sg-fallback +-I %(bn)s-o_port1 3 -p udp -m udp --sport 68 --dport 67 -j RETURN +-I %(bn)s-o_port1 4 -p udp -m udp --sport 67 -m udp --dport 68 -j DROP +-I %(bn)s-o_port1 5 -m state --state RELATED,ESTABLISHED -j RETURN +-I %(bn)s-o_port1 6 -j RETURN +-I %(bn)s-o_port1 7 -m state --state INVALID -j DROP +-I %(bn)s-o_port1 8 -j %(bn)s-sg-fallback -I %(bn)s-s_port1 1 -s 10.0.0.3/32 -m mac --mac-source 12:34:56:78:9A:BC \ -j RETURN -I %(bn)s-s_port1 2 -j DROP @@ -1944,14 +1945,15 @@ def test_security_groups_member_not_updated(self): -I %(bn)s-i_port1 3 -p tcp -m tcp --dport 22 -j RETURN -I %(bn)s-i_port1 4 -m state --state INVALID -j DROP -I %(bn)s-i_port1 5 -j %(bn)s-sg-fallback --I %(bn)s-o_port1 1 -p udp -m udp --sport 68 -m udp --dport 67 \ --j RETURN +-I %(bn)s-o_port1 1 -s 0.0.0.0/32 -d 255.255.255.255/32 -p udp -m udp \ +--sport 68 --dport 67 -j RETURN -I %(bn)s-o_port1 2 -j %(bn)s-s_port1 --I %(bn)s-o_port1 3 -p udp -m udp --sport 67 -m udp --dport 68 -j DROP --I %(bn)s-o_port1 4 -m state --state RELATED,ESTABLISHED -j RETURN --I %(bn)s-o_port1 5 -j RETURN --I %(bn)s-o_port1 6 -m state --state INVALID -j DROP --I %(bn)s-o_port1 7 -j %(bn)s-sg-fallback +-I %(bn)s-o_port1 3 -p udp -m udp --sport 68 --dport 67 -j RETURN +-I %(bn)s-o_port1 4 -p udp -m udp --sport 67 -m udp --dport 68 -j DROP +-I %(bn)s-o_port1 5 -m state --state RELATED,ESTABLISHED -j RETURN +-I %(bn)s-o_port1 6 -j RETURN +-I %(bn)s-o_port1 7 -m state --state INVALID -j DROP +-I %(bn)s-o_port1 8 -j %(bn)s-sg-fallback -I %(bn)s-s_port1 1 -s 10.0.0.3/32 -m mac --mac-source 12:34:56:78:9A:BC \ -j RETURN -I %(bn)s-s_port1 2 -j DROP @@ -2002,14 +2004,15 @@ def test_security_groups_member_not_updated(self): -I %(bn)s-i_port1 4 -s 10.0.0.4/32 -j RETURN -I %(bn)s-i_port1 5 -m state --state INVALID -j DROP -I %(bn)s-i_port1 6 -j %(bn)s-sg-fallback --I %(bn)s-o_port1 1 -p udp -m udp --sport 68 -m udp --dport 67 \ --j RETURN +-I %(bn)s-o_port1 1 -s 0.0.0.0/32 -d 255.255.255.255/32 -p udp -m udp \ +--sport 68 --dport 67 -j RETURN -I %(bn)s-o_port1 2 -j %(bn)s-s_port1 --I %(bn)s-o_port1 3 -p udp -m udp --sport 67 -m udp --dport 68 -j DROP --I %(bn)s-o_port1 4 -m state --state RELATED,ESTABLISHED -j RETURN --I %(bn)s-o_port1 5 -j RETURN --I %(bn)s-o_port1 6 -m state --state INVALID -j DROP --I %(bn)s-o_port1 7 -j %(bn)s-sg-fallback +-I %(bn)s-o_port1 3 -p udp -m udp --sport 68 --dport 67 -j RETURN +-I %(bn)s-o_port1 4 -p udp -m udp --sport 67 -m udp --dport 68 -j DROP +-I %(bn)s-o_port1 5 -m state --state RELATED,ESTABLISHED -j RETURN +-I %(bn)s-o_port1 6 -j RETURN +-I %(bn)s-o_port1 7 -m state --state INVALID -j DROP +-I %(bn)s-o_port1 8 -j %(bn)s-sg-fallback -I %(bn)s-s_port1 1 -s 10.0.0.3/32 -m mac --mac-source 12:34:56:78:9A:BC \ -j RETURN -I %(bn)s-s_port1 2 -j DROP @@ -2077,20 +2080,24 @@ def test_security_groups_member_not_updated(self): -I %(bn)s-i_%(port2)s 4 -m set --match-set NIPv4security_group1 src -j RETURN -I %(bn)s-i_%(port2)s 5 -m state --state INVALID -j DROP -I %(bn)s-i_%(port2)s 6 -j %(bn)s-sg-fallback --I %(bn)s-o_%(port1)s 1 -p udp -m udp --sport 68 -m udp --dport 67 -j RETURN +-I %(bn)s-o_%(port1)s 1 -s 0.0.0.0/32 -d 255.255.255.255/32 -p udp -m udp \ +--sport 68 --dport 67 -j RETURN -I %(bn)s-o_%(port1)s 2 -j %(bn)s-s_%(port1)s --I %(bn)s-o_%(port1)s 3 -p udp -m udp --sport 67 -m udp --dport 68 -j DROP --I %(bn)s-o_%(port1)s 4 -m state --state RELATED,ESTABLISHED -j RETURN --I %(bn)s-o_%(port1)s 5 -j RETURN --I %(bn)s-o_%(port1)s 6 -m state --state INVALID -j DROP --I %(bn)s-o_%(port1)s 7 -j %(bn)s-sg-fallback --I %(bn)s-o_%(port2)s 1 -p udp -m udp --sport 68 -m udp --dport 67 -j RETURN +-I %(bn)s-o_%(port1)s 3 -p udp -m udp --sport 68 --dport 67 -j RETURN +-I %(bn)s-o_%(port1)s 4 -p udp -m udp --sport 67 -m udp --dport 68 -j DROP +-I %(bn)s-o_%(port1)s 5 -m state --state RELATED,ESTABLISHED -j RETURN +-I %(bn)s-o_%(port1)s 6 -j RETURN +-I %(bn)s-o_%(port1)s 7 -m state --state INVALID -j DROP +-I %(bn)s-o_%(port1)s 8 -j %(bn)s-sg-fallback +-I %(bn)s-o_%(port2)s 1 -s 0.0.0.0/32 -d 255.255.255.255/32 -p udp -m udp \ +--sport 68 --dport 67 -j RETURN -I %(bn)s-o_%(port2)s 2 -j %(bn)s-s_%(port2)s --I %(bn)s-o_%(port2)s 3 -p udp -m udp --sport 67 -m udp --dport 68 -j DROP --I %(bn)s-o_%(port2)s 4 -m state --state RELATED,ESTABLISHED -j RETURN --I %(bn)s-o_%(port2)s 5 -j RETURN --I %(bn)s-o_%(port2)s 6 -m state --state INVALID -j DROP --I %(bn)s-o_%(port2)s 7 -j %(bn)s-sg-fallback +-I %(bn)s-o_%(port2)s 3 -p udp -m udp --sport 68 --dport 67 -j RETURN +-I %(bn)s-o_%(port2)s 4 -p udp -m udp --sport 67 -m udp --dport 68 -j DROP +-I %(bn)s-o_%(port2)s 5 -m state --state RELATED,ESTABLISHED -j RETURN +-I %(bn)s-o_%(port2)s 6 -j RETURN +-I %(bn)s-o_%(port2)s 7 -m state --state INVALID -j DROP +-I %(bn)s-o_%(port2)s 8 -j %(bn)s-sg-fallback -I %(bn)s-s_%(port1)s 1 -s %(ip1)s -m mac --mac-source %(mac1)s -j RETURN -I %(bn)s-s_%(port1)s 2 -j DROP -I %(bn)s-s_%(port2)s 1 -s %(ip2)s -m mac --mac-source %(mac2)s -j RETURN @@ -2163,20 +2170,24 @@ def test_security_groups_member_not_updated(self): -I %(bn)s-i_%(port2)s 5 -p icmp -j RETURN -I %(bn)s-i_%(port2)s 6 -m state --state INVALID -j DROP -I %(bn)s-i_%(port2)s 7 -j %(bn)s-sg-fallback --I %(bn)s-o_%(port1)s 1 -p udp -m udp --sport 68 -m udp --dport 67 -j RETURN +-I %(bn)s-o_%(port1)s 1 -s 0.0.0.0/32 -d 255.255.255.255/32 -p udp -m udp \ +--sport 68 --dport 67 -j RETURN -I %(bn)s-o_%(port1)s 2 -j %(bn)s-s_%(port1)s --I %(bn)s-o_%(port1)s 3 -p udp -m udp --sport 67 -m udp --dport 68 -j DROP --I %(bn)s-o_%(port1)s 4 -m state --state RELATED,ESTABLISHED -j RETURN --I %(bn)s-o_%(port1)s 5 -j RETURN --I %(bn)s-o_%(port1)s 6 -m state --state INVALID -j DROP --I %(bn)s-o_%(port1)s 7 -j %(bn)s-sg-fallback --I %(bn)s-o_%(port2)s 1 -p udp -m udp --sport 68 -m udp --dport 67 -j RETURN +-I %(bn)s-o_%(port1)s 3 -p udp -m udp --sport 68 --dport 67 -j RETURN +-I %(bn)s-o_%(port1)s 4 -p udp -m udp --sport 67 -m udp --dport 68 -j DROP +-I %(bn)s-o_%(port1)s 5 -m state --state RELATED,ESTABLISHED -j RETURN +-I %(bn)s-o_%(port1)s 6 -j RETURN +-I %(bn)s-o_%(port1)s 7 -m state --state INVALID -j DROP +-I %(bn)s-o_%(port1)s 8 -j %(bn)s-sg-fallback +-I %(bn)s-o_%(port2)s 1 -s 0.0.0.0/32 -d 255.255.255.255/32 -p udp -m udp \ +--sport 68 --dport 67 -j RETURN -I %(bn)s-o_%(port2)s 2 -j %(bn)s-s_%(port2)s --I %(bn)s-o_%(port2)s 3 -p udp -m udp --sport 67 -m udp --dport 68 -j DROP --I %(bn)s-o_%(port2)s 4 -m state --state RELATED,ESTABLISHED -j RETURN --I %(bn)s-o_%(port2)s 5 -j RETURN --I %(bn)s-o_%(port2)s 6 -m state --state INVALID -j DROP --I %(bn)s-o_%(port2)s 7 -j %(bn)s-sg-fallback +-I %(bn)s-o_%(port2)s 3 -p udp -m udp --sport 68 --dport 67 -j RETURN +-I %(bn)s-o_%(port2)s 4 -p udp -m udp --sport 67 -m udp --dport 68 -j DROP +-I %(bn)s-o_%(port2)s 5 -m state --state RELATED,ESTABLISHED -j RETURN +-I %(bn)s-o_%(port2)s 6 -j RETURN +-I %(bn)s-o_%(port2)s 7 -m state --state INVALID -j DROP +-I %(bn)s-o_%(port2)s 8 -j %(bn)s-sg-fallback -I %(bn)s-s_%(port1)s 1 -s %(ip1)s -m mac --mac-source %(mac1)s -j RETURN -I %(bn)s-s_%(port1)s 2 -j DROP -I %(bn)s-s_%(port2)s 1 -s %(ip2)s -m mac --mac-source %(mac2)s -j RETURN @@ -2247,22 +2258,24 @@ def test_security_groups_member_not_updated(self): -I %(bn)s-i_%(port2)s 4 -s %(ip1)s -j RETURN -I %(bn)s-i_%(port2)s 5 -m state --state INVALID -j DROP -I %(bn)s-i_%(port2)s 6 -j %(bn)s-sg-fallback --I %(bn)s-o_%(port1)s 1 -p udp -m udp --sport 68 -m udp --dport 67 \ --j RETURN +-I %(bn)s-o_%(port1)s 1 -s 0.0.0.0/32 -d 255.255.255.255/32 -p udp -m udp \ +--sport 68 --dport 67 -j RETURN -I %(bn)s-o_%(port1)s 2 -j %(bn)s-s_%(port1)s --I %(bn)s-o_%(port1)s 3 -p udp -m udp --sport 67 -m udp --dport 68 -j DROP --I %(bn)s-o_%(port1)s 4 -m state --state RELATED,ESTABLISHED -j RETURN --I %(bn)s-o_%(port1)s 5 -j RETURN --I %(bn)s-o_%(port1)s 6 -m state --state INVALID -j DROP --I %(bn)s-o_%(port1)s 7 -j %(bn)s-sg-fallback --I %(bn)s-o_%(port2)s 1 -p udp -m udp --sport 68 -m udp --dport 67 \ --j RETURN +-I %(bn)s-o_%(port1)s 3 -p udp -m udp --sport 68 --dport 67 -j RETURN +-I %(bn)s-o_%(port1)s 4 -p udp -m udp --sport 67 -m udp --dport 68 -j DROP +-I %(bn)s-o_%(port1)s 5 -m state --state RELATED,ESTABLISHED -j RETURN +-I %(bn)s-o_%(port1)s 6 -j RETURN +-I %(bn)s-o_%(port1)s 7 -m state --state INVALID -j DROP +-I %(bn)s-o_%(port1)s 8 -j %(bn)s-sg-fallback +-I %(bn)s-o_%(port2)s 1 -s 0.0.0.0/32 -d 255.255.255.255/32 -p udp -m udp \ +--sport 68 --dport 67 -j RETURN -I %(bn)s-o_%(port2)s 2 -j %(bn)s-s_%(port2)s --I %(bn)s-o_%(port2)s 3 -p udp -m udp --sport 67 -m udp --dport 68 -j DROP --I %(bn)s-o_%(port2)s 4 -m state --state RELATED,ESTABLISHED -j RETURN --I %(bn)s-o_%(port2)s 5 -j RETURN --I %(bn)s-o_%(port2)s 6 -m state --state INVALID -j DROP --I %(bn)s-o_%(port2)s 7 -j %(bn)s-sg-fallback +-I %(bn)s-o_%(port2)s 3 -p udp -m udp --sport 68 --dport 67 -j RETURN +-I %(bn)s-o_%(port2)s 4 -p udp -m udp --sport 67 -m udp --dport 68 -j DROP +-I %(bn)s-o_%(port2)s 5 -m state --state RELATED,ESTABLISHED -j RETURN +-I %(bn)s-o_%(port2)s 6 -j RETURN +-I %(bn)s-o_%(port2)s 7 -m state --state INVALID -j DROP +-I %(bn)s-o_%(port2)s 8 -j %(bn)s-sg-fallback -I %(bn)s-s_%(port1)s 1 -s %(ip1)s -m mac --mac-source %(mac1)s -j RETURN -I %(bn)s-s_%(port1)s 2 -j DROP -I %(bn)s-s_%(port2)s 1 -s %(ip2)s -m mac --mac-source %(mac2)s -j RETURN @@ -2332,20 +2345,24 @@ def test_security_groups_member_not_updated(self): -I %(bn)s-i_%(port2)s 4 -s %(ip1)s -j RETURN -I %(bn)s-i_%(port2)s 5 -m state --state INVALID -j DROP -I %(bn)s-i_%(port2)s 6 -j %(bn)s-sg-fallback --I %(bn)s-o_%(port1)s 1 -p udp -m udp --sport 68 -m udp --dport 67 -j RETURN +-I %(bn)s-o_%(port1)s 1 -s 0.0.0.0/32 -d 255.255.255.255/32 -p udp -m udp \ +--sport 68 --dport 67 -j RETURN -I %(bn)s-o_%(port1)s 2 -j %(bn)s-s_%(port1)s --I %(bn)s-o_%(port1)s 3 -p udp -m udp --sport 67 -m udp --dport 68 -j DROP --I %(bn)s-o_%(port1)s 4 -m state --state RELATED,ESTABLISHED -j RETURN --I %(bn)s-o_%(port1)s 5 -j RETURN --I %(bn)s-o_%(port1)s 6 -m state --state INVALID -j DROP --I %(bn)s-o_%(port1)s 7 -j %(bn)s-sg-fallback --I %(bn)s-o_%(port2)s 1 -p udp -m udp --sport 68 -m udp --dport 67 -j RETURN +-I %(bn)s-o_%(port1)s 3 -p udp -m udp --sport 68 --dport 67 -j RETURN +-I %(bn)s-o_%(port1)s 4 -p udp -m udp --sport 67 -m udp --dport 68 -j DROP +-I %(bn)s-o_%(port1)s 5 -m state --state RELATED,ESTABLISHED -j RETURN +-I %(bn)s-o_%(port1)s 6 -j RETURN +-I %(bn)s-o_%(port1)s 7 -m state --state INVALID -j DROP +-I %(bn)s-o_%(port1)s 8 -j %(bn)s-sg-fallback +-I %(bn)s-o_%(port2)s 1 -s 0.0.0.0/32 -d 255.255.255.255/32 -p udp -m udp \ +--sport 68 --dport 67 -j RETURN -I %(bn)s-o_%(port2)s 2 -j %(bn)s-s_%(port2)s --I %(bn)s-o_%(port2)s 3 -p udp -m udp --sport 67 -m udp --dport 68 -j DROP --I %(bn)s-o_%(port2)s 4 -m state --state RELATED,ESTABLISHED -j RETURN --I %(bn)s-o_%(port2)s 5 -j RETURN --I %(bn)s-o_%(port2)s 6 -m state --state INVALID -j DROP --I %(bn)s-o_%(port2)s 7 -j %(bn)s-sg-fallback +-I %(bn)s-o_%(port2)s 3 -p udp -m udp --sport 68 --dport 67 -j RETURN +-I %(bn)s-o_%(port2)s 4 -p udp -m udp --sport 67 -m udp --dport 68 -j DROP +-I %(bn)s-o_%(port2)s 5 -m state --state RELATED,ESTABLISHED -j RETURN +-I %(bn)s-o_%(port2)s 6 -j RETURN +-I %(bn)s-o_%(port2)s 7 -m state --state INVALID -j DROP +-I %(bn)s-o_%(port2)s 8 -j %(bn)s-sg-fallback -I %(bn)s-s_%(port1)s 1 -s %(ip1)s -m mac --mac-source %(mac1)s -j RETURN -I %(bn)s-s_%(port1)s 2 -j DROP -I %(bn)s-s_%(port2)s 1 -s %(ip2)s -m mac --mac-source %(mac2)s -j RETURN @@ -2418,20 +2435,24 @@ def test_security_groups_member_not_updated(self): -I %(bn)s-i_%(port2)s 5 -p icmp -j RETURN -I %(bn)s-i_%(port2)s 6 -m state --state INVALID -j DROP -I %(bn)s-i_%(port2)s 7 -j %(bn)s-sg-fallback --I %(bn)s-o_%(port1)s 1 -p udp -m udp --sport 68 -m udp --dport 67 -j RETURN +-I %(bn)s-o_%(port1)s 1 -s 0.0.0.0/32 -d 255.255.255.255/32 -p udp -m udp \ +--sport 68 --dport 67 -j RETURN -I %(bn)s-o_%(port1)s 2 -j %(bn)s-s_%(port1)s --I %(bn)s-o_%(port1)s 3 -p udp -m udp --sport 67 -m udp --dport 68 -j DROP --I %(bn)s-o_%(port1)s 4 -m state --state RELATED,ESTABLISHED -j RETURN --I %(bn)s-o_%(port1)s 5 -j RETURN --I %(bn)s-o_%(port1)s 6 -m state --state INVALID -j DROP --I %(bn)s-o_%(port1)s 7 -j %(bn)s-sg-fallback --I %(bn)s-o_%(port2)s 1 -p udp -m udp --sport 68 -m udp --dport 67 -j RETURN +-I %(bn)s-o_%(port1)s 3 -p udp -m udp --sport 68 --dport 67 -j RETURN +-I %(bn)s-o_%(port1)s 4 -p udp -m udp --sport 67 -m udp --dport 68 -j DROP +-I %(bn)s-o_%(port1)s 5 -m state --state RELATED,ESTABLISHED -j RETURN +-I %(bn)s-o_%(port1)s 6 -j RETURN +-I %(bn)s-o_%(port1)s 7 -m state --state INVALID -j DROP +-I %(bn)s-o_%(port1)s 8 -j %(bn)s-sg-fallback +-I %(bn)s-o_%(port2)s 1 -s 0.0.0.0/32 -d 255.255.255.255/32 -p udp -m udp \ +--sport 68 --dport 67 -j RETURN -I %(bn)s-o_%(port2)s 2 -j %(bn)s-s_%(port2)s --I %(bn)s-o_%(port2)s 3 -p udp -m udp --sport 67 -m udp --dport 68 -j DROP --I %(bn)s-o_%(port2)s 4 -m state --state RELATED,ESTABLISHED -j RETURN --I %(bn)s-o_%(port2)s 5 -j RETURN --I %(bn)s-o_%(port2)s 6 -m state --state INVALID -j DROP --I %(bn)s-o_%(port2)s 7 -j %(bn)s-sg-fallback +-I %(bn)s-o_%(port2)s 3 -p udp -m udp --sport 68 --dport 67 -j RETURN +-I %(bn)s-o_%(port2)s 4 -p udp -m udp --sport 67 -m udp --dport 68 -j DROP +-I %(bn)s-o_%(port2)s 5 -m state --state RELATED,ESTABLISHED -j RETURN +-I %(bn)s-o_%(port2)s 6 -j RETURN +-I %(bn)s-o_%(port2)s 7 -m state --state INVALID -j DROP +-I %(bn)s-o_%(port2)s 8 -j %(bn)s-sg-fallback -I %(bn)s-s_%(port1)s 1 -s %(ip1)s -m mac --mac-source %(mac1)s -j RETURN -I %(bn)s-s_%(port1)s 2 -j DROP -I %(bn)s-s_%(port2)s 1 -s %(ip2)s -m mac --mac-source %(mac2)s -j RETURN
997d7b03fb7fOVS: Add mac spoofing filtering to flows
7 files changed · +93 −17
neutron/plugins/ml2/drivers/openvswitch/agent/common/constants.py+3 −0 modified@@ -50,6 +50,9 @@ # Table for ARP poison/spoofing prevention rules ARP_SPOOF_TABLE = 24 +# Table for MAC spoof filtering +MAC_SPOOF_TABLE = 25 + # Tables used for ovs firewall BASE_EGRESS_TABLE = 71 RULES_EGRESS_TABLE = 72
neutron/plugins/ml2/drivers/openvswitch/agent/openflow/native/br_int.py+36 −5 modified@@ -19,6 +19,8 @@ ** OVS agent https://wiki.openstack.org/wiki/Ovs-flow-logic """ +import netaddr + from oslo_log import log as logging from ryu.lib.packet import ether_types from ryu.lib.packet import icmpv6 @@ -174,16 +176,45 @@ def install_icmpv6_na_spoofing_protection(self, port, ip_addresses): match=match, dest_table_id=constants.ARP_SPOOF_TABLE) + def set_allowed_macs_for_port(self, port, mac_addresses=None, + allow_all=False): + if allow_all: + self.delete_flows(table_id=constants.LOCAL_SWITCHING, in_port=port) + self.delete_flows(table_id=constants.MAC_SPOOF_TABLE, in_port=port) + return + mac_addresses = mac_addresses or [] + for address in mac_addresses: + self.install_normal( + table_id=constants.MAC_SPOOF_TABLE, priority=2, + eth_src=address, in_port=port) + # normalize so we can see if macs are the same + mac_addresses = {netaddr.EUI(mac) for mac in mac_addresses} + flows = self.dump_flows(constants.MAC_SPOOF_TABLE) + for flow in flows: + matches = dict(flow.match.items()) + if matches.get('in_port') != port: + continue + if not matches.get('eth_src'): + continue + flow_mac = matches['eth_src'] + if netaddr.EUI(flow_mac) not in mac_addresses: + self.delete_flows(table_id=constants.MAC_SPOOF_TABLE, + in_port=port, eth_src=flow_mac) + self.install_goto(table_id=constants.LOCAL_SWITCHING, + priority=9, in_port=port, + dest_table_id=constants.MAC_SPOOF_TABLE) + def install_arp_spoofing_protection(self, port, ip_addresses): # allow ARP replies as long as they match addresses that actually # belong to the port. for ip in ip_addresses: masked_ip = self._cidr_to_ryu(ip) - self.install_normal(table_id=constants.ARP_SPOOF_TABLE, - priority=2, - eth_type=ether_types.ETH_TYPE_ARP, - arp_spa=masked_ip, - in_port=port) + self.install_goto(table_id=constants.ARP_SPOOF_TABLE, + priority=2, + eth_type=ether_types.ETH_TYPE_ARP, + arp_spa=masked_ip, + in_port=port, + dest_table_id=constants.MAC_SPOOF_TABLE) # Now that the rules are ready, direct ARP traffic from the port into # the anti-spoof table.
neutron/plugins/ml2/drivers/openvswitch/agent/openflow/ovs_ofctl/br_int.py+33 −3 modified@@ -18,6 +18,9 @@ * references ** OVS agent https://wiki.openstack.org/wiki/Ovs-flow-logic """ + +import netaddr + from neutron.common import constants as const from neutron.plugins.common import constants as p_const from neutron.plugins.ml2.drivers.openvswitch.agent.common import constants @@ -128,13 +131,40 @@ def install_icmpv6_na_spoofing_protection(self, port, ip_addresses): icmp_type=const.ICMPV6_TYPE_NA, in_port=port, actions=("resubmit(,%s)" % constants.ARP_SPOOF_TABLE)) + def set_allowed_macs_for_port(self, port, mac_addresses=None, + allow_all=False): + if allow_all: + self.delete_flows(table_id=constants.LOCAL_SWITCHING, in_port=port) + self.delete_flows(table_id=constants.MAC_SPOOF_TABLE, in_port=port) + return + mac_addresses = mac_addresses or [] + for address in mac_addresses: + self.install_normal( + table_id=constants.MAC_SPOOF_TABLE, priority=2, + eth_src=address, in_port=port) + # normalize so we can see if macs are the same + mac_addresses = {netaddr.EUI(mac) for mac in mac_addresses} + flows = self.dump_flows_for(table=constants.MAC_SPOOF_TABLE, + in_port=port).splitlines() + for flow in flows: + if 'dl_src' not in flow: + continue + flow_mac = flow.split('dl_src=')[1].split(' ')[0].split(',')[0] + if netaddr.EUI(flow_mac) not in mac_addresses: + self.delete_flows(table_id=constants.MAC_SPOOF_TABLE, + in_port=port, eth_src=flow_mac) + self.add_flow(table=constants.LOCAL_SWITCHING, + priority=9, in_port=port, + actions=("resubmit(,%s)" % constants.MAC_SPOOF_TABLE)) + def install_arp_spoofing_protection(self, port, ip_addresses): # allow ARPs as long as they match addresses that actually # belong to the port. for ip in ip_addresses: - self.install_normal( - table_id=constants.ARP_SPOOF_TABLE, priority=2, - proto='arp', arp_spa=ip, in_port=port) + self.add_flow( + table=constants.ARP_SPOOF_TABLE, priority=2, + proto='arp', arp_spa=ip, in_port=port, + actions=("resubmit(,%s)" % constants.MAC_SPOOF_TABLE)) # Now that the rules are ready, direct ARP traffic from the port into # the anti-spoof table.
neutron/plugins/ml2/drivers/openvswitch/agent/ovs_neutron_agent.py+3 −0 modified@@ -885,12 +885,14 @@ def setup_arp_spoofing_protection(bridge, vif, port_details): LOG.info(_LI("Skipping ARP spoofing rules for port '%s' because " "it has port security disabled"), vif.port_name) bridge.delete_arp_spoofing_protection(port=vif.ofport) + bridge.set_allowed_macs_for_port(port=vif.ofport, allow_all=True) return if port_details['device_owner'].startswith( n_const.DEVICE_OWNER_NETWORK_PREFIX): LOG.debug("Skipping ARP spoofing rules for network owned port " "'%s'.", vif.port_name) bridge.delete_arp_spoofing_protection(port=vif.ofport) + bridge.set_allowed_macs_for_port(port=vif.ofport, allow_all=True) return # clear any previous flows related to this port in our ARP table bridge.delete_arp_spoofing_allow_rules(port=vif.ofport) @@ -904,6 +906,7 @@ def setup_arp_spoofing_protection(bridge, vif, port_details): for p in port_details['allowed_address_pairs'] if p.get('mac_address')} + bridge.set_allowed_macs_for_port(vif.ofport, mac_addresses) ipv6_addresses = {ip for ip in addresses if netaddr.IPNetwork(ip).version == 6} # Allow neighbor advertisements for LLA address.
neutron/tests/functional/agent/test_ovs_flows.py+14 −1 modified@@ -184,6 +184,17 @@ def test_arp_spoof_doesnt_block_normal_traffic(self): self.dst_p.addr.add('%s/24' % self.dst_addr) net_helpers.assert_ping(self.src_namespace, self.dst_addr, count=2) + def test_mac_spoof_blocks_wrong_mac(self): + self._setup_arp_spoof_for_port(self.src_p.name, [self.src_addr]) + self._setup_arp_spoof_for_port(self.dst_p.name, [self.dst_addr]) + self.src_p.addr.add('%s/24' % self.src_addr) + self.dst_p.addr.add('%s/24' % self.dst_addr) + net_helpers.assert_ping(self.src_namespace, self.dst_addr, count=2) + # changing the allowed mac should stop the port from working + self._setup_arp_spoof_for_port(self.src_p.name, [self.src_addr], + mac='00:11:22:33:44:55') + net_helpers.assert_no_ping(self.src_namespace, self.dst_addr, count=2) + def test_arp_spoof_doesnt_block_ipv6(self): self.src_addr = '2000::1' self.dst_addr = '2000::2' @@ -282,7 +293,7 @@ def test_arp_spoof_disable_network_port(self): net_helpers.assert_ping(self.src_namespace, self.dst_addr, count=2) def _setup_arp_spoof_for_port(self, port, addrs, psec=True, - device_owner='nobody'): + device_owner='nobody', mac=None): vif = next( vif for vif in self.br.get_vif_ports() if vif.port_name == port) ip_addr = addrs.pop() @@ -291,6 +302,8 @@ def _setup_arp_spoof_for_port(self, port, addrs, psec=True, 'device_owner': device_owner, 'allowed_address_pairs': [ dict(ip_address=ip) for ip in addrs]} + if mac: + vif.vif_mac = mac ovsagt.OVSNeutronAgent.setup_arp_spoofing_protection( self.br_int, vif, details)
neutron/tests/unit/plugins/ml2/drivers/openvswitch/agent/openflow/native/test_br_int.py+2 −6 modified@@ -347,9 +347,7 @@ def test_install_arp_spoofing_protection(self): call._send_msg(ofpp.OFPFlowMod(dp, cookie=self.stamp, instructions=[ - ofpp.OFPInstructionActions(ofp.OFPIT_APPLY_ACTIONS, [ - ofpp.OFPActionOutput(ofp.OFPP_NORMAL, 0), - ]), + ofpp.OFPInstructionGotoTable(table_id=25), ], match=ofpp.OFPMatch( eth_type=self.ether_types.ETH_TYPE_ARP, @@ -361,9 +359,7 @@ def test_install_arp_spoofing_protection(self): call._send_msg(ofpp.OFPFlowMod(dp, cookie=self.stamp, instructions=[ - ofpp.OFPInstructionActions(ofp.OFPIT_APPLY_ACTIONS, [ - ofpp.OFPActionOutput(ofp.OFPP_NORMAL, 0), - ]), + ofpp.OFPInstructionGotoTable(table_id=25), ], match=ofpp.OFPMatch( eth_type=self.ether_types.ETH_TYPE_ARP,
neutron/tests/unit/plugins/ml2/drivers/openvswitch/agent/openflow/ovs_ofctl/test_br_int.py+2 −2 modified@@ -215,10 +215,10 @@ def test_install_arp_spoofing_protection(self): ip_addresses = ['192.0.2.1', '192.0.2.2/32'] self.br.install_arp_spoofing_protection(port, ip_addresses) expected = [ - call.add_flow(proto='arp', actions='normal', + call.add_flow(proto='arp', actions='resubmit(,25)', arp_spa='192.0.2.1', priority=2, table=24, in_port=8888), - call.add_flow(proto='arp', actions='normal', + call.add_flow(proto='arp', actions='resubmit(,25)', arp_spa='192.0.2.2/32', priority=2, table=24, in_port=8888), call.add_flow(priority=10, table=0, in_port=8888,
Vulnerability mechanics
Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
18- github.com/advisories/GHSA-9pp3-cvmq-9p22ghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2016-5363ghsaADVISORY
- security.openstack.org/ossa/OSSA-2016-009.htmlnvdVendor AdvisoryWEB
- www.openwall.com/lists/oss-security/2016/06/10/5nvdWEB
- www.openwall.com/lists/oss-security/2016/06/10/6nvdWEB
- access.redhat.com/errata/RHSA-2016:1473nvdWEB
- access.redhat.com/errata/RHSA-2016:1474nvdWEB
- bugs.launchpad.net/neutron/+bug/1558658nvdWEB
- github.com/openstack/neutron/commit/5853af9cba6733725d6c9ac0db644f426713f0cfghsaWEB
- github.com/openstack/neutron/commit/6a93ee8ac1a901c255e3475a24f1afc11d8bf80fghsaWEB
- github.com/openstack/neutron/commit/997d7b03fb7f5528f0a3ce70867b9dcd9321509eghsaWEB
- github.com/openstack/neutron/commit/fd5fd259a02156babdfcb12f66cde6ec9e7274aeghsaWEB
- review.openstack.orgghsaWEB
- review.openstack.orgghsaWEB
- review.openstack.orgghsaWEB
- review.openstack.orgnvd
- review.openstack.orgnvd
- review.openstack.orgnvd
News mentions
0No linked articles in our index yet.