Merge "[ovs fw] Restrict IPv6 NA and DHCP(v6) IP and MAC source addresses" into stable/ussuri
This commit is contained in:
commit
b76800474d
|
@ -36,8 +36,11 @@ ICMPV6_ALLOWED_INGRESS_TYPES = (n_const.ICMPV6_TYPE_MLD_QUERY,
|
|||
# List of ICMPv6 types that should be permitted (egress) by default.
|
||||
ICMPV6_ALLOWED_EGRESS_TYPES = (n_const.ICMPV6_TYPE_MLD_QUERY,
|
||||
n_const.ICMPV6_TYPE_RS,
|
||||
n_const.ICMPV6_TYPE_NS,
|
||||
n_const.ICMPV6_TYPE_NA)
|
||||
n_const.ICMPV6_TYPE_NS)
|
||||
|
||||
# List of ICMPv6 types that should be permitted depending on payload content
|
||||
# to avoid spoofing (egress) by default.
|
||||
ICMPV6_RESTRICTED_EGRESS_TYPES = (n_const.ICMPV6_TYPE_NA, )
|
||||
|
||||
|
||||
def port_sec_enabled(port):
|
||||
|
|
|
@ -909,8 +909,7 @@ class OVSFirewallDriver(firewall.FirewallDriver):
|
|||
self._initialize_ingress(port)
|
||||
|
||||
def _initialize_egress_ipv6_icmp(self, port, allowed_pairs):
|
||||
# NOTE(slaweq): should we include also fe80::/64 (link-local) subnet
|
||||
# in the allowed pairs here?
|
||||
allowed_pairs = allowed_pairs.union({(port.mac, port.lla_address)})
|
||||
for mac_addr, ip_addr in allowed_pairs:
|
||||
for icmp_type in firewall.ICMPV6_ALLOWED_EGRESS_TYPES:
|
||||
self._add_flow(
|
||||
|
@ -926,6 +925,19 @@ class OVSFirewallDriver(firewall.FirewallDriver):
|
|||
actions='resubmit(,%d)' % (
|
||||
ovs_consts.ACCEPTED_EGRESS_TRAFFIC_NORMAL_TABLE)
|
||||
)
|
||||
for icmp_type in firewall.ICMPV6_RESTRICTED_EGRESS_TYPES:
|
||||
self._add_flow(
|
||||
table=ovs_consts.BASE_EGRESS_TABLE,
|
||||
priority=95,
|
||||
in_port=port.ofport,
|
||||
reg_port=port.ofport,
|
||||
dl_type=lib_const.ETHERTYPE_IPV6,
|
||||
nw_proto=lib_const.PROTO_NUM_IPV6_ICMP,
|
||||
icmp_type=icmp_type,
|
||||
nd_target=ip_addr,
|
||||
actions='resubmit(,%d)' % (
|
||||
ovs_consts.ACCEPTED_EGRESS_TRAFFIC_NORMAL_TABLE)
|
||||
)
|
||||
|
||||
def _initialize_egress_no_port_security(self, port_id, ovs_ports=None):
|
||||
try:
|
||||
|
@ -1000,9 +1012,9 @@ class OVSFirewallDriver(firewall.FirewallDriver):
|
|||
"""Identify egress traffic and send it to egress base"""
|
||||
|
||||
# Apply mac/ip pairs for IPv4
|
||||
allowed_pairs = port.allowed_pairs_v4.union(
|
||||
allowed_mac_ipv4_pairs = port.allowed_pairs_v4.union(
|
||||
{(port.mac, ip_addr) for ip_addr in port.ipv4_addresses})
|
||||
for mac_addr, ip_addr in allowed_pairs:
|
||||
for mac_addr, ip_addr in allowed_mac_ipv4_pairs:
|
||||
self._add_flow(
|
||||
table=ovs_consts.BASE_EGRESS_TABLE,
|
||||
priority=95,
|
||||
|
@ -1028,10 +1040,10 @@ class OVSFirewallDriver(firewall.FirewallDriver):
|
|||
)
|
||||
|
||||
# Apply mac/ip pairs for IPv6
|
||||
allowed_pairs = port.allowed_pairs_v6.union(
|
||||
allowed_mac_ipv6_pairs = port.allowed_pairs_v6.union(
|
||||
{(port.mac, ip_addr) for ip_addr in port.ipv6_addresses})
|
||||
self._initialize_egress_ipv6_icmp(port, allowed_pairs)
|
||||
for mac_addr, ip_addr in allowed_pairs:
|
||||
self._initialize_egress_ipv6_icmp(port, allowed_mac_ipv6_pairs)
|
||||
for mac_addr, ip_addr in allowed_mac_ipv6_pairs:
|
||||
self._add_flow(
|
||||
table=ovs_consts.BASE_EGRESS_TABLE,
|
||||
priority=65,
|
||||
|
@ -1046,21 +1058,30 @@ class OVSFirewallDriver(firewall.FirewallDriver):
|
|||
)
|
||||
|
||||
# DHCP discovery
|
||||
for dl_type, src_port, dst_port in (
|
||||
(lib_const.ETHERTYPE_IP, 68, 67),
|
||||
(lib_const.ETHERTYPE_IPV6, 546, 547)):
|
||||
self._add_flow(
|
||||
table=ovs_consts.BASE_EGRESS_TABLE,
|
||||
priority=80,
|
||||
reg_port=port.ofport,
|
||||
in_port=port.ofport,
|
||||
dl_type=dl_type,
|
||||
nw_proto=lib_const.PROTO_NUM_UDP,
|
||||
tp_src=src_port,
|
||||
tp_dst=dst_port,
|
||||
actions='resubmit(,{:d})'.format(
|
||||
ovs_consts.ACCEPT_OR_INGRESS_TABLE)
|
||||
)
|
||||
additional_ipv4_filters = [
|
||||
{"dl_src": mac, "nw_src": ip}
|
||||
for mac, ip in (*allowed_mac_ipv4_pairs,
|
||||
(port.mac, '0.0.0.0'),)]
|
||||
additional_ipv6_filters = [
|
||||
{"dl_src": mac, "ipv6_src": ip}
|
||||
for mac, ip in allowed_mac_ipv6_pairs]
|
||||
for dl_type, src_port, dst_port, filters_list in (
|
||||
(lib_const.ETHERTYPE_IP, 68, 67, additional_ipv4_filters),
|
||||
(lib_const.ETHERTYPE_IPV6, 546, 547, additional_ipv6_filters)):
|
||||
for additional_filters in filters_list:
|
||||
self._add_flow(
|
||||
table=ovs_consts.BASE_EGRESS_TABLE,
|
||||
priority=80,
|
||||
reg_port=port.ofport,
|
||||
in_port=port.ofport,
|
||||
dl_type=dl_type,
|
||||
**additional_filters,
|
||||
nw_proto=lib_const.PROTO_NUM_UDP,
|
||||
tp_src=src_port,
|
||||
tp_dst=dst_port,
|
||||
actions='resubmit(,{:d})'.format(
|
||||
ovs_consts.ACCEPT_OR_INGRESS_TABLE)
|
||||
)
|
||||
# Ban dhcp service running on an instance
|
||||
for dl_type, src_port, dst_port in (
|
||||
(lib_const.ETHERTYPE_IP, 67, 68),
|
||||
|
|
|
@ -1030,6 +1030,19 @@ class TestOVSFirewallDriver(base.BaseTestCase):
|
|||
ipv6_src='2003::1',
|
||||
actions='resubmit(,%d)' % (
|
||||
ovs_consts.ACCEPTED_EGRESS_TRAFFIC_NORMAL_TABLE)))
|
||||
for icmp_type in agent_firewall.ICMPV6_RESTRICTED_EGRESS_TYPES:
|
||||
expected_calls.append(
|
||||
mock.call(
|
||||
table=ovs_consts.BASE_EGRESS_TABLE,
|
||||
priority=95,
|
||||
in_port=TESTING_VLAN_TAG,
|
||||
reg5=TESTING_VLAN_TAG,
|
||||
dl_type='0x86dd',
|
||||
nw_proto=constants.PROTO_NUM_IPV6_ICMP,
|
||||
icmp_type=icmp_type,
|
||||
nd_target='2003::1',
|
||||
actions='resubmit(,%d)' % (
|
||||
ovs_consts.ACCEPTED_EGRESS_TRAFFIC_NORMAL_TABLE)))
|
||||
self.mock_bridge.br.add_flow.assert_has_calls(expected_calls)
|
||||
|
||||
def test_process_trusted_ports_caches_port_id(self):
|
||||
|
|
Loading…
Reference in New Issue