RFC 9244

Distributed Denial-of-Service Open Threat Signaling (DOTS) Telemetry

πŸ“… published June 2022, from ietf

RFC 9244: Distributed Denial-of-Service Open Threat Signaling (DOTS) Telemetry πŸ¦‹

Okay bestie, here's the paperwork vibe first ✨

  • Stream: Internet Engineering Task Force (IETF) 🌸
  • RFC number: 9244
  • Authors: M. Boucadair (Ed.) from Orange, T. Reddy.K (Ed.) from Akamai, E. Doron from Radware Ltd., M. Chen from CMCC, and J. Shallow (no affiliation listed) πŸ’œ
  • Category: Standards Track, so this is an official Internet standard, not just a suggestion πŸ‘‘
  • Date: June 2022
  • ISSN: 2070-1721
  • Obsoletes/Updates: the title block doesn't list any documents this one obsoletes or updates 🧚

Abstract ✨

Okay so this doc wants to level up the DOTS signal channel protocol with a bunch of telemetry attributes, so DDoS attack mitigation can be optimal πŸ”₯. It covers three things. First, the normal traffic baseline and attack traffic telemetry a DOTS client can send to its DOTS server inside a mitigation request. Second, the mitigation status telemetry a DOTS server can send back to a DOTS client. Third, the mitigation efficacy telemetry a DOTS client can send to a DOTS server. These attributes help the mitigator pick the right DDoS mitigation techniques and actually do the job well πŸ’….

It also specifies two YANG modules: one for representing DOTS telemetry message types, and one for sharing the attack mapping details over the DOTS data channel 🌈.

Status of This Memo

This is an Internet Standards Track document. πŸŽ€

It's a product of the Internet Engineering Task Force (IETF), so it represents the consensus of the IETF community. It went through public review and got approved for publication by the Internet Engineering Steering Group (IESG). If you want more info about Internet Standards, check out Section 2 of RFC 7841 🧚.

Info about the current status of this document, any errata, and how to give feedback is at https://www.rfc-editor.org/info/rfc9244 ✨.

Copyright (c) 2022 IETF Trust and the persons identified as the document authors. All rights reserved. πŸ’–

This document is subject to BCP 78 and the IETF Trust's Legal Provisions Relating to IETF Documents (https://trustee.ietf.org/license-info) as they were in effect on the date of publication. Please read these carefully, because they spell out your rights and restrictions for this document 🫢. Code Components pulled from this document must include Revised BSD License text as described in Section 4.e of the Trust Legal Provisions, and they come without warranty, as described in the Revised BSD License πŸ”₯.

Table of Contents 🌸

1.  Introduction
2.  Terminology
3.  DOTS Telemetry: Overview and Purpose
  3.1.  Need for More Visibility
  3.2.  Enhanced Detection
  3.3.  Efficient Mitigation
4.  Design Overview
  4.1.  Overview of Telemetry Operations
  4.2.  Block-Wise Transfers
  4.3.  DOTS Multihoming Considerations
  4.4.  YANG Considerations
5.  Generic Considerations
  5.1.  DOTS Client Identification
  5.2.  DOTS Gateways
  5.3.  Uri-Path Parameters and Empty Values
  5.4.  Controlling Configuration Data
  5.5.  Message Validation
  5.6.  A Note about Examples
6.  Telemetry Operation Paths
7.  DOTS Telemetry Setup Configuration
  7.1.  Telemetry Configuration
    7.1.1.  Retrieving the Current DOTS Telemetry Configuration
    7.1.2.  Conveying the DOTS Telemetry Configuration
    7.1.3.  Retrieving the Installed DOTS Telemetry Configuration
    7.1.4.  Deleting the DOTS Telemetry Configuration
  7.2.  Total Pipe Capacity
    7.2.1.  Conveying DOTS Client Domain Pipe Capacity
    7.2.2.  Retrieving Installed DOTS Client Domain Pipe Capacity
    7.2.3.  Deleting Installed DOTS Client Domain Pipe Capacity
  7.3.  Telemetry Baseline
    7.3.1.  Conveying DOTS Client Domain Baseline Information
    7.3.2.  Retrieving Installed Normal Traffic Baseline
            Information
    7.3.3.  Deleting Installed Normal Traffic Baseline Information
  7.4.  Resetting the Installed Telemetry Setup
  7.5.  Conflict with Other DOTS Clients of the Same Domain
8.  DOTS Pre-or-Ongoing-Mitigation Telemetry
  8.1.  Pre-or-Ongoing-Mitigation DOTS Telemetry Attributes
    8.1.1.  Target
    8.1.2.  Total Traffic
    8.1.3.  Total Attack Traffic
    8.1.4.  Total Attack Connections
    8.1.5.  Attack Details
    8.1.6.  Vendor Attack Mapping
  8.2.  From DOTS Clients to DOTS Servers
  8.3.  From DOTS Servers to DOTS Clients
9.  DOTS Telemetry Mitigation Status Update
  9.1.  From DOTS Clients to DOTS Servers: Mitigation Efficacy DOTS
        Telemetry Attributes
  9.2.  From DOTS Servers to DOTS Clients: Mitigation Status DOTS
        Telemetry Attributes
10. Error Handling
11. YANG Modules
  11.1.  DOTS Signal Channel Telemetry YANG Module
  11.2.  Vendor Attack Mapping Details YANG Module
12. YANG/JSON Mapping Parameters to CBOR
13. IANA Considerations
  13.1.  DOTS Signal Channel CBOR Key Values
  13.2.  DOTS Signal Channel Conflict Cause Codes
  13.3.  DOTS Telemetry URIs and YANG Module Registrations
14. Security Considerations
  14.1.  DOTS Signal Channel Telemetry
  14.2.  Vendor Attack Mapping
15. References
  15.1.  Normative References
  15.2.  Informative References
Acknowledgments
Contributors
Authors' Addresses

1. Introduction ✨

Okay so IT orgs and service providers are dealing with Distributed Denial-of-Service (DDoS) attacks, and they mostly fall into two big buckets πŸ’€:

  1. Network-layer and transport-layer attacks target the victim's infrastructure. These aren't always trying to take down the actual services. Instead, they stop network elements (routers, switches, firewalls, transit links, and so on) from serving legit users' traffic 😭.

The main move here is to blast a huge volume of traffic (for example, high-pps (packets per second) traffic) at the victim's infrastructure. Attack volumes can range from a few hundred Mbps to hundreds of Gbps, or even Tbps πŸ”₯. Attackers usually use botnets and attack reflectors for amplification attacks (Section 3.1 of [RFC4732]) with protocols like NTP (Network Time Protocol), DNS (Domain Name System), SNMP (Simple Network Management Protocol), or SSDP (Simple Service Discovery Protocol) 🌈.

  1. Application-layer attacks target various applications. Typical examples are attacks against HTTP/HTTPS, DNS, SIP (Session Initiation Protocol), or SMTP (Simple Mail Transfer Protocol). Honestly, any application with its port numbers open at network edges can be an attractive target πŸ™ˆ.

Application-layer attacks are seen as more complex, harder to categorize, and therefore harder to detect and mitigate efficiently πŸ’….

To make things worse, attackers love multi-vector attacks. These are put together from dynamic network-layer and application-layer attack vectors plus other tactics. So multiple attack vectors, made of multiple attack types and volumes, get launched at a victim all at once 😀. Multi-vector attacks are harder to detect and defend against, and you need multiple mitigation techniques running at the same time to beat these campaigns 🫠. It's also super common for attackers to switch vectors right after a successful mitigation, which means defenders have to keep changing their methods πŸ™ƒ.

The takeaway from all these attack scenarios is that modern attack detection and mitigation are seriously complicated and highly convoluted tasks πŸŒ€. They need deep knowledge of attack attributes, the normal behavior of the targeted systems (including normal traffic patterns), and the attacker's ongoing and past actions. Even harder, getting all the analytics needed to detect these attacks is not simple with the industry's current reporting capabilities 😩.

The Distributed Denial-of-Service Open Threat Signaling (DOTS) signal channel protocol [RFC9132] carries information about a network resource, or a network (or part of one), that's under a DDoS attack. A DOTS client sends that info to one or multiple DOTS servers so that the right mitigation actions get taken on suspicious traffic πŸ¦‹. Various use cases are discussed in [RFC8903] πŸŽ€.

DOTS clients can live inside a DDoS attack detector, or inside network and security elements that are actively dealing with ongoing attacks. At some point the DOTS client's mitigation environment decides it can't handle these attacks by itself anymore, whether because of a lack of resources or security capabilities, given how complex and intense the attacks are πŸ₯Ί. At that point the DOTS client has priceless knowledge about the actual attacks its DOTS server(s) need to handle. When the DOTS client is allowed to share that knowledge of an ongoing attack under specific circumstances, the DOTS server can seriously boost its chances of successful mitigation πŸ‘‘. While the mitigation resources tied to the DOTS server are handling the attack, the DOTS server knows what's happening with the mitigation. It can share that with the DOTS client so the client can better assess and evaluate the mitigation that actually happened πŸ’–.

DOTS clients can send mitigation hints based on attack details to DOTS servers, fully understanding that a DOTS server may ignore those hints, as described in [RFC8612] (Gen-004) πŸ™ˆ. Mitigation hints go across the DOTS signal channel, because the data channel may not be working during an attack 🧚. How a DOTS server handles normal and attack traffic attributes, plus mitigation hints, is implementation specific ✨.

Both DOTS clients and servers can benefit from this info by showing it in relevant management, reporting, and portal systems 🌈.

This document defines DOTS telemetry attributes that DOTS clients can send to DOTS servers, and the other way around. These attributes are not mandatory for the DOTS signal channel protocol [RFC9132]. When no limitation policy is given to a DOTS agent, it can signal its available telemetry attributes to its peers to optimize the overall mitigation service provisioned using DOTS πŸ’œ. That policy could be, for example, agreed upon during a service subscription (which is out of scope for this document), to pick out a subset of DOTS clients in a DOTS client domain that are allowed to send or receive telemetry data 🫢.

Section 11.2 of this document specifies a YANG module that augments the DOTS data channel [RFC8783] with attack details information. Sharing those details during 'idle' time is meant to optimize the data exchanged over the DOTS signal channel πŸ“.

  1. Terminology

The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in BCP 14 [RFC2119] [RFC8174] when, and only when, they appear in all capitals, as shown here.

Okay bestie, let's get into the vocab, because this part is where the whole doc starts making sense πŸ“šβœ¨ The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in BCP 14 [RFC2119] [RFC8174] when, and only when, they appear in all capitals, as shown here. So yeah, the capital-letter rule is strict πŸ’… lowercase "should" is just a regular word, no cap πŸ™ˆ

The reader should be familiar with the terms defined in [RFC8612]. πŸŽ€ Translation: go read RFC 8612 first, it's giving homework but it's important πŸ€“

"DOTS telemetry" is defined as the collection of attributes that are used to characterize the normal traffic baseline, attacks and their mitigation measures, and any related information that may help in enforcing countermeasures. "DOTS telemetry" is an optional set of attributes that can be signaled in the DOTS signal channel protocol. πŸ¦‹ So DOTS telemetry is basically the group chat of stats: the normal traffic baseline, the attacks, how they're being mitigated, and anything that helps enforce countermeasures. It's OPTIONAL to signal, so it's a nice-to-have bonus, not a must-have πŸ’–

The Telemetry Setup Identifier (tsid) is an identifier that is generated by DOTS clients to uniquely identify DOTS telemetry setup configuration data. See Section 7.1.2 for more details. 🧚 So the tsid is the ID clients make up to label their telemetry setup config. Want the deets? Jump to Section 7.1.2 🌸

The Telemetry Identifier (tmid) is an identifier that is generated by DOTS clients to uniquely identify DOTS telemetry data that is communicated prior to or during a mitigation. See Section 8.2 for more details. πŸ’œ And the tmid is the sibling ID, for the actual telemetry data sent before or during a mitigation. Section 8.2 has the full tea β˜•

"Overlapped" lower numeric 'tsid' (or 'tmid') refers to the lower 'tsid' (or 'tmid') value of two overlapping telemetry requests. πŸ™ƒ So when two telemetry requests overlap, the one with the lower numeric value is the "overlapped" one. Easy to mix up, so don't let it trip you up bestie 🫢

The term "pipe" represents the maximum level of traffic that the DOTS client domain can receive. Whether a "pipe" is mapped to one or a group of network interfaces is deployment specific. For example, each interconnection link may be considered as a specific pipe if the DOTS server is hosted by each upstream provider, while the aggregate of all links to connect to upstream network providers can be considered by a DOTS client domain as a single pipe when communicating with a DOTS server not hosted by these upstream providers. 🌈 A "pipe" is basically the max amount of traffic the DOTS client domain can take in. It can be one interface or a bunch of them, and that depends on how the deployment is set up πŸ”₯ Example: if each upstream provider hosts its own DOTS server, each link is its own pipe. But if the DOTS server isn't hosted by those upstreams, you can treat all the links together as one big pipe πŸ‘‘

This document uses IANA-assigned Enterprise Numbers. These numbers are also known as "Private Enterprise Numbers" and "SMI (Structure of Management Information) Network Management Private Enterprise Codes" [Private-Enterprise-Numbers]. ⭐ So this doc uses the IANA Enterprise Numbers, which also go by "Private Enterprise Numbers" and "SMI Network Management Private Enterprise Codes" [Private-Enterprise-Numbers] πŸ“

The meanings of the symbols in YANG tree diagrams are defined in [RFC8340] and [RFC8791]. πŸ§šβ€β™€οΈ If YANG tree diagrams look like hieroglyphics to you, the symbol meanings live in [RFC8340] and [RFC8791] ✨

Consistent with the convention set in Section 2 of [RFC8783], the examples in Section 8.1.6 use "/restconf" as the discovered RESTCONF API root path. Within these examples, some protocol header lines are split into multiple lines for display purposes only. When a line ends with a backslash ("") as the last character, the line is wrapped for display purposes. It is considered to be joined to the next line by deleting the backslash, the following line break, and the leading whitespace of the next line. πŸ’… Quick heads up on the examples in Section 8.1.6: they follow the convention from Section 2 of [RFC8783] and use "/restconf" as the RESTCONF API root path πŸŽ€ Some header lines get split across lines just so they fit on your screen. If a line ends with a backslash (""), that's a display wrap: delete the backslash, the line break, and the leading whitespace on the next line, and boom, it's one line again πŸ¦‹


3. DOTS Telemetry: Overview and Purpose ✨

Timely and effective signaling of up-to-date DDoS telemetry to all elements involved in the mitigation process is essential and improves the overall DDoS mitigation service's effectiveness. Bidirectional feedback between DOTS agents is required for increased awareness by each party of the attack and mitigation efforts, supporting a superior and highly efficient attack mitigation service. 🌸 Okay so, sending fresh DDoS telemetry to everyone involved in mitigation is ESSENTIAL 😭 It makes the whole service way more effective. And the DOTS agents on both ends need to give each other feedback so everyone knows what's going on with the attack and the mitigation. Main character energy for the whole system πŸ‘‘

3.1. Need for More Visibility πŸ‘€

When signaling a mitigation request, it is most certainly beneficial for DOTS clients to signal to DOTS servers any knowledge regarding ongoing attacks. This can happen in cases where DOTS clients are asking DOTS servers for support in defending against attacks that they have already detected and/or (partially) mitigated. πŸ’– So when a client asks for mitigation, it's SO helpful if it also tells the server what it already knows about the ongoing attacks. This is especially true when the client already spotted the attack and maybe partially handled it already 🫢

If attacks are already detected and categorized within a DOTS client domain, the DOTS server, and its associated mitigation services, can proactively benefit from this information and optimize the overall service delivery. It is important to note that DOTS client domains' and DOTS server domains' detection and mitigation approaches can be different and can potentially result in different results and attack classifications. The DDoS mitigation service treats the ongoing attack details received from DOTS clients as hints and cannot completely rely on or trust the attack details conveyed by DOTS clients. πŸ”₯ If the client already sorted and labeled the attacks, the server and its mitigation services can use that to get ahead and optimize things. BUT, heads up 🚨 the client and server might detect and classify things differently, so the results can disagree. The mitigation service treats client attack details as hints, not gospel, and can't fully trust or rely on them πŸ’…

In addition to the DOTS server directly using telemetry data as operational hints, the DOTS server's security operation team also benefits from telemetry data. A basic requirement of security operation teams is to be aware of and get visibility into the attacks they need to handle. This holds especially for the case of ongoing attacks, where DOTS telemetry provides data about the current attack status. Even if some mitigation can be automated, operational teams can use the DOTS telemetry information to be prepared for attack mitigation and to assign the correct resources (e.g., operation staff, networking resources, mitigation resources) for the specific service. Similarly, security operations personnel at the DOTS client side ask for feedback about their requests for protection. Therefore, it is valuable for DOTS servers to share DOTS telemetry with DOTS clients. 🧚 The server isn't the only one who benefits: the server's security ops team also gets to use telemetry, because seeing the attacks they have to handle is basically their whole job πŸ‘€ Even with automation, the ops team can use the data to get ready and assign the right staff, network, and mitigation resources πŸŽ€ And the client side's security folks want feedback on their protection requests too, so it's valuable for servers to share DOTS telemetry back with clients πŸ¦‹

Mutual sharing of information is thus crucial for "closing the mitigation loop" between DOTS clients and servers. For the server- side team, it is important to confirm that the same attacks that the DOTS server's mitigation resources are seeing are those for which a DOTS client is requesting mitigation. For the DOTS client-side team, it is important to realize that the DOTS clients receive the required service -- for example, understanding that "I asked for mitigation of two attacks, and my DOTS server detects and mitigates only one of them." Cases of inconsistency in attack classification between DOTS clients and servers can be highlighted, and maybe handled, using the DOTS telemetry attributes. πŸ”„ So sharing both ways is what "closes the mitigation loop" πŸ’œ The server team needs to confirm the attacks they see are the same ones the client asked about. The client team needs to make sure they're actually getting the service they need, like noticing "I asked for two attacks to be mitigated, but only one got handled" 😭 And if the two sides classify attacks differently, telemetry attributes can help flag that and maybe fix it 🌈

In addition, management and orchestration systems, at both the DOTS client and server sides, can use DOTS telemetry as feedback to automate various control and management activities derived from signaled telemetry information. βš™οΈ Management and orchestration systems on both sides can also use telemetry as feedback to automate control and management tasks based on what's been signaled ✨

If the DOTS server's mitigation resources have the capabilities to facilitate the DOTS telemetry, the DOTS server adapts its protection strategy and activates the required countermeasures immediately (automation enabled) for the sake of optimized attack mitigation decisions and actions. Discussion regarding the interface from the DOTS server to the mitigator to signal the telemetry data is out of scope for this document. πŸ“ If the server's mitigation resources can handle telemetry, the server adapts its protection strategy and turns on the required countermeasures right away, all automated, for smarter mitigation πŸ”₯ How the server talks to the mitigator to pass telemetry along is OUT OF SCOPE for this doc, so don't look for it here πŸ™ˆ

3.2. Enhanced Detection πŸ”

DOTS telemetry can also be used as input for determining what values to use for the tuning parameters available on the mitigation resources. During the last few years, DDoS attack detection technologies have evolved from threshold-based detection (that is, cases when all or specific parts of traffic cross a predefined threshold for a certain period of time is considered as an attack) to an "anomaly detection" approach. For the latter, it is required to maintain rigorous learning of "normal" behavior, and an "anomaly" (or an attack) is identified and categorized based on the knowledge about the normal behavior and a deviation from this normal behavior. Statistical and artificial intelligence algorithms (e.g., machine learning) are used such that the actual traffic thresholds are automatically calculated by learning the protected entity's normal traffic behavior during 'idle' time (i.e., no mitigation is active). The normal traffic characterization learned is referred to as the "normal traffic baseline". An attack is detected when the victim's actual traffic is deviating from this normal baseline pattern. 🧠 Telemetry can also feed the tuning knobs on mitigation gear. Detection used to be threshold-based, which means "if traffic crosses a set line for a while, it's an attack" πŸ“ˆ Then it glowed up to "anomaly detection": you have to keep learning what "normal" looks like, and anything that deviates from it gets flagged as an attack πŸ‘€ Stats and AI (like machine learning) work out the real thresholds automatically by learning normal traffic during 'idle' time, meaning when no mitigation is running πŸ€– That learned pattern is the "normal traffic baseline", and an attack is spotted when the victim's traffic drifts away from it 🚨

In addition, subsequent activities toward mitigating an attack are much more challenging. The ability to distinguish legitimate traffic from attacker traffic on a per-packet basis is complex. For example, a packet may look "legitimate" and no attack signature can be identified. The anomaly can be identified only after detailed statistical analysis. DDoS attack mitigators use the normal baseline during the mitigation of an attack to identify and categorize the expected appearance of a specific traffic pattern. Particularly, the mitigators use the normal baseline to recognize the "level of normality" that needs to be achieved during the various mitigation processes. 😀 And mitigating is the hard part. Telling good traffic from bad one packet at a time is genuinely tricky πŸ’€ A packet can look totally legit with no attack signature, and the anomaly only shows up after detailed stats analysis πŸ“Š So mitigators lean on the normal baseline to know what "normal-looking" traffic should look like, and aim for that "level of normality" during mitigation πŸ’…

Normal baseline calculation is performed based on continuous learning of the normal behavior of the protected entities. The minimum learning period varies from hours to days and even weeks, depending on the protected applications' behavior. The baseline cannot be learned during active attacks because attack conditions do not characterize the protected entities' normal behavior. ⏳ Baseline calculation comes from continuously learning normal behavior of the protected entities 🌊 How long that takes depends on the app: it can be hours, days, or even weeks ⏰ And you CAN'T learn the baseline during an active attack, because attack conditions don't show what normal looks like πŸ™…β€β™€οΈ

If the DOTS client has calculated the normal baseline of its protected entities, signaling such information to the DOTS server along with the attack traffic levels provides value. The DOTS server benefits from this telemetry by tuning its mitigation resources with the DOTS client's normal baseline. The DOTS server's mitigators use the baseline to familiarize themselves with the attack victim's normal behavior and target the baseline as the level of normality they need to achieve. Fed with this information, the overall mitigation performance is expected to be improved in terms of time to mitigate, accuracy, and false-negative and false-positive rates. 🎁 If the client has already worked out the normal baseline for its protected entities, sending that to the server along with the attack traffic levels is super valuable πŸ’– The server uses it to tune its mitigation gear, and mitigators get to know the victim's normal behavior and aim for that as the goal 🎯 With this info, mitigation performance is expected to improve in terms of time to mitigate, accuracy, and false-negative and false-positive rates ✨

Mitigation of attacks without having certain knowledge of normal traffic can be inaccurate at best. This is especially true for recursive signaling (see Section 3.2.3 of [RFC8811]). Given that DOTS clients can be integrated in a highly diverse set of scenarios and use cases, this emphasizes the need for knowledge of the behavior of each DOTS client domain -- especially given that common global thresholds for attack detection can almost never be realized. Each DOTS client domain can have its own levels of traffic and normal behavior. Without facilitating normal baseline signaling, it may be very difficult for DOTS servers in some cases to detect and mitigate the attacks accurately: 🫠 Mitigating attacks without solid knowledge of normal traffic is, at best, inaccurate 😬 That's extra true for recursive signaling (see Section 3.2.3 of [RFC8811]) πŸ” DOTS clients come in SO many different setups, so the server really needs to know how each client domain behaves, since one global threshold for detection basically never works 🌍 Each client domain has its own traffic levels and normal behavior πŸ’… Skip the baseline signaling and the server might really struggle to detect and mitigate attacks accurately πŸ˜΅β€πŸ’«

  • It is important to emphasize that it is practically impossible for the DOTS server's mitigators to calculate the normal baseline in cases where they do not have any knowledge of the traffic beforehand. 🚨 Real talk: if the mitigators know nothing about the traffic beforehand, calculating the normal baseline is practically impossible πŸ™ƒ

Of course, this information can be provided using out-of-band mechanisms or manual configuration, at the risk of unmaintained information becoming inaccurate as the network evolves and "normal" patterns change. The use of a dynamic and collaborative means between the DOTS client and server to identify and share key parameters for the sake of efficient DDoS protection is valuable. 🧐 Sure, you can pass this info around out-of-band or configure it by hand, BUT it can go stale as the network changes and "normal" shifts πŸ“‰ A dynamic, collaborative approach where client and server work together to identify and share the key parameters is way more valuable for efficient DDoS protection 🌟

3.3. Efficient Mitigation πŸ›‘οΈβœ¨

Okay so, during a high-volume attack, DOTS client pipes can get totally saturated 😭. The DOTS clients ask their DOTS servers to handle the attack upstream so the pipes can chill back to a reasonable load level (normal pattern, ideally 🫢). At that point it is essential that the mitigator doesn't flood the DOTS client pipes by sending back huge amounts of "clean traffic", or whatever it thinks is "clean" πŸ™ˆ. This can happen when the mitigator hasn't managed to detect and mitigate every attack launched toward the DOTS client domain.

So in this case it can be super valuable for DOTS clients to tell DOTS servers the total pipe capacity, which is the level of traffic the DOTS client domain can absorb from its upstream network πŸ’…. This is usually the circuit size, and it includes all the packet overheads. Dynamic updates on the condition of pipes between DOTS agents during a DDoS attack are essential (e.g., where multiple DOTS clients share the same physical connectivity pipes) 🌈. The DOTS server should activate other mechanisms so it doesn't let the DOTS client domain's pipes get saturated by accident. The rate-limit action defined in [RFC8783] is a reasonable candidate for this πŸŽ€. The DOTS client can indicate the type(s) of traffic it prefers to limit, like ICMP, UDP, or TCP port number 80. And the rate-limit action can be controlled via the signal channel [RFC9133] even when the pipe is overwhelmed πŸ’ͺ.


4. Design Overview πŸŽ€

4.1. Overview of Telemetry Operations πŸ¦‹

The DOTS protocol suite is split into two logical channels: the signal channel [RFC9132] and the data channel [RFC8783] 🧚. This split exists because the traffic they carry has vastly different requirements 😀. The DOTS signal channel has to stay available and usable even when attack traffic is saturating one direction of the links involved. That makes acknowledgment-based mechanisms unreliable and strongly encourages messages small enough to fit in a single IP packet (Section 2.2 of [RFC8612]) πŸ’€. The DOTS data channel, on the other hand, is there for high-bandwidth data transfer before or after an attack, using more conventional transport protocol techniques (Section 2.3 of [RFC8612]) πŸ“. It's generally better to do advance configuration over the DOTS data channel, including configuring aliases for static or nearly static data sets, like sets of network addresses/prefixes that might be hit by related attacks. This keeps the DOTS signal channel free for the small messages that really matter during an attack ✨. As a friendly reminder, both the DOTS signal channel and the data channel require secure communication channels (Section 11 of [RFC9132] and Section 10 of [RFC8783]) πŸ”.

