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

This commit is contained in:
Jenkins 2016-05-14 02:33:24 +00:00 committed by Gerrit Code Review
commit b1c83a928a
3 changed files with 96 additions and 42 deletions

View File

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

View File

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

View File

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