VYPR
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.

PackageAffected versionsPatched versions
neutronPyPI
< 7.1.07.1.0
neutronPyPI
>= 8.0.0, < 8.1.08.1.0

Affected products

7
  • OpenStack/Neutron7 versions
    cpe: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

4
fd5fd259a021

Iptables firewall prevent IP spoofed DHCP requests

https://github.com/openstack/neutronDustin LundquistMar 31, 2016via ghsa
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
    
5853af9cba67

Iptables firewall prevent IP spoofed DHCP requests

https://github.com/openstack/neutronDustin LundquistMar 31, 2016via ghsa
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
    
6a93ee8ac1a9

Iptables firewall prevent IP spoofed DHCP requests

https://github.com/openstack/neutronDustin LundquistMar 31, 2016via ghsa
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
    
997d7b03fb7f

OVS: Add mac spoofing filtering to flows

https://github.com/openstack/neutronKevin BentonMar 25, 2016via ghsa
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

News mentions

0

No linked articles in our index yet.