Telemetry info has parts that match both operational modes (signal channel and data channel) 🌸. There's definitely a need to share updated info about ongoing attack traffic and targets during an attack, so people can see detailed mitigation status and update their mitigation strategy when attacks are adaptive πŸ‘‘. But it's also useful to give mitigation services a picture of normal or "baseline" traffic toward potential targets. That helps them notice when incoming traffic drifts from normal into attack territory πŸ”₯. And one might populate a "database" of classifications of known attack types, so a short attack identifier can describe an observed attack during an attack period. This specification does make provision for using the DOTS data channel for that last function (Section 8.1.6), but otherwise most telemetry functionality stays in the DOTS signal channel πŸ’œ.

Here's the important bit: it's a functional requirement to convey info about ongoing attack traffic during an attack, and the info about baseline traffic uses an essentially identical data structure. That structure is naturally defined to sit right next to the description of attack traffic πŸ™Œ. The related telemetry setup info that parameterizes the actual traffic data is also sent over the signal channel, purely out of expediency 🧠.

This document specifies an extension to the DOTS signal channel protocol. Considerations about how to establish, maintain, and make use of the DOTS signal channel are specified in [RFC9132] πŸ“œ.

Once the DOTS signal channel is up, DOTS clients that support the DOTS telemetry extension move on to the telemetry setup configuration (e.g., measurement interval, telemetry notification interval, pipe capacity, normal traffic baseline) as detailed in Section 7 βš™οΈ. DOTS agents can then include DOTS telemetry attributes using the DOTS signal channel (Section 8.1). A DOTS client can use separate messages to share a set of telemetry data bound to an ongoing mitigation with its DOTS server(s) (Section 8.2) 🀝. And a DOTS client that wants telemetry notifications about some of its resources follows the procedure defined in Section 8.3 πŸ””. Once it gets those notifications, it can decide to send a mitigation request if an attack can't be mitigated locally within the DOTS client domain 🫢.

Aggregate DOTS telemetry data can also be included in efficacy update (Section 9.1) or mitigation update (Section 9.2) messages πŸ“¨.

4.2. Block-Wise Transfers 🧁

DOTS clients can use a block-wise transfer [RFC7959] with the recommendation detailed in Section 4.4.2 of [RFC9132] to control the size of a response when the data to be returned doesn't fit in a single datagram πŸ“¦.

DOTS clients can also use the Constrained Application Protocol (CoAP) Block1 Option in a PUT request (Section 2.5 of [RFC7959]) to start large transfers. But these Block1 transfers are likely to fail if the inbound "pipe" is running full 😩. The reason is that the transfer needs a message from the server for each block, and that message would likely get lost in the incoming flood 🌊. So it's worth considering whether the PUT can fit into a single transfer, or whether it should be split into several discrete PUTs where each one fits into a single packet 🧩.

Q-Block1 and Q-Block2 Options are similar to the CoAP Block1 and Block2 Options, but they enable robust transmissions of big blocks of data with fewer packet interchanges using NON messages. They're defined in [RFC9177] πŸš€. DOTS implementations can consider using Q-Block1 and Q-Block2 Options [DOTS-Robust-Blocks] πŸ’–.

4.3. DOTS Multihoming Considerations 🌐

Considerations for multihomed DOTS clients, about which DOTS server to contact and which IP prefixes to include in a telemetry message to a given peer DOTS server, are discussed in [DOTS-Multihoming] πŸ—ΊοΈ. For example, if each upstream network exposes a DOTS server and the DOTS client keeps DOTS channels with all of them, only the info related to prefixes assigned by an upstream network to the DOTS client domain will be signaled over the DOTS channel established with that upstream network's DOTS server 🎯.

Considerations about whether (and how) a DOTS client gleans some telemetry info (e.g., attack details) it receives from a first DOTS server and shares it with a second DOTS server are implementation and deployment specific πŸ› οΈ.

4.4. YANG Considerations πŸ“

Telemetry messages exchanged between DOTS agents are serialized using Concise Binary Object Representation (CBOR) [RFC8949] 🧸. CBOR-encoded payloads carry the signal-channel-specific payload messages that convey request parameters and response info, like errors πŸ™ˆ.

This document specifies a YANG module [RFC7950] for representing DOTS telemetry message types (Section 11.1) 🌷. All parameters in the payload of the DOTS signal channel are mapped to CBOR types as specified in Section 12. And as a reminder, Section 3 of [RFC9132] defines the rules for mapping YANG-modeled data to CBOR πŸŽ€.

The DOTS telemetry module (Section 11.1) is not intended to be used via the Network Configuration Protocol (NETCONF) / RESTCONF for DOTS server management purposes. It only serves to provide a data model and encoding following [RFC8791] 🚫. Server deviations (Section 5.6.3 of [RFC7950]) are strongly discouraged, because the peer DOTS agent doesn't have a way to retrieve the list of deviations, so interoperability issues are likely to pop up 😬.

The DOTS telemetry module (Section 11.1) uses "enumerations" rather than "identities" to define units, samples, and intervals. Otherwise the namespace identifier "ietf-dots-telemetry" would have to be included whenever a telemetry attribute is included (e.g., in a mitigation efficacy update) πŸ™ƒ. So "identities" are a bit suboptimal when it comes to message compactness, and message compactness is one of the key requirements for DOTS signal channel messages 🀏.

The DOTS telemetry module (Section 11.1) includes some lists that have no "key" statement. This is compliant with [RFC8791] πŸ’…. The reason those keys aren't included is that they aren't part of the message body of DOTS requests. Instead, such keys are included as mandatory Uri-Paths in requests (Sections 7 and 8) πŸ›£οΈ. Otherwise, whenever a "key" statement is used in the module, the same definition as the one in Section 7.8.2 of [RFC7950] is assumed βœ….

Some parameters (e.g., low-percentile values) may be associated with different YANG types (e.g., decimal64 and yang:gauge64). To tell these parameter types apart while keeping meaningful names, the following suffixes are used 🏷️:

               +========+==============+==================+
               | Suffix | YANG Type    | Example          |
               +========+==============+==================+
               | -g     | yang:gauge64 | low-percentile-g |
               +--------+--------------+------------------+
               | -c     | container    | connection-c     |
               +--------+--------------+------------------+
               | -ps    | per second   | connection-ps    |
               +--------+--------------+------------------+

                     Table 1: Suffixes and YANG Types

The full tree diagram of the DOTS telemetry module can be generated using the "pyang" tool [PYANG] 🌳. That tree isn't included here because it's too long (Section 3.3 of [RFC8340]). Instead, subtrees are provided for the reader's convenience πŸ™.

To optimize the data exchanged over the DOTS signal channel, this document specifies a second YANG module ("ietf-dots-mapping"; see Section 11.2). It augments the DOTS data channel [RFC8783] πŸ’«. This augmentation can be used during 'idle' time to share the attack mapping details (Section 8.1.5) 😌. DOTS clients can use tools, e.g., the YANG Library [RFC8525], to retrieve the list of features and deviations supported by the DOTS server over the data channel 🧰.

5. Generic Considerations 🌷

5.1. DOTS Client Identification πŸͺͺ

Following the rules in Section 4.4.1 of [RFC9132], a unique identifier is generated by a DOTS client to prevent request collisions ('cuid') πŸ†”.

As a reminder, Section 4.4.1.3 of [RFC9132] forbids 'cuid' to be returned in a response message body πŸ™…β€β™€οΈπŸ’œ.

5.2. DOTS Gateways πŸŒ‰

Okay bestie, DOTS gateways can hang out between DOTS clients and servers 🫢. The considerations in Section 4.4.1 of [RFC9132] must be followed. The big one is that the cdid attribute is what unambiguously identifies a DOTS client domain πŸ’….

Quick reminder: Section 4.4.1.3 of [RFC9132] forbids cdid (if present) from being returned in a response message body πŸ™ˆ.

5.3. Uri-Path Parameters and Empty Values 🚫

Uri-Path parameters and attributes with empty values MUST NOT be present in a request πŸ’€. If that empty value shows up, the entire containing message is invalid. No exceptions, no vibes 😭.

5.4. Controlling Configuration Data πŸŽ€

The DOTS server follows the same considerations from Section 4.5.3 of [RFC9132] for managing DOTS telemetry configuration freshness and notifications ✨.

Likewise, a DOTS client may control which configuration and non-configuration data nodes get selected when it sends a GET request. It does this with the c (content) Uri-Query option, following the procedure in Section 4.4.2 of [RFC9132] 🧚. These considerations aren't repeated in the following sections, so keep them in mind πŸ˜‰.

5.5. Message Validation πŸ”

The authoritative references for validating telemetry messages exchanged over the DOTS signal channel are Sections 7, 8, and 9, together with the mapping table provided in Section 12. The structure of telemetry message bodies is represented as a YANG data structure (Section 11.1) πŸ“š.

5.6. A Note about Examples πŸ“

Examples are provided for illustration purposes 🌸. This document doesn't try to be a comprehensive list of message examples, so don't expect every possible case.

JSON encoding of YANG-modeled data is used to illustrate the various telemetry operations. To keep things readable, the examples use parameter names and their JSON types instead of their CBOR key values and CBOR types. The mappings are in Section 12. These conventions are inherited from [RFC9132] πŸ“.

The examples use Enterprise Number 32473, which is defined for documentation use. See [RFC5612] πŸ’–.


6. Telemetry Operation Paths πŸ›€οΈ

As discussed in Section 4.2 of [RFC9132], each DOTS operation is marked by a path suffix that shows the intended operation. That operation path gets appended to the path prefix to form the URI used with a CoAP request to perform the desired DOTS operation πŸ”—. The following telemetry path suffixes are defined (Table 2):

          +=================+================+===========+
          | Operation       | Operation Path | Details   |
          +=================+================+===========+
          | Telemetry Setup | /tm-setup      | Section 7 |
          +-----------------+----------------+-----------+
          | Telemetry       | /tm            | Section 8 |
          +-----------------+----------------+-----------+

                 Table 2: DOTS Telemetry Operations

So the "ietf-dots-telemetry" YANG module defined in Section 11.1 is the one that defines a data structure to represent the new DOTS message types called telemetry-setup and telemetry 🧩. The tree structure is shown in Figure 1. More details about the exact structure of telemetry-setup and telemetry message types are in Sections 7 and 8 🌳.

  structure dots-telemetry:
    +-- (telemetry-message-type)?
       +--:(telemetry-setup)
       |  ...
       |  +-- telemetry* []
       |     ...
       |     +-- (setup-type)?
       |        +--:(telemetry-config)
       |        |  ...
       |        +--:(pipe)
       |        |  ...
       |        +--:(baseline)
       |           ...
       +--:(telemetry)
          ...

        Figure 1: New DOTS Message Types (YANG Tree Structure)

DOTS implementations MUST support the Observe Option [RFC7641] for tm (Section 8) πŸ‘€.


7. DOTS Telemetry Setup Configuration βš™οΈ

Looking at Figure 1, a DOTS telemetry setup message MUST include only telemetry-related configuration parameters (Section 7.1), information about DOTS client domain pipe capacity (Section 7.2), or information about the telemetry traffic baseline (Section 7.3). So requests that mix telemetry configuration, pipe capacity, and traffic baseline information MUST be rejected by DOTS servers with a 4.00 (Bad Request) Response Code 🚨.

A DOTS client can reset all installed DOTS telemetry setup configuration data, following the considerations in Section 7.4 πŸ”„.

A DOTS server may detect conflicts. This can happen when it processes requests about DOTS client domain pipe capacity or telemetry traffic baseline information alongside requests from other DOTS clients in the same DOTS client domain. More details are in Section 7.5 πŸ•΅οΈβ€β™€οΈ.

Telemetry setup configuration is bound to a DOTS client domain πŸŽ€. DOTS servers MUST NOT expect DOTS clients to send regular requests to refresh the telemetry setup configuration. Any available telemetry setup configuration stays valid until the DOTS server stops servicing a DOTS client domain ⏳. DOTS servers MUST NOT reset tsid just because a session failed with a DOTS client. And DOTS clients update their telemetry setup configuration whenever a parameter that may impact attack mitigation changes πŸ›‘οΈ.

DOTS telemetry setup configuration request and response messages are marked as Confirmable messages (Section 2.1 of [RFC7252]) βœ….

7.1. Telemetry Configuration πŸ“Š

DOTS telemetry uses several percentile values to give a picture of the overall traffic distribution, instead of just one snapshot of observed traffic at a single point in time πŸ“ˆ. To model raw traffic flow data as a distribution, you pick a measurement period for the distribution to describe, plus a number of sampling intervals (or "buckets") within that period. Traffic within each bucket is treated as a single event (i.e., averaged). Then the distribution of buckets describes the distribution of traffic over the measurement period. A distribution can be described with statistical measures (e.g., mean, median, and standard deviation). It can also be described by reporting the value of the distribution at various percentile levels of the data set in question (e.g., "quartiles" that correspond to 25th, 50th, and 75th percentiles). More details about percentile values and how they're computed are in Section 11.3 of [RFC2330] πŸ€“.

DOTS telemetry uses up to three percentile values, plus the overall peak, to characterize traffic distributions 🌈. Which percentile thresholds are used for the "low-percentile", "mid-percentile", and "high-percentile" values is configurable. Default values are defined in Section 7.1.2 βš–οΈ.

A DOTS client can negotiate a set of telemetry configuration parameters with its server(s) to use for telemetry 🀝. Those parameters include:

  • Percentile-related measurement parameters. In particular, measurement-interval defines the period during which percentiles are computed, while measurement-sample defines the time distribution for measuring values that are used to compute percentiles 🧁.
  • Measurement units πŸ“.
  • Acceptable percentile values πŸ’….
  • Telemetry notification interval ⏰.
  • Acceptable server-originated telemetry πŸ’Œ.

7.1.1. Retrieving the Current DOTS Telemetry Configuration πŸ”Ž

A GET request is how you obtain the acceptable and current telemetry configuration parameters on the DOTS server πŸ‘€. This request may include a cdid Uri-Path when it's relayed by a DOTS gateway. An example of such a GET request (without a gateway) is shown in Figure 2.

Header: GET (Code=0.01)
Uri-Path: ".well-known"
Uri-Path: "dots"
Uri-Path: "tm-setup"
Uri-Path: "cuid=dz6pHjaADkaFTbjr0JGBpw"

 Figure 2: GET to Retrieve the Current and Acceptable DOTS Telemetry
                            Configuration

When the request is handled without any error, the DOTS server replies with a 2.05 (Content) response. It carries the telemetry parameters that are acceptable to the DOTS server, any pipe information (Section 7.2), and the current baseline information (Section 7.3) that the DOTS server is maintaining for this DOTS client 🎁. The tree structure of the response message body is in Figure 3.

DOTS servers that support sending telemetry information to DOTS clients prior to or during a mitigation (Section 9.2) set server-originated-telemetry under max-config-values to true (and false otherwise) 🌟. If server-originated-telemetry isn't present in a response, that's the same as receiving a response with server-originated-telemetry set to false.

  structure dots-telemetry:
    +-- (telemetry-message-type)?
       +--:(telemetry-setup)
       |  +-- (direction)?
       |  |  +--:(server-to-client-only)
       |  |     +-- max-config-values
       |  |     |  +-- measurement-interval?          interval
       |  |     |  +-- measurement-sample?            sample
       |  |     |  +-- low-percentile?                percentile
       |  |     |  +-- mid-percentile?                percentile
       |  |     |  +-- high-percentile?               percentile
       |  |     |  +-- server-originated-telemetry?   boolean
       |  |     |  +-- telemetry-notify-interval?     uint16
       |  |     +-- min-config-values
       |  |     |  +-- measurement-interval?        interval
       |  |     |  +-- measurement-sample?          sample
       |  |     |  +-- low-percentile?              percentile
       |  |     |  +-- mid-percentile?              percentile
       |  |     |  +-- high-percentile?             percentile
       |  |     |  +-- telemetry-notify-interval?   uint16
       |  |     +-- supported-unit-classes
       |  |     |  +-- unit-config* [unit]
       |  |     |     +-- unit           unit-class
       |  |     |     +-- unit-status    boolean
       |  |     +-- supported-query-type*  query-type
       |  +-- telemetry* []
       |     +-- (direction)?
       |     |  +--:(server-to-client-only)
       |     |     +-- tsid?                  uint32
       |     +-- (setup-type)?
       |        +--:(telemetry-config)
       |        |  +-- current-config
       |        |     +-- measurement-interval?          interval
       |        |     +-- measurement-sample?            sample
       |        |     +-- low-percentile?                percentile
       |        |     +-- mid-percentile?                percentile
       |        |     +-- high-percentile?               percentile
       |        |     +-- unit-config* [unit]
       |        |     |  +-- unit           unit-class
       |        |     |  +-- unit-status    boolean
       |        |     +-- server-originated-telemetry?   boolean
       |        |     +-- telemetry-notify-interval?     uint16
       |        +--:(pipe)
       |        |  ...
       |        +--:(baseline)
       |           ...
       +--:(telemetry)
          ...

           Figure 3: Telemetry Configuration Tree Structure

When both min-config-values and max-config-values attributes are present, the values carried in max-config-values attributes MUST be greater than or equal to their counterparts in min-config-values attributes 🧁✨.

Okay bestie, picking up right where we left off! πŸ’– Here's the next bit of the telemetry setup chat.


7.1.2. Conveying the DOTS Telemetry Configuration

Okay so a PUT request is how a DOTS client sends its telemetry config parameters πŸŽ€ (things like the low, mid, or high percentile values). For example, a DOTS client might ping its DOTS server to change the default percentile values that act as the baseline for telemetry data. ✨ Figure 3 lists the attributes a DOTS client can set in a PUT like this, and Figure 4 shows a client changing all of the percentile reference values. πŸ’…

Note: The payload of the message in Figure 4 is CBOR-encoded, which is flagged by setting Content-Format to "application/dots+cbor" (Section 10.3 of [RFC9132]). But for better readability, the example (and the other similar figures showing a DOTS telemetry message body) follows the conventions in Section 5.6: it uses the JSON names and types defined in Section 12. 🧚
Header: PUT (Code=0.03)
Uri-Path: ".well-known"
Uri-Path: "dots"
Uri-Path: "tm-setup"
Uri-Path: "cuid=dz6pHjaADkaFTbjr0JGBpw"
Uri-Path: "tsid=123"
Content-Format: "application/dots+cbor"

{
  "ietf-dots-telemetry:telemetry-setup": {
    "telemetry": [
      {
        "current-config": {
          "low-percentile": "5.00",
          "mid-percentile": "65.00",
          "high-percentile": "95.00"
        }
      }
    ]
  }
}

Figure 4: PUT to Convey the DOTS Telemetry Configuration, Depicted as per Section 5.6 🌸

'cuid' is a mandatory Uri-Path parameter for PUT requests. πŸ”

The following additional Uri-Path parameter is defined:

  • tsid: The Telemetry Setup Identifier is an identifier for the DOTS telemetry setup configuration data, represented as an integer. This identifier MUST be generated by DOTS clients. 'tsid' values MUST increase monotonically whenever new configuration parameters (not just for changed values) need to be conveyed by the DOTS client.

The procedure specified in Section 4.4.1 of [RFC9132] for 'mid' rollover MUST also be followed for 'tsid' rollover. πŸ”„

This is a mandatory attribute. 'tsid' MUST appear after 'cuid' in the Uri-Path options. πŸ‘‘

'cuid' and 'tsid' MUST NOT appear in the PUT request message body. πŸ™…

At least one configurable attribute MUST be present in the PUT request. πŸ’œ

A PUT request with a higher numeric 'tsid' value overrides the DOTS telemetry configuration data installed by a PUT request with a lower numeric 'tsid' value. To avoid a long list of 'tsid' requests piling up from a DOTS client, the lower numeric 'tsid' MUST be automatically deleted and no longer be available at the DOTS server. πŸ—‘οΈ

The DOTS server indicates the result of processing the PUT request using the following Response Codes:

  • If the request is missing a mandatory attribute, does not include 'cuid' or 'tsid' Uri-Path parameters, or contains one or more invalid or unknown parameters, a 4.00 (Bad Request) Response Code MUST be returned in the response. πŸ™ˆ
  • If the DOTS server does not find the 'tsid' parameter value conveyed in the PUT request in its configuration data and if the DOTS server has accepted the configuration parameters, then a 2.01 (Created) Response Code MUST be returned in the response. πŸŽ‰
  • If the DOTS server finds the 'tsid' parameter value conveyed in the PUT request in its configuration data and if the DOTS server has accepted the updated configuration parameters, a 2.04 (Changed) Response Code MUST be returned in the response. ✨
  • If any of the enclosed configurable attribute values are not acceptable to the DOTS server (Section 7.1.1), a 4.22 (Unprocessable Entity) Response Code MUST be returned in the response. πŸ’€

The DOTS client may retry and send the PUT request with updated attribute values acceptable to the DOTS server. πŸ”

By default, low-percentile (10th percentile), mid-percentile (50th percentile), high-percentile (90th percentile), and peak (100th percentile) values are used to represent telemetry data. Nevertheless, a DOTS client can disable some percentile types (low, mid, high). In particular, setting 'low-percentile' to "0.00" indicates that the DOTS client is not interested in receiving low-percentiles. Likewise, setting 'mid-percentile' (or 'high-percentile') to the same value as 'low-percentile' (or 'mid-percentile') indicates that the DOTS client is not interested in receiving mid-percentiles (or high-percentiles). For example, a DOTS client can send the request depicted in Figure 5 to tell the server it only wants high-percentiles. This assumes the client will only use that percentile type when sharing telemetry data with the server. πŸ¦‹

Header: PUT (Code=0.03)
Uri-Path: ".well-known"
Uri-Path: "dots"
Uri-Path: "tm-setup"
Uri-Path: "cuid=dz6pHjaADkaFTbjr0JGBpw"
Uri-Path: "tsid=124"
Content-Format: "application/dots+cbor"

{
  "ietf-dots-telemetry:telemetry-setup": {
    "telemetry": [
      {
        "current-config": {
          "low-percentile": "0.00",
          "mid-percentile": "0.00",
          "high-percentile": "95.00"
        }
      }
    ]
  }
}

Figure 5: PUT to Disable Low- and Mid-Percentiles, Depicted as per Section 5.6 🌈

DOTS clients can also configure the unit class(es) used for traffic-related telemetry data, choosing from packets per second, bits per second, and bytes per second. Supplying both bits per second and bytes per second unit classes is allowed for a given set of telemetry data. However, receiving conflicting values is treated as invalid parameters and rejected with a 4.00 (Bad Request) Response Code. ⚠️

DOTS clients that want pre-or-ongoing-mitigation telemetry ('pre-or-ongoing-mitigation') information from a DOTS server (Section 9.2) MUST set 'server-originated-telemetry' to 'true'. If 'server-originated-telemetry' is not present in a PUT request, that is equivalent to receiving a request with 'server-originated-telemetry' set to 'false'. An example of a request enabling pre-or-ongoing-mitigation telemetry from DOTS servers is shown in Figure 6. πŸ“

Header: PUT (Code=0.03)
Uri-Path: ".well-known"
Uri-Path: "dots"
Uri-Path: "tm-setup"
Uri-Path: "cuid=dz6pHjaADkaFTbjr0JGBpw"
Uri-Path: "tsid=125"
Content-Format: "application/dots+cbor"

{
  "ietf-dots-telemetry:telemetry-setup": {
    "telemetry": [
      {
        "current-config": {
          "server-originated-telemetry": true
        }
      }
    ]
  }
}

Figure 6: PUT to Enable Pre-or-Ongoing-Mitigation Telemetry from the DOTS Server, Depicted as per Section 5.6 🫢

7.1.3. Retrieving the Installed DOTS Telemetry Configuration

A DOTS client may issue a GET message with a 'tsid' Uri-Path parameter to retrieve the current DOTS telemetry configuration. An example of such a request is shown in Figure 7. πŸ”

Header: GET (Code=0.01)
Uri-Path: ".well-known"
Uri-Path: "dots"
Uri-Path: "tm-setup"
Uri-Path: "cuid=dz6pHjaADkaFTbjr0JGBpw"
Uri-Path: "tsid=123"

Figure 7: GET to Retrieve the Current DOTS Telemetry Configuration

If the DOTS server does not find the 'tsid' Uri-Path value conveyed in the GET request in its configuration data for the requesting DOTS client, it MUST respond with a 4.04 (Not Found) error Response Code. 😭

7.1.4. Deleting the DOTS Telemetry Configuration

A DELETE request is used to delete the installed DOTS telemetry configuration data (Figure 8). 'cuid' and 'tsid' are mandatory Uri-Path parameters for such DELETE requests. 🧹

Header: DELETE (Code=0.04)
Uri-Path: ".well-known"
Uri-Path: "dots"
Uri-Path: "tm-setup"
Uri-Path: "cuid=dz6pHjaADkaFTbjr0JGBpw"
Uri-Path: "tsid=123"

Figure 8: Deleting the Telemetry Configuration

The DOTS server resets the DOTS telemetry configuration back to the default values and acknowledges a DOTS client's request to remove the DOTS telemetry configuration using a 2.02 (Deleted) Response Code. A 2.02 (Deleted) Response Code is returned even if the 'tsid' parameter value conveyed in the DELETE request does not exist in its configuration data before the request. 🌟

Section 7.4 discusses the procedure to reset all DOTS telemetry setup configuration data. πŸ“–

7.2. Total Pipe Capacity

A DOTS client can tell the DOTS server(s) about its DOTS client domain pipe information. The tree structure of the pipe information is shown in Figure 9. 🌊

  structure dots-telemetry:
    +-- (telemetry-message-type)?
       +--:(telemetry-setup)
       |  ...
       |  +-- telemetry* []
       |     +-- (direction)?
       |     |  +--:(server-to-client-only)
       |     |     +-- tsid?                  uint32
       |     +-- (setup-type)?
       |        +--:(telemetry-config)
       |        |  ...
       |        +--:(pipe)
       |        |  +-- total-pipe-capacity* [link-id unit]
       |        |     +-- link-id     nt:link-id
       |        |     +-- capacity    uint64
       |        |     +-- unit        unit
       |        +--:(baseline)
       |           ...
       +--:(telemetry)
          ...

Figure 9: Pipe Tree Structure

A DOTS client domain pipe is defined as a list of limits on (incoming) traffic volume ('total-pipe-capacity') that can be forwarded over ingress interconnection links of a DOTS client domain. Each of these links is identified with a 'link-id' [RFC8345]. πŸ”—

