From: Dustin Lundquist Date: Fri, 20 May 2016 19:48:16 +0000 (-0700) Subject: ovn-northd: Restrict use of unspecified source addresses X-Git-Url: http://git.cascardo.eti.br/?a=commitdiff_plain;h=9e687b239a801d822de015bfc9d09d6c8dc40bfc;p=cascardo%2Fovs.git ovn-northd: Restrict use of unspecified source addresses Restrict use of the unspecified source addresses (:: and 0.0.0.0) to traffic necessary to obtain an IP address. DHCP discovery messages for the IPv4 case, and ICMP6 types necessary for duplicate address detection for IPv6. This breaks the existing ovn -- portsecurity : 3 HVs, 1 LS, 3 lports/HV test since it tests sourcing IPv6 packets from the unspecified address with and invalid ICMPv6 type (0). Modified this test should be extended to verify ICMPv6 types for DAD are permitted, and other IPv6 traffic sourced from the unspecified address are dropped. Signed-off-by: Dustin Lundquist Signed-off-by: Ben Pfaff --- diff --git a/ovn/northd/ovn-northd.8.xml b/ovn/northd/ovn-northd.8.xml index 970c352cd..2665ed542 100644 --- a/ovn/northd/ovn-northd.8.xml +++ b/ovn/northd/ovn-northd.8.xml @@ -159,12 +159,28 @@ and valid ip4.src address(es). +
  • + Priority 90 flow to allow IPv4 DHCP discovery traffic if it has a + valid eth.src. This is necessary since DHCP discovery + messages are sent from the unspecified IPv4 address (0.0.0.0) since + the IPv4 address has not yet been assigned. +
  • +
  • Priority 90 flow to allow IPv6 traffic if it has IPv6 addresses which match the inport, valid eth.src and valid ip6.src address(es).
  • +
  • + Priority 90 flow to allow IPv6 DAD (Duplicate Address Detection) + traffic if it has a valid eth.src. This is is + necessary since DAD include requires joining an multicast group and + sending neighbor solicitations for the newly assigned address. Since + no address is yet assigned, these are sent from the unspecified + IPv6 address (::). +
  • +
  • Priority 80 flow to drop IP (both IPv4 and IPv6) traffic which match the inport and valid eth.src. diff --git a/ovn/northd/ovn-northd.c b/ovn/northd/ovn-northd.c index 44e9430e4..ad1f38138 100644 --- a/ovn/northd/ovn-northd.c +++ b/ovn/northd/ovn-northd.c @@ -1033,12 +1033,17 @@ build_port_security_ipv6_flow( ipv6_string_mapped(ip6_str, &lla); ds_put_format(match, "%s, ", ip6_str); - /* Allow ip6.src=:: and ip6.dst=ff00::/8 for ND packets */ - ds_put_cstr(match, pipeline == P_IN ? "::" : "ff00::/8"); + /* Allow ip6.dst=ff00::/8 for multicast packets */ + if (pipeline == P_OUT) { + ds_put_cstr(match, "ff00::/8, "); + } for(int i = 0; i < n_ipv6_addrs; i++) { ipv6_string_mapped(ip6_str, &ipv6_addrs[i].addr); - ds_put_format(match, ", %s", ip6_str); + ds_put_format(match, "%s, ", ip6_str); } + /* Replace ", " by "}". */ + ds_chomp(match, ' '); + ds_chomp(match, ','); ds_put_cstr(match, "}"); } @@ -1174,8 +1179,19 @@ build_port_security_ip(enum ovn_pipeline pipeline, struct ovn_port *op, if (ps.n_ipv4_addrs) { struct ds match = DS_EMPTY_INITIALIZER; if (pipeline == P_IN) { + /* Permit use of the unspecified address for DHCP discovery */ + struct ds dhcp_match = DS_EMPTY_INITIALIZER; + ds_put_format(&dhcp_match, "inport == %s" + " && eth.src == "ETH_ADDR_FMT + " && ip4.src == 0.0.0.0" + " && ip4.dst == 255.255.255.255" + " && udp.src == 68 && udp.dst == 67", op->json_key, + ETH_ADDR_ARGS(ps.ea)); + ovn_lflow_add(lflows, op->od, stage, 90, + ds_cstr(&dhcp_match), "next;"); + ds_destroy(&dhcp_match); ds_put_format(&match, "inport == %s && eth.src == "ETH_ADDR_FMT - " && ip4.src == {0.0.0.0, ", op->json_key, + " && ip4.src == {", op->json_key, ETH_ADDR_ARGS(ps.ea)); } else { ds_put_format(&match, "outport == %s && eth.dst == "ETH_ADDR_FMT @@ -1219,6 +1235,20 @@ build_port_security_ip(enum ovn_pipeline pipeline, struct ovn_port *op, if (ps.n_ipv6_addrs) { struct ds match = DS_EMPTY_INITIALIZER; + if (pipeline == P_IN) { + /* Permit use of unspecified address for duplicate address + * detection */ + struct ds dad_match = DS_EMPTY_INITIALIZER; + ds_put_format(&dad_match, "inport == %s" + " && eth.src == "ETH_ADDR_FMT + " && ip6.src == ::" + " && ip6.dst == ff02::/16" + " && icmp6.type == {131, 135, 143}", op->json_key, + ETH_ADDR_ARGS(ps.ea)); + ovn_lflow_add(lflows, op->od, stage, 90, + ds_cstr(&dad_match), "next;"); + ds_destroy(&dad_match); + } ds_put_format(&match, "%s == %s && %s == "ETH_ADDR_FMT"", port_direction, op->json_key, pipeline == P_IN ? "eth.src" : "eth.dst", diff --git a/tests/ovn.at b/tests/ovn.at index e6ac1d718..5f224838e 100644 --- a/tests/ovn.at +++ b/tests/ovn.at @@ -1789,6 +1789,21 @@ test_ipv6() { done } +# test_icmpv6 INPORT SRC_MAC DST_MAC SRC_IP DST_IP ICMP_TYPE OUTPORT... +# This function is similar to test_ipv6() except it specifies the ICMPv6 type +# of the test packet +test_icmpv6() { + local inport=$1 src_mac=$2 dst_mac=$3 src_ip=$4 dst_ip=$5 icmp_type=$6 + local packet=${dst_mac}${src_mac}86dd6000000000083aff${src_ip}${dst_ip}${icmp_type}00000000000000 + shift; shift; shift; shift; shift; shift + hv=`vif_to_hv $inport` + as $hv ovs-appctl netdev-dummy/receive vif$inport $packet + #as $hv ovs-appctl ofproto/trace br-int in_port=$inport $packet + for outport; do + echo $packet | trim_zeros >> $outport.expected + done +} + ip_to_hex() { printf "%02x%02x%02x%02x" "$@" } @@ -1926,8 +1941,15 @@ for i in 1 2 3; do sip=fe80000000000000ea2aeafffe2800${i}3 test_ipv6 ${i}3 f00000000${i}${i}3 f00000000021 $sip $tip 21 + # Test ICMPv6 MLD reports (v1 and v2) and NS for DAD sip=00000000000000000000000000000000 - test_ipv6 ${i}3 f00000000${i}${i}3 f00000000021 $sip $tip 21 + test_icmpv6 ${i}3 f00000000${i}${i}3 f00000000021 $sip ff020000000000000000000000160000 83 21 + test_icmpv6 ${i}3 f00000000${i}${i}3 f00000000021 $sip ff020000000000000000000000160000 8f 21 + test_icmpv6 ${i}3 f00000000${i}${i}3 f00000000021 $sip ff0200000000000000ea2aeafffe2800 87 21 + # Traffic to non-multicast traffic should be dropped + test_icmpv6 ${i}3 f00000000${i}${i}3 f00000000021 $sip $tip 83 + # Traffic of other ICMPv6 types should be dropped + test_icmpv6 ${i}3 f00000000${i}${i}3 f00000000021 $sip ff020000000000000000000000160000 80 # should be dropped sip=ae80000000000000ea2aeafffe2800aa