Merge "[ovs fw] Restrict IPv6 NA and DHCP(v6) IP and MAC source addresses" into stable/rocky
This commit is contained in:
commit
99f0a11163
|
@ -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.
|
# List of ICMPv6 types that should be permitted (egress) by default.
|
||||||
ICMPV6_ALLOWED_EGRESS_TYPES = (n_const.ICMPV6_TYPE_MLD_QUERY,
|
ICMPV6_ALLOWED_EGRESS_TYPES = (n_const.ICMPV6_TYPE_MLD_QUERY,
|
||||||
n_const.ICMPV6_TYPE_RS,
|
n_const.ICMPV6_TYPE_RS,
|
||||||
n_const.ICMPV6_TYPE_NS,
|
n_const.ICMPV6_TYPE_NS)
|
||||||
n_const.ICMPV6_TYPE_NA)
|
|
||||||
|
# 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):
|
def port_sec_enabled(port):
|
||||||
|
|
|
@ -892,8 +892,7 @@ class OVSFirewallDriver(firewall.FirewallDriver):
|
||||||
self._initialize_ingress(port)
|
self._initialize_ingress(port)
|
||||||
|
|
||||||
def _initialize_egress_ipv6_icmp(self, port, allowed_pairs):
|
def _initialize_egress_ipv6_icmp(self, port, allowed_pairs):
|
||||||
# NOTE(slaweq): should we include also fe80::/64 (link-local) subnet
|
allowed_pairs = allowed_pairs.union({(port.mac, port.lla_address)})
|
||||||
# in the allowed pairs here?
|
|
||||||
for mac_addr, ip_addr in allowed_pairs:
|
for mac_addr, ip_addr in allowed_pairs:
|
||||||
for icmp_type in firewall.ICMPV6_ALLOWED_EGRESS_TYPES:
|
for icmp_type in firewall.ICMPV6_ALLOWED_EGRESS_TYPES:
|
||||||
self._add_flow(
|
self._add_flow(
|
||||||
|
@ -909,6 +908,19 @@ class OVSFirewallDriver(firewall.FirewallDriver):
|
||||||
actions='resubmit(,%d)' % (
|
actions='resubmit(,%d)' % (
|
||||||
ovs_consts.ACCEPTED_EGRESS_TRAFFIC_NORMAL_TABLE)
|
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=constants.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):
|
def _initialize_egress_no_port_security(self, port_id, ovs_ports=None):
|
||||||
try:
|
try:
|
||||||
|
@ -983,9 +995,9 @@ class OVSFirewallDriver(firewall.FirewallDriver):
|
||||||
"""Identify egress traffic and send it to egress base"""
|
"""Identify egress traffic and send it to egress base"""
|
||||||
|
|
||||||
# Apply mac/ip pairs for IPv4
|
# 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})
|
{(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(
|
self._add_flow(
|
||||||
table=ovs_consts.BASE_EGRESS_TABLE,
|
table=ovs_consts.BASE_EGRESS_TABLE,
|
||||||
priority=95,
|
priority=95,
|
||||||
|
@ -1011,10 +1023,10 @@ class OVSFirewallDriver(firewall.FirewallDriver):
|
||||||
)
|
)
|
||||||
|
|
||||||
# Apply mac/ip pairs for IPv6
|
# 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})
|
{(port.mac, ip_addr) for ip_addr in port.ipv6_addresses})
|
||||||
self._initialize_egress_ipv6_icmp(port, allowed_pairs)
|
self._initialize_egress_ipv6_icmp(port, allowed_mac_ipv6_pairs)
|
||||||
for mac_addr, ip_addr in allowed_pairs:
|
for mac_addr, ip_addr in allowed_mac_ipv6_pairs:
|
||||||
self._add_flow(
|
self._add_flow(
|
||||||
table=ovs_consts.BASE_EGRESS_TABLE,
|
table=ovs_consts.BASE_EGRESS_TABLE,
|
||||||
priority=65,
|
priority=65,
|
||||||
|
@ -1029,21 +1041,31 @@ class OVSFirewallDriver(firewall.FirewallDriver):
|
||||||
)
|
)
|
||||||
|
|
||||||
# DHCP discovery
|
# DHCP discovery
|
||||||
for dl_type, src_port, dst_port in (
|
additional_ipv4_filters = [
|
||||||
(constants.ETHERTYPE_IP, 68, 67),
|
{"dl_src": mac, "nw_src": ip}
|
||||||
(constants.ETHERTYPE_IPV6, 546, 547)):
|
for mac, ip in allowed_mac_ipv4_pairs]
|
||||||
self._add_flow(
|
additional_ipv4_filters.append(
|
||||||
table=ovs_consts.BASE_EGRESS_TABLE,
|
{"dl_src": port.mac, "nw_src": "0.0.0.0"})
|
||||||
priority=80,
|
additional_ipv6_filters = [
|
||||||
reg_port=port.ofport,
|
{"dl_src": mac, "ipv6_src": ip}
|
||||||
in_port=port.ofport,
|
for mac, ip in allowed_mac_ipv6_pairs]
|
||||||
dl_type=dl_type,
|
for dl_type, src_port, dst_port, filters_list in (
|
||||||
nw_proto=lib_const.PROTO_NUM_UDP,
|
(constants.ETHERTYPE_IP, 68, 67, additional_ipv4_filters),
|
||||||
tp_src=src_port,
|
(constants.ETHERTYPE_IPV6, 546, 547, additional_ipv6_filters)):
|
||||||
tp_dst=dst_port,
|
for additional_filters in filters_list:
|
||||||
actions='resubmit(,{:d})'.format(
|
self._add_flow(
|
||||||
ovs_consts.ACCEPT_OR_INGRESS_TABLE)
|
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_filters
|
||||||
|
)
|
||||||
# Ban dhcp service running on an instance
|
# Ban dhcp service running on an instance
|
||||||
for dl_type, src_port, dst_port in (
|
for dl_type, src_port, dst_port in (
|
||||||
(constants.ETHERTYPE_IP, 67, 68),
|
(constants.ETHERTYPE_IP, 67, 68),
|
||||||
|
|
|
@ -994,6 +994,19 @@ class TestOVSFirewallDriver(base.BaseTestCase):
|
||||||
ipv6_src='2003::1',
|
ipv6_src='2003::1',
|
||||||
actions='resubmit(,%d)' % (
|
actions='resubmit(,%d)' % (
|
||||||
ovs_consts.ACCEPTED_EGRESS_TRAFFIC_NORMAL_TABLE)))
|
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)
|
self.mock_bridge.br.add_flow.assert_has_calls(expected_calls)
|
||||||
|
|
||||||
def test_process_trusted_ports_caches_port_id(self):
|
def test_process_trusted_ports_caches_port_id(self):
|
||||||
|
|
Loading…
Reference in New Issue