The unit used by a DOTS client when conveying pipe information is captured in the 'unit' attribute. The DOTS client MUST auto-scale so that the appropriate unit is used. That is, for a given unit class, the DOTS client uses the largest unit that gives a value greater than one. As such, only one unit per unit class is allowed. πŸ“βœ¨

7.2.1. Conveying DOTS Client Domain Pipe Capacity

okay so considerations similar to Section 7.1.2 apply here too, with one twist πŸ’…

  • The relative order of two PUT requests carrying DOTS client domain pipe attributes from a DOTS client is decided by comparing their 'tsid' values. If both requests have overlapping 'link-id' and 'unit' settings, the PUT with the higher numeric 'tsid' overrides the one with the lower numeric 'tsid'. The overridden lower numeric 'tsid' MUST be automatically deleted and is no longer available πŸ—‘οΈβœ¨

DOTS clients SHOULD minimize how many active 'tsid's they use for pipe information 🧠 To avoid juggling a huge list of 'tsid's, it is RECOMMENDED that DOTS clients include in any update about a given link the info about their other links (already sent with a lower 'tsid'). That way the new request overrides the old ones, and the number of 'tsid' requests per DOTS client stays lean πŸŽ€

Note: This assumes that all link information can fit in one single message.

Here's an example of pipe info setup. A DOTS client managing a single-homed domain (Figure 10) can send a PUT request (Figure 11) to share the capacity of "link1", the link it uses to connect to its ISP 🌸

                     ,--,--,--.             ,--,--,--.
                  ,-'          `-.       ,-'          `-.
                 (  DOTS Client   )=====(     ISP#A      )
                  `-.  Domain  ,-' link1 `-.          ,-'
                     `--'--'--'             `--'--'--'

Figure 10: Single-Homed DOTS Client Domain

Header: PUT (Code=0.03)
Uri-Path: ".well-known"
Uri-Path: "dots"
Uri-Path: "tm-setup"
Uri-Path: "cuid=dz6pHjaADkaFTbjr0JGBpw"
Uri-Path: "tsid=126"
Content-Format: "application/dots+cbor"

{
  "ietf-dots-telemetry:telemetry-setup": {
    "telemetry": [
      {
        "total-pipe-capacity": [
          {
            "link-id": "link1",
            "capacity": "500",
            "unit": "megabit-ps"
          }
        ]
      }
    ]
  }
}

Figure 11: Example of a PUT Request to Convey Pipe Information (Single-Homed), Depicted as per Section 5.6

Sometimes DOTS clients get told to signal a link aggregate instead of individual links 🫢 For instance, a DOTS client handling a domain with two interconnection links to an upstream ISP (Figure 12) can send a PUT request (Figure 13) to share the aggregate link capacity with its ISP. Whether you signal individual or aggregate capacity is deployment specific, so it's totally up to the setup πŸ¦‹

                     ,--,--,--.             ,--,--,--.
                  ,-'          `-.===== ,-'          `-.
                 (  DOTS Client   )    (     ISP#C      )
                  `-.  Domain  ,-'====== `-.          ,-'
                     `--'--'--'             `--'--'--'

Figure 12: DOTS Client Domain with Two Interconnection Links

Header: PUT (Code=0.03)
Uri-Path: ".well-known"
Uri-Path: "dots"
Uri-Path: "tm-setup"
Uri-Path: "cuid=hmcpH87lmPGsSTjkhXCbin"
Uri-Path: "tsid=896"
Content-Format: "application/dots+cbor"

{
  "ietf-dots-telemetry:telemetry-setup": {
    "telemetry": [
      {
        "total-pipe-capacity": [
          {
            "link-id": "aggregate",
            "capacity": "700",
            "unit": "megabit-ps"
          }
        ]
      }
    ]
  }
}

Figure 13: Example of a PUT Request to Convey Pipe Information (Aggregated Link), Depicted as per Section 5.6

