Merge "IPtables firewall prevent ICMPv6 spoofing" into stable/mitaka

This commit is contained in:
Jenkins 2016-05-14 02:35:36 +00:00 committed by Gerrit Code Review
commit 84d28d73a3
4 changed files with 117 additions and 42 deletions

View File

@ -40,6 +40,7 @@ SPOOF_FILTER = 'spoof-filter'
CHAIN_NAME_PREFIX = {firewall.INGRESS_DIRECTION: 'i',
firewall.EGRESS_DIRECTION: 'o',
SPOOF_FILTER: 's'}
ICMPV6_ALLOWED_UNSPEC_ADDR_TYPES = [131, 135, 143]
IPSET_DIRECTION = {firewall.INGRESS_DIRECTION: 'src',
firewall.EGRESS_DIRECTION: 'dst'}
# length of all device prefixes (e.g. qvo, tap, qvb)
@ -379,21 +380,25 @@ class IptablesFirewallDriver(firewall.FirewallDriver):
mac_ipv4_pairs.append((mac, ip_address))
else:
mac_ipv6_pairs.append((mac, ip_address))
lla = str(ipv6_utils.get_ipv6_addr_by_EUI64(
constants.IPV6_LLA_PREFIX, mac))
mac_ipv6_pairs.append((mac, lla))
def _spoofing_rule(self, port, ipv4_rules, ipv6_rules):
# Fixed rules for traffic sourced from unspecified addresses: 0.0.0.0
# and ::
# 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 '
'-j DROP' % constants.ICMPV6_TYPE_RA,
comment=ic.IPV6_RA_DROP)]
ipv6_rules += [comment_rule('-p ipv6-icmp -j RETURN',
comment=ic.IPV6_ICMP_ALLOW)]
ipv6_rules += [comment_rule('-p udp -m udp --sport 546 '
'-m udp --dport 547 '
'-j RETURN', comment=ic.DHCP_CLIENT)]
# Allow neighbor solicitation and multicast listener discovery
# from the unspecified address for duplicate address detection
for icmp6_type in ICMPV6_ALLOWED_UNSPEC_ADDR_TYPES:
ipv6_rules += [comment_rule('-s ::/128 -d ff02::/16 '
'-p ipv6-icmp -m icmp6 '
'--icmpv6-type %s -j RETURN' %
icmp6_type,
comment=ic.IPV6_ICMP_ALLOW)]
mac_ipv4_pairs = []
mac_ipv6_pairs = []
@ -415,9 +420,19 @@ class IptablesFirewallDriver(firewall.FirewallDriver):
mac_ipv4_pairs, ipv4_rules)
self._setup_spoof_filter_chain(port, self.iptables.ipv6['filter'],
mac_ipv6_pairs, ipv6_rules)
# Fixed rules for traffic after source address is verified
# Allow dhcp client renewal and rebinding
ipv4_rules += [comment_rule('-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 '
'-j DROP' % constants.ICMPV6_TYPE_RA,
comment=ic.IPV6_RA_DROP)]
ipv6_rules += [comment_rule('-p ipv6-icmp -j RETURN',
comment=ic.IPV6_ICMP_ALLOW)]
ipv6_rules += [comment_rule('-p udp -m udp --sport 546 '
'-m udp --dport 547 '
'-j RETURN', comment=ic.DHCP_CLIENT)]
def _drop_dhcp_rule(self, ipv4_rules, ipv6_rules):
#Note(nati) Drop dhcp packet from VM

View File

@ -660,3 +660,23 @@ class FirewallTestCaseIPv6(BaseFirewallTestCase):
direction=self.tester.EGRESS)
self.tester.assert_no_connection(protocol=self.tester.ICMP,
direction=self.tester.EGRESS)
@skip_if_firewall('openvswitch')
def test_ip_spoofing(self):
sg_rules = [{'ethertype': constants.IPv6,
'direction': firewall.INGRESS_DIRECTION,
'protocol': constants.PROTO_NAME_ICMP}]
self._apply_security_group_rules(self.FAKE_SECURITY_GROUP_ID, sg_rules)
not_allowed_ip = "%s/64" % (
netaddr.IPAddress(self.tester.vm_ip_address) + 1)
self.tester.assert_connection(protocol=self.tester.ICMP,
direction=self.tester.INGRESS)
self.tester.vm_ip_cidr = not_allowed_ip
self.tester.assert_no_connection(protocol=self.tester.ICMP,
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=546, dst_port=547,
direction=self.tester.EGRESS)

View File