Now say the DOTS client domain got upgraded and now connects to an additional ISP (e.g., ISP#B in Figure 14) πŸ“ˆ The DOTS client can tell a DOTS server that isn't hosted with the ISP#A and ISP#B domains about this change by sending the PUT request in Figure 15. This request also includes info about "link1", even though that link isn't upgraded 🧚 When the DOTS server gets this request, it removes the request with tsid=126 and updates its configuration base to keep two links (link1 and link2) ✨

                    ,--,--,--.
                  ,-'          `-.
                 (     ISP#B      )
                  `-.          ,-'
                     `--'--'--'
                         ||
                         || link2
                    ,--,--,--.             ,--,--,--.
                  ,-'          `-.       ,-'          `-.
                 (  DOTS Client   )=====(     ISP#A      )
                  `-.  Domain  ,-' link1 `-.          ,-'
                     `--'--'--'             `--'--'--'

Figure 14: Multihomed DOTS Client Domain

Header: PUT (Code=0.03)
Uri-Path: ".well-known"
Uri-Path: "dots"
Uri-Path: "tm-setup"
Uri-Path: "cuid=dz6pHjaADkaFTbjr0JGBpw"
Uri-Path: "tsid=127"
Content-Format: "application/dots+cbor"

{
  "ietf-dots-telemetry:telemetry-setup": {
    "telemetry": [
      {
        "total-pipe-capacity": [
          {
            "link-id": "link1",
            "capacity": "500",
            "unit": "megabit-ps"
          },
          {
            "link-id": "link2",
            "capacity": "500",
            "unit": "megabit-ps"
          }
        ]
      }
    ]
  }
}

Figure 15: Example of a PUT Request to Convey Pipe Information (Multihomed), Depicted as per Section 5.6

A DOTS client can delete a link by sending a PUT request with the 'capacity' attribute set to "0", as long as other links are still active for the same DOTS client domain πŸ—‘οΈ For example, if a DOTS client domain re-homes (meaning it changes its ISP), the DOTS client can tell its DOTS server about this (e.g., going from the network in Figure 10 to the network in Figure 16) by sending the PUT request in Figure 17 πŸ’œ When the DOTS server gets this request, and assuming no error shows up while processing it, the server removes "link1" from its configuration bases for this DOTS client domain. Heads up: if the DOTS server receives a PUT request with a 'capacity' attribute set to "0" for every included link, it MUST reject the request with a 4.00 (Bad Request) Response Code πŸ™…β€β™€οΈ Instead, the DOTS client can use a DELETE request to delete all links (Section 7.2.3).

                    ,--,--,--.
                  ,-'          `-.
                 (     ISP#B      )
                  `-.          ,-'
                     `--'--'--'
                         ||
                         || link2
                    ,--,--,--.
                  ,-'          `-.
                 (  DOTS Client   )
                  `-.  Domain  ,-'
                     `--'--'--'

Figure 16: Multihomed DOTS Client Domain

Header: PUT (Code=0.03)
Uri-Path: ".well-known"
Uri-Path: "dots"
Uri-Path: "tm-setup"
Uri-Path: "cuid=dz6pHjaADkaFTbjr0JGBpw"
Uri-Path: "tsid=128"
Content-Format: "application/dots+cbor"

{
  "ietf-dots-telemetry:telemetry-setup": {
    "telemetry": [
      {
        "total-pipe-capacity": [
          {
            "link-id": "link1",
            "capacity": "0",
            "unit": "megabit-ps"
          },
          {
            "link-id": "link2",
            "capacity": "500",
            "unit": "megabit-ps"
          }
        ]
      }
    ]
  }
}

Figure 17: Example of a PUT Request to Convey Pipe Information (Multihomed), Depicted as per Section 5.6

7.2.2. Retrieving Installed DOTS Client Domain Pipe Capacity

A GET request with a 'tsid' Uri-Path parameter is how you grab the specific info for an installed DOTS client domain pipe πŸ‘€ The same procedure as Section 7.1.3 applies here.

Want all the pipe info bound to a DOTS client? Then the DOTS client follows Section 7.1.1 🧁

7.2.3. Deleting Installed DOTS Client Domain Pipe Capacity

A DELETE request is used to delete the specific info for an installed DOTS client domain pipe 🌈 The same procedure as Section 7.1.4 is followed, and that's the whole vibe πŸ’…βœ¨

7.3. Telemetry Baseline πŸ“ˆ

Okay so a DOTS client can tell its DOTS server(s) what its normal traffic baseline looks like and how much connection capacity it has πŸ’…

Total traffic normal baseline: this is the percentile data that represents the total traffic normal baseline 🌸. For a target, it's represented using 'total-traffic-normal'.

The per-protocol baseline ('total-traffic-normal-per-protocol') is represented for a target, and it's transport-protocol specific. The per-port-number baseline ('total-traffic-normal-per-port') is represented for each port number bound to a target πŸŽ€

If the DOTS client negotiated percentile values and units (Section 7.1), those negotiated parameters get used instead of the default ones. For each unit class used, the DOTS client MUST auto-scale so the right unit is used πŸ¦‹

Total connection capacity: if the target is susceptible to resource-consuming DDoS attacks, the following optional attributes for the target per transport protocol are useful for spotting those attacks πŸ”₯

  • The maximum number of simultaneous connections that are allowed to the target.
  • The maximum number of simultaneous connections that are allowed to the target per client.
  • The maximum number of simultaneous embryonic connections that are allowed to the target. The term "embryonic connection" refers to a connection whose connection handshake is not finished. Embryonic connections are only possible in connection-oriented transport protocols like TCP or the Stream Control Transmission Protocol (SCTP) [RFC9260].
  • The maximum number of simultaneous embryonic connections that are allowed to the target per client.
  • The maximum number of connections allowed per second to the target.
  • The maximum number of connections allowed per second to the target per client.
  • The maximum number of requests (e.g., HTTP/DNS/SIP requests) allowed per second to the target.
  • The maximum number of requests allowed per second to the target per client.
  • The maximum number of outstanding partial requests allowed to the target. Attacks relying upon partial requests create a connection with a target but do not send a complete request (e.g., an HTTP request).
  • The maximum number of outstanding partial requests allowed to the target per client.

The aggregate per transport protocol is captured in 'total-connection-capacity', while port-specific capabilities are represented using 'total-connection-capacity-per-port' ✨

Quick reminder: a target resource is identified using the attributes 'target-prefix', 'target-port-range', 'target-protocol', 'target-fqdn', 'target-uri', or 'alias-name', as defined in Section 4.4.1.1 of [RFC9132] 🧚

The tree structure of the normal traffic baseline is shown in Figure 18 πŸ‘‘

  structure dots-telemetry:
    +-- (telemetry-message-type)?
       +--:(telemetry-setup)
       |  ...
       |  +-- telemetry* []
       |     +-- (direction)?
       |     |  +--:(server-to-client-only)
       |     |     +-- tsid?                  uint32
       |     +-- (setup-type)?
       |        +--:(telemetry-config)
       |        |  ...
       |        +--:(pipe)
       |        |  ...
       |        +--:(baseline)
       |           +-- baseline* [id]
       |              +-- id                     uint32
       |              +-- target-prefix*
       |              |       inet:ip-prefix
       |              +-- target-port-range* [lower-port]
       |              |  +-- lower-port    inet:port-number
       |              |  +-- upper-port?   inet:port-number
       |              +-- target-protocol*                      uint8
       |              +-- target-fqdn*
       |              |       inet:domain-name
       |              +-- target-uri*
       |              |       inet:uri
       |              +-- alias-name*
       |              |       string
       |              +-- total-traffic-normal* [unit]
       |              |  +-- unit                 unit
       |              |  +-- low-percentile-g?    yang:gauge64
       |              |  +-- mid-percentile-g?    yang:gauge64
       |              |  +-- high-percentile-g?   yang:gauge64
       |              |  +-- peak-g?              yang:gauge64
       |              +-- total-traffic-normal-per-protocol*
       |              |       [unit protocol]
       |              |  +-- protocol             uint8
       |              |  +-- unit                 unit
       |              |  +-- low-percentile-g?    yang:gauge64
       |              |  +-- mid-percentile-g?    yang:gauge64
       |              |  +-- high-percentile-g?   yang:gauge64
       |              |  +-- peak-g?              yang:gauge64
       |              +-- total-traffic-normal-per-port* [unit port]
       |              |  +-- port                 inet:port-number
       |              |  +-- unit                 unit
       |              |  +-- low-percentile-g?    yang:gauge64
       |              |  +-- mid-percentile-g?    yang:gauge64
       |              |  +-- high-percentile-g?   yang:gauge64
       |              |  +-- peak-g?              yang:gauge64
       |              +-- total-connection-capacity* [protocol]
       |              |  +-- protocol                     uint8
       |              |  +-- connection?                  uint64
       |              |  +-- connection-client?           uint64
       |              |  +-- embryonic?                   uint64
       |              |  +-- embryonic-client?            uint64
       |              |  +-- connection-ps?               uint64
       |              |  +-- connection-client-ps?        uint64
       |              |  +-- request-ps?                  uint64
       |              |  +-- request-client-ps?           uint64
       |              |  +-- partial-request-max?         uint64
       |              |  +-- partial-request-client-max?  uint64
       |              +-- total-connection-capacity-per-port*
       |                      [protocol port]
       |                 +-- port
       |                 |       inet:port-number
       |                 +-- protocol                     uint8
       |                 +-- connection?                  uint64
       |                 +-- connection-client?           uint64
       |                 +-- embryonic?                   uint64
       |                 +-- embryonic-client?            uint64
       |                 +-- connection-ps?               uint64
       |                 +-- connection-client-ps?        uint64
       |                 +-- request-ps?                  uint64
       |                 +-- request-client-ps?           uint64
       |                 +-- partial-request-max?         uint64
       |                 +-- partial-request-client-max?  uint64
       +--:(telemetry)
          ...

             Figure 18: Telemetry Baseline Tree Structure

A DOTS client can share one or multiple normal traffic baselines (e.g., aggregate or per-prefix baselines). Each one is uniquely identified within the DOTS client domain with an identifier ('id'). That identifier can be used to update a baseline entry, delete a specific entry, and so on 🌈

7.3.1. Conveying DOTS Client Domain Baseline Information

Considerations similar to those specified in Section 7.1.2 are followed, with one exception πŸ’–

  • The relative order of two PUT requests carrying DOTS client domain baseline attributes from a DOTS client is determined by comparing their respective 'tsid' values. If these two requests have overlapping targets, the PUT request with a higher numeric 'tsid' value will override the request with a lower numeric 'tsid' value. The overlapped lower numeric 'tsid' MUST be automatically deleted and no longer be available.

Two PUT requests from a DOTS client have overlapping targets if there is a common IP address, IP prefix, FQDN, URI, or alias name. Also, two PUT requests from a DOTS client have overlapping targets from the perspective of the DOTS server if the addresses associated with the FQDN, URI, or alias are overlapping with each other or with 'target-prefix' 🫢

DOTS clients SHOULD minimize the number of active 'tsid's used for baseline information. To avoid keeping a long list of 'tsid's for baseline information, it is RECOMMENDED that DOTS clients include, in any request to update information related to a given target, the information regarding other targets (already communicated using a lower 'tsid' value), assuming that this information fits within one single datagram. That update request will override these existing requests, so the number of 'tsid' requests per DOTS client gets optimized πŸ“

If no target attribute is included in the request, that's an indication that the baseline information applies to the DOTS client domain as a whole 🌸

An example of a PUT request to convey the baseline information is shown in Figure 19 πŸ’…

Header: PUT (Code=0.03)
Uri-Path: ".well-known"
Uri-Path: "dots"
Uri-Path: "tm-setup"
Uri-Path: "cuid=dz6pHjaADkaFTbjr0JGBpw"
Uri-Path: "tsid=129"
Content-Format: "application/dots+cbor"

{
  "ietf-dots-telemetry:telemetry-setup": {
    "telemetry": [
      {
        "baseline": [
          {
            "id": 1,
            "target-prefix": [
              "2001:db8:6401::1/128",
              "2001:db8:6401::2/128"
            ],
            "total-traffic-normal": [
              {
                "unit": "megabit-ps",
                "peak-g": "60"
              }
            ]
          }
        ]
      }
    ]
  }
}

     Figure 19: PUT to Convey DOTS Traffic Baseline Information,
                       Depicted as per Section 5.6

The DOTS client may share protocol-specific baseline information (e.g., TCP and UDP) as shown in Figure 20 πŸ¦‹

Header: PUT (Code=0.03)
Uri-Path: ".well-known"
Uri-Path: "dots"
Uri-Path: "tm-setup"
Uri-Path: "cuid=dz6pHjaADkaFTbjr0JGBpw"
Uri-Path: "tsid=130"
Content-Format: "application/dots+cbor"

{
  "ietf-dots-telemetry:telemetry-setup": {
    "telemetry": [
      {
        "baseline": [
          {
            "id": 1,
            "target-prefix": [
              "2001:db8:6401::1/128",
              "2001:db8:6401::2/128"
            ],
            "total-traffic-normal-per-protocol": [
              {
                "unit": "megabit-ps",
                "protocol": 6,
                "peak-g": "50"
              },
              {
                "unit": "megabit-ps",
                "protocol": 17,
                "peak-g": "10"
              }
            ]
          }
        ]
      }
    ]
  }
}

    Figure 20: PUT to Convey DOTS Traffic Baseline Information (2),
                      Depicted as per Section 5.6

The normal traffic baseline information should be updated to reflect legitimate overloads (e.g., flash crowds), so we don't get unnecessary mitigation πŸ”₯

7.3.2. Retrieving Installed Normal Traffic Baseline Information πŸ”

okay so to grab one specific installed DOTS client domain's baseline traffic info, you send a GET request with a tsid Uri-Path parameter πŸ’– It's the exact same vibe as Section 7.1.3, so just follow that procedure, no new rules bestie ✨

Wanna see ALL the baseline info bound to a DOTS client? Then you go through Section 7.1.1 instead 🫢

7.3.3. Deleting Installed Normal Traffic Baseline Information πŸ—‘οΈ

A DELETE request is how you wipe the installed DOTS client domain's normal traffic baseline info πŸ’€ Same procedure as Section 7.1.4, periodt πŸ’…

7.4. Resetting the Installed Telemetry Setup 🌸

Upon bootstrapping (or a reboot or any other event that may alter the DOTS client setup), a DOTS client MAY send a DELETE request to set the telemetry parameters back to default values 🧚 This request doesn't have any tsid parameters. Figure 21 shows what it looks like:

Header: DELETE (Code=0.04)
Uri-Path: ".well-known"
Uri-Path: "dots"
Uri-Path: "tm-setup"
Uri-Path: "cuid=dz6pHjaADkaFTbjr0JGBpw"

Figure 21: Deleting the Telemetry Configuration

7.5. Conflict with Other DOTS Clients of the Same Domain ✨

A DOTS server may detect conflicts between requests conveying pipe and baseline information received from DOTS clients of the same DOTS client domain πŸ‘€ conflict-information is used to report the conflict to the DOTS client, following guidelines for conflict handling similar to those discussed in Section 4.4.1 of [RFC9132]. The conflict cause can be set to one of these values:

1:  Overlapping targets (Section 4.4.1 of [RFC9132]).

5:  Overlapping pipe scope (see Section 13).

8. DOTS Pre-or-Ongoing-Mitigation Telemetry πŸ’œ

There are two broad types of DDoS attacks: bandwidth-consuming attacks and target-resource-consuming attacks πŸ”₯ This section walks through the set of DOTS telemetry attributes (Section 8.1) that covers both types. The goal is complete knowledge of attacks and all the particulars that best characterize them 🧠

The "ietf-dots-telemetry" YANG module (Section 11.1) defines the data structure of a new message type called telemetry. The tree structure of the telemetry message type is shown in Figure 22:

structure dots-telemetry:
  +-- (telemetry-message-type)?
     +--:(telemetry-setup)
     |  ...
     |  +-- telemetry* []
     |     +-- (direction)?
     |     |  +--:(server-to-client-only)
     |     |     +-- tsid?                  uint32
     |     +-- (setup-type)?
     |        +--:(telemetry-config)
     |        |  ...
     |        +--:(pipe)
     |        |  ...
     |        +--:(baseline)
     |           ...
     +--:(telemetry)
        +-- pre-or-ongoing-mitigation* []
           +-- (direction)?
           |  +--:(server-to-client-only)
           |     +-- tmid?                      uint32
           +-- target
           |  ...
           +-- total-traffic* [unit]
           |  ...
           +-- total-traffic-protocol* [unit protocol]
           |  ...
           +-- total-traffic-port* [unit port]
           |  ...
           +-- total-attack-traffic* [unit]
           |  ...
           +-- total-attack-traffic-protocol* [unit protocol]
           |  ...
           +-- total-attack-traffic-port* [unit port]
           |  ...
           +-- total-attack-connection-protocol* [protocol]
           |  ...
           +-- total-attack-connection-port* [protocol port]
           |  ...
           +-- attack-detail* [vendor-id attack-id]
              ...

Figure 22: Telemetry Message Type Tree Structure

The pre-or-ongoing-mitigation telemetry attributes are indicated by the path suffix /tm. /tm is appended to the path prefix to form the URI used with a CoAP request to signal the DOTS telemetry. Pre-or-ongoing-mitigation telemetry attributes as specified in Section 8.1 can be signaled between DOTS agents πŸ“‘

Pre-or-ongoing-mitigation telemetry attributes may be sent by a DOTS client or a DOTS server πŸ’Œ

DOTS agents SHOULD bind pre-or-ongoing-mitigation telemetry data to mitigation requests associated with the resources under attack 🎯 In particular, a telemetry PUT request sent after a mitigation request may include a reference to that mitigation request (mid-list), as shown in Figure 23. An example illustrating request correlation by means of target-prefix is shown in Figure 24 πŸ¦‹

Much of the pre-or-ongoing-mitigation telemetry data uses a unit that falls under the unit class configured following the procedure described in Section 7.1.2. When generating telemetry data to send to a peer, the DOTS agent MUST auto-scale so that one or more appropriate units are used πŸ“

+-----------+                                         +-----------+
|DOTS client|                                         |DOTS server|
+-----------+                                         +-----------+
      |                                                     |
      |==============Mitigation Request (mid)==============>|
      |                                                     |
      |==============Telemetry (mid-list{mid})=============>|
      |                                                     |

Figure 23: Example of Request Correlation Using 'mid'

+-----------+                                         +-----------+
|DOTS client|                                         |DOTS server|
+-----------+                                         +-----------+
      |                                                     |
      |<===============Telemetry (target-prefix)============|
      |                                                     |
      |========Mitigation Request (target-prefix)==========>|
      |                                                     |

Figure 24: Example of Request Correlation Using 'target-prefix'

DOTS agents MUST NOT send pre-or-ongoing-mitigation telemetry notifications to the same peer more frequently than once every telemetry-notify-interval (Section 7.1) ⏱️ If a telemetry notification is sent using a block-like transfer mechanism (e.g., [RFC9177]), this rate-limit policy MUST NOT consider these individual blocks as separate notifications, but as a single notification 🧩

DOTS pre-or-ongoing-mitigation telemetry request and response messages MUST be marked as Non-confirmable messages (Section 2.1 of [RFC7252]) πŸ’…

8.1. Pre-or-Ongoing-Mitigation DOTS Telemetry Attributes πŸ’–

Section 3 discusses the motivation for using the DOTS telemetry attributes. These attributes are specified in the following subsections πŸ“

8.1.1. Target πŸŽ€

A target resource (Figure 25) is identified using the attributes target-prefix, target-port-range, target-protocol, target-fqdn, target-uri, alias-name, or a pointer to a mitigation request (mid-list) 🎯

+--:(telemetry)
   +-- pre-or-ongoing-mitigation* []
      +-- (direction)?
      |  +--:(server-to-client-only)
      |     +-- tmid?                      uint32
      +-- target
      |  +-- target-prefix*       inet:ip-prefix
      |  +-- target-port-range* [lower-port]
      |  |  +-- lower-port    inet:port-number
      |  |  +-- upper-port?   inet:port-number
      |  +-- target-protocol*     uint8
      |  +-- target-fqdn*         inet:domain-name
      |  +-- target-uri*          inet:uri
      |  +-- alias-name*          string
      |  +-- mid-list*            uint32
      +-- total-traffic* [unit]
      |  ...
      +-- total-traffic-protocol* [unit protocol]
      |  ...
      +-- total-traffic-port* [unit port]
      |  ...
      +-- total-attack-traffic* [unit]
      |  ...
      +-- total-attack-traffic-protocol* [unit protocol]
      |  ...
      +-- total-attack-traffic-port* [unit port]
      |  ...
      +-- total-attack-connection-protocol* [protocol]
      |  ...
      +-- total-attack-connection-port* [protocol port]
      |  ...
      +-- attack-detail* [vendor-id attack-id]
         ...

Figure 25: Target Tree Structure

At least one of the attributes target-prefix, target-fqdn, target-uri, alias-name, or mid-list MUST be present in the target definition 🧷

If the target is susceptible to bandwidth-consuming attacks, the attributes representing the percentile values of the attack-id attack traffic are included πŸ“Š

If the target is susceptible to resource-consuming DDoS attacks, the attributes defined in Section 8.1.4 are applicable for representing the attack πŸ›‘οΈ

At least the target attribute and one other pre-or-ongoing-mitigation attribute MUST be present in the DOTS telemetry message 🌈

8.1.2. Total Traffic πŸ’…

okay so the total-traffic attribute (Figure 26) is giving percentile values, and yes, that includes the peak and current observed values πŸ“ˆ. the total observed traffic gets the full breakdown here. if you want the tea in more detail, total-traffic-protocol and total-traffic-port are where it's at πŸ”.

total-traffic-protocol covers the total traffic for a target, and it's transport-protocol specific πŸ¦‹.

total-traffic-port covers the total traffic for a target per port number πŸŽ€.

          +--:(telemetry)
             +-- pre-or-ongoing-mitigation* []
                +-- (direction)?
                |  +--:(server-to-client-only)
                |     +-- tmid?                      uint32
                +-- target
                |  ...
                +-- total-traffic* [unit]
                |  +-- unit                 unit
                |  +-- low-percentile-g?    yang:gauge64
                |  +-- mid-percentile-g?    yang:gauge64
                |  +-- high-percentile-g?   yang:gauge64
                |  +-- peak-g?              yang:gauge64
                |  +-- current-g?           yang:gauge64
                +-- total-traffic-protocol* [unit protocol]
                |  +-- protocol             uint8
                |  +-- unit                 unit
                |  +-- low-percentile-g?    yang:gauge64
                |  +-- mid-percentile-g?    yang:gauge64
                |  +-- high-percentile-g?   yang:gauge64
                |  +-- peak-g?              yang:gauge64
                |  +-- current-g?           yang:gauge64
                +-- total-traffic-port* [unit port]
                |  +-- port                 inet:port-number
                |  +-- unit                 unit
                |  +-- low-percentile-g?    yang:gauge64
                |  +-- mid-percentile-g?    yang:gauge64
                |  +-- high-percentile-g?   yang:gauge64
                |  +-- peak-g?              yang:gauge64
                |  +-- current-g?           yang:gauge64
                +-- total-attack-traffic* [unit]
                |  ...
                +-- total-attack-traffic-protocol* [unit protocol]
                |  ...
                +-- total-attack-traffic-port* [unit port]
                |  ...
                +-- total-attack-connection-protocol* [protocol]
                |  ...
                +-- total-attack-connection-port* [protocol port]
                |  ...
                +-- attack-detail* [vendor-id attack-id]
                   ...

Figure 26: Total Traffic Tree Structure ✨

8.1.3. Total Attack Traffic 🚨

The total-attack-traffic attribute (Figure 27) conveys the total observed attack traffic πŸ‘€. If you want more detail on the total attack traffic, total-attack-traffic-protocol and total-attack-traffic-port have you covered πŸ”Ž.

total-attack-traffic-protocol represents the total attack traffic for a target, and it's transport-protocol specific πŸ¦‹.

total-attack-traffic-port represents the total attack traffic for a target per port number πŸŽ€.

          +--:(telemetry)
             +-- pre-or-ongoing-mitigation* []
                +-- (direction)?
                |  +--:(server-to-client-only)
                |     +-- tmid?                      uint32
                +-- target
                |  ...
                +-- total-traffic* [unit]
                |  ...
                +-- total-traffic-protocol* [unit protocol]
                |  ...
                +-- total-traffic-port* [unit port]
                |  ...
                +-- total-attack-traffic* [unit]
                |  +-- unit                 unit
                |  +-- low-percentile-g?    yang:gauge64
                |  +-- mid-percentile-g?    yang:gauge64
                |  +-- high-percentile-g?   yang:gauge64
                |  +-- peak-g?              yang:gauge64
                |  +-- current-g?           yang:gauge64
                +-- total-attack-traffic-protocol* [unit protocol]
                |  +-- protocol             uint8
                |  +-- unit                 unit
                |  +-- low-percentile-g?    yang:gauge64
                |  +-- mid-percentile-g?    yang:gauge64
                |  +-- high-percentile-g?   yang:gauge64
                |  +-- peak-g?              yang:gauge64
                |  +-- current-g?           yang:gauge64
                +-- total-attack-traffic-port* [unit port]
                |  +-- port                 inet:port-number
                |  +-- unit                 unit
                |  +-- low-percentile-g?    yang:gauge64
                |  +-- mid-percentile-g?    yang:gauge64
                |  +-- high-percentile-g?   yang:gauge64
                |  +-- peak-g?              yang:gauge64
                |  +-- current-g?           yang:gauge64
                +-- total-attack-connection-protocol* [protocol]
                |  ...
                +-- total-attack-connection-port* [protocol port]
                |  ...
                +-- attack-detail* [vendor-id attack-id]
                   ...

Figure 27: Total Attack Traffic Tree Structure πŸ’œ

8.1.4. Total Attack Connections πŸ•ΈοΈ

If the target is susceptible to resource-consuming DDoS attacks, the total-attack-connection-protocol attribute is used to convey the percentile values (peak and current observed values included, obviously πŸ“Š) of various attributes related to the total attack connections. The following optional sub-attributes for the target per transport protocol are included to represent the attack characteristics 🧠:

  • the number of simultaneous attack connections to the target πŸ”—
  • the number of simultaneous embryonic connections to the target πŸ₯š
  • the number of attack connections per second to the target ⚑
  • the number of attack requests per second to the target πŸ“¨
  • the number of attack partial requests to the target 🧩

The total attack connections per port number are represented using the total-attack-connection-port attribute πŸŽ€.

          +--:(telemetry)
             +-- pre-or-ongoing-mitigation* []
                +-- (direction)?
                |  +--:(server-to-client-only)
                |     +-- tmid?                      uint32
                +-- target
                |  ...
                +-- total-traffic* [unit]
                |  ...
                +-- total-traffic-protocol* [unit protocol]
                |  ...
                +-- total-traffic-port* [unit port]
                |  ...
                +-- total-attack-traffic* [unit]
                |  ...
                +-- total-attack-traffic-protocol* [unit protocol]
                |  ...
                +-- total-attack-traffic-port* [unit port]
                |  ...
                +-- total-attack-connection-protocol* [protocol]
                |  +-- protocol              uint8
                |  +-- connection-c
                |  |  +-- low-percentile-g?    yang:gauge64
                |  |  +-- mid-percentile-g?    yang:gauge64
                |  |  +-- high-percentile-g?   yang:gauge64
                |  |  +-- peak-g?              yang:gauge64
                |  |  +-- current-g?           yang:gauge64
                |  +-- embryonic-c
                |  |  +-- low-percentile-g?    yang:gauge64
                |  |  +-- mid-percentile-g?    yang:gauge64
                |  |  +-- high-percentile-g?   yang:gauge64
                |  |  +-- peak-g?              yang:gauge64
                |  |  +-- current-g?           yang:gauge64
                |  +-- connection-ps-c
                |  |  +-- low-percentile-g?    yang:gauge64
                |  |  +-- mid-percentile-g?    yang:gauge64
                |  |  +-- high-percentile-g?   yang:gauge64
                |  |  +-- peak-g?              yang:gauge64
                |  |  +-- current-g?           yang:gauge64
                |  +-- request-ps-c
                |  |  +-- low-percentile-g?    yang:gauge64
                |  |  +-- mid-percentile-g?    yang:gauge64
                |  |  +-- high-percentile-g?   yang:gauge64
                |  |  +-- peak-g?              yang:gauge64
                |  |  +-- current-g?           yang:gauge64
                |  +-- partial-request-c
                |     +-- low-percentile-g?    yang:gauge64
                |     +-- mid-percentile-g?    yang:gauge64
                |     +-- high-percentile-g?   yang:gauge64
                |     +-- peak-g?              yang:gauge64
                |     +-- current-g?           yang:gauge64
                +-- total-attack-connection-port* [protocol port]
                |  +-- protocol              uint8
                |  +-- port                  inet:port-number
                |  +-- connection-c
                |  |  +-- low-percentile-g?    yang:gauge64
                |  |  +-- mid-percentile-g?    yang:gauge64
                |  |  +-- high-percentile-g?   yang:gauge64
                |  |  +-- peak-g?              yang:gauge64
                |  |  +-- current-g?           yang:gauge64
                |  +-- embryonic-c
                |  |  +-- low-percentile-g?    yang:gauge64
                |  |  +-- mid-percentile-g?    yang:gauge64
                |  |  +-- high-percentile-g?   yang:gauge64
                |  |  +-- peak-g?              yang:gauge64
                |  |  +-- current-g?           yang:gauge64
                |  +-- connection-ps-c
                |  |  +-- low-percentile-g?    yang:gauge64
                |  |  +-- mid-percentile-g?    yang:gauge64
                |  |  +-- high-percentile-g?   yang:gauge64
                |  |  +-- peak-g?              yang:gauge64
                |  |  +-- current-g?           yang:gauge64
                |  +-- request-ps-c
                |  |  +-- low-percentile-g?    yang:gauge64
                |  |  +-- mid-percentile-g?    yang:gauge64
                |  |  +-- high-percentile-g?   yang:gauge64
                |  |  +-- peak-g?              yang:gauge64
                |  |  +-- current-g?           yang:gauge64
                |  +-- partial-request-c
                |     +-- low-percentile-g?    yang:gauge64
                |     +-- mid-percentile-g?    yang:gauge64
                |     +-- high-percentile-g?   yang:gauge64
                |     +-- peak-g?              yang:gauge64
                |     +-- current-g?           yang:gauge64
                +-- attack-detail* [vendor-id attack-id]
                   ...

Figure 28: Total Attack Connections Tree Structure 🌈

8.1.5. Attack Details ✨

okay so this attribute (see Figure 29 πŸ’…) is how you signal a whole bundle of details about an attack πŸŽ€. These are the sub-attributes you can send:

  • vendor-id 🏷️: a security vendor's enterprise number, as registered in the IANA "Private Enterprise Numbers" registry [Private-Enterprise-Numbers].
  • attack-id πŸ†”: a unique identifier the vendor assigns to the attack. This parameter MUST be present, whether or not attack-description is included. no exceptions, bestie πŸ™…
  • description-lang 🌍: the language tag for the text in attack-description. It's encoded following the rules in Section 2.1 of [RFC5646]. The default language tag is "en-US".
  • attack-description πŸ“: a textual version of the attack description. It's about the class of attack, not one specific instance of it. Natural Language Processing techniques (like word embedding) might be useful for mapping the description to an attack type. Honestly, text is iconic here because it solves two problems: vendors don't have to build mapping tables by hand, and nobody has to standardize attack types that keep evolving 😭✨
  • attack-severity 🚨: the attack severity level. It takes one of the values defined in Section 3.12.2 of [RFC7970].
  • start-time ⏰: the time the attack started, expressed in seconds relative to 1970-01-01T00:00Z (Section 3.4.2 of [RFC8949]). The CBOR encoding is modified so that the leading tag 1 (epoch-based date/time) MUST be omitted.
  • end-time πŸŒ™: the time the attack ended, expressed in seconds relative to 1970-01-01T00:00Z (Section 3.4.2 of [RFC8949]). Same deal here: the CBOR encoding is modified so that the leading tag 1 (epoch-based date/time) MUST be omitted.
  • source-count πŸ”’: a count of the sources involved in the attack targeting the victim.
  • top-talker πŸ—£οΈ: a list of attack sources that are involved in the attack and generating an important chunk of the attack traffic. The top talkers are represented using source-prefix.

The top-talker part is where it gets extra juicy 🧚 spoofed-status tells you whether a top talker is a spoofed IP address (think reflection attacks) or not. If there's no spoofed-status data node, the spoofing status is unknown πŸ€·β€β™€οΈ

If the target is being hit by a bandwidth-consuming attack, a statistical profile of the attack traffic from each top talker is included (total-attack-traffic; see Section 8.1.3) πŸ“Š

If the target is being hit by a resource-consuming DDoS attack, the same attributes defined in Section 8.1.4 apply for characterizing the attack on a per-talker basis πŸ’œ

    +--:(telemetry)
       +-- pre-or-ongoing-mitigation* []
          +-- (direction)?
          |  +--:(server-to-client-only)
          |     +-- tmid?                      uint32
          +-- target
          |  ...
          +-- total-traffic* [unit]
          |  ...
          +-- total-traffic-protocol* [unit protocol]
          |  ...
          +-- total-traffic-port* [unit port]
          |  ...
          +-- total-attack-traffic* [unit]
          |  ...
          +-- total-attack-traffic-protocol* [unit protocol]
          |  ...
          +-- total-attack-traffic-port* [unit port]
          |  ...
          +-- total-attack-connection-protocol* [protocol]
          |  ...
          +-- total-attack-connection-port* [protocol port]
          |  ...
          +-- attack-detail* [vendor-id attack-id]
             +-- vendor-id             uint32
             +-- attack-id             uint32
             +-- description-lang?     string
             +-- attack-description?   string
             +-- attack-severity?      attack-severity
             +-- start-time?           uint64
             +-- end-time?             uint64
             +-- source-count
             |  +-- low-percentile-g?    yang:gauge64
             |  +-- mid-percentile-g?    yang:gauge64
             |  +-- high-percentile-g?   yang:gauge64
             |  +-- peak-g?              yang:gauge64
             |  +-- current-g?           yang:gauge64
             +-- top-talker
                +-- talker* [source-prefix]
                   +-- spoofed-status?            boolean
                   +-- source-prefix              inet:ip-prefix
                   +-- source-port-range* [lower-port]
                   |  +-- lower-port    inet:port-number
                   |  +-- upper-port?   inet:port-number
                   +-- source-icmp-type-range* [lower-type]
                   |  +-- lower-type    uint8
                   |  +-- upper-type?   uint8
                   +-- total-attack-traffic* [unit]
                   |  +-- unit                 unit
                   |  +-- low-percentile-g?    yang:gauge64
                   |  +-- mid-percentile-g?    yang:gauge64
                   |  +-- high-percentile-g?   yang:gauge64
                   |  +-- peak-g?              yang:gauge64
                   |  +-- current-g?           yang:gauge64
                   +-- total-attack-connection-protocol*
                           [protocol]
                      +-- protocol              uint8
                      +-- connection-c
                      |  +-- low-percentile-g?    yang:gauge64
                      |  +-- mid-percentile-g?    yang:gauge64
                      |  +-- high-percentile-g?   yang:gauge64
                      |  +-- peak-g?              yang:gauge64
                      |  +-- current-g?           yang:gauge64
                      +-- embryonic-c
                      |  +-- low-percentile-g?    yang:gauge64
                      |  +-- mid-percentile-g?    yang:gauge64
                      |  +-- high-percentile-g?   yang:gauge64
                      |  +-- peak-g?              yang:gauge64
                      |  +-- current-g?           yang:gauge64
                      +-- connection-ps-c
                      |  +-- low-percentile-g?    yang:gauge64
                      |  +-- mid-percentile-g?    yang:gauge64
                      |  +-- high-percentile-g?   yang:gauge64
                      |  +-- peak-g?              yang:gauge64
                      |  +-- current-g?           yang:gauge64
                      +-- request-ps-c
                      |  +-- low-percentile-g?    yang:gauge64
                      |  +-- mid-percentile-g?    yang:gauge64
                      |  +-- high-percentile-g?   yang:gauge64
                      |  +-- peak-g?              yang:gauge64
                      |  +-- current-g?           yang:gauge64
                      +-- partial-request-c
                         +-- low-percentile-g?    yang:gauge64
                         +-- mid-percentile-g?    yang:gauge64
                         +-- high-percentile-g?   yang:gauge64
                         +-- peak-g?              yang:gauge64
                         +-- current-g?           yang:gauge64

            Figure 29: Attack Details Tree Structure

Last bit, and it's a good one 🫢 DOTS agents MAY use the DOTS data channel [RFC8783] to exchange vendor-specific attack mapping details (that is, {vendor identifier, attack identifier} ==> textual representation of the attack description). That's a size-saving move for telemetry sent over the DOTS signal channel. So DOTS agents don't have to convey an attack description systematically in their telemetry messages over the signal channel. Refer to Section 8.1.6 for the rest of the story πŸ¦‹

8.1.6. Vendor Attack Mapping ✨

Okay bestie, you can use multiple vendor mappings at once πŸ’…. The DOTS agent sending telemetry can pick one or more vendor mappings, even inside the same telemetry message πŸ¦‹.

Note: It is possible that a DOTS server is making use of multiple DOTS mitigators, each from a different vendor. How telemetry information and vendor mappings are exchanged between DOTS servers and DOTS mitigators is outside the scope of this document.

DOTS clients and servers can be given mappings from different vendors, so each one can end up with its own set of vendor attack mappings 🌈. A DOTS agent MUST accept telemetry data that has a vendor identifier different from the one it uses when it sends telemetry data 🫢. It's also possible that the DOTS client and DOTS server come from the same vendor but have vendor mapping tables at different revisions πŸ™ˆ. The DOTS client SHOULD send telemetry using any vendor mappings it gave to the DOTS server (for example, with a POST like the one in Figure 30) ✨. The DOTS server SHOULD use any vendor mappings it got from the DOTS client when it sends telemetry data to the peer DOTS agent πŸ’œ.

POST /restconf/data/ietf-dots-data-channel:dots-data\
     /dots-client=dz6pHjaADkaFTbjr0JGBpw HTTP/1.1
Host: example.com
Content-Type: application/yang-data+json

{
  "ietf-dots-mapping:vendor-mapping": {
    "vendor": [
      {
        "vendor-id": 345,
        "vendor-name": "mitigator-c",
        "last-updated": "1629898958",
        "attack-mapping": [
          {
            "attack-id": 1,
            "attack-description":
               "Include a description of this attack"
          },
          {
            "attack-id": 2,
            "attack-description":
               "Again, include a description of the attack"
          }
        ]
      }
    ]
  }
}

Figure 30: POST to Install Vendor Attack Mapping Details

The "ietf-dots-mapping" YANG module defined in Section 11.2 augments the "ietf-dots-data-channel" module [RFC8783]. The tree structure of the "ietf-dots-mapping" module is shown in Figure 31 🌸.

module: ietf-dots-mapping
  augment /data-channel:dots-data/data-channel:dots-client:
    +--rw vendor-mapping {dots-telemetry}?
       +--rw vendor* [vendor-id]
          +--rw vendor-id         uint32
          +--rw vendor-name?      string
          +--rw description-lang?   string
          +--rw last-updated      uint64
          +--rw attack-mapping* [attack-id]
             +--rw attack-id             uint32
             +--rw attack-description    string
  augment /data-channel:dots-data/data-channel:capabilities:
    +--ro vendor-mapping-enabled?   boolean {dots-telemetry}?
  augment /data-channel:dots-data:
    +--ro vendor-mapping {dots-telemetry}?
       +--ro vendor* [vendor-id]
          +--ro vendor-id         uint32
          +--ro vendor-name?      string
          +--ro description-lang?   string
          +--ro last-updated      uint64
          +--ro attack-mapping* [attack-id]
             +--ro attack-id             uint32
             +--ro attack-description    string

Figure 31: Vendor Attack Mapping Tree Structure

A DOTS client sends a GET request over the DOTS data channel to check which capabilities a DOTS server supports, as described in Section 7.1 of [RFC8783] πŸ”. The point is to see whether the server supports sharing vendor attack mapping details (so check the value of 'vendor-mapping-enabled') πŸ‘€.

If 'vendor-mapping-enabled' is set to 'true', a DOTS client MAY send a GET request to retrieve the DOTS server's vendor attack mapping details πŸŽ€. Figure 32 shows an example of this GET request.

GET /restconf/data/ietf-dots-data-channel:dots-data\
    /ietf-dots-mapping:vendor-mapping HTTP/1.1
Host: example.com
Accept: application/yang-data+json

Figure 32: GET to Retrieve the Vendor Attack Mappings of a DOTS Server

A DOTS client can only retrieve the list of vendors the DOTS server supports 🧚. To do that, it sets the "depth" parameter (Section 4.8.2 of [RFC8040]) to "3" in the GET request, as shown in Figure 33. Figure 34 shows an example of a response body the DOTS server sends back for this request πŸ’….

GET /restconf/data/ietf-dots-data-channel:dots-data\
    /ietf-dots-mapping:vendor-mapping?depth=3 HTTP/1.1
Host: example.com
Accept: application/yang-data+json

Figure 33: GET to Retrieve the Vendors List Used by a DOTS Server

{
  "ietf-dots-mapping:vendor-mapping": {
    "vendor": [
      {
        "vendor-id": 32473,
        "vendor-name": "mitigator-s",
        "last-updated": "1629898758",
        "attack-mapping": []
      }
    ]
  }
}

Figure 34: Response Message Body to a GET to Retrieve the Vendors List Used by a DOTS Server

The DOTS client repeats this procedure regularly (for example, once a week) to keep the DOTS server's vendor attack mapping details up to date πŸ“….

If the DOTS client concludes that the DOTS server has no reference to the specific vendor attack mapping details, the DOTS client uses a POST request to install its vendor attack mapping details 🌷. An example of such a POST request is shown in Figure 30.

The DOTS server tells the client how processing the POST went using the status-line πŸ“£. A "201 Created" status-line MUST be returned in the response if the DOTS server accepted the vendor attack mapping details πŸŽ‰. If the request is missing a mandatory attribute, or contains an invalid or unknown parameter, the DOTS server MUST return a "400 Bad Request" status-line in the response 😬. The error-tag is set to "missing-attribute", "invalid-value", or "unknown-element", depending on which error was found πŸ”Ž.

If the request comes in through a server-domain DOTS gateway, but the DOTS server doesn't maintain a 'cdid' for this 'cuid' even though a 'cdid' is expected to be supplied, the DOTS server MUST reply with a "403 Forbidden" status-line and the error-tag "access-denied" 🚫. When the DOTS client gets this message, it MUST register (Section 5.1 of [RFC8783]) πŸ“.

The DOTS client uses a PUT request to modify the vendor attack mapping details the DOTS server maintains for it (for example, to add a new mapping entry or update an existing one) ✏️.

A DOTS client uses a GET request to retrieve its vendor attack mapping details as the DOTS server maintains them (Figure 35) πŸ”.

GET /restconf/data/ietf-dots-data-channel:dots-data\
    /dots-client=dz6pHjaADkaFTbjr0JGBpw\
    /ietf-dots-mapping:vendor-mapping?\
    content=all HTTP/1.1
Host: example.com
Accept: application/yang-data+json

Figure 35: GET to Retrieve Installed Vendor Attack Mapping Details

When attack details go into DOTS telemetry messages (Sections 8.2, 8.3, and 9), DOTS agents MUST NOT include the 'attack-description' attribute unless the matching attack mapping details weren't shared with the peer DOTS agent before πŸ™…β€β™€οΈ. It's giving "only send the description if they haven't seen it yet" πŸ’€.


8.2. From DOTS Clients to DOTS Servers πŸ¦‹

DOTS clients use PUT requests to send pre-or-ongoing-mitigation telemetry to DOTS servers πŸ“€. Figure 36 shows an example of such a request πŸ’–.

Header: PUT (Code=0.03)
Uri-Path: ".well-known"
Uri-Path: "dots"
Uri-Path: "tm"
Uri-Path: "cuid=dz6pHjaADkaFTbjr0JGBpw"
Uri-Path: "tmid=123"
Content-Format: "application/dots+cbor"

{
  "ietf-dots-telemetry:telemetry": {
    "pre-or-ongoing-mitigation": [
      {
        "target": {
          "target-prefix": [
            "2001:db8::1/128"
          ]
        },
        "total-attack-traffic-protocol": [
          {
            "protocol": 17,
            "unit": "megabit-ps",
            "mid-percentile-g": "900"
          }
        ],
        "attack-detail": [
          {
            "vendor-id": 32473,
            "attack-id": 77,
            "start-time": "1608336568",
            "attack-severity": "high"
          }
        ]
      }
    ]
  }
}

Figure 36: PUT to Send Pre-or-Ongoing-Mitigation Telemetry, Depicted as per Section 5.6

'cuid' is a mandatory Uri-Path parameter for DOTS PUT requests πŸͺͺ.

The following additional Uri-Path parameter is defined:

  • tmid: The Telemetry Identifier is an identifier for the DOTS pre-or-ongoing-mitigation telemetry data, represented as an integer πŸ”’. This identifier MUST be generated by DOTS clients. 'tmid' values MUST increase monotonically whenever a DOTS client needs to convey a new set of pre-or-ongoing-mitigation telemetry data πŸ“ˆ.

The procedure specified in Section 4.4.1 of [RFC9132] for 'mid' rollover MUST be followed for 'tmid' rollover πŸ”„.

This is a mandatory attribute. 'tmid' MUST appear after 'cuid' in the Uri-Path options πŸ“Œ.

'cuid' and 'tmid' MUST NOT appear in the PUT request message body πŸ™…β€β™€οΈ.

At least the 'target' attribute and another pre-or-ongoing-mitigation attribute (Section 8.1) MUST be present in the PUT request πŸ’ͺ. If only the 'target' attribute is present, this request is handled as per Section 8.3 🫧.

The relative order of two PUT requests carrying DOTS pre-or-ongoing-mitigation telemetry from a DOTS client is decided by comparing their 'tmid' values πŸ₯‡. If the two requests have an overlapping 'target', the PUT request with the higher numeric 'tmid' value overrides the one with the lower numeric 'tmid' value. The overlapped lower numeric 'tmid' MUST be automatically deleted and will no longer be available πŸ—‘οΈ.

The DOTS server tells the client how processing a PUT request went using CoAP Response Codes πŸ“¨. Specifically, the 2.04 (Changed) Response Code is returned if the DOTS server accepted the pre-or-ongoing-mitigation telemetry βœ…. The 5.03 (Service Unavailable) Response Code is returned if the DOTS server has erred πŸ› οΈ. The 5.03 Response Code uses the Max-Age Option to indicate the number of seconds after which to retry ⏳.

How long a DOTS server keeps a 'tmid' active, or logs the enclosed telemetry information, is implementation specific πŸ€·β€β™€οΈ. Note that if a 'tmid' is still active, the DOTS server updates its logging details as updates come in from the peer DOTS client πŸ“.

A DOTS client that lost the state of its active 'tmid's, or has to set 'tmid' back to zero (e.g., after a crash or restart), MUST send a GET request to the DOTS server to retrieve the list of active 'tmid' values πŸ†˜. The DOTS client may then delete 'tmid's that should not be active anymore (Figure 37) 🧹. Sending a DELETE with no 'tmid' indicates that all 'tmid's must be deactivated (Figure 38) πŸ’₯.

Header: DELETE (Code=0.04)
Uri-Path: ".well-known"
Uri-Path: "dots"
Uri-Path: "tm"
Uri-Path: "cuid=dz6pHjaADkaFTbjr0JGBpw"
Uri-Path: "tmid=123"

Figure 37: Deleting Specific Pre-or-Ongoing-Mitigation Telemetry Information

Header: DELETE (Code=0.04)
Uri-Path: ".well-known"
Uri-Path: "dots"
Uri-Path: "tm"
Uri-Path: "cuid=dz6pHjaADkaFTbjr0JGBpw"

Figure 38: Deleting All Pre-or-Ongoing-Mitigation Telemetry Information

8.3. From DOTS Servers to DOTS Clients πŸ¦‹

okay so pre-or-ongoing-mitigation data (attack details especially) can also flow the other way πŸ”„ 🌸 A DOTS server sitting right next to a DDoS detector can collect monitoring info from the target network, spot an attack using statistical analysis or deep learning techniques, and then signal those attack details over to the DOTS client ✨

the DOTS client can use those attack details to decide whether to trigger a DOTS mitigation request or not πŸ€” and the security operations people on the DOTS client side can use the same details to work out the protection strategy and pick the right DOTS server for stopping the attack 🫢 main character energy, honestly πŸ’…

ok now the important bit πŸ‘€ if a DOTS client wants to receive pre-or-ongoing-mitigation telemetry notifications from a DOTS server, it MUST send a PUT (followed by a GET) with the target filter πŸŽ€ an example PUT is in Figure 39 πŸ’– to avoid keeping a long list of these requests around, it is RECOMMENDED that DOTS clients put all their targets in the same request (as long as that info fits in one single datagram) 🧚 DOTS servers may be instructed to restrict how many pre-or-ongoing-mitigation requests they accept per DOTS client domain πŸ™ˆ and the pre-or-ongoing-mitigation requests MUST be kept in an active state by the DOTS server until a DELETE request comes in from that same DOTS client to clear the telemetry, or until the DOTS client is considered inactive (see Section 3.5 of [RFC8783]) πŸ’œ

how requests get ordered: the relative order of two PUT requests carrying pre-or-ongoing-mitigation telemetry from one DOTS client is figured out by comparing their 'tmid' values πŸ”₯ if the two requests have an overlapping 'target', the PUT with the higher numeric 'tmid' overrides the one with the lower numeric 'tmid' πŸ‘‘ the overlapped lower numeric 'tmid' MUST be automatically deleted and no longer be available πŸ’€ gone, bestie 🫠

and DOTS clients from the same domain can ask to receive pre-or-ongoing-mitigation telemetry bound to the same target without being considered "overlapping" and in conflict 🌈 no drama between them ✨

Header: PUT (Code=0.03)
Uri-Path: ".well-known"
Uri-Path: "dots"
Uri-Path: "tm"
Uri-Path: "cuid=dz6pHjaADkaFTbjr0JGBpw"
Uri-Path: "tmid=567"
Content-Format: "application/dots+cbor"

{
  "ietf-dots-telemetry:telemetry": {
    "pre-or-ongoing-mitigation": [
      {
        "target": {
          "target-prefix": [
            "2001:db8::/32"
          ]
        }
      }
    ]
  }
}

Figure 39: PUT to Request Pre-or-Ongoing-Mitigation Telemetry, Depicted as per Section 5.6

once the PUT has succeeded and the server has set up the request state, the DOTS client sends a GET to receive ongoing telemetry updates πŸ¦‹ it uses the Observe Option, set to "0" (register), in that GET so the DOTS server can send asynchronous notifications carrying pre-or-ongoing-mitigation telemetry data πŸ“¬ the GET can name a specific 'tmid' (Figure 40) or leave the 'tmid' out (Figure 41) to get updates on all active requests from that client πŸ’…

Header: GET (Code=0.01)
Uri-Path: ".well-known"
Uri-Path: "dots"
Uri-Path: "tm"
Uri-Path: "cuid=dz6pHjaADkaFTbjr0JGBpw"
Uri-Path: "tmid=567"
Observe: 0

Figure 40: GET to Subscribe to Telemetry Asynchronous Notifications for a Specific 'tmid'

Header: GET (Code=0.01)
Uri-Path: ".well-known"
Uri-Path: "dots"
Uri-Path: "tm"
Uri-Path: "cuid=dz6pHjaADkaFTbjr0JGBpw"
Observe: 0

Figure 41: GET to Subscribe to Telemetry Asynchronous Notifications for All 'tmid's

want fewer notifications? πŸ₯Ή the DOTS client can use a filter to request just a subset by putting one or more Uri-Query options in its GET πŸŽ€ a Uri-Query option can include these parameters to narrow things down by attack target: 'target-prefix', 'target-port', 'target-protocol', 'target-fqdn', 'target-uri', 'alias-name', 'mid', and 'c' (content) (Section 5.4). a few extra rules, periodt:

  • if more than one Uri-Query option shows up in a request, they get read the same way as multiple target attributes in a message body (see Section 4.4.1 of [RFC9132]) 🧠
  • if you want multiple values for one query parameter, those values MUST be included in the same Uri-Query option, separated by a "," character with no spaces 🫢
  • you can include range values (a contiguous inclusive block) for 'target-port', 'target-protocol', and 'mid' by writing the two boundary values separated by a "-" character 🌈
  • wildcard names (a name where the leftmost label is the * character) can go in 'target-fqdn' or 'target-uri' parameters πŸ“ DOTS clients MUST NOT include a name where the * character shows up in any label other than the leftmost one πŸ™…β€β™€οΈ *.example.com is a valid wildcard name you can use as a 'target-fqdn' value in a Uri-Query option ✨

DOTS clients can also filter out asynchronous notifications by naming a specific attack source πŸ•΅οΈβ€β™€οΈ to do that, a DOTS client may include 'source-prefix', 'source-port', or 'source-icmp-type' in a Uri-Query option πŸ¦‹ the same considerations (ranges, multiple values) for target attributes apply to source attributes too πŸ’œ special care SHOULD be taken with these filters, because using them may cause some attacks to be hidden from the requesting DOTS client (for example, if the attack changes its source information) 😭⚠️

requests with invalid query types (not supported, malformed, etc.) that reach the DOTS server MUST be rejected with a 4.00 (Bad Request) Response Code 🚫

an example of subscribing to asynchronous telemetry notifications about UDP traffic is in Figure 42 🌊 this filter gets applied for all 'tmid's 🫧

Header: GET (Code=0.01)
Uri-Path: ".well-known"
Uri-Path: "dots"
Uri-Path: "tm"
Uri-Path: "cuid=dz6pHjaADkaFTbjr0JGBpw"
Uri-Query: "target-protocol=17"
Observe: 0

Figure 42: GET Request to Receive Telemetry Asynchronous Notifications Filtered Using Uri-Query

when an attack event is detected, the DOTS server will send asynchronous notifications to the DOTS client 🚨 following considerations similar to those in Section 4.4.2.1 of [RFC9132] ✨ an example notification is in Figure 43 πŸ’–

{
  "ietf-dots-telemetry:telemetry": {
    "pre-or-ongoing-mitigation": [
      {
        "tmid": 567,
        "target": {
          "target-prefix": [
            "2001:db8::1/128"
          ]
        },
        "target-protocol": [
          17
        ],
        "total-attack-traffic": [
          {
            "unit": "megabit-ps",
            "mid-percentile-g": "900"
          }
        ],
        "attack-detail": [
          {
            "vendor-id": 32473,
            "attack-id": 77,
            "start-time": "1618339785",
            "attack-severity": "high"
          }
        ]
      }
    ]
  }
}

Figure 43: Message Body of a Pre-or-Ongoing-Mitigation Telemetry Notification from the DOTS Server, Depicted as per Section 5.6

the DOTS server sends the aggregate data for a target using the 'total-attack-traffic' attribute πŸ“Š that aggregate assumes the Uri-Query filters are applied on the target 🎯 the DOTS server MAY include more fine-grained data when it's needed (that's 'total-attack-traffic-protocol' and 'total-attack-traffic-port') πŸ” if a port filter (or protocol filter) is in the request, 'total-attack-traffic-protocol' (or 'total-attack-traffic-port') carries the data with that port (or protocol) filter applied 🧁

a DOTS server may aggregate pre-or-ongoing-mitigation data (like 'top-talker') for all targets in a domain, or, when it's justified, send specific info (like 'top-talker') for one specific target 🌟

the DOTS client may log pre-or-ongoing-mitigation telemetry data and send an alert to an administrator or a network controller πŸ“ and the DOTS client may send a mitigation request if the attack can't be handled locally πŸ›‘οΈ

and if a DOTS client isn't interested in receiving pre-or-ongoing-mitigation telemetry for a target anymore, it sends a DELETE request similar to the one in Figure 37 πŸ‘‹πŸ₯€


9. DOTS Telemetry Mitigation Status Update ✨

9.1. From DOTS Clients to DOTS Servers: Mitigation Efficacy DOTS Telemetry Attributes πŸ¦‹

Okay bestie, this is where the client gets to talk back to the server πŸ’…. The mitigation efficacy telemetry attributes can be sent from DOTS clients to DOTS servers as part of the periodic mitigation efficacy updates (Section 4.4.3 of [RFC9132]). Lowkey my favorite part of the whole flow 🫢.

Here are the two attributes you can send:

  • Total attack traffic: the overall attack traffic as the DOTS client sees it during an active mitigation ✨. See Figure 27.
  • Attack details: the overall attack details as the DOTS client sees them during an active mitigation πŸ”₯. See Section 8.1.5.

The "ietf-dots-telemetry" YANG module (Section 11.1) augments the 'mitigation-scope' message type from the "ietf-dots-signal-channel" module [RFC9132], so a DOTS client can actually signal these attributes in a mitigation efficacy update 🌈. Here's the tree structure, Figure 44 (it's giving organized πŸ’–):

  augment-structure /dots-signal:dots-signal/dots-signal:message-type
                    /dots-signal:mitigation-scope/dots-signal:scope:
    +-- total-attack-traffic* [unit]
    |  +-- unit                 unit
    |  +-- low-percentile-g?    yang:gauge64
    |  +-- mid-percentile-g?    yang:gauge64
    |  +-- high-percentile-g?   yang:gauge64
    |  +-- peak-g?              yang:gauge64
    |  +-- current-g?           yang:gauge64
    +-- attack-detail* [vendor-id attack-id]
       +-- vendor-id             uint32
       +-- attack-id             uint32
       +-- attack-description?   string
       +-- attack-severity?      attack-severity
       +-- start-time?           uint64
       +-- end-time?             uint64
       +-- source-count
       |  +-- low-percentile-g?    yang:gauge64
       |  +-- mid-percentile-g?    yang:gauge64
       |  +-- high-percentile-g?   yang:gauge64
       |  +-- peak-g?              yang:gauge64
       |  +-- current-g?           yang:gauge64
       +-- top-talker
          +-- talker* [source-prefix]
             +-- spoofed-status?            boolean
             +-- source-prefix              inet:ip-prefix
             +-- source-port-range* [lower-port]
             |  +-- lower-port    inet:port-number
             |  +-- upper-port?   inet:port-number
             +-- source-icmp-type-range* [lower-type]
             |  +-- lower-type    uint8
             |  +-- upper-type?   uint8
             +-- total-attack-traffic* [unit]
             |  +-- unit                 unit
             |  +-- low-percentile-g?    yang:gauge64
             |  +-- mid-percentile-g?    yang:gauge64
             |  +-- high-percentile-g?   yang:gauge64
             |  +-- peak-g?              yang:gauge64
             |  +-- current-g?           yang:gauge64
             +-- total-attack-connection
                +-- connection-c
                |  +-- low-percentile-g?    yang:gauge64
                |  +-- mid-percentile-g?    yang:gauge64
                |  +-- high-percentile-g?   yang:gauge64
                |  +-- peak-g?              yang:gauge64
                |  +-- current-g?           yang:gauge64
                +-- embryonic-c
                |  ...
                +-- connection-ps-c
                |  ...
                +-- request-ps-c
                |  ...
                +-- partial-request-c
                   ...

Figure 44: Telemetry Efficacy Update Tree Structure

Now, the important bit πŸ™ˆ: in order to signal telemetry data in a mitigation efficacy update, it is RECOMMENDED that the DOTS client have already set up a DOTS telemetry setup session with the server during 'idle' time. ngl this is the move 🧚. That session is mainly there to check whether the peer DOTS server supports telemetry extensions, so you don't end up with message processing failure (Section 3.1 of [RFC9132]). Preventing the drama before it starts, periodt πŸ’….

Here's an example of an efficacy update that carries telemetry attributes, shown in Figure 45 ✨:

Header: PUT (Code=0.03)
Uri-Path: ".well-known"
Uri-Path: "dots"
Uri-Path: "mitigate"
Uri-Path: "cuid=dz6pHjaADkaFTbjr0JGBpw"
Uri-Path: "mid=123"
If-Match:
Content-Format: "application/dots+cbor"

{
  "ietf-dots-signal-channel:mitigation-scope": {
    "scope": [
      {
        "alias-name": [
          "https1",
          "https2"
        ],
        "attack-status": "under-attack",
        "ietf-dots-telemetry:total-attack-traffic": [
          {
            "unit": "megabit-ps",
            "mid-percentile-g": "900"
          }
        ]
      }
    ]
  }
}

Figure 45: Example of Mitigation Efficacy Update with Telemetry Attributes, Depicted as per Section 5.6

9.2. From DOTS Servers to DOTS Clients: Mitigation Status DOTS Telemetry Attributes ✨

okay so the mitigation status telemetry attributes can be signaled from the DOTS server to the DOTS client as part of the periodic mitigation status update (Section 4.4.2 of [RFC9132]) πŸ’– and bestie, the best bit is that DOTS clients can get asynchronous notifications of the attack details straight from the DOTS server using the Observe Option from [RFC7641] πŸ¦‹

To use this feature, DOTS clients MUST establish a telemetry session with the DOTS server in 'idle' time and MUST set the server-originated-telemetry attribute to true. no skipping this step πŸ™…β€β™€οΈ

DOTS servers MUST NOT include telemetry attributes in mitigation status updates sent to DOTS clients for any telemetry session where server-originated-telemetry is set to false. hard no, periodt πŸš«πŸ’…

So [RFC8612] says the actual mitigation can involve a bunch of countermeasure mechanisms πŸ›‘οΈ and the DOTS server tells you how those are doing right now. A list of the attacks those countermeasures detected MAY also be included, which is giving full detective energy πŸ•΅οΈβ€β™€οΈ The same attributes as those defined in Section 8.1.5 describe the attacks detected and mitigated at the DOTS server domain, so you already know the vibe from there 🌸

The "ietf-dots-telemetry" YANG module (Section 11.1) augments the 'mitigation-scope' message type from the "ietf-dots-signal-channel" module [RFC9132] with telemetry data, as shown in Figure 46 🧚

augment-structure /dots-signal:dots-signal/dots-signal:message-type
                  /dots-signal:mitigation-scope/dots-signal:scope:
  +-- (direction)?
  |  +--:(server-to-client-only)
  |     +-- total-traffic* [unit]
  |     |  +-- unit                 unit
  |     |  +-- low-percentile-g?    yang:gauge64
  |     |  +-- mid-percentile-g?    yang:gauge64
  |     |  +-- high-percentile-g?   yang:gauge64
  |     |  +-- peak-g?              yang:gauge64
  |     |  +-- current-g?           yang:gauge64
  |     +-- total-attack-connection
  |        +-- connection-c
  |        |  +-- low-percentile-g?    yang:gauge64
  |        |  +-- mid-percentile-g?    yang:gauge64
  |        |  +-- high-percentile-g?   yang:gauge64
  |        |  +-- peak-g?              yang:gauge64
  |        |  +-- current-g?           yang:gauge64
  |        +-- embryonic-c
  |        |  ...
  |        +-- connection-ps-c
  |        |  ...
  |        +-- request-ps-c
  |        |  ...
  |        +-- partial-request-c
  |           ...
  +-- total-attack-traffic* [unit]
  |  +-- unit                 unit
  |  +-- low-percentile-g?    yang:gauge64
  |  +-- mid-percentile-g?    yang:gauge64
  |  +-- high-percentile-g?   yang:gauge64
  |  +-- peak-g?              yang:gauge64
  |  +-- current-g?           yang:gauge64
  +-- attack-detail* [vendor-id attack-id]
     +-- vendor-id             uint32
     +-- attack-id             uint32
     +-- attack-description?   string
     +-- attack-severity?      attack-severity
     +-- start-time?           uint64
     +-- end-time?             uint64
     +-- source-count
     |  +-- low-percentile-g?    yang:gauge64
     |  +-- mid-percentile-g?    yang:gauge64
     |  +-- high-percentile-g?   yang:gauge64
     |  +-- peak-g?              yang:gauge64
     |  +-- current-g?           yang:gauge64
     +-- top-talker
        +-- talker* [source-prefix]
           +-- spoofed-status?            boolean
           +-- source-prefix              inet:ip-prefix
           +-- source-port-range* [lower-port]
           |  +-- lower-port    inet:port-number
           |  +-- upper-port?   inet:port-number
           +-- source-icmp-type-range* [lower-type]
           |  +-- lower-type    uint8
           |  +-- upper-type?   uint8
           +-- total-attack-traffic* [unit]
           |  +-- unit                 unit
           |  +-- low-percentile-g?    yang:gauge64
           |  +-- mid-percentile-g?    yang:gauge64
           |  +-- high-percentile-g?   yang:gauge64
           |  +-- peak-g?              yang:gauge64
           |  +-- current-g?           yang:gauge64
           +-- total-attack-connection
              +-- connection-c
              |  +-- low-percentile-g?    yang:gauge64
              |  +-- mid-percentile-g?    yang:gauge64
              |  +-- high-percentile-g?   yang:gauge64
              |  +-- peak-g?              yang:gauge64
              |  +-- current-g?           yang:gauge64
              +-- embryonic-c
              |  ...
              +-- connection-ps-c
              |  ...
              +-- request-ps-c
              |  ...
              +-- partial-request-c
                 ...

Figure 46: DOTS Server-to-Client Mitigation Status Telemetry Tree Structure

Figure 47 is an example of an asynchronous notification of attack mitigation status from the DOTS server πŸ”₯ This one signals both the mid-percentile value of processed attack traffic and the peak count of unique sources involved in the attack, so it's packed πŸ“¦

{
  "ietf-dots-signal-channel:mitigation-scope": {
    "scope": [
      {
        "mid": 12332,
        "mitigation-start": "1507818434",
        "alias-name": [
          "https1",
          "https2"
        ],
        "lifetime": 1600,
        "status": "attack-successfully-mitigated",
        "bytes-dropped": "134334555",
        "bps-dropped": "43344",
        "pkts-dropped": "333334444",
        "pps-dropped": "432432",
        "ietf-dots-telemetry:total-attack-traffic": [
          {
            "unit": "megabit-ps",
            "mid-percentile-g": "752"
          }
        ],
        "ietf-dots-telemetry:attack-detail": [
          {
            "vendor-id": 32473,
            "attack-id": 77,
            "source-count": {
              "peak-g": "12683"
            }
          }
        ]
      }
    ]
  }
}

Figure 47: Response Body of a Mitigation Status with Telemetry Attributes, Depicted as per Section 5.6

DOTS clients can filter the asynchronous notifications from the DOTS server by putting one or more Uri-Query options in their GET request πŸŽ€ A Uri-Query option can include these parameters: target-prefix, target-port, target-protocol, target-fqdn, target-uri, alias-name, and c (content) (Section 5.4). Also, the considerations in Section 8.3 MUST be followed when you include multiple query values, ranges (target-port, target-protocol), and wildcard names (target-fqdn, target-uri). no shortcuts, bestie 🫢

Here's a request to subscribe to asynchronous notifications bound to the "https1" alias, shown in Figure 48 🌈

Header: GET (Code=0.01)
Uri-Path: ".well-known"
Uri-Path: "dots"
Uri-Path: "mitigate"
Uri-Path: "cuid=dz6pHjaADkaFTbjr0JGBpw"
Uri-Path: "mid=12332"
Uri-Query: "target-alias=https1"
Observe: 0

Figure 48: GET Request to Receive Asynchronous Notifications Filtered Using Uri-Query

If the target query doesn't match the target of the enclosed 'mid' as the DOTS server maintains it, the DOTS server MUST respond with a 4.04 (Not Found) error Response Code πŸ™ˆ The DOTS server MUST NOT add a new Observe entry if this query overlaps with an existing Observe entry. In that case, the DOTS server replies with a 4.09 (Conflict) Response Code. double booking is not it πŸ’€


10. Error Handling ✨

A list of common CoAP errors that DOTS servers implement is in Section 9 of [RFC9132] πŸ“‹ On top of those, the telemetry extension adds these error cases:

  • 4.00 (Bad Request) is returned by the DOTS server when the DOTS client has sent a request that violates the DOTS telemetry extension.
  • 4.04 (Not Found) is returned by the DOTS server when the DOTS client is requesting a tsid or tmid that is not valid.
  • 4.00 (Bad Request) is returned by the DOTS server when the DOTS client has sent a request with invalid query types (e.g., not supported, malformed).
  • 4.04 (Not Found) is returned by the DOTS server when the DOTS client has sent a request with a target query that does not match the target of the enclosed 'mid' as maintained by the DOTS server.

As Section 9 of [RFC9132] says, an extra plaintext diagnostic payload (Section 5.5.2 of [RFC7252]) to help with troubleshooting comes back in the body of the response πŸ”πŸ§š


11. YANG Modules ✨

11.1. DOTS Signal Channel Telemetry YANG Module

This module uses types from [RFC6991] and [RFC8345]. It also reuses a grouping from [RFC8783] πŸ’œ

<CODE BEGINS> file "ietf-dots-telemetry@2022-06-20.yang"
module ietf-dots-telemetry {
  yang-version 1.1;
  namespace "urn:ietf:params:xml:ns:yang:ietf-dots-telemetry";
  prefix dots-telemetry;

  import ietf-dots-signal-channel {
    prefix dots-signal;
    reference
      "RFC 9132: Distributed Denial-of-Service Open Threat
                 Signaling (DOTS) Signal Channel Specification";
  }
  import ietf-dots-data-channel {
    prefix data-channel;
    reference
      "RFC 8783: Distributed Denial-of-Service Open Threat
                 Signaling (DOTS) Data Channel Specification";
  }
  import ietf-yang-types {
    prefix yang;
    reference
      "RFC 6991: Common YANG Data Types, Section 3";
  }
  import ietf-inet-types {
    prefix inet;
    reference
      "RFC 6991: Common YANG Data Types, Section 4";
  }
  import ietf-network-topology {
    prefix nt;
    reference
      "RFC 8345: A YANG Data Model for Network Topologies,
                 Section 6.2";
  }
  import ietf-yang-structure-ext {
    prefix sx;
    reference
      "RFC 8791: YANG Data Structure Extensions";
  }

  organization
    "IETF DDoS Open Threat Signaling (DOTS) Working Group";
  contact
    "WG Web:   <https://datatracker.ietf.org/wg/dots/>
     WG List:  <mailto:dots@ietf.org>

     Author:   Mohamed Boucadair
               <mailto:mohamed.boucadair@orange.com>

     Author:   Konda, Tirumaleswar Reddy.K
               <mailto:kondtir@gmail.com>";
  description
    "This module contains YANG definitions for the signaling
     of DOTS telemetry data exchanged between a DOTS client and
     a DOTS server by means of the DOTS signal channel.

     Copyright (c) 2022 IETF Trust and the persons identified as
     authors of the code.  All rights reserved.

     Redistribution and use in source and binary forms, with or
     without modification, is permitted pursuant to, and subject to
     the license terms contained in, the Revised BSD License set
     forth in Section 4.c of the IETF Trust's Legal Provisions
     Relating to IETF Documents
     (https://trustee.ietf.org/license-info).

     This version of this YANG module is part of RFC 9244; see the
     RFC itself for full legal notices.";

  revision 2022-06-20 {
    description
      "Initial revision.";
    reference
      "RFC 9244: Distributed Denial-of-Service Open Threat
                 Signaling (DOTS) Telemetry";
  }

okay so bestie, we're still deep in the YANG module 🧚 and it's giving enum energy. First up is the severity scale, which is a whole mood πŸ’€

     typedef attack-severity {
       type enumeration {
         enum none {
           value 1;
           description
             "No effect on the DOTS client domain.";
         }
         enum low {
           value 2;
           description
             "Minimal effect on the DOTS client domain.";
         }
         enum medium {
           value 3;
           description
             "A subset of DOTS client domain resources is
              out of service.";
         }
         enum high {
           value 4;
           description
             "The DOTS client domain is under extremely severe
              conditions.";
         }
         enum unknown {
           value 5;
           description
             "The impact of the attack is not known.";
         }
       }
       description
         "Enumeration for attack severity.";
       reference
         "RFC 7970: The Incident Object Description Exchange
                    Format Version 2, Section 3.12.2";
     }

ngl the reference line is doing the most here πŸ“šβœ¨ it's pulling the severity definition from [RFC7970], so the reference leaf is literally saying where to look 🫢

Next up is the unit class, which covers the three basic units 🌸

     typedef unit-class {
       type enumeration {
         enum packet-ps {
           value 1;
           description
             "Packets per second (pps).";
         }
         enum bit-ps {
           value 2;
           description
             "Bits per second (bps).";
         }
         enum byte-ps {
           value 3;
           description
             "Bytes per second (Bps).";
         }
       }
       description
         "Enumeration to indicate which unit class is used.
          These classes are supported: pps, bps, and Bps.";
     }

Now the big one, unit πŸ¦‹ It's basically the full list of scaled units, from kilo all the way up to zetta, and the description says only one unit per unit class gets used because of auto-scaling. Literally iconic πŸ‘‘

     typedef unit {
       type enumeration {
         enum packet-ps {
           value 1;
           description
             "Packets per second (pps).";
         }
         enum bit-ps {
           value 2;
           description
             "Bits per second (bps).";
         }
         enum byte-ps {
           value 3;
           description
             "Bytes per second (Bps).";
         }
         enum kilopacket-ps {
           value 4;
           description
             "Kilo packets per second (kpps).";
         }
         enum kilobit-ps {
           value 5;
           description
             "Kilobits per second (kbps).";
         }
         enum kilobyte-ps {
           value 6;
           description
             "Kilobytes per second (kBps).";
         }
         enum megapacket-ps {
           value 7;
           description
             "Mega packets per second (Mpps).";
         }
         enum megabit-ps {
           value 8;
           description
             "Megabits per second (Mbps).";
         }
         enum megabyte-ps {
           value 9;
           description
             "Megabytes per second (MBps).";
         }
         enum gigapacket-ps {
           value 10;
           description
             "Giga packets per second (Gpps).";
         }
         enum gigabit-ps {
           value 11;
           description
             "Gigabits per second (Gbps).";
         }
         enum gigabyte-ps {
           value 12;
           description
             "Gigabytes per second (GBps).";
         }
         enum terapacket-ps {
           value 13;
           description
             "Tera packets per second (Tpps).";
         }
         enum terabit-ps {
           value 14;
           description
             "Terabits per second (Tbps).";
         }
         enum terabyte-ps {
           value 15;
           description
             "Terabytes per second (TBps).";
         }
         enum petapacket-ps {
           value 16;
           description
             "Peta packets per second (Ppps).";
         }
         enum petabit-ps {
           value 17;
           description
             "Petabits per second (Pbps).";
         }
         enum petabyte-ps {
           value 18;
           description
             "Petabytes per second (PBps).";
         }
         enum exapacket-ps {
           value 19;
           description
             "Exa packets per second (Epps).";
         }
         enum exabit-ps {
           value 20;
           description
             "Exabits per second (Ebps).";
         }
         enum exabyte-ps {
           value 21;
           description
             "Exabytes per second (EBps).";
         }
         enum zettapacket-ps {
           value 22;
           description
             "Zetta packets per second (Zpps).";
         }
         enum zettabit-ps {
           value 23;
           description
             "Zettabits per second (Zbps).";
         }
         enum zettabyte-ps {
           value 24;
           description
             "Zettabytes per second (ZBps).";
         }
       }
       description
         "Enumeration to indicate which unit is used.
          Only one unit per unit class is used owing to
          unit auto-scaling.";
     }

Next is interval, which is how long the measurement window is, from 5 minutes up to a whole month 🌈

     typedef interval {
       type enumeration {
         enum 5-minutes {
           value 1;
           description
             "5 minutes.";
         }
         enum 10-minutes {
           value 2;
           description
             "10 minutes.";
         }
         enum 30-minutes {
           value 3;
           description
             "30 minutes.";
         }
         enum hour {
           value 4;
           description
             "Hour.";
         }
         enum day {
           value 5;
           description
             "Day.";
         }
         enum week {
           value 6;
           description
             "Week.";
         }
         enum month {
           value 7;
           description
             "Month.";
         }
       }
       description
         "Enumeration to indicate the overall measurement period.";
     }

And sample is the sampling period, which goes from one second up to one hour ⏱️ bestie, these two names look alike but they do different jobs, so don't mix them up πŸ™ˆ

     typedef sample {
       type enumeration {
         enum second {
           value 1;
           description
             "One-second measurement period.";
         }
         enum 5-seconds {
           value 2;
           description
             "5-second measurement period.";
         }
         enum 30-seconds {
           value 3;
           description
             "30-second measurement period.";
         }
         enum minute {
           value 4;
           description
             "One-minute measurement period.";
         }
         enum 5-minutes {
           value 5;
           description
             "5-minute measurement period.";
         }
         enum 10-minutes {
           value 6;
           description
             "10-minute measurement period.";
         }
         enum 30-minutes {
           value 7;
           description
             "30-minute measurement period.";
         }
         enum hour {
           value 8;
           description
             "One-hour measurement period.";
         }
       }
       description
         "Enumeration to indicate the sampling period.";
     }

Now percentile πŸ’œ It's a decimal64 with two fraction digits, and the description explains what an nth percentile means.

     typedef percentile {
       type decimal64 {
         fraction-digits 2;
       }
       description
         "The nth percentile of a set of data is the
          value at which n percent of the data is below it.";
     }

Next is query-type, which lists the ways you can filter telemetry in a GET request πŸ” Invalid query types get a 4.00 (Bad Request) Response Code, so no sneaky filters allowed 😀

     typedef query-type {
       type enumeration {
         enum target-prefix {
           value 1;
           description
             "Query based on target prefix.";
         }
         enum target-port {
           value 2;
           description
             "Query based on target port number.";
         }
         enum target-protocol {
           value 3;
           description
             "Query based on target protocol.";
         }
         enum target-fqdn {
           value 4;
           description
             "Query based on target FQDN.";
         }
         enum target-uri {
           value 5;
           description
             "Query based on target URI.";
         }
         enum target-alias {
           value 6;
           description
             "Query based on target alias.";
         }
         enum mid {
           value 7;
           description
             "Query based on mitigation identifier (mid).";
         }
         enum source-prefix {
           value 8;
           description
             "Query based on source prefix.";
         }
         enum source-port {
           value 9;
           description
             "Query based on source port number.";
         }
         enum source-icmp-type {
           value 10;
           description
             "Query based on ICMP type.";
         }
         enum content {
           value 11;
           description
             "Query based on the 'c' (content) Uri-Query option,
              which is used to control the selection of configuration
              and non-configuration data nodes.";
           reference
             "RFC 9132: Distributed Denial-of-Service Open Threat
                        Signaling (DOTS) Signal Channel
                        Specification, Section 4.4.2";
         }
       }
       description
         "Enumeration of support for query types that can be used
          in a GET request to filter out data.  Requests with
          invalid query types (e.g., not supported, malformed)
          received by the DOTS server are rejected with
          a 4.00 (Bad Request) Response Code.";
     }

Now the telemetry-parameters grouping πŸŽ€ This one bundles the measurement interval, the sample period, and the low, mid, and high percentiles together. The must constraints are the fun part: mid has to be at least low, and high has to be at least mid πŸ’…

     grouping telemetry-parameters {
       description
         "A grouping that includes a set of parameters that
          are used to prepare the reported telemetry data.

          The grouping indicates a measurement interval,
          a measurement sample period, and
          low-percentile/mid-percentile/high-percentile values.";
       leaf measurement-interval {
         type interval;
         description
           "Defines the period during which percentiles are
            computed.";
       }
       leaf measurement-sample {
         type sample;
         description
           "Defines the time distribution for measuring
            values that are used to compute percentiles.

            The measurement sample value must be less than the
            measurement interval value.";
       }
       leaf low-percentile {
         type percentile;
         default "10.00";
         description
           "Low-percentile.  If set to '0', this means that
            the use of low-percentile values is disabled.";
       }
       leaf mid-percentile {
         type percentile;
         must '. >= ../low-percentile' {
           error-message
             "The mid-percentile must be greater than
              or equal to the low-percentile.";
         }
         default "50.00";
         description
           "Mid-percentile.  If set to the same value as
            'low-percentile', this means that the use of
            mid-percentile values is disabled.";
       }
       leaf high-percentile {
         type percentile;
         must '. >= ../mid-percentile' {
           error-message
             "The high-percentile must be greater than
              or equal to the mid-percentile.";
         }
         default "90.00";
         description
           "High-percentile.  If set to the same value as
            'mid-percentile', this means that the use of
            high-percentile values is disabled.";
       }
     }

Last up in this part is percentile-and-peak, a generic grouping that holds low, mid, and high percentile values plus a peak value, all as yang:gauge64 ⭐

     grouping percentile-and-peak {
       description
         "Generic grouping for percentile and peak values.";
       leaf low-percentile-g {
         type yang:gauge64;
         description
           "Low-percentile value.";
       }
       leaf mid-percentile-g {
         type yang:gauge64;
         description
           "Mid-percentile value.";
       }
       leaf high-percentile-g {
         type yang:gauge64;
         description
           "High-percentile value.";
       }
       leaf peak-g {
         type yang:gauge64;
         description
           "Peak value.";
       }
     }

okay so the groupings are where the YANG gets really fun πŸŽ€ each one is basically a little template that the other parts can reuse 🫢

     grouping percentile-peak-and-current {
       description
         "Generic grouping for percentile and peak values.";
       uses percentile-and-peak;
       leaf current-g {
         type yang:gauge64;
         description
           "Current value.";
       }
     }

     grouping unit-config {
       description
         "Generic grouping for unit configuration.";
       list unit-config {
         key "unit";
         description
           "Controls which unit classes are allowed when sharing
            telemetry data.";
         leaf unit {
           type unit-class;
           description
             "Can be 'packet-ps', 'bit-ps', or 'byte-ps'.";
         }
         leaf unit-status {
           type boolean;
           mandatory true;
           description
             "Enable/disable the use of the measurement unit class.";
         }
       }
     }

     grouping traffic-unit {
       description
         "Grouping of traffic as a function of the
          measurement unit.";
       leaf unit {
         type unit;
         description
           "The traffic can be measured using unit classes:
            'packet-ps', 'bit-ps', or 'byte-ps'.  DOTS agents
            auto-scale to the appropriate units (e.g., 'megabit-ps',
            'kilobit-ps').";
       }
       uses percentile-and-peak;
     }

     grouping traffic-unit-all {
       description
         "Grouping of traffic as a function of the measurement unit,
          including current values.";
       uses traffic-unit;
       leaf current-g {
         type yang:gauge64;
         description
           "Current observed value.";
       }
     }

     grouping traffic-unit-protocol {
       description
         "Grouping of traffic of a given transport protocol as
          a function of the measurement unit.";
       leaf protocol {
         type uint8;
         description
           "The transport protocol.
            Values are taken from the IANA 'Protocol Numbers'
            registry:
            <https://www.iana.org/assignments/protocol-numbers/>.

            For example, this parameter contains 6 for TCP,
            17 for UDP, 33 for the Datagram Congestion Control
            Protocol (DCCP), or 132 for the Stream Control
            Transmission Protocol (SCTP).";
       }
       uses traffic-unit;
     }

     grouping traffic-unit-protocol-all {
       description
         "Grouping of traffic of a given transport protocol as
          a function of the measurement unit, including current
          values.";
       uses traffic-unit-protocol;
       leaf current-g {
         type yang:gauge64;
         description
           "Current observed value.";
       }
     }

     grouping traffic-unit-port {
       description
         "Grouping of traffic bound to a port number as
          a function of the measurement unit.";
       leaf port {
         type inet:port-number;
         description
           "Port number used by a transport protocol.";
       }
       uses traffic-unit;
     }

     grouping traffic-unit-port-all {
       description
         "Grouping of traffic bound to a port number as
          a function of the measurement unit, including
          current values.";
       uses traffic-unit-port;
       leaf current-g {
         type yang:gauge64;
         description
           "Current observed value.";
       }
     }

     grouping total-connection-capacity {
       description
         "Total connection capacities for various types of
          connections, as well as overall capacity.  These data nodes
          are useful for detecting resource-consuming DDoS attacks.";
       leaf connection {
         type uint64;
         description
           "The maximum number of simultaneous connections that
            are allowed to the target server.";
       }
       leaf connection-client {
         type uint64;
         description
           "The maximum number of simultaneous connections that
            are allowed to the target server per client.";
       }
       leaf embryonic {
         type uint64;
         description
           "The maximum number of simultaneous embryonic connections
            that are allowed to the target server.  The term
            'embryonic connection' refers to a connection whose
            connection handshake is not finished.  Embryonic
            connections are only possible in connection-oriented
            transport protocols like TCP or SCTP.";
       }
       leaf embryonic-client {
         type uint64;
         description
           "The maximum number of simultaneous embryonic connections
            that are allowed to the target server per client.";
       }
       leaf connection-ps {
         type uint64;
         description
           "The maximum number of new connections allowed per second
            to the target server.";
       }
       leaf connection-client-ps {
         type uint64;
         description
           "The maximum number of new connections allowed per second
            to the target server per client.";
       }
       leaf request-ps {
         type uint64;
         description
           "The maximum number of requests allowed per second
            to the target server.";
       }
       leaf request-client-ps {
         type uint64;
         description
           "The maximum number of requests allowed per second
            to the target server per client.";
       }
       leaf partial-request-max {
         type uint64;
         description
           "The maximum number of outstanding partial requests
            that are allowed to the target server.";
       }
       leaf partial-request-client-max {
         type uint64;
         description
           "The maximum number of outstanding partial requests
            that are allowed to the target server per client.";
       }
     }

     grouping total-connection-capacity-protocol {
       description
         "Total connection capacity per protocol.  These data nodes
          are useful for detecting resource-consuming DDoS attacks.";
       leaf protocol {
         type uint8;
         description
           "The transport protocol.
            Values are taken from the IANA 'Protocol Numbers'
            registry:
            <https://www.iana.org/assignments/protocol-numbers/>.";
       }
       uses total-connection-capacity;
     }

     grouping connection-percentile-and-peak {
       description
         "A set of data nodes that represent the attack
          characteristics.";
       container connection-c {
         uses percentile-and-peak;
         description
           "The number of simultaneous attack connections to
            the target server.";
       }
       container embryonic-c {
         uses percentile-and-peak;
         description
           "The number of simultaneous embryonic connections to
            the target server.";
       }
       container connection-ps-c {
         uses percentile-and-peak;
         description
           "The number of attack connections per second to
            the target server.";
       }
       container request-ps-c {
         uses percentile-and-peak;
         description
           "The number of attack requests per second to
            the target server.";
       }
       container partial-request-c {
         uses percentile-and-peak;
         description
           "The number of attack partial requests to
            the target server.";
       }
     }

     grouping connection-all {
       description
         "Total attack connections, including current values.";
       container connection-c {
         uses percentile-peak-and-current;
         description
           "The number of simultaneous attack connections to
            the target server.";
       }
       container embryonic-c {
         uses percentile-peak-and-current;
         description
           "The number of simultaneous embryonic connections to
            the target server.";
       }
       container connection-ps-c {
         uses percentile-peak-and-current;
         description
           "The number of attack connections per second to
            the target server.";
       }
       container request-ps-c {
         uses percentile-peak-and-current;
         description
           "The number of attack requests per second to
            the target server.";
       }
       container partial-request-c {
         uses percentile-peak-and-current;
         description
           "The number of attack partial requests to
            the target server.";
       }
     }

     grouping connection-protocol {
       description
         "Total attack connections.";
       leaf protocol {
         type uint8;
         description
           "The transport protocol.
            Values are taken from the IANA 'Protocol Numbers'
            registry:
            <https://www.iana.org/assignments/protocol-numbers/>.";
       }
       uses connection-percentile-and-peak;
     }

     grouping connection-port {
       description
         "Total attack connections per port number.";
       leaf protocol {
         type uint8;
         description
           "The transport protocol.
            Values are taken from the IANA 'Protocol Numbers'
            registry:
            <https://www.iana.org/assignments/protocol-numbers/>.";
       }
       leaf port {
         type inet:port-number;
         description
           "Port number.";
       }
       uses connection-percentile-and-peak;
     }

     grouping connection-protocol-all {
       description
         "Total attack connections per protocol, including current
          values.";
       leaf protocol {
         type uint8;
         description
           "The transport protocol.
            Values are taken from the IANA 'Protocol Numbers'
            registry:
            <https://www.iana.org/assignments/protocol-numbers/>.";
       }
       uses connection-all;
     }

     grouping connection-protocol-port-all {
       description
         "Total attack connections per port number, including current
          values.";
       leaf protocol {
         type uint8;
         description
           "The transport protocol.
            Values are taken from the IANA 'Protocol Numbers'
            registry:
            <https://www.iana.org/assignments/protocol-numbers/>.";
       }
       leaf port {
         type inet:port-number;
         description
           "Port number.";
       }
       uses connection-all;
     }

Okay bestie, this part is all about the YANG groupings that package up attack info πŸ’– The attack-detail grouping is where the vendor and attack identifiers live, along with the language tag, severity, start and end times, and source count πŸ¦‹

     grouping attack-detail {
       description
         "Various details that describe the ongoing
          attacks that need to be mitigated by the DOTS server.
          The attack details need to cover well-known and common
          attacks (such as a SYN flood) along with new emerging or
          vendor-specific attacks.";
       leaf vendor-id {
         type uint32;
         description
           "The Vendor ID is a security vendor's Private Enterprise
            Number as registered with IANA.";
         reference
           "IANA: Private Enterprise Numbers
            (https://www.iana.org/assignments/enterprise-numbers/)";
       }
       leaf attack-id {
         type uint32;
         description
           "Unique identifier assigned by the vendor for the attack.";
       }
       leaf description-lang {
         type string {
           pattern '((([A-Za-z]{2,3}(-[A-Za-z]{3}(-[A-Za-z]{3})'
                 + '{0,2})?)|[A-Za-z]{4}|[A-Za-z]{5,8})(-[A-Za-z]{4})'
                 + '?(-([A-Za-z]{2}|[0-9]{3}))?(-([A-Za-z0-9]{5,8}'
                 + '|([0-9][A-Za-z0-9]{3})))*(-[0-9A-WYZa-wyz]'
                 + '(-([A-Za-z0-9]{2,8}))+)*(-[Xx](-([A-Za-z0-9]'
                 + '{1,8}))+)?|[Xx](-([A-Za-z0-9]{1,8}))+|'
                 + '(([Ee][Nn]-[Gg][Bb]-[Oo][Ee][Dd]|[Ii]-'
                 + '[Aa][Mm][Ii]|[Ii]-[Bb][Nn][Nn]|[Ii]-'
                 + '[Dd][Ee][Ff][Aa][Uu][Ll][Tt]|[Ii]-'
                 + '[Ee][Nn][Oo][Cc][Hh][Ii][Aa][Nn]'
                 + '|[Ii]-[Hh][Aa][Kk]|'
                 + '[Ii]-[Kk][Ll][Ii][Nn][Gg][Oo][Nn]|'
                 + '[Ii]-[Ll][Uu][Xx]|[Ii]-[Mm][Ii][Nn][Gg][Oo]|'
                 + '[Ii]-[Nn][Aa][Vv][Aa][Jj][Oo]|[Ii]-[Pp][Ww][Nn]|'
                 + '[Ii]-[Tt][Aa][Oo]|[Ii]-[Tt][Aa][Yy]|'
                 + '[Ii]-[Tt][Ss][Uu]|[Ss][Gg][Nn]-[Bb][Ee]-[Ff][Rr]|'
                 + '[Ss][Gg][Nn]-[Bb][Ee]-[Nn][Ll]|[Ss][Gg][Nn]-'
                 + '[Cc][Hh]-[Dd][Ee])|([Aa][Rr][Tt]-'
                 + '[Ll][Oo][Jj][Bb][Aa][Nn]|[Cc][Ee][Ll]-'
                 + '[Gg][Aa][Uu][Ll][Ii][Ss][Hh]|'
                 + '[Nn][Oo]-[Bb][Oo][Kk]|[Nn][Oo]-'
                 + '[Nn][Yy][Nn]|[Zz][Hh]-[Gg][Uu][Oo][Yy][Uu]|'
                 + '[Zz][Hh]-[Hh][Aa][Kk][Kk][Aa]|[Zz][Hh]-'
                 + '[Mm][Ii][Nn]|[Zz][Hh]-[Mm][Ii][Nn]-'
                 + '[Nn][Aa][Nn]|[Zz][Hh]-[Xx][Ii][Aa][Nn][Gg])))';
         }
         default "en-US";
         description
           "Indicates the language tag that is used for
            'attack-description'.";
         reference
           "RFC 5646: Tags for Identifying Languages, Section 2.1";
       }
       leaf attack-description {
         type string;
         description
           "Textual representation of the attack description.
            Natural Language Processing techniques (e.g.,
            word embedding) might provide some utility in mapping
            the attack description to an attack type.";
       }
       leaf attack-severity {
         type attack-severity;
         description
           "Severity level of an attack.  How this level is
            determined is implementation specific.";
       }
       leaf start-time {
         type uint64;
         description
           "The time the attack started.  The start time is
            represented in seconds relative to
            1970-01-01T00:00:00Z.";
       }
       leaf end-time {
         type uint64;
         description
           "The time the attack ended.  The end time is represented
            in seconds relative to 1970-01-01T00:00:00Z.";
       }
       container source-count {
         description
           "Indicates the count of unique sources involved
            in the attack.";
         uses percentile-and-peak;
         leaf current-g {
           type yang:gauge64;
           description
             "Current observed value.";
         }
       }
     }

Next up is the talker grouping 🌸 It holds the spoofed-status flag, the source prefix, the source port and ICMP type ranges (both with those cute must checks that keep the upper bound at or above the lower one πŸ™ˆ), and the total attack traffic list πŸ’…

     grouping talker {
       description
         "Defines generic data related to top talkers.";
       leaf spoofed-status {
         type boolean;
         description
           "When set to 'true', it indicates whether this address
            is spoofed.";
       }
       leaf source-prefix {
         type inet:ip-prefix;
         description
           "IPv4 or IPv6 prefix identifying the attacker(s).";
       }
       list source-port-range {
         key "lower-port";
         description
           "Port range.  When only 'lower-port' is
            present, it represents a single port number.";
         leaf lower-port {
           type inet:port-number;
           description
             "Lower port number of the port range.";
         }
         leaf upper-port {
           type inet:port-number;
           must '. >= ../lower-port' {
             error-message
               "The upper port number must be greater than
                or equal to the lower port number.";
           }
           description
             "Upper port number of the port range.";
         }
       }
       list source-icmp-type-range {
         key "lower-type";
         description
           "ICMP type range.  When only 'lower-type' is
            present, it represents a single ICMP type.";
         leaf lower-type {
           type uint8;
           description
             "Lower ICMP type of the ICMP type range.";
         }
         leaf upper-type {
           type uint8;
           must '. >= ../lower-type' {
             error-message
               "The upper ICMP type must be greater than
                or equal to the lower ICMP type.";
           }
           description
             "Upper type of the ICMP type range.";
         }
       }
       list total-attack-traffic {
         key "unit";
         description
           "Total attack traffic issued from this source.";
         uses traffic-unit-all;
       }
     }

Now the two top-talker groupings 🧚 top-talker-aggregate pairs each talker with a single total attack connection container, and it's the one typically used inside a mitigation request ✨ The plain top-talker version goes per protocol instead, with a keyed list of connections for each protocol πŸ‘‘

     grouping top-talker-aggregate {
       description
         "An aggregate of top attack sources.  This aggregate is
          typically used when included in a mitigation request.";
       list talker {
         key "source-prefix";
         description
           "Refers to a top talker that is identified by an IPv4
            or IPv6 prefix identifying the attacker(s).";
         uses talker;
         container total-attack-connection {
           description
             "Total attack connections issued from this source.";
           uses connection-all;
         }
       }
     }

     grouping top-talker {
       description
         "Top attack sources with detailed per-protocol
          structure.";
       list talker {
         key "source-prefix";
         description
           "Refers to a top talker that is identified by an IPv4
            or IPv6 prefix identifying the attacker(s).";
         uses talker;
         list total-attack-connection-protocol {
           key "protocol";
           description
             "Total attack connections issued from this source.";
           uses connection-protocol-all;
         }
       }
     }

Next is baseline πŸ“ This is the telemetry baseline grouping, and it pulls in the target, aliases, normal traffic (total, per protocol, and per port), and connection capacity (total and per port) 🌈

     grouping baseline {
       description
         "Grouping for the telemetry baseline.";
       uses data-channel:target;
       leaf-list alias-name {
         type string;
         description
           "An alias name that points to an IP resource.
            An IP resource can be a router, a host,
            an Internet of Things (IoT) object, a server, etc.";
       }
       list total-traffic-normal {
         key "unit";
         description
           "Total traffic normal baselines.";
         uses traffic-unit;
       }
       list total-traffic-normal-per-protocol {
         key "unit protocol";
         description
           "Total traffic normal baselines per protocol.";
         uses traffic-unit-protocol;
       }
       list total-traffic-normal-per-port {
         key "unit port";
         description
           "Total traffic normal baselines per port number.";
         uses traffic-unit-port;
       }
       list total-connection-capacity {
         key "protocol";
         description
           "Total connection capacity.";
         uses total-connection-capacity-protocol;
       }
       list total-connection-capacity-per-port {
         key "protocol port";
         description
           "Total connection capacity per port number.";
         leaf port {
           type inet:port-number;
           description
             "The target port number.";
         }
         uses total-connection-capacity-protocol;
       }
     }

Last but definitely not least, pre-or-ongoing-mitigation πŸ¦‹ This one is the telemetry data grouping, covering total traffic and attack traffic (broken down by unit, protocol, and port), attack connections by protocol and port, and the attack-detail list with its top-talker container πŸ’œ

     grouping pre-or-ongoing-mitigation {
       description
         "Grouping for the telemetry data.";
       list total-traffic {
         key "unit";
         description
           "Total traffic.";
         uses traffic-unit-all;
       }
       list total-traffic-protocol {
         key "unit protocol";
         description
           "Total traffic per protocol.";
         uses traffic-unit-protocol-all;
       }
       list total-traffic-port {
         key "unit port";
         description
           "Total traffic per port number.";
         uses traffic-unit-port-all;
       }
       list total-attack-traffic {
         key "unit";
         description
           "Total attack traffic.";
         uses traffic-unit-all;
       }
       list total-attack-traffic-protocol {
         key "unit protocol";
         description
           "Total attack traffic per protocol.";
         uses traffic-unit-protocol-all;
       }
       list total-attack-traffic-port {
         key "unit port";
         description
           "Total attack traffic per port number.";
         uses traffic-unit-port-all;
       }
       list total-attack-connection-protocol {
         key "protocol";
         description
           "Total attack connections.";
         uses connection-protocol-all;
       }
       list total-attack-connection-port {
         key "protocol port";
         description
           "Total attack connections per target port number.";
         uses connection-protocol-port-all;
       }
       list attack-detail {
         key "vendor-id attack-id";
         description
           "Provides a set of attack details.";
         uses attack-detail;
         container top-talker {
           description
             "Lists the top attack sources.";
           uses top-talker;
         }
       }
     }

That's the whole vibe for this chunk, and it's giving complete, accurate, and totally ready for the next part 🫢

Okay bestie, the telemetry module keeps going and it's giving πŸ’– the YANG augments and structures that let the server and client swap telemetry data with zero drama πŸ¦‹ Every line below is the spec itself, so I'm keeping it exact ✨

     sx:augment-structure "/dots-signal:dots-signal"
                        + "/dots-signal:message-type"
                        + "/dots-signal:mitigation-scope"
                        + "/dots-signal:scope" {
       description
         "Extends mitigation scope with telemetry update data.";
       choice direction {
         description
           "Indicates the communication direction in which the
            data nodes can be included.";
         case server-to-client-only {
           description
             "These data nodes appear only in a mitigation message
              sent from the server to the client.";
           list total-traffic {
             key "unit";
             description
               "Total traffic.";
             uses traffic-unit-all;
           }
           container total-attack-connection {
             description
               "Total attack connections.";
             uses connection-all;
           }
         }
       }
       list total-attack-traffic {
         key "unit";
         description
           "Total attack traffic.";
         uses traffic-unit-all;
       }
       list attack-detail {
         key "vendor-id attack-id";
         description
           "Attack details.";
         uses attack-detail;
         container top-talker {
           description
             "Top attack sources.";
           uses top-talker-aggregate;
         }
       }
     }
     sx:structure dots-telemetry {
       description
         "Main structure for DOTS telemetry messages.";
       choice telemetry-message-type {
         description
           "Can be 'telemetry-setup' or telemetry data.";
         case telemetry-setup {
           description
             "Indicates that the message is about telemetry setup.";
           choice direction {
             description
               "Indicates the communication direction in which the
                data nodes can be included.";
             case server-to-client-only {
               description
                 "These data nodes appear only in a telemetry message
                  sent from the server to the client.";
               container max-config-values {
                 description
                   "Maximum acceptable configuration values.";
                 uses telemetry-parameters;
                 leaf server-originated-telemetry {
                   type boolean;
                   default "false";
                   description
                     "Indicates whether the DOTS server can be
                      instructed to send pre-or-ongoing-mitigation
                      telemetry.  If set to 'false' or the data node
                      is not present, this is an indication that
                      the server does not support this capability.";
                 }
                 leaf telemetry-notify-interval {
                   type uint16 {
                     range "1 .. 3600";
                   }
                   units "seconds";
                   must '. >= ../../min-config-values'
                      + '/telemetry-notify-interval' {
                     error-message
                       "The value must be greater than or equal
                        to the 'telemetry-notify-interval' value in
                        the 'min-config-values' attribute";
                   }
                   description
                     "Minimum number of seconds between successive
                      telemetry notifications.";
                 }
               }
               container min-config-values {
                 description
                   "Minimum acceptable configuration values.";
                 uses telemetry-parameters;
                 leaf telemetry-notify-interval {
                   type uint16 {
                     range "1 .. 3600";
                   }
                   units "seconds";
                   description
                     "Minimum number of seconds between successive
                      telemetry notifications.";
                 }
               }
               container supported-unit-classes {
                 description
                   "Supported unit classes and default activation
                    status.";
                 uses unit-config;
               }
               leaf-list supported-query-type {
                 type query-type;
                 description
                   "Indicates which query types are supported by
                    the server.  If the server does not announce
                    the query types it supports, the client will
                    be unable to use any of the potential
                    'query-type' values to reduce the returned data
                    content from the server.";
               }
             }
           }
           list telemetry {
             description
               "The telemetry data per DOTS client.  The keys
                of the list are 'cuid' and 'tsid', but these keys are
                not represented here because these keys are conveyed
                as mandatory Uri-Paths in requests.  Omitting keys
                is compliant with RFC 8791.";
             reference
               "RFC 8791: YANG Data Structure Extensions";
             choice direction {
               description
                 "Indicates the communication direction in which the
                  data nodes can be included.";
               case server-to-client-only {
                 description
                   "These data nodes appear only in a telemetry
                    message sent from the server to the client.";
                 leaf tsid {
                   type uint32;
                   description
                     "A client-assigned identifier for the DOTS
                      telemetry setup data.";
                 }
               }
             }
             choice setup-type {
               description
                 "Can be a mitigation configuration, a pipe capacity,
                  or a baseline message.";
               case telemetry-config {
                 description
                   "Used to set telemetry parameters such as setting
                    low-, mid-, and high-percentile values.";
                 container current-config {
                   description
                     "Current telemetry configuration values.";
                   uses telemetry-parameters;
                   uses unit-config;
                   leaf server-originated-telemetry {
                     type boolean;
                     description
                       "Used by a DOTS client to enable/disable
                        whether it requests pre-or-ongoing-mitigation
                        telemetry from the DOTS server.";
                   }
                   leaf telemetry-notify-interval {
                     type uint16 {
                       range "1 .. 3600";
                     }
                     units "seconds";
                     description
                       "Minimum number of seconds between successive
                        telemetry notifications.";
                   }
                 }
               }
               case pipe {
                 description
                   "Total pipe capacity of a DOTS client domain.";
                 list total-pipe-capacity {
                   key "link-id unit";
                   description
                     "Total pipe capacity of a DOTS client domain.";
                   leaf link-id {
                     type nt:link-id;
                     description
                       "Identifier of an interconnection link of
                        the DOTS client domain.";
                   }
                   leaf capacity {
                     type uint64;
                     mandatory true;
                     description
                       "Pipe capacity.  This attribute is mandatory
                        when 'total-pipe-capacity' is included in a
                        message.";
                   }
                   leaf unit {
                     type unit;
                     description
                       "The traffic can be measured using unit
                        classes: packets per second (pps), bits per
                        second (bps), and/or bytes per second
                        (Bps).

                        For a given unit class, the DOTS agents
                        auto-scale to the appropriate units (e.g.,
                        'megabit-ps', 'kilobit-ps').";
                   }
                 }
               }
               case baseline {
                 description
                   "Traffic baseline information related to a DOTS
                    client domain.";
                 list baseline {
                   key "id";
                   description
                     "Traffic baseline information related to a DOTS
                      client domain.";
                   leaf id {
                     type uint32;
                     must '. >= 1';
                     description
                       "An identifier that uniquely identifies a
                        baseline entry communicated by a
                        DOTS client.";
                   }
                   uses baseline;
                 }
               }
             }
           }
         }
         case telemetry {
           description
             "Telemetry information.";
           list pre-or-ongoing-mitigation {
             description
               "Pre-or-ongoing-mitigation telemetry per DOTS client.
                The keys of the list are 'cuid' and 'tmid', but these
                keys are not represented here because these keys are
                conveyed as mandatory Uri-Paths in requests.
                Omitting keys is compliant with RFC 8791.";
             reference
               "RFC 8791: YANG Data Structure Extensions";
             choice direction {
               description
                 "Indicates the communication direction in which the
                  data nodes can be included.";
               case server-to-client-only {
                 description
                   "These data nodes appear only in a telemetry
                    message sent from the server to the client.";
                 leaf tmid {
                   type uint32;
                   description
                     "A client-assigned identifier for the DOTS
                      telemetry data.";
                 }
               }
             }
             container target {
               description
                 "Indicates the target.  At least one of the
                  attributes 'target-prefix', 'target-fqdn',
                  'target-uri', 'alias-name', or 'mid-list'
                  must be present in the target definition.";
               uses data-channel:target;
               leaf-list alias-name {
                 type string;
                 description
                   "An alias name that points to a resource.";
               }
               leaf-list mid-list {
                 type uint32;
                 description
                   "Reference to a list of associated mitigation
                    requests.";
                 reference
                   "RFC 9132: Distributed Denial-of-Service Open
                              Threat Signaling (DOTS) Signal Channel
                              Specification, Section 4.4.1";
               }
             }
             uses pre-or-ongoing-mitigation;
           }
         }
       }
     }
   }
   <CODE ENDS>

11.2. Vendor Attack Mapping Details YANG Module πŸŽ€

okay so this is the module for the vendor attack mapping details, and it's giving organized πŸ’… it lets a DOTS client and a DOTS server swap DDoS attack mapping info over the DOTS data channel πŸ¦‹

   <CODE BEGINS> file "ietf-dots-mapping@2022-06-20.yang"
   module ietf-dots-mapping {
     yang-version 1.1;
     namespace "urn:ietf:params:xml:ns:yang:ietf-dots-mapping";
     prefix dots-mapping;

     import ietf-dots-data-channel {
       prefix data-channel;
       reference
         "RFC 8783: Distributed Denial-of-Service Open Threat
                    Signaling (DOTS) Data Channel Specification";
     }

     organization
       "IETF DDoS Open Threat Signaling (DOTS) Working Group";
     contact
       "WG Web:   <https://datatracker.ietf.org/wg/dots/>
        WG List:  <mailto:dots@ietf.org>

        Author:   Mohamed Boucadair
                  <mailto:mohamed.boucadair@orange.com>

        Author:   Jon Shallow
                  <mailto:supjps-ietf@jpshallow.com>";
     description
       "This module contains YANG definitions for the sharing
        of DDoS attack mapping details between a DOTS client and
        a DOTS server by means of the DOTS data channel.

        Copyright (c) 2022 IETF Trust and the persons identified as
        authors of the code.  All rights reserved.

        Redistribution and use in source and binary forms, with or
        without modification, is permitted pursuant to, and subject to
        the license terms contained in, the Revised BSD License set
        forth in Section 4.c of the IETF Trust's Legal Provisions
        Relating to IETF Documents
        (https://trustee.ietf.org/license-info).

        This version of this YANG module is part of RFC 9244; see the
        RFC itself for full legal notices.";

     revision 2022-06-20 {
       description
         "Initial revision.";
       reference
         "RFC 9244: Distributed Denial-of-Service Open Threat
                    Signaling (DOTS) Telemetry";
     }

     feature dots-telemetry {
       description
         "This feature indicates that DOTS telemetry data can be
          shared between DOTS clients and servers.";
     }

     grouping attack-mapping {
       description
         "A set of information used for sharing vendor attack mapping
          information with a peer.";
       list vendor {
         key "vendor-id";
         description
           "Vendor attack mapping information related to the
            client/server.";
         leaf vendor-id {
           type uint32;
           description
             "The Vendor ID is a security vendor's Private Enterprise
              Number as registered with IANA.";
           reference
             "IANA: Private Enterprise Numbers
              (https://www.iana.org/assignments/enterprise-numbers/)";
         }
         leaf vendor-name {
           type string;
           description
             "The name of the vendor (e.g., company A).";
         }
         leaf description-lang {
           type string {
             pattern '((([A-Za-z]{2,3}(-[A-Za-z]{3}(-[A-Za-z]{3})'
                   + '{0,2})?)|[A-Za-z]{4}|[A-Za-z]{5,8})(-[A-Za-z]{4})'
                   + '?(-([A-Za-z]{2}|[0-9]{3}))?(-([A-Za-z0-9]{5,8}'
                   + '|([0-9][A-Za-z0-9]{3})))*(-[0-9A-WYZa-wyz]'
                   + '(-([A-Za-z0-9]{2,8}))+)*(-[Xx](-([A-Za-z0-9]'
                   + '{1,8}))+)?|[Xx](-([A-Za-z0-9]{1,8}))+|'
                   + '(([Ee][Nn]-[Gg][Bb]-[Oo][Ee][Dd]|[Ii]-'
                   + '[Aa][Mm][Ii]|[Ii]-[Bb][Nn][Nn]|[Ii]-'
                   + '[Dd][Ee][Ff][Aa][Uu][Ll][Tt]|[Ii]-'
                   + '[Ee][Nn][Oo][Cc][Hh][Ii][Aa][Nn]'
                   + '|[Ii]-[Hh][Aa][Kk]|'
                   + '[Ii]-[Kk][Ll][Ii][Nn][Gg][Oo][Nn]|'
                   + '[Ii]-[Ll][Uu][Xx]|[Ii]-[Mm][Ii][Nn][Gg][Oo]|'
                   + '[Ii]-[Nn][Aa][Vv][Aa][Jj][Oo]|[Ii]-[Pp][Ww][Nn]|'
                   + '[Ii]-[Tt][Aa][Oo]|[Ii]-[Tt][Aa][Yy]|'
                   + '[Ii]-[Tt][Ss][Uu]|[Ss][Gg][Nn]-[Bb][Ee]-[Ff][Rr]|'
                   + '[Ss][Gg][Nn]-[Bb][Ee]-[Nn][Ll]|[Ss][Gg][Nn]-'
                   + '[Cc][Hh]-[Dd][Ee])|([Aa][Rr][Tt]-'
                   + '[Ll][Oo][Jj][Bb][Aa][Nn]|[Cc][Ee][Ll]-'
                   + '[Gg][Aa][Uu][Ll][Ii][Ss][Hh]|'
                   + '[Nn][Oo]-[Bb][Oo][Kk]|[Nn][Oo]-'
                   + '[Nn][Yy][Nn]|[Zz][Hh]-[Gg][Uu][Oo][Yy][Uu]|'
                   + '[Zz][Hh]-[Hh][Aa][Kk][Kk][Aa]|[Zz][Hh]-'
                   + '[Mm][Ii][Nn]|[Zz][Hh]-[Mm][Ii][Nn]-'
                   + '[Nn][Aa][Nn]|[Zz][Hh]-[Xx][Ii][Aa][Nn][Gg])))';
             }
           default "en-US";
           description
             "Indicates the language tag that is used for
              'attack-description'.";
           reference
             "RFC 5646: Tags for Identifying Languages, Section 2.1";
         }
         leaf last-updated {
           type uint64;
           mandatory true;
           description
             "The time the mapping table was updated.  It is
              represented in seconds relative to
              1970-01-01T00:00:00Z.";
         }
         list attack-mapping {
           key "attack-id";
           description
             "Attack mapping details.";
           leaf attack-id {
             type uint32;
             description
               "Unique identifier assigned by the vendor for the
                attack.";
           }
           leaf attack-description {
             type string;
             mandatory true;
             description
               "Textual representation of the attack description.
                Natural Language Processing techniques (e.g.,
                word embedding) might provide some utility in
                mapping the attack description to an attack type.";
           }
         }
       }
     }

     augment "/data-channel:dots-data/data-channel:dots-client" {
       if-feature "dots-telemetry";
       description
         "Augments the data channel with a vendor attack
          mapping table of the DOTS client.";
       container vendor-mapping {
         description
           "Used by DOTS clients to share their vendor
            attack mapping information with DOTS servers.";
         uses attack-mapping;
       }
     }

     augment "/data-channel:dots-data/data-channel:capabilities" {
       if-feature "dots-telemetry";
       description
         "Augments the DOTS server capabilities with a
          parameter to indicate whether they can share
          attack mapping details.";
       leaf vendor-mapping-enabled {
         type boolean;
         config false;
         description
           "Indicates that the DOTS server supports sharing
            attack vendor mapping details with DOTS clients.";
       }
     }

     augment "/data-channel:dots-data" {
       if-feature "dots-telemetry";
       description
         "Augments the data channel with a vendor attack
          mapping table of the DOTS server.";
       container vendor-mapping {
         config false;
         description
           "Includes the list of vendor attack mapping details
            that will be shared with DOTS clients upon request.";
         uses attack-mapping;
       }
     }
   }
   <CODE ENDS>

12. YANG/JSON Mapping Parameters to CBOR ✨

okay bestie, this part is all about the CBOR side of things 🧚 every DOTS telemetry parameter that rides in the DOTS signal channel payload MUST get mapped to CBOR types the way Table 3 shows πŸ’œ

All DOTS telemetry parameters in the payload of the DOTS signal channel MUST be mapped to CBOR types as shown in Table 3:

   |  Note: Implementers must check that the mapping output provided
   |  by their YANG-to-CBOR encoding schemes is aligned with the
   |  contents of Table 3.

okay bestie, we're still in the YANG/JSON-to-CBOR mapping table, so here's the next chunk πŸŽ€βœ¨

   +======================+==============+======+=============+========+
   |Parameter Name        |YANG Type     |CBOR  |CBOR Major   | JSON   |
   |                      |              |Key   |Type &       | Type   |
   |                      |              |      |Information  |        |
   +======================+==============+======+=============+========+
   |tsid                  |uint32        |128   |0 unsigned   | Number |
   +----------------------+--------------+------+-------------+--------+
   |telemetry             |list          |129   |4 array      | Array  |
   +----------------------+--------------+------+-------------+--------+
   |low-percentile        |decimal64     |130   |6 tag 4 [-2, | String |
   |                      |              |      |integer]     |        |
   +----------------------+--------------+------+-------------+--------+
   |mid-percentile        |decimal64     |131   |6 tag 4 [-2, | String |
   |                      |              |      |integer]     |        |
   +----------------------+--------------+------+-------------+--------+
   |high-percentile       |decimal64     |132   |6 tag 4 [-2, | String |
   |                      |              |      |integer]     |        |
   +----------------------+--------------+------+-------------+--------+
   |unit-config           |list          |133   |4 array      | Array  |
   +----------------------+--------------+------+-------------+--------+
   |unit                  |enumeration   |134   |0 unsigned   | String |
   +----------------------+--------------+------+-------------+--------+
   |unit-status           |boolean       |135   |7 bits 20    | False  |
   |                      |              |      +-------------+--------+
   |                      |              |      |7 bits 21    | True   |
   +----------------------+--------------+------+-------------+--------+
   |total-pipe-capacity   |list          |136   |4 array      | Array  |
   +----------------------+--------------+------+-------------+--------+
   |link-id               |string        |137   |3 text string| String |
   +----------------------+--------------+------+-------------+--------+
   |pre-or-ongoing-       |list          |138   |4 array      | Array  |
   |mitigation            |              |      |             |        |
   +----------------------+--------------+------+-------------+--------+
   |total-traffic-normal  |list          |139   |4 array      | Array  |
   +----------------------+--------------+------+-------------+--------+
   |low-percentile-g      |yang:gauge64  |140   |0 unsigned   | String |
   +----------------------+--------------+------+-------------+--------+
   |mid-percentile-g      |yang:gauge64  |141   |0 unsigned   | String |
   +----------------------+--------------+------+-------------+--------+
   |high-percentile-g     |yang:gauge64  |142   |0 unsigned   | String |
   +----------------------+--------------+------+-------------+--------+
   |peak-g                |yang:gauge64  |143   |0 unsigned   | String |
   +----------------------+--------------+------+-------------+--------+
   |total-attack-traffic  |list          |144   |4 array      | Array  |
   +----------------------+--------------+------+-------------+--------+
   |total-traffic         |list          |145   |4 array      | Array  |
   +----------------------+--------------+------+-------------+--------+
   |total-connection-     |list          |146   |4 array      | Array  |
   |capacity              |              |      |             |        |
   +----------------------+--------------+------+-------------+--------+
   |connection            |uint64        |147   |0 unsigned   | String |
   +----------------------+--------------+------+-------------+--------+
   |connection-client     |uint64        |148   |0 unsigned   | String |
   +----------------------+--------------+------+-------------+--------+
   |embryonic             |uint64        |149   |0 unsigned   | String |
   +----------------------+--------------+------+-------------+--------+
   |embryonic-client      |uint64        |150   |0 unsigned   | String |
   +----------------------+--------------+------+-------------+--------+
   |connection-ps         |uint64        |151   |0 unsigned   | String |
   +----------------------+--------------+------+-------------+--------+
   |connection-client-ps  |uint64        |152   |0 unsigned   | String |
   +----------------------+--------------+------+-------------+--------+
   |request-ps            |uint64        |153   |0 unsigned   | String |
   +----------------------+--------------+------+-------------+--------+
   |request-client-ps     |uint64        |154   |0 unsigned   | String |
   +----------------------+--------------+------+-------------+--------+
   |partial-request-max   |uint64        |155   |0 unsigned   | String |
   +----------------------+--------------+------+-------------+--------+
   |partial-request-      |uint64        |156   |0 unsigned   | String |
   |client-max            |              |      |             |        |
   +----------------------+--------------+------+-------------+--------+
   |total-attack-         |container     |157   |5 map        | Object |
   |connection            |              |      |             |        |
   +----------------------+--------------+------+-------------+--------+
   |connection-c          |container     |158   |5 map        | Object |
   +----------------------+--------------+------+-------------+--------+
   |embryonic-c           |container     |159   |5 map        | Object |
   +----------------------+--------------+------+-------------+--------+
   |connection-ps-c       |container     |160   |5 map        | Object |
   +----------------------+--------------+------+-------------+--------+
   |request-ps-c          |container     |161   |5 map        | Object |
   +----------------------+--------------+------+-------------+--------+
   |attack-detail         |list          |162   |4 array      | Array  |
   +----------------------+--------------+------+-------------+--------+
   |id                    |uint32        |163   |0 unsigned   | Number |
   +----------------------+--------------+------+-------------+--------+
   |attack-id             |uint32        |164   |0 unsigned   | Number |
   +----------------------+--------------+------+-------------+--------+
   |attack-description    |string        |165   |3 text string| String |
   +----------------------+--------------+------+-------------+--------+
   |attack-severity       |enumeration   |166   |0 unsigned   | String |
   +----------------------+--------------+------+-------------+--------+
   |start-time            |uint64        |167   |0 unsigned   | String |
   +----------------------+--------------+------+-------------+--------+
   |end-time              |uint64        |168   |0 unsigned   | String |
   +----------------------+--------------+------+-------------+--------+
   |source-count          |container     |169   |5 map        | Object |
   +----------------------+--------------+------+-------------+--------+
   |top-talker            |container     |170   |5 map        | Object |
   +----------------------+--------------+------+-------------+--------+
   |spoofed-status        |boolean       |171   |7 bits 20    | False  |
   |                      |              |      +-------------+--------+
   |                      |              |      |7 bits 21    | True   |
   +----------------------+--------------+------+-------------+--------+
   |partial-request-c     |container     |172   |5 map        | Object |
   +----------------------+--------------+------+-------------+--------+
   |total-attack-         |list          |173   |4 array      | Array  |
   |connection-protocol   |              |      |             |        |
   +----------------------+--------------+------+-------------+--------+
   |baseline              |list          |174   |4 array      | Array  |
   +----------------------+--------------+------+-------------+--------+
   |current-config        |container     |175   |5 map        | Object |
   +----------------------+--------------+------+-------------+--------+
   |max-config-values     |container     |176   |5 map        | Object |
   +----------------------+--------------+------+-------------+--------+
   |min-config-values     |container     |177   |5 map        | Object |
   +----------------------+--------------+------+-------------+--------+
   |supported-unit-classes|container     |178   |5 map        | Object |
   +----------------------+--------------+------+-------------+--------+
   |server-originated-    |boolean       |179   |7 bits 20    | False  |
   |telemetry             |              |      +-------------+--------+
   |                      |              |      |7 bits 21    | True   |
   +----------------------+--------------+------+-------------+--------+
   |telemetry-notify-     |uint16        |180   |0 unsigned   | Number |
   |interval              |              |      |             |        |
   +----------------------+--------------+------+-------------+--------+
   |tmid                  |uint32        |181   |0 unsigned   | Number |
   +----------------------+--------------+------+-------------+--------+
   |measurement-interval  |enumeration   |182   |0 unsigned   | String |
   +----------------------+--------------+------+-------------+--------+
   |measurement-sample    |enumeration   |183   |0 unsigned   | String |
   +----------------------+--------------+------+-------------+--------+
   |talker                |list          |184   |4 array      | Array  |
   +----------------------+--------------+------+-------------+--------+
   |source-prefix         |inet:ip-prefix|185   |3 text string| String |
   +----------------------+--------------+------+-------------+--------+
   |mid-list              |leaf-list     |186   |4 array      | Array  |
   |                      +--------------+------+-------------+--------+
   |                      |uint32        |      |0 unsigned   | Number |
   +----------------------+--------------+------+-------------+--------+
   |source-port-range     |list          |187   |4 array      | Array  |
   +----------------------+--------------+------+-------------+--------+
   |source-icmp-type-range|list          |188   |4 array      | Array  |
   +----------------------+--------------+------+-------------+--------+
   |target                |container     |189   |5 map        | Object |
   +----------------------+--------------+------+-------------+--------+
   |capacity              |uint64        |190   |0 unsigned   | String |
   +----------------------+--------------+------+-------------+--------+
   |protocol              |uint8         |191   |0 unsigned   | Number |
   +----------------------+--------------+------+-------------+--------+
   |total-traffic-normal- |list          |192   |4 array      | Array  |
   |per-protocol          |              |      |             |        |
   +----------------------+--------------+------+-------------+--------+
   |total-traffic-normal- |list          |193   |4 array      | Array  |
   |per-port              |              |      |             |        |
   +----------------------+--------------+------+-------------+--------+
   |total-connection-     |list          |194   |4 array      | Array  |
   |capacity-per-port     |              |      |             |        |
   +----------------------+--------------+------+-------------+--------+
   |total-traffic-protocol|list          |195   |4 array      | Array  |
   +----------------------+--------------+------+-------------+--------+
   |total-traffic-port    |list          |196   |4 array      | Array  |
   +----------------------+--------------+------+-------------+--------+
   |total-attack-traffic- |list          |197   |4 array      | Array  |
   |protocol              |              |      |             |        |
   +----------------------+--------------+------+-------------+--------+
   |total-attack-traffic- |list          |198   |4 array      | Array  |
   |port                  |              |      |             |        |
   +----------------------+--------------+------+-------------+--------+
   |total-attack-         |list          |199   |4 array      | Array  |
   |connection-port       |              |      |             |        |
   +----------------------+--------------+------+-------------+--------+
   |port                  |inet:port-    |200   |0 unsigned   | Number |
   |                      |number        |      |             |        |
   +----------------------+--------------+------+-------------+--------+
   |supported-query-type  |leaf-list     |201   |4 array      | Array  |
   |                      +--------------+------+-------------+--------+
   |                      |              |      |0 unsigned   | String |
   +----------------------+--------------+------+-------------+--------+
   |vendor-id             |uint32        |202   |0 unsigned   | Number |
   +----------------------+--------------+------+-------------+--------+
   |ietf-dots-            |container     |203   |5 map        | Object |
   |telemetry:telemetry-  |              |      |             |        |
   |setup                 |              |      |             |        |
   +----------------------+--------------+------+-------------+--------+
   |ietf-dots-            |list          |204   |4 array      | Array  |
   |telemetry:total-      |              |      |             |        |
   |traffic               |              |      |             |        |
   +----------------------+--------------+------+-------------+--------+
   |ietf-dots-            |list          |205   |4 array      | Array  |
   |telemetry:total-      |              |      |             |        |
   |attack-traffic        |              |      |             |        |
   +----------------------+--------------+------+-------------+--------+
   |ietf-dots-            |container     |206   |5 map        | Object |
   |telemetry:total-      |              |      |             |        |
   |attack-connection     |              |      |             |        |
   +----------------------+--------------+------+-------------+--------+
   |ietf-dots-            |list          |207   |4 array      | Array  |
   |telemetry:attack-     |              |      |             |        |
   |detail                |              |      |             |        |
   +----------------------+--------------+------+-------------+--------+
   |ietf-dots-            |container     |208   |5 map        | Object |
   |telemetry:telemetry   |              |      |             |        |
   +----------------------+--------------+------+-------------+--------+
   |current-g             |yang:gauge64  |209   |0 unsigned   | String |
   +----------------------+--------------+------+-------------+--------+
   |description-lang      |string        |210   |3 text string| String |
   +----------------------+--------------+------+-------------+--------+
   |lower-type            |uint8         |32771 |0 unsigned   | Number |
   +----------------------+--------------+------+-------------+--------+
   |upper-type            |uint8         |32772 |0 unsigned   | Number |
   +----------------------+--------------+------+-------------+--------+

               Table 3: YANG/JSON Mapping Parameters to CBOR

13. IANA Considerations 🌸

13.1. DOTS Signal Channel CBOR Key Values πŸ’–

okay so this bit is where IANA gets some new stuff 🫢 this spec is registering a bunch of comprehension-optional parameters in the IANA "DOTS Signal Channel CBOR Key Values" registry [Key-Map] ✨ it's giving organized, no cap πŸ’…

Okay bestie, this is the big CBOR key table πŸŽ€ Every single row has the same Change Controller (IESG) and points back to RFC 9244 πŸ’…

   +======================+==========+=======+============+===========+
   | Parameter Name       | CBOR Key | CBOR  | Change     | Reference |
   |                      | Value    | Major | Controller |           |
   |                      |          | Type  |            |           |
   +======================+==========+=======+============+===========+
   | tsid                 | 128      | 0     | IESG       | RFC 9244  |
   +----------------------+----------+-------+------------+-----------+
   | telemetry            | 129      | 4     | IESG       | RFC 9244  |
   +----------------------+----------+-------+------------+-----------+
   | low-percentile       | 130      | 6tag4 | IESG       | RFC 9244  |
   +----------------------+----------+-------+------------+-----------+
   | mid-percentile       | 131      | 6tag4 | IESG       | RFC 9244  |
   +----------------------+----------+-------+------------+-----------+
   | high-percentile      | 132      | 6tag4 | IESG       | RFC 9244  |
   +----------------------+----------+-------+------------+-----------+
   | unit-config          | 133      | 4     | IESG       | RFC 9244  |
   +----------------------+----------+-------+------------+-----------+
   | unit                 | 134      | 0     | IESG       | RFC 9244  |
   +----------------------+----------+-------+------------+-----------+
   | unit-status          | 135      | 7     | IESG       | RFC 9244  |
   +----------------------+----------+-------+------------+-----------+
   | total-pipe-capacity  | 136      | 4     | IESG       | RFC 9244  |
   +----------------------+----------+-------+------------+-----------+
   | link-id              | 137      | 3     | IESG       | RFC 9244  |
   +----------------------+----------+-------+------------+-----------+
   | pre-or-ongoing-      | 138      | 4     | IESG       | RFC 9244  |
   | mitigation           |          |       |            |           |
   +----------------------+----------+-------+------------+-----------+
   | total-traffic-normal | 139      | 4     | IESG       | RFC 9244  |
   +----------------------+----------+-------+------------+-----------+
   | low-percentile-g     | 140      | 0     | IESG       | RFC 9244  |
   +----------------------+----------+-------+------------+-----------+
   | mid-percentile-g     | 141      | 0     | IESG       | RFC 9244  |
   +----------------------+----------+-------+------------+-----------+
   | high-percentile-g    | 142      | 0     | IESG       | RFC 9244  |
   +----------------------+----------+-------+------------+-----------+
   | peak-g               | 143      | 0     | IESG       | RFC 9244  |
   +----------------------+----------+-------+------------+-----------+
   | total-attack-traffic | 144      | 4     | IESG       | RFC 9244  |
   +----------------------+----------+-------+------------+-----------+
   | total-traffic        | 145      | 4     | IESG       | RFC 9244  |
   +----------------------+----------+-------+------------+-----------+
   | total-connection-    | 146      | 4     | IESG       | RFC 9244  |
   | capacity             |          |       |            |           |
   +----------------------+----------+-------+------------+-----------+
   | connection           | 147      | 0     | IESG       | RFC 9244  |
   +----------------------+----------+-------+------------+-----------+
   | connection-client    | 148      | 0     | IESG       | RFC 9244  |
   +----------------------+----------+-------+------------+-----------+
   | embryonic            | 149      | 0     | IESG       | RFC 9244  |
   +----------------------+----------+-------+------------+-----------+
   | embryonic-client     | 150      | 0     | IESG       | RFC 9244  |
   +----------------------+----------+-------+------------+-----------+
   | connection-ps        | 151      | 0     | IESG       | RFC 9244  |
   +----------------------+----------+-------+------------+-----------+
   | connection-client-ps | 152      | 0     | IESG       | RFC 9244  |
   +----------------------+----------+-------+------------+-----------+
   | request-ps           | 153      | 0     | IESG       | RFC 9244  |
   +----------------------+----------+-------+------------+-----------+
   | request-client-ps    | 154      | 0     | IESG       | RFC 9244  |
   +----------------------+----------+-------+------------+-----------+
   | partial-request-max  | 155      | 0     | IESG       | RFC 9244  |
   +----------------------+----------+-------+------------+-----------+
   | partial-request-     | 156      | 0     | IESG       | RFC 9244  |
   | client-max           |          |       |            |           |
   +----------------------+----------+-------+------------+-----------+
   | total-attack-        | 157      | 5     | IESG       | RFC 9244  |
   | connection           |          |       |            |           |
   +----------------------+----------+-------+------------+-----------+
   | connection-c         | 158      | 5     | IESG       | RFC 9244  |
   +----------------------+----------+-------+------------+-----------+
   | embryonic-c          | 159      | 5     | IESG       | RFC 9244  |
   +----------------------+----------+-------+------------+-----------+
   | connection-ps-c      | 160      | 5     | IESG       | RFC 9244  |
   +----------------------+----------+-------+------------+-----------+
   | request-ps-c         | 161      | 5     | IESG       | RFC 9244  |
   +----------------------+----------+-------+------------+-----------+
   | attack-detail        | 162      | 4     | IESG       | RFC 9244  |
   +----------------------+----------+-------+------------+-----------+
   | id                   | 163      | 0     | IESG       | RFC 9244  |
   +----------------------+----------+-------+------------+-----------+
   | attack-id            | 164      | 0     | IESG       | RFC 9244  |
   +----------------------+----------+-------+------------+-----------+
   | attack-description   | 165      | 3     | IESG       | RFC 9244  |
   +----------------------+----------+-------+------------+-----------+
   | attack-severity      | 166      | 0     | IESG       | RFC 9244  |
   +----------------------+----------+-------+------------+-----------+
   | start-time           | 167      | 0     | IESG       | RFC 9244  |
   +----------------------+----------+-------+------------+-----------+
   | end-time             | 168      | 0     | IESG       | RFC 9244  |
   +----------------------+----------+-------+------------+-----------+
   | source-count         | 169      | 5     | IESG       | RFC 9244  |
   +----------------------+----------+-------+------------+-----------+
   | top-talker           | 170      | 5     | IESG       | RFC 9244  |
   +----------------------+----------+-------+------------+-----------+
   | spoofed-status       | 171      | 7     | IESG       | RFC 9244  |
   +----------------------+----------+-------+------------+-----------+
   | partial-request-c    | 172      | 5     | IESG       | RFC 9244  |
   +----------------------+----------+-------+------------+-----------+
   | total-attack-        | 173      | 4     | IESG       | RFC 9244  |
   | connection-protocol  |          |       |            |           |
   +----------------------+----------+-------+------------+-----------+
   | baseline             | 174      | 4     | IESG       | RFC 9244  |
   +----------------------+----------+-------+------------+-----------+
   | current-config       | 175      | 5     | IESG       | RFC 9244  |
   +----------------------+----------+-------+------------+-----------+
   | max-config-values    | 176      | 5     | IESG       | RFC 9244  |
   +----------------------+----------+-------+------------+-----------+
   | min-config-values    | 177      | 5     | IESG       | RFC 9244  |
   +----------------------+----------+-------+------------+-----------+
   | supported-unit-      | 178      | 5     | IESG       | RFC 9244  |
   | classes              |          |       |            |           |
   +----------------------+----------+-------+------------+-----------+
   | server-originated-   | 179      | 7     | IESG       | RFC 9244  |
   | telemetry            |          |       |            |           |
   +----------------------+----------+-------+------------+-----------+
   | telemetry-notify-    | 180      | 0     | IESG       | RFC 9244  |
   | interval             |          |       |            |           |
   +----------------------+----------+-------+------------+-----------+
   | tmid                 | 181      | 0     | IESG       | RFC 9244  |
   +----------------------+----------+-------+------------+-----------+
   | measurement-interval | 182      | 0     | IESG       | RFC 9244  |
   +----------------------+----------+-------+------------+-----------+
   | measurement-sample   | 183      | 0     | IESG       | RFC 9244  |
   +----------------------+----------+-------+------------+-----------+
   | talker               | 184      | 4     | IESG       | RFC 9244  |
   +----------------------+----------+-------+------------+-----------+
   | source-prefix        | 185      | 3     | IESG       | RFC 9244  |
   +----------------------+----------+-------+------------+-----------+
   | mid-list             | 186      | 4     | IESG       | RFC 9244  |
   +----------------------+----------+-------+------------+-----------+
   | source-port-range    | 187      | 4     | IESG       | RFC 9244  |
   +----------------------+----------+-------+------------+-----------+
   | source-icmp-type-    | 188      | 4     | IESG       | RFC 9244  |
   | range                |          |       |            |           |
   +----------------------+----------+-------+------------+-----------+
   | target               | 189      | 5     | IESG       | RFC 9244  |
   +----------------------+----------+-------+------------+-----------+
   | capacity             | 190      | 0     | IESG       | RFC 9244  |
   +----------------------+----------+-------+------------+-----------+
   | protocol             | 191      | 0     | IESG       | RFC 9244  |
   +----------------------+----------+-------+------------+-----------+
   | total-traffic-       | 192      | 4     | IESG       | RFC 9244  |
   | normal-per-protocol  |          |       |            |           |
   +----------------------+----------+-------+------------+-----------+
   | total-traffic-       | 193      | 4     | IESG       | RFC 9244  |
   | normal-per-port      |          |       |            |           |
   +----------------------+----------+-------+------------+-----------+
   | total-connection-    | 194      | 4     | IESG       | RFC 9244  |
   | capacity-per-port    |          |       |            |           |
   +----------------------+----------+-------+------------+-----------+
   | total-traffic-       | 195      | 4     | IESG       | RFC 9244  |
   | protocol             |          |       |            |           |
   +----------------------+----------+-------+------------+-----------+
   | total-traffic-port   | 196      | 4     | IESG       | RFC 9244  |
   +----------------------+----------+-------+------------+-----------+
   | total-attack-        | 197      | 4     | IESG       | RFC 9244  |
   | traffic-protocol     |          |       |            |           |
   +----------------------+----------+-------+------------+-----------+
   | total-attack-        | 198      | 4     | IESG       | RFC 9244  |
   | traffic-port         |          |       |            |           |
   +----------------------+----------+-------+------------+-----------+
   | total-attack-        | 199      | 4     | IESG       | RFC 9244  |
   | connection-port      |          |       |            |           |
   +----------------------+----------+-------+------------+-----------+
   | port                 | 200      | 0     | IESG       | RFC 9244  |
   +----------------------+----------+-------+------------+-----------+
   | supported-query-type | 201      | 4     | IESG       | RFC 9244  |
   +----------------------+----------+-------+------------+-----------+
   | vendor-id            | 202      | 0     | IESG       | RFC 9244  |
   +----------------------+----------+-------+------------+-----------+
   | ietf-dots-           | 203      | 5     | IESG       | RFC 9244  |
   | telemetry:telemetry- |          |       |            |           |
   | setup                |          |       |            |           |
   +----------------------+----------+-------+------------+-----------+
   | ietf-dots-           | 204      | 4     | IESG       | RFC 9244  |
   | telemetry:total-     |          |       |            |           |
   | traffic              |          |       |            |           |
   +----------------------+----------+-------+------------+-----------+
   | ietf-dots-           | 205      | 4     | IESG       | RFC 9244  |
   | telemetry:total-     |          |       |            |           |
   | attack-traffic       |          |       |            |           |
   +----------------------+----------+-------+------------+-----------+
   | ietf-dots-           | 206      | 5     | IESG       | RFC 9244  |
   | telemetry:total-     |          |       |            |           |
   | attack-connection    |          |       |            |           |
   +----------------------+----------+-------+------------+-----------+
   | ietf-dots-           | 207      | 4     | IESG       | RFC 9244  |
   | telemetry:attack-    |          |       |            |           |
   | detail               |          |       |            |           |
   +----------------------+----------+-------+------------+-----------+
   | ietf-dots-           | 208      | 5     | IESG       | RFC 9244  |
   | telemetry:telemetry  |          |       |            |           |
   +----------------------+----------+-------+------------+-----------+
   | current-g            | 209      | 0     | IESG       | RFC 9244  |
   +----------------------+----------+-------+------------+-----------+
   | description-lang     | 210      | 3     | IESG       | RFC 9244  |
   +----------------------+----------+-------+------------+-----------+

         Table 4: Registered DOTS Signal Channel CBOR Key Values

## 13.2. DOTS Signal Channel Conflict Cause Codes

Okay bestie, IANA gave us a brand new code πŸ¦‹ in the "DOTS Signal Channel Conflict Cause Codes" registry [Cause], and that's all thanks to this document ✨

+======+===================+========================+===========+

CodeLabelDescriptionReference

+======+===================+========================+===========+

5overlapping-pipesOverlapping pipe scopeRFC 9244

+------+-------------------+------------------------+-----------+

Table 5: Registered DOTS Signal Channel Conflict Cause Code


## 13.3. DOTS Telemetry URIs and YANG Module Registrations

Per this document, IANA registered these URIs in the "ns" subregistry within the "IETF XML Registry" [RFC3688] πŸ’œ

URI: urn:ietf:params:xml:ns:yang:ietf-dots-telemetry Registrant Contact: The IESG. XML: N/A; the requested URI is an XML namespace.

URI: urn:ietf:params:xml:ns:yang:ietf-dots-mapping Registrant Contact: The IESG. XML: N/A; the requested URI is an XML namespace.


Per this document, IANA also registered these YANG modules in the "YANG Module Names" subregistry [RFC6020] within the "YANG Parameters" registry. Main character moment πŸ‘‘

Name: ietf-dots-telemetry Namespace: urn:ietf:params:xml:ns:yang:ietf-dots-telemetry Maintained by IANA: N Prefix: dots-telemetry Reference: RFC 9244

Name: ietf-dots-mapping Namespace: urn:ietf:params:xml:ns:yang:ietf-dots-mapping Maintained by IANA: N Prefix: dots-mapping Reference: RFC 9244


# 14. Security Considerations πŸ”₯

## 14.1. DOTS Signal Channel Telemetry

The security considerations for the DOTS signal channel protocol are discussed in Section 11 of [RFC9132]. This part covers the security stuff that's specific to the DOTS signal channel extension defined in this document, so pay attention πŸ™ˆ

The DOTS telemetry info includes DOTS client network topology, DOTS client domain pipe capacity, normal traffic baseline and connection capacity, plus threat and mitigation information. This is seriously sensitive tea, so it MUST be protected at rest by the DOTS server domain to prevent data leakage. Sharing this data with a trusted DOTS server doesn't add any big new worries beyond that protection, ngl. That server is already trusted to see this kind of info because it's the one watching and mitigating attacks anyway πŸ’…

DOTS clients are usually treated as trusted devices by the DOTS client domain. They may be co-located on network security services (like firewall devices), and a compromised security service can potentially do way more damage to the network than just the DOTS client component πŸ’€ This is different from the popular "zero-trust model" view, where devices are treated as untrusted. A compromised DOTS client can send fake DOTS telemetry data to a DOTS server to mislead it. You can prevent this by monitoring and auditing DOTS clients to catch misbehavior and deter misuse, and by only authorizing the DOTS client to convey DOTS telemetry information for specific target resources. For example, an application server is authorized to exchange DOTS telemetry for its IP addresses, but a DDoS mitigator can exchange DOTS telemetry for any target resource in the network. As a reminder, this is a variation of dealing with compromised DOTS clients as discussed in Section 11 of [RFC9132] 🫢

DOTS servers must be capable of defending themselves against DoS attacks from compromised DOTS clients. This list isn't complete, but these mitigation techniques can be used by a DOTS server to handle misbehaving DOTS clients:

- The probing rate (defined in Section 4.5 of [RFC9132]) can be used to limit the average data rate to the DOTS server.
- Rate-limiting DOTS telemetry, including packets with new `'tmid'` values from the same DOTS client, defends against DoS attacks that would result in varying the `'tmid'` to exhaust DOTS server resources. Likewise, the DOTS server can enforce a quota and time limit on the number of active pre-or-ongoing-mitigation telemetry data items (identified by `'tmid'`) from the DOTS client.

Also, the telemetry notification interval may be used to rate-limit the pre-or-ongoing-mitigation telemetry notifications received by a DOTS client domain 🌈

## 14.2. Vendor Attack Mapping

The security considerations for the DOTS data channel protocol are discussed in Section 10 of [RFC8783]. This section covers the security stuff specific to the DOTS data channel extension defined in this document πŸŽ€

All data nodes defined in the YANG module specified in Section 11.2 that can be created, modified, and deleted (that's config true, which is the default) are considered sensitive 😭 Write operations to these data nodes without proper protection can have a negative effect on network operations. Appropriate security measures are recommended to stop illegitimate users from invoking DOTS data channel primitives, as discussed in [RFC8783]. Even so, an attacker who can access a DOTS client is technically capable of doing stuff like:

- Communicating invalid attack mapping details to the server (`'/data-channel:dots-data/data-channel:dots-client/dots-telemetry:vendor-mapping'`), which will mislead the server when it correlates attack details.

Some of the readable data nodes in the YANG module specified in Section 11.2 may be considered sensitive, so controlling read access to them is important. Here are those data nodes and why they're sensitive πŸ“

- `'/data-channel:dots-data/data-channel:dots-client/dots-telemetry:vendor-mapping'` can be misused to infer the DDoS protection technology deployed in a DOTS client domain.
- `'/data-channel:dots-data/dots-telemetry:vendor-mapping'` can be used by a compromised DOTS client to leak the attack detection capabilities of the DOTS server. This is a variation of the compromised DOTS client attacks discussed in Section 14.1 🧚

# 15. References ✨

## 15.1. Normative References

okay bestie, the normative references are the must-read crew πŸ“š these are the docs the spec leans on hardcore, so they're all listed with every detail πŸ’–

- `[Private-Enterprise-Numbers]` IANA, "Private Enterprise Numbers", `https://www.iana.org/assignments/enterprise-numbers/`.
- `[RFC2119]` Bradner, S., "Key words for use in RFCs to Indicate Requirement Levels", BCP 14, RFC 2119, DOI 10.17487/RFC2119, March 1997, `https://www.rfc-editor.org/info/rfc2119`.
- `[RFC3688]` Mealling, M., "The IETF XML Registry", BCP 81, RFC 3688, DOI 10.17487/RFC3688, January 2004, `https://www.rfc-editor.org/info/rfc3688`.
- `[RFC5646]` Phillips, A., Ed. and M. Davis, Ed., "Tags for Identifying Languages", BCP 47, RFC 5646, DOI 10.17487/RFC5646, September 2009, `https://www.rfc-editor.org/info/rfc5646`.
- `[RFC6020]` Bjorklund, M., Ed., "YANG - A Data Modeling Language for the Network Configuration Protocol (NETCONF)", RFC 6020, DOI 10.17487/RFC6020, October 2010, `https://www.rfc-editor.org/info/rfc6020`.
- `[RFC6991]` Schoenwaelder, J., Ed., "Common YANG Data Types", RFC 6991, DOI 10.17487/RFC6991, July 2013, `https://www.rfc-editor.org/info/rfc6991`.
- `[RFC7252]` Shelby, Z., Hartke, K., and C. Bormann, "The Constrained Application Protocol (CoAP)", RFC 7252, DOI 10.17487/RFC7252, June 2014, `https://www.rfc-editor.org/info/rfc7252`.
- `[RFC7641]` Hartke, K., "Observing Resources in the Constrained Application Protocol (CoAP)", RFC 7641, DOI 10.17487/RFC7641, September 2015, `https://www.rfc-editor.org/info/rfc7641`.
- `[RFC7950]` Bjorklund, M., Ed., "The YANG 1.1 Data Modeling Language", RFC 7950, DOI 10.17487/RFC7950, August 2016, `https://www.rfc-editor.org/info/rfc7950`.
- `[RFC7959]` Bormann, C. and Z. Shelby, Ed., "Block-Wise Transfers in the Constrained Application Protocol (CoAP)", RFC 7959, DOI 10.17487/RFC7959, August 2016, `https://www.rfc-editor.org/info/rfc7959`.
- `[RFC7970]` Danyliw, R., "The Incident Object Description Exchange Format Version 2", RFC 7970, DOI 10.17487/RFC7970, November 2016, `https://www.rfc-editor.org/info/rfc7970`.
- `[RFC8040]` Bierman, A., Bjorklund, M., and K. Watsen, "RESTCONF Protocol", RFC 8040, DOI 10.17487/RFC8040, January 2017, `https://www.rfc-editor.org/info/rfc8040`.
- `[RFC8174]` Leiba, B., "Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words", BCP 14, RFC 8174, DOI 10.17487/RFC8174, May 2017, `https://www.rfc-editor.org/info/rfc8174`.
- `[RFC8345]` Clemm, A., Medved, J., Varga, R., Bahadur, N., Ananthakrishnan, H., and X. Liu, "A YANG Data Model for Network Topologies", RFC 8345, DOI 10.17487/RFC8345, March 2018, `https://www.rfc-editor.org/info/rfc8345`.
- `[RFC8783]` Boucadair, M., Ed. and T. Reddy.K, Ed., "Distributed Denial-of-Service Open Threat Signaling (DOTS) Data Channel Specification", RFC 8783, DOI 10.17487/RFC8783, May 2020, `https://www.rfc-editor.org/info/rfc8783`.
- `[RFC8791]` Bierman, A., BjΓΆrklund, M., and K. Watsen, "YANG Data Structure Extensions", RFC 8791, DOI 10.17487/RFC8791, June 2020, `https://www.rfc-editor.org/info/rfc8791`.
- `[RFC8949]` Bormann, C. and P. Hoffman, "Concise Binary Object Representation (CBOR)", STD 94, RFC 8949, DOI 10.17487/RFC8949, December 2020, `https://www.rfc-editor.org/info/rfc8949`.
- `[RFC9132]` Boucadair, M., Ed., Shallow, J., and T. Reddy.K, "Distributed Denial-of-Service Open Threat Signaling (DOTS) Signal Channel Specification", RFC 9132, DOI 10.17487/RFC9132, September 2021, `https://www.rfc-editor.org/info/rfc9132`.

---

## 15.2. Informative References

these ones are the extra reading 🧠 handy for context, not required to get the spec right, but they're so worth a peek πŸŽ€

- `[Cause]` IANA, "DOTS Signal Channel Conflict Cause Codes", `https://www.iana.org/assignments/dots/`.
- `[DOTS-Multihoming]` Boucadair, M., Reddy.K, T., and W. Pan, "Multi-homing Deployment Considerations for Distributed-Denial-of-Service Open Threat Signaling (DOTS)", Work in Progress, Internet-Draft, draft-ietf-dots-multihoming-13, 26 April 2022, `https://datatracker.ietf.org/doc/html/draft-ietf-dots-multihoming-13`.
- `[DOTS-Robust-Blocks]` Boucadair, M. and J. Shallow, "Distributed Denial-of-Service Open Threat Signaling (DOTS) Signal Channel Configuration Attributes for Robust Block Transmission", Work in Progress, Internet-Draft, draft-ietf-dots-robust-blocks-03, 11 February 2022, `https://datatracker.ietf.org/doc/html/draft-ietf-dots-robust-blocks-03`.
- `[DOTS-Telemetry-Specs]` Doron, E., Reddy, T., Andreasen, F., Xia, L., and K. Nishizuka, "Distributed Denial-of-Service Open Threat Signaling (DOTS) Telemetry Specifications", Work in Progress, Internet-Draft, draft-doron-dots-telemetry-00, 30 October 2016, `https://datatracker.ietf.org/doc/html/draft-doron-dots-telemetry-00`.
- `[Key-Map]` IANA, "DOTS Signal Channel CBOR Key Values", `https://www.iana.org/assignments/dots/`.
- `[PYANG]` "pyang", commit dad5c68, April 2022, `https://github.com/mbj4668/pyang`.
- `[RFC2330]` Paxson, V., Almes, G., Mahdavi, J., and M. Mathis, "Framework for IP Performance Metrics", RFC 2330, DOI 10.17487/RFC2330, May 1998, `https://www.rfc-editor.org/info/rfc2330`.
- `[RFC4732]` Handley, M., Ed., Rescorla, E., Ed., and IAB, "Internet Denial-of-Service Considerations", RFC 4732, DOI 10.17487/RFC4732, December 2006, `https://www.rfc-editor.org/info/rfc4732`.
- `[RFC5612]` Eronen, P. and D. Harrington, "Enterprise Number for Documentation Use", RFC 5612, DOI 10.17487/RFC5612, August 2009, `https://www.rfc-editor.org/info/rfc5612`.
- `[RFC8340]` Bjorklund, M. and L. Berger, Ed., "YANG Tree Diagrams", BCP 215, RFC 8340, DOI 10.17487/RFC8340, March 2018, `https://www.rfc-editor.org/info/rfc8340`.
- `[RFC8525]` Bierman, A., Bjorklund, M., Schoenwaelder, J., Watsen, K., and R. Wilton, "YANG Library", RFC 8525, DOI 10.17487/RFC8525, March 2019, `https://www.rfc-editor.org/info/rfc8525`.
- `[RFC8612]` Mortensen, A., Reddy, T., and R. Moskowitz, "DDoS Open Threat Signaling (DOTS) Requirements", RFC 8612, DOI 10.17487/RFC8612, May 2019, `https://www.rfc-editor.org/info/rfc8612`.
- `[RFC8811]` Mortensen, A., Ed., Reddy.K, T., Ed., Andreasen, F., Teague, N., and R. Compton, "DDoS Open Threat Signaling (DOTS) Architecture", RFC 8811, DOI 10.17487/RFC8811, August 2020, `https://www.rfc-editor.org/info/rfc8811`.
- `[RFC8903]` Dobbins, R., Migault, D., Moskowitz, R., Teague, N., Xia, L., and K. Nishizuka, "Use Cases for DDoS Open Threat Signaling", RFC 8903, DOI 10.17487/RFC8903, May 2021, `https://www.rfc-editor.org/info/rfc8903`.
- `[RFC9133]` Nishizuka, K., Boucadair, M., Reddy.K, T., and T. Nagata, "Controlling Filtering Rules Using Distributed Denial-of-Service Open Threat Signaling (DOTS) Signal Channel", RFC 9133, DOI 10.17487/RFC9133, September 2021, `https://www.rfc-editor.org/info/rfc9133`.
- `[RFC9177]` Boucadair, M. and J. Shallow, "Constrained Application Protocol (CoAP) Block-Wise Transfer Options Supporting Robust Transmission", RFC 9177, DOI 10.17487/RFC9177, March 2022, `https://www.rfc-editor.org/info/rfc9177`.
- `[RFC9260]` Stewart, R., TΓΌxen, M., and K. Nielsen, "Stream Control Transmission Protocol", RFC 9260, DOI 10.17487/RFC9260, June 2022, `https://www.rfc-editor.org/info/rfc9260`.

---

# Acknowledgments 🫢

the authors wanna give a huge shoutout to Flemming Andreasen, Liang Xia, and Kaname Nishizuka, who co-wrote [DOTS-Telemetry-Specs], plus everyone else who helped out on that doc πŸ’œ

big thanks to Kaname Nishizuka, Yuhei Hayashi, and Tom Petch for leaving comments and reviewing things πŸ™ˆ

extra special thanks to Jon Shallow and Kaname Nishizuka for all their implementation and interoperability work ✨

so many thank-yous to Jan Lindblad (yangdoctors review), Nagendra Nainar (opsdir review), James Gruessing (artart review), Michael Scharf (tsv-art review), Ted Lemon (int-dir review), and Robert Sparks (gen-art review) 🌈

thanks to Benjamin Kaduk for the detailed AD review πŸ‘‘

and thanks to Roman Danyliw, Γ‰ric Vyncke, Francesca Palombini, Warren Kumari, Erik Kline, Lars Eggert, and Robert Wilton for the IESG review πŸ’…

---

# Contributors 🌸

the following people helped contribute to this document 🧚

- Li Su, CMCC, Email: suli@chinamobile.com
- Pan Wei, Huawei, Email: william.panwei@huawei.com

---

# Authors' Addresses πŸ¦‹

these are the people who actually wrote it, so here are their contact details πŸ’–

Mohamed Boucadair (editor)

Orange 35000 Rennes France Email: mohamed.boucadair@orange.com


Tirumaleswar Reddy.K (editor)

Akamai Embassy Golf Link Business Park Bangalore 560071 Karnataka India Email: kondtir@gmail.com


Ehud Doron

Radware Ltd. Raoul Wallenberg Street Tel-Aviv 69710 Israel Email: ehudd@radware.com


Meiling Chen

CMCC 32 Xuanwumen West Street Beijing 100053 China Email: chenmeiling@chinamobile.com


Jon Shallow

United Kingdom Email: supjps-ietf@jpshallow.com


<rainbow>That's the whole spec, bestie! πŸŒˆβœ¨πŸ’…</rainbow>
πŸ“¦ where this page comes from