@ -952,17 +952,22 @@ class IptablesFirewallTestCase(BaseIptablesFirewallTestCase):
if ethertype == 'IPv6':
filter_inst = self.v6filter_inst
dhcp_rule = [mock.call.add_rule('ofake_dev', '-p ipv6-icmp '
'-m icmp6 '
'--icmpv6-type %s -j DROP'
% constants.ICMPV6_TYPE_RA,
dhcp_rule = [mock.call.add_rule('ofake_dev',
'-s ::/128 -d ff02::/16 '
'-p ipv6-icmp -m icmp6 '
'--icmpv6-type 131 -j RETURN',
comment=None),
mock.call.add_rule('ofake_dev',
'-p ipv6-icmp -j RETURN',
'-s ::/128 -d ff02::/16 '
'-p ipv6-icmp -m icmp6 '
'--icmpv6-type %s -j RETURN' %
constants.ICMPV6_TYPE_NC,
comment=None),
mock.call.add_rule('ofake_dev', '-p udp -m udp '
'--sport 546 -m udp --dport 547 '
'-j RETURN', comment=None)]
mock.call.add_rule('ofake_dev',
'-s ::/128 -d ff02::/16 '
'-p ipv6-icmp -m icmp6 '
'--icmpv6-type 143 -j RETURN',
comment=None)]
sg = [rule]
port['security_group_rules'] = sg
self.firewall.prepare_port_filter(port)
@ -1025,10 +1030,15 @@ class IptablesFirewallTestCase(BaseIptablesFirewallTestCase):
'sfake_dev',
'-s %s -m mac --mac-source FF:FF:FF:FF:FF:FF -j RETURN'
% prefix,
comment=ic.PAIR_ALLOW),
mock.call.add_rule(
'sfake_dev', '-j DROP',
comment=ic.PAIR_DROP)]
comment=ic.PAIR_ALLOW)]
if ethertype == 'IPv6':
calls.append(mock.call.add_rule('sfake_dev',
'-s fe80::fdff:ffff:feff:ffff/128 -m mac '
'--mac-source FF:FF:FF:FF:FF:FF -j RETURN',
comment=ic.PAIR_ALLOW))
calls.append(mock.call.add_rule('sfake_dev', '-j DROP',
comment=ic.PAIR_DROP))
calls += dhcp_rule
calls.append(mock.call.add_rule('ofake_dev', '-j $sfake_dev',
comment=None))
@ -1042,6 +1052,17 @@ class IptablesFirewallTestCase(BaseIptablesFirewallTestCase):
'-p udp -m udp --sport 67 -m udp --dport 68 -j DROP',
comment=None))
if ethertype == 'IPv6':
calls.append(mock.call.add_rule('ofake_dev',
'-p ipv6-icmp -m icmp6 '
'--icmpv6-type %s -j DROP' %
constants.ICMPV6_TYPE_RA,
comment=None))
calls.append(mock.call.add_rule('ofake_dev',
'-p ipv6-icmp -j RETURN',
comment=None))
calls.append(mock.call.add_rule('ofake_dev', '-p udp -m udp '
'--sport 546 -m udp --dport 547 '
'-j RETURN', comment=None))
calls.append(mock.call.add_rule(
'ofake_dev',
'-p udp -m udp --sport 547 -m udp --dport 546 -j DROP',
@ -1862,6 +1883,7 @@ class IptablesFirewallEnhancedIpsetTestCase(BaseIptablesFirewallTestCase):
fake_ipv4_pair.append((mac_unix, ipv4))
fake_ipv6_pair = []
fake_ipv6_pair.append((mac_unix, ipv6))
fake_ipv6_pair.append((mac_unix, 'fe80::fdff:ffff:fe0f:ffff'))
mac_ipv4_pairs = []
mac_ipv6_pairs = []

View File

@ -2536,13 +2536,19 @@ IPTABLES_FILTER_V6_1 = """# Generated by iptables_manager
-I %(bn)s-i_port1 6 -m state --state RELATED,ESTABLISHED -j RETURN
-I %(bn)s-i_port1 7 -m state --state INVALID -j DROP
-I %(bn)s-i_port1 8 -j %(bn)s-sg-fallback
-I %(bn)s-o_port1 1 -p ipv6-icmp -m icmp6 --icmpv6-type 134 -j DROP
-I %(bn)s-o_port1 2 -p ipv6-icmp -j RETURN
-I %(bn)s-o_port1 3 -p udp -m udp --sport 546 -m udp --dport 547 -j RETURN
-I %(bn)s-o_port1 4 -p udp -m udp --sport 547 -m udp --dport 546 -j DROP
-I %(bn)s-o_port1 5 -m state --state RELATED,ESTABLISHED -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 1 -s ::/128 -d ff02::/16 -p ipv6-icmp -m icmp6 \
--icmpv6-type 131 -j RETURN
-I %(bn)s-o_port1 2 -s ::/128 -d ff02::/16 -p ipv6-icmp -m icmp6 \
--icmpv6-type 135 -j RETURN
-I %(bn)s-o_port1 3 -s ::/128 -d ff02::/16 -p ipv6-icmp -m icmp6 \
--icmpv6-type 143 -j RETURN
-I %(bn)s-o_port1 4 -p ipv6-icmp -m icmp6 --icmpv6-type 134 -j DROP
-I %(bn)s-o_port1 5 -p ipv6-icmp -j RETURN
-I %(bn)s-o_port1 6 -p udp -m udp --sport 546 -m udp --dport 547 -j RETURN
-I %(bn)s-o_port1 7 -p udp -m udp --sport 547 -m udp --dport 546 -j DROP
-I %(bn)s-o_port1 8 -m state --state RELATED,ESTABLISHED -j RETURN
-I %(bn)s-o_port1 9 -m state --state INVALID -j DROP
-I %(bn)s-o_port1 10 -j %(bn)s-sg-fallback
-I %(bn)s-sg-chain 1 %(physdev_mod)s --physdev-INGRESS tap_port1 \
%(physdev_is_bridged)s -j %(bn)s-i_port1
-I %(bn)s-sg-chain 2 %(physdev_mod)s --physdev-EGRESS tap_port1 \
@ -2608,20 +2614,32 @@ IPTABLES_FILTER_V6_2 = """# Generated by iptables_manager
-I %(bn)s-i_%(port2)s 6 -m state --state RELATED,ESTABLISHED -j RETURN
-I %(bn)s-i_%(port2)s 7 -m state --state INVALID -j DROP
-I %(bn)s-i_%(port2)s 8 -j %(bn)s-sg-fallback
-I %(bn)s-o_%(port1)s 1 -p ipv6-icmp -m icmp6 --icmpv6-type 134 -j DROP
-I %(bn)s-o_%(port1)s 2 -p ipv6-icmp -j RETURN
-I %(bn)s-o_%(port1)s 3 -p udp -m udp --sport 546 -m udp --dport 547 -j RETURN
-I %(bn)s-o_%(port1)s 4 -p udp -m udp --sport 547 -m udp --dport 546 -j DROP
-I %(bn)s-o_%(port1)s 5 -m state --state RELATED,ESTABLISHED -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 ipv6-icmp -m icmp6 --icmpv6-type 134 -j DROP
-I %(bn)s-o_%(port2)s 2 -p ipv6-icmp -j RETURN
-I %(bn)s-o_%(port2)s 3 -p udp -m udp --sport 546 -m udp --dport 547 -j RETURN
-I %(bn)s-o_%(port2)s 4 -p udp -m udp --sport 547 -m udp --dport 546 -j DROP
-I %(bn)s-o_%(port2)s 5 -m state --state RELATED,ESTABLISHED -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_%(port1)s 1 -s ::/128 -d ff02::/16 -p ipv6-icmp -m icmp6 \
--icmpv6-type 131 -j RETURN
-I %(bn)s-o_%(port1)s 2 -s ::/128 -d ff02::/16 -p ipv6-icmp -m icmp6 \
--icmpv6-type 135 -j RETURN
-I %(bn)s-o_%(port1)s 3 -s ::/128 -d ff02::/16 -p ipv6-icmp -m icmp6 \
--icmpv6-type 143 -j RETURN
-I %(bn)s-o_%(port1)s 4 -p ipv6-icmp -m icmp6 --icmpv6-type 134 -j DROP
-I %(bn)s-o_%(port1)s 5 -p ipv6-icmp -j RETURN
-I %(bn)s-o_%(port1)s 6 -p udp -m udp --sport 546 -m udp --dport 547 -j RETURN
-I %(bn)s-o_%(port1)s 7 -p udp -m udp --sport 547 -m udp --dport 546 -j DROP
-I %(bn)s-o_%(port1)s 8 -m state --state RELATED,ESTABLISHED -j RETURN
-I %(bn)s-o_%(port1)s 9 -m state --state INVALID -j DROP
-I %(bn)s-o_%(port1)s 10 -j %(bn)s-sg-fallback
-I %(bn)s-o_%(port2)s 1 -s ::/128 -d ff02::/16 -p ipv6-icmp -m icmp6 \
--icmpv6-type 131 -j RETURN
-I %(bn)s-o_%(port2)s 2 -s ::/128 -d ff02::/16 -p ipv6-icmp -m icmp6 \
--icmpv6-type 135 -j RETURN
-I %(bn)s-o_%(port2)s 3 -s ::/128 -d ff02::/16 -p ipv6-icmp -m icmp6 \
--icmpv6-type 143 -j RETURN
-I %(bn)s-o_%(port2)s 4 -p ipv6-icmp -m icmp6 --icmpv6-type 134 -j DROP
-I %(bn)s-o_%(port2)s 5 -p ipv6-icmp -j RETURN
-I %(bn)s-o_%(port2)s 6 -p udp -m udp --sport 546 -m udp --dport 547 -j RETURN
-I %(bn)s-o_%(port2)s 7 -p udp -m udp --sport 547 -m udp --dport 546 -j DROP
-I %(bn)s-o_%(port2)s 8 -m state --state RELATED,ESTABLISHED -j RETURN
-I %(bn)s-o_%(port2)s 9 -m state --state INVALID -j DROP
-I %(bn)s-o_%(port2)s 10 -j %(bn)s-sg-fallback
-I %(bn)s-sg-chain 1 %(physdev_mod)s --physdev-INGRESS tap_%(port1)s \
%(physdev_is_bridged)s -j %(bn)s-i_%(port1)s
-I %(bn)s-sg-chain 2 %(physdev_mod)s --physdev-EGRESS tap_%(port1)s \