RFC 8783

Distributed Denial-of-Service Open Threat Signaling (DOTS) Data Channel Specification

πŸ“… published May 2020, from ietf

Distributed Denial-of-Service Open Threat Signaling (DOTS) Data Channel Specification ✨

RFC 8783 πŸŽ€ Title: Distributed Denial-of-Service Open Threat Signaling (DOTS) Data Channel Specification Authors: M. Boucadair, Ed. (Orange) and T. Reddy.K, Ed. (McAfee) πŸ’– Category: Standards Track Date: May 2020 ISSN: 2070-1721 Publisher: Internet Engineering Task Force (IETF) 🌸 Obsoletes / Updates: the title block doesn't list any, so it doesn't obsolete or update anything else πŸ¦‹


Abstract 🌈

okay so this doc specs the DOTS data channel 🧚, which is basically the bulk-data lane for stuff that just can't squeeze through the DOTS signal channel when a network is under attack πŸ’€. it's a companion to the signal channel spec in RFC 8782 🫢

Status of This Memo πŸ’…

this is an Internet Standards Track document, no cap πŸ‘‘

it's a product of the Internet Engineering Task Force (IETF) and it represents the consensus of the IETF community. it got public review and the Internet Engineering Steering Group (IESG) approved it for publication. if you want more on Internet Standards, check Section 2 of RFC 7841 πŸ“š

for info on the current status, any errata, or how to send feedback, go to https://www.rfc-editor.org/info/rfc8783 πŸ”—

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

this doc is subject to BCP 78 and the IETF Trust's Legal Provisions Relating to IETF Documents (https://trustee.ietf.org/license-info) as they stand on the publication date. please actually read these, because they explain your rights and restrictions for this document πŸ™ˆ code components pulled out of this doc have to include Simplified BSD License text, as described in Section 4.e of the Trust Legal Provisions, and they come with no warranty, as the Simplified BSD License describes πŸ“

Table of Contents πŸ¦‹

1.  Introduction
2.  Terminology
3.  DOTS Data Channel
  3.1.  Design Overview
  3.2.  DOTS Server(s) Discovery
  3.3.  DOTS Gateways
  3.4.  Detecting and Preventing Infinite Loops
  3.5.  Preventing Stale Entries
4.  DOTS Data Channel YANG Module
  4.1.  Generic Tree Structure
  4.2.  Filtering Fields
  4.3.  YANG Module
5.  Managing DOTS Clients
  5.1.  Registering DOTS Clients
  5.2.  De-registering DOTS Clients
6.  Managing DOTS Aliases
  6.1.  Creating Aliases
  6.2.  Retrieving Installed Aliases
  6.3.  Deleting Aliases
7.  Managing DOTS Filtering Rules
  7.1.  Retrieving DOTS Filtering Capabilities
  7.2.  Installing Filtering Rules
  7.3.  Retrieving Installed Filtering Rules
  7.4.  Removing Filtering Rules
8.  Operational Considerations
9.  IANA Considerations
10. Security Considerations
11. References
  11.1.  Normative References
  11.2.  Informative References
Appendix A.  Examples: Filtering Fragments
Appendix B.  Examples: Filtering TCP Messages
  B.1.  Discard TCP Null Attack
  B.2.  Rate-Limit SYN Flooding
  B.3.  Rate-Limit ACK Flooding
Acknowledgements
Contributors
Authors' Addresses

1. Introduction ✨

okay so a distributed denial-of-service (DDoS) attack is when someone tries to make machines or network resources unavailable to the people who are supposed to use them 😭 usually the attacker gets enough scale by compromising a bunch of end hosts and using those infected machines to run and amplify the attack. the victim can be an application server, a router, a firewall, a whole network, and so on πŸ’€

as [RFC8612] explains, there isn't a common way for the involved actors and network domains to coordinate a real-time response, and that slows down and weakens DDoS mitigation πŸ™ˆ so DDoS Open Threat Signaling (DOTS) defines an architecture where a DOTS client can send requests to a DOTS server for DDoS attack mitigation [DOTS-ARCH] 🫢 the whole point is to shrink the impact of these attacks, which helps make defensive, even proactive, security strategies actually efficient πŸ’… to do that, DOTS has two channels: the signal channel and the data channel (Figure 1) 🌸

+---------------+                                 +---------------+
|               | <------- Signal Channel ------> |               |
|  DOTS Client  |                                 |  DOTS Server  |
|               | <=======  Data Channel  ======> |               |
+---------------+                                 +---------------+

                      Figure 1: DOTS Channels

the DOTS signal channel carries info about a device or network (or part of one) that's under DDoS attack 🚨 a DOTS client sends that info upstream to a DOTS server, so the right mitigation actions can happen on traffic that looks suspicious πŸ‘€ the signal channel gets more detail in [RFC8782] ✨

the DOTS data channel is for infrequent bulk data exchange between DOTS agents, and it's a big deal for coordinating everyone who's responding to an attack πŸ”₯ Section 2 of [DOTS-ARCH] says the data channel is used for these tasks:

  • Creation of aliases for resources that might need mitigation 🧚

a DOTS client can send its DOTS server a collection of prefixes it wants to refer to by an alias when it asks for mitigation. the DOTS server can answer with either a success or a failure response (see Section 2 of [DOTS-ARCH]) πŸ’–

Refer to Section 6 for more details. πŸ’œ

  • Policy management, which lets a DOTS client ask for traffic filters to be installed or withdrawn, unwanted traffic to be dropped or rate-limited, and accept-listed traffic to be permitted πŸŽ€

a DOTS client is only allowed to instruct filtering rules on IP resources that belong to its own domain πŸ™…β€β™€οΈ here are some sample use cases for populating drop-list or accept-list filtering rules:

  • if a network resource (DOTS client) hears about a potential DDoS attack from a set of IP addresses, the DOTS client tells its servicing DOTS gateway about all the suspect IP addresses that need to go on the drop list for further investigation 🌈 it can also list protocols and port numbers in the drop-list rule ✨

the DOTS gateway then passes those drop-listed IP addresses to a DOTS server, which takes action so that traffic from these IP addresses heading to the target network (the one named by the DOTS client) gets blocked πŸ’€

  • a network with partner sites that only send legitimate traffic might want to make sure traffic from those sites doesn't get hit by DDoS attack mitigation πŸ¦‹ the DOTS client uses the DOTS data channel to send the accept-listed IP prefixes of those partner sites to its DOTS server 🫢

the DOTS server uses that info to accept-list flows from those IP prefixes that reach the network πŸ‘‘

Refer to Section 7 for more details. πŸ’…

2. Terminology 🌸

the key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document get read as described in BCP 14 [RFC2119] [RFC8174], but only when they show up in all capitals, like they do right here πŸ’œ lowercase versions are just regular words πŸ™ˆ

you should already know the terms defined in [RFC8612] 🧚

the terminology for describing YANG modules is defined in [RFC7950] πŸ“š and the meaning of the symbols in the tree diagrams is defined in [RFC8340] πŸŽ€

this document generalizes the idea of an Access Control List (ACL) so it isn't tied to one device [RFC8519] 🌈 so in this doc, an ACL is an ordered set of rules used to filter traffic, and each rule is an Access Control Entry (ACE) ✨ ACLs sent over the DOTS data channel aren't bound to a device interface πŸ’–

just to keep things simple, the examples in this document use /restconf as the discovered RESTCONF API root path πŸ“ a lot of protocol header lines and message-body text in the examples get split across multiple lines purely so they fit on the page 😭 when a line ends with a backslash (\) as its last character, that line is wrapped for display only, and you join it to the next line by deleting the backslash, the line break after it, and the leading whitespace on the next line 🫢

3. DOTS Data Channel 🧚

3.1. Design Overview πŸŽ€

okay so, unlike the DOTS signal channel, which has to stay operational even when packet loss is making a mess of things, the DOTS data channel is not expected to be fully operational at all times, especially when a DDoS attack is underway 😭. the requirements for a DOTS data channel protocol are documented in [RFC8612].

This specification does not require an order of DOTS signal and data channel creation nor does it mandate a time interval between them. These considerations are implementation and deployment specific 🌸.

As the primary function of the data channel is data exchange, a reliable transport mode is required in order for DOTS agents to detect data delivery success or failure πŸ’…. This document uses RESTCONF [RFC8040] over TLS over TCP as the DOTS data channel protocol. The abstract layering of the DOTS data channel is shown in Figure 2 πŸ¦‹.

                           +-------------------+
                           | DOTS Data Channel |
                           +-------------------+
                           |      RESTCONF     |
                           +-------------------+
                           |        TLS        |
                           +-------------------+
                           |        TCP        |
                           +-------------------+
                           |        IP         |
                           +-------------------+

              Figure 2: Abstract Layering of DOTS Data Channel

The HTTP POST, PUT, PATCH, and DELETE methods are used to edit data resources represented by DOTS data channel YANG modules 🧚. These basic edit operations let a DOTS client alter the running configuration of the DOTS data channel. Rules for generating and processing RESTCONF methods are defined in Section 4 of [RFC8040].

DOTS data channel configuration information, as well as state information, can be retrieved with the GET method πŸ”₯. An HTTP status-line is returned for each request to report success or failure for RESTCONF operations (Section 5.4 of [RFC8040]). The error-tag provides more information about encountered errors (Section 7 of [RFC8040]).

DOTS clients perform the root resource discovery procedure discussed in Section 3.1 of [RFC8040] to determine the root of the RESTCONF API πŸ‘‘. After discovering the RESTCONF API root, a DOTS client uses this value as the initial part of the path in the request URI in any subsequent request to the DOTS server. The DOTS server may support the retrieval of the YANG modules it supports (Section 3.7 of [RFC8040]). For example, a DOTS client may use RESTCONF to retrieve the vendor-specific YANG modules supported by its DOTS server ✨.

JavaScript Object Notation (JSON) [RFC8259] payloads are used to propagate the DOTS data-channel-specific payload messages that carry request parameters and response information, such as errors πŸ“. This specification uses the encoding rules defined in [RFC7951] for representing DOTS data channel configuration data using YANG (Section 4) as JSON text.

A DOTS client registers itself with its DOTS server(s) in order to set up DOTS data channel-related configuration data and to receive state data (i.e., non-configuration data) from the DOTS server(s) (Section 5) 🫢. Mutual authentication considerations are specified in Section 8 of [RFC8782]. The coupling of signal and data channels is discussed in Section 4.4.1 of [RFC8782].

A DOTS client can either maintain a persistent connection or initiate periodic connections with its DOTS server(s) πŸ’œ. If the DOTS client needs to frequently update the drop-list or accept-list filtering rules or aliases, it maintains a persistent connection with the DOTS server. For example, CAPTCHA and cryptographic puzzles can be used by the mitigation service in the DOTS client domain to determine whether or not the IP address is used for legitimate purpose, and the DOTS client can frequently update the drop-list filtering rules πŸ™ˆ. A persistent connection is also useful if the DOTS client subscribes to event notifications (Section 6.3 of [RFC8040]). Additional considerations related to RESTCONF connection management (including configuring the connection type or the reconnect strategy) can be found in [RESTCONF-MODELS].

A single DOTS data channel between DOTS agents can be used to exchange multiple requests and multiple responses. To reduce DOTS client and DOTS server workload, DOTS clients SHOULD reuse the same TLS session 🌈. While the communication to the DOTS server is quiescent, the DOTS client MAY probe the server to ensure it has maintained cryptographic state. Such probes can also keep firewall and/or NAT bindings alive. A TLS heartbeat [RFC6520] verifies that the DOTS server still has TLS state by returning a TLS message πŸ¦‹.

A DOTS server may detect conflicting filtering requests from distinct DOTS clients that belong to the same domain. For example, a DOTS client could request to drop-list a prefix by specifying the source prefix, while another DOTS client could request to accept-list that same source prefix, but both having the same destination prefix πŸ’€. DOTS servers SHOULD support a configuration parameter to indicate the behavior to follow when a conflict is detected (e.g., reject all, reject the new request, notify an administrator for validation). Section 7.2 specifies a default behavior when no instruction is supplied to a DOTS server.

How a DOTS client synchronizes its configuration with the one maintained by its DOTS server(s) is implementation specific. For example:

  • A DOTS client can systematically send a GET message before and/or after a configuration change request.
  • A DOTS client can reestablish the disconnected DOTS session after an attack is mitigated. Then, it sends a GET message before a configuration change request.

NAT considerations for the DOTS data channel are similar to those discussed in Section 3 of [RFC8782] 🌸.

The translation of filtering rules instantiated on a DOTS server into network configuration actions is out of scope of this specification.

Some of the fields introduced in Section 4 are also discussed in Sections 5, 6, and 7. These sections are authoritative for these fields πŸ‘‘.


3.2. DOTS Server(s) Discovery 🧚

This document assumes that DOTS clients are provisioned with the knowledge of how to reach their DOTS server(s), which could occur by a variety of means (e.g., local configuration or dynamic means such as DHCP [DOTS-SERVER-DISC]). The specification of such means is out of scope of this document πŸ’….

Likewise, it is out of scope of this document to specify the behavior to be followed by a DOTS client to send DOTS requests when multiple DOTS servers are provisioned (e.g., contact all DOTS servers, select one DOTS server among the list) ✨.


3.3. DOTS Gateways 🌸

When a server-domain DOTS gateway is involved in DOTS data channel exchanges, the same considerations for manipulating the cdid (client domain identifier) parameter specified in [RFC8782] MUST be followed by DOTS agents πŸŽ€. As a reminder, cdid is meant to assist the DOTS server in enforcing some policies (e.g., limit the number of filtering rules per DOTS client or per DOTS client domain). A loop detection mechanism for DOTS gateways is specified in Section 3.4.

If a DOTS gateway is involved, the DOTS gateway verifies that the DOTS client is authorized to undertake a data channel action (e.g., instantiate filtering rules). If the DOTS client is authorized, it propagates the rules to the upstream DOTS server. Likewise, the DOTS server verifies that the DOTS gateway is authorized to relay data channel actions 🫢. For example, to create or purge filters, a DOTS client sends its request to its DOTS gateway. The DOTS gateway validates the rules in the request and proxies the requests containing the filtering rules to its DOTS server. When the DOTS gateway receives the associated response from the DOTS server, it propagates the response back to the DOTS client πŸ¦‹.


3.4. Detecting and Preventing Infinite Loops πŸ”

In order to detect and prevent infinite loops, DOTS gateways MUST support the procedure defined in Section 5.7.1 of [RFC7230] 😭. In particular, each intermediate DOTS gateway MUST check that none of its own information (e.g., server names, literal IP addresses) is present in the Via header field of a DOTS message it receives:

  • If it detects that its own information is present in the Via header field, the DOTS gateway MUST NOT forward the DOTS message. Messages that cannot be forwarded because of a loop SHOULD be logged with a "508 Loop Detected" status-line returned to the DOTS peer. The structure of the reported error is depicted in Figure 3 πŸ’€.
error-app-tag:  loop-detected
error-tag:      operation-failed
error-type:     transport, application
error-info:     <via-header> : A copy of the Via header field when
                the loop was detected.
Description:    An infinite loop has been detected when forwarding
                a requests via a proxy.

                  Figure 3: Loop Detected Error

It is RECOMMENDED that DOTS clients and gateways support methods to alert administrators about loop errors so that appropriate actions are undertaken 🚨.

  • Otherwise, the DOTS agent MUST update or insert the Via header field by appending its own information 🌈.

Unless configured otherwise, DOTS gateways at the boundaries of a DOTS client domain SHOULD remove the previous Via header field information after checking for a loop before forwarding. This behavior is required for topology hiding purposes but can also serve to minimize potential conflicts that may arise if overlapping information is used in distinct DOTS domains (e.g., private IPv4 addresses, aliases that are not globally unique) πŸ•΅οΈβ€β™€οΈ.


3.5. Preventing Stale Entries 🧹

In order to avoid stale entries, a lifetime is associated with alias and filtering entries created by DOTS clients ⏳. Also, DOTS servers may track the inactivity timeout of DOTS clients to detect stale entries πŸ’œ.

4. DOTS Data Channel YANG Module ✨

4.1. Generic Tree Structure ✨

okay so the ietf-dots-data-channel YANG module gives DOTS clients a way to manage aliases πŸ¦‹ for resources they might want mitigation for. the vibe is: once you've made an alias, you can use it in later DOTS signal channel exchanges to point at the resources under attack way more efficiently πŸ’…

fair warning, the full module tree is split across several figures so each subtree is easier to read πŸŽ€

the tree for the DOTS alias is in Figure 4 πŸ‘‡

module: ietf-dots-data-channel
  +--rw dots-data
     +--rw dots-client* [cuid]
     |  +--rw cuid            string
     |  +--rw cdid?           string
     |  +--rw aliases
     |  |  +--rw alias* [name]
     |  |     +--rw name                 string
     |  |     +--rw target-prefix*       inet:ip-prefix
     |  |     +--rw target-port-range* [lower-port]
     |  |     |  +--rw lower-port    inet:port-number
     |  |     |  +--rw upper-port?   inet:port-number
     |  |     +--rw target-protocol*     uint8
     |  |     +--rw target-fqdn*         inet:domain-name
     |  |     +--rw target-uri*          inet:uri
     |  |     +--ro pending-lifetime?    int32
     |  +--rw acls
     |     ...
     +--ro capabilities
        ...

                     Figure 4: DOTS Alias Subtree

the ietf-dots-data-channel module ALSO lets DOTS clients manage filtering rules πŸ”₯ the main flavours are:

  • Drop-list management 🚫, where a DOTS client tells a DOTS server which sources traffic should be discarded from.
  • Accept-list management πŸ’œ, where a DOTS client tells a DOTS server which sources traffic should always be accepted from.
  • Policy management πŸ‘‘, where a DOTS client asks for traffic filters to be installed or withdrawn, unwanted traffic to be dropped or rate-limited, and accept-listed traffic to be allowed through.

these are examples, not the full list, so don't treat them as the whole menu πŸ“

the tree for the DOTS filtering entries is in Figure 5 🧚

the investigators looked at whether they could just augment ietf-access-control-list to cover DOTS needs, and it was a no-go πŸ’€ it couldn't handle a bunch of the DOTS requirements, like:

  • Retrieving a filtering entry (or all of them) that a DOTS client created πŸ”
  • Deleting a filtering entry that a DOTS client instantiated πŸ—‘οΈ

so the move was to define new DOTS filtering entries (aka ACLs) that copy the structure from [RFC8519] 🫢 the way it works: DOTS agents handle an ordered list of ACLs, and each ACL has its own ordered list of ACEs. every ACE has a group of match criteria and a group of action criteria ✨

here's the processing logic, bestie 🧠 once every ACE in an ACL has been walked through with no match, the ACE entries of the following ACLs get walked through too, until something matches. at that point the specified action is applied. if nothing matches while the system is idle (meaning no mitigation is active), there's no further action to take on that packet. if nothing matches during active mitigation, the packet still gets scrubbed by the DDoS mitigator πŸ›‘οΈ

the ACL subtree is in Figure 5 🌈

module: ietf-dots-data-channel
  +--rw dots-data
     +--rw dots-client* [cuid]
     |  +--rw cuid            string
     |  +--rw cdid?           string
     |  +--rw aliases
     |  |  ...
     |  +--rw acls
     |     +--rw acl* [name]
     |        +--rw name                string
     |        +--rw type?               ietf-acl:acl-type
     |        +--rw activation-type?    activation-type
     |        +--ro pending-lifetime?   int32
     |        +--rw aces
     |           +--rw ace* [name]
     |              +--rw name          string
     |              +--rw matches
     |              |  +--rw (l3)?
     |              |  |  +--:(ipv4)
     |              |  |  |  ...
     |              |  |  +--:(ipv6)
     |              |  |     ...
     |              |  +--rw (l4)?
     |              |     +--:(tcp)
     |              |     |  ...
     |              |     +--:(udp)
     |              |     |  ...
     |              |     +--:(icmp)
     |              |        ...
     |              +--rw actions
     |              |  +--rw forwarding    identityref
     |              |  +--rw rate-limit?   decimal64
     |              +--ro statistics
     |                 +--ro matched-packets?   yang:counter64
     |                 +--ro matched-octets?    yang:counter64
     +--ro capabilities
        ...

                 Figure 5: DOTS ACLs Subtree

filtering rules from a DOTS client assume a default direction: the destination is the DOTS client's domain 🎯

DOTS forwarding actions can be accept (accept the matching traffic) or drop (drop the matching traffic WITHOUT sending any ICMP error message) πŸ™…β€β™€οΈ accepted traffic can also be subject to rate-limiting via rate-limit 🚦

the reject action (drop the matching traffic AND send an ICMP error message to the source) is NOT supported in ietf-dots-data-channel πŸ™ˆ why? because it's not appropriate for DDoS mitigation. generating ICMP messages to report drops during a DDoS attack will make the attack worse 😭 and an attacker can literally use those ICMP messages as a signal that their traffic is being blocked πŸ’€

4.2. Filtering Fields πŸŽ€

the ietf-dots-data-channel module reuses the packet fields module ietf-packet-fields from [RFC8519] πŸ§šβ€β™€οΈ that one lets you match on packet fields across IPv4, IPv6, and transport layers. the ietf-dots-data-channel module can also be augmented to add protocol-specific matching fields if needed πŸ’–

this spec adds a brand-new IPv4/IPv6 matching field called fragment 🧩 why? because [RFC8519] doesn't support fragment matching for IPv6, and for IPv4 it only partly covers it through flags πŸ₯² the problem with flags is that it doesn't let you define a bitmask. so if a packet has other bits set that aren't covered by the flags filtering clause, it'll sneak right through (because it won't match the ACE) 😀 you can check out how fragment is used in Appendix A πŸ“–

Figure 6 is the IPv4 match subtree πŸ‘‡

module: ietf-dots-data-channel
  +--rw dots-data
     +--rw dots-client* [cuid]
     |  ...
     |  +--rw acls
     |     +--rw acl* [name]
     |        ...
     |        +--rw aces
     |           +--rw ace* [name]
     |              +--rw name          string
     |              +--rw matches
     |              |  +--rw (l3)?
     |              |  |  +--:(ipv4)
     |              |  |  |  +--rw ipv4
     |              |  |  |     +--rw dscp?                 inet:dscp
     |              |  |  |     +--rw ecn?                  uint8
     |              |  |  |     +--rw length?               uint16
     |              |  |  |     +--rw ttl?                  uint8
     |              |  |  |     +--rw protocol?             uint8
     |              |  |  |     +--rw ihl?                  uint8
     |              |  |  |     +--rw flags?                bits
     |              |  |  |     +--rw offset?               uint16
     |              |  |  |     +--rw identification?       uint16
     |              |  |  |     +--rw (destination-network)?
     |              |  |  |     |  +--:(destination-ipv4-network)
     |              |  |  |     |     +--rw destination-ipv4-network?
     |              |  |  |     |             inet:ipv4-prefix
     |              |  |  |     +--rw (source-network)?
     |              |  |  |     |  +--:(source-ipv4-network)
     |              |  |  |     |     +--rw source-ipv4-network?
     |              |  |  |     |             inet:ipv4-prefix
     |              |  |  |     +--rw fragment
     |              |  |  |        +--rw operator?        operator
     |              |  |  |        +--rw type        fragment-type
     |              |  |  +--:(ipv6)
     |              |  |     ...
     |              |  +--rw (l4)?
     |              |     ...
     |              +--rw actions
     |              |  ...
     |              +--ro statistics
     |                 ...
     +--ro capabilities
        ...

              Figure 6: DOTS ACLs Subtree (IPv4 Match)

Figure 7 is the IPv6 match subtree πŸ‘‡

module: ietf-dots-data-channel
  +--rw dots-data
     +--rw dots-client* [cuid]
     |  ...
     |  +--rw acls
     |     +--rw acl* [name]
     |        ...
     |        +--rw aces
     |           +--rw ace* [name]
     |              +--rw name          string
     |              +--rw matches
     |              |  +--rw (l3)?
     |              |  |  +--:(ipv4)
     |              |  |  |  ...
     |              |  |  +--:(ipv6)
     |              |  |     +--rw ipv6
     |              |  |        +--rw dscp?                 inet:dscp
     |              |  |        +--rw ecn?                  uint8
     |              |  |        +--rw length?               uint16
     |              |  |        +--rw ttl?                  uint8
     |              |  |        +--rw protocol?             uint8
     |              |  |        +--rw (destination-network)?
     |              |  |        |  +--:(destination-ipv6-network)
     |              |  |        |     +--rw destination-ipv6-network?
     |              |  |        |             inet:ipv6-prefix
     |              |  |        +--rw (source-network)?
     |              |  |        |  +--:(source-ipv6-network)
     |              |  |        |     +--rw source-ipv6-network?
     |              |  |        |             inet:ipv6-prefix
     |              |  |        +--rw flow-label?
     |              |  |        |       inet:ipv6-flow-label
     |              |  |        +--rw fragment
     |              |  |           +--rw operator?       operator
     |              |  |           +--rw type       fragment-type
     |              |  +--rw (l4)?
     |              |     ...
     |              +--rw actions
     |              |  ...
     |              +--ro statistics
     |                 ...
     +--ro capabilities
        ...

              Figure 7: DOTS ACLs Subtree (IPv6 Match)

Figure 8 shows the TCP match subtree πŸ¦‹ on top of the fields defined in [RFC8519], this spec also defines a new TCP matching field called flags-bitmask πŸ’œ it's there to make TCP flags filtering rules way more efficient 🫢 there are some examples in Appendix B 🌸

Okay bestie, the TCP match tree is the main character of this section πŸ’… It's the one with all the port and flag fields, and yes, it's giving detail πŸŽ€

      +--rw matches
      |  +--rw (l3)?
      |  |  ...
      |  +--rw (l4)?
      |     +--:(tcp)
      |     |  +--rw tcp
      |     |     +--rw sequence-number?          uint32
      |     |     +--rw acknowledgement-number?   uint32
      |     |     +--rw data-offset?              uint8
      |     |     +--rw reserved?                 uint8
      |     |     +--rw flags?                    bits
      |     |     +--rw window-size?              uint16
      |     |     +--rw urgent-pointer?           uint16
      |     |     +--rw options?                  binary
      |     |     +--rw flags-bitmask
      |     |     |  +--rw operator?            operator
      |     |     |  +--rw bitmask                uint16
      |     |     +--rw (source-port)?
      |     |     |  +--:(source-port-range-or-operator)
      |     |     |     +--rw source-port-range-or-operator
      |     |     |        +--rw (port-range-or-operator)?
      |     |     |           +--:(range)
      |     |     |           |  +--rw lower-port
      |     |     |           |  |       inet:port-number
      |     |     |           |  +--rw upper-port
      |     |     |           |          inet:port-number
      |     |     |           +--:(operator)
      |     |     |              +--rw operator?
      |     |     |              |       operator
      |     |     |              +--rw port
      |     |     |                      inet:port-number
      |     |     +--rw (destination-port)?
      |     |        +--:(destination-port-range-or-operator)
      |     |           +--rw destination-port-range-or-operator
      |     |              +--rw (port-range-or-operator)?
      |     |                 +--:(range)
      |     |                 |  +--rw lower-port
      |     |                 |  |       inet:port-number
      |     |                 |  +--rw upper-port
      |     |                 |          inet:port-number
      |     |                 +--:(operator)
      |     |                    +--rw operator?
      |     |                    |       operator
      |     |                    +--rw port
      |     |                            inet:port-number
      |     +--:(udp)
      |     |  ...
      |     +--:(icmp)
      |        ...
      +--rw actions
      |  ...

                  Figure 8: DOTS ACLs Subtree (TCP Match)

Figure 9 is the UDP and ICMP version πŸ’– Same vibe, different fields πŸ¦‹ Both ICMP and ICMPv6 use the same structure, and whether an ACL is about ICMP or ICMPv6 comes down to the 'l3' match or the ACL type 🧚

      +--rw matches
      |  +--rw (l3)?
      |  |  ...
      |  +--rw (l4)?
      |     +--:(tcp)
      |     |  ...
      |     +--:(udp)
      |     |  +--rw udp
      |     |     +--rw length?          uint16
      |     |     +--rw (source-port)?
      |     |     |  +--:(source-port-range-or-operator)
      |     |     |     +--rw source-port-range-or-operator
      |     |     |        +--rw (port-range-or-operator)?
      |     |     |           +--:(range)
      |     |     |           |  +--rw lower-port
      |     |     |           |  |       inet:port-number
      |     |     |           |  +--rw upper-port
      |     |     |           |          inet:port-number
      |     |     |           +--:(operator)
      |     |     |              +--rw operator?
      |     |     |              |       operator
      |     |     |              +--rw port
      |     |     |                      inet:port-number
      |     |     +--rw (destination-port)?
      |     |        +--:(destination-port-range-or-operator)
      |     |           +--rw destination-port-range-or-operator
      |     |              +--rw (port-range-or-operator)?
      |     |                 +--:(range)
      |     |                 |  +--rw lower-port
      |     |                 |  |       inet:port-number
      |     |                 |  +--rw upper-port
      |     |                 |          inet:port-number
      |     |                 +--:(operator)
      |     |                    +--rw operator?
      |     |                    |       operator
      |     |                    +--rw port
      |     |                            inet:port-number
      |     +--:(icmp)
      |        +--rw icmp
      |           +--rw type?             uint8
      |           +--rw code?             uint8
      |           +--rw rest-of-header?   binary
      +--rw actions
      |  ...

              Figure 9: DOTS ACLs Subtree (UDP and ICMP Match)

Now for the big rule 🚨 DOTS implementations MUST support matching on the IP header (IPv4 and IPv6), matching on the transport header (TCP, UDP, and ICMP), and matching on any combination of those. The same matching fields work for both ICMP and ICMPv6, so you don't have to double up πŸ™Œ

These match fields MUST be supported by DOTS implementations, and this table is the list πŸ‘‘

       +-----------+-----------------------------------------------+
       | ACL Match | Mandatory Fields                              |
       +===========+===============================================+
       | ipv4      | length, protocol, destination-ipv4-network,   |
       |           | source-ipv4-network, and fragment             |
       +-----------+-----------------------------------------------+
       | ipv6      | length, protocol, destination-ipv6-network,   |
       |           | source-ipv6-network, and fragment             |
       +-----------+-----------------------------------------------+
       | tcp       | flags-bitmask, source-port-range-or-operator, |
       |           | and destination-port-range-or-operator        |
       +-----------+-----------------------------------------------+
       | udp       | length, source-port-range-or-operator, and    |
       |           | destination-port-range-or-operator            |
       +-----------+-----------------------------------------------+
       | icmp      | type and code                                 |
       +-----------+-----------------------------------------------+

                Table 1: Mandatory DOTS Channel Match Fields

Implementations MAY support other filtering match fields and actions, so this is where the extras live ✨ The 'ietf-dots-data-channel' YANG module gives an implementation a way to show off what its filtering can do πŸ’… The tree for 'capabilities' is in Figure 10. One big heads-up: DOTS clients that support both 'fragment' and 'flags' (or 'flags-bitmask' and 'flags') matching fields MUST NOT set these fields in the same request. Don't mix them, bestie πŸ™…β€β™€οΈ

   module: ietf-dots-data-channel
     +--rw dots-data
        ...
        +--ro capabilities
           +--ro address-family*        enumeration
           +--ro forwarding-actions*    identityref
           +--ro rate-limit?            boolean
           +--ro transport-protocols*   uint8
           +--ro ipv4
           |  +--ro dscp?                 boolean
           |  +--ro ecn?                  boolean
           |  +--ro length?               boolean
           |  +--ro ttl?                  boolean
           |  +--ro protocol?             boolean
           |  +--ro ihl?                  boolean
           |  +--ro flags?                boolean
           |  +--ro offset?               boolean
           |  +--ro identification?       boolean
           |  +--ro source-prefix?        boolean
           |  +--ro destination-prefix?   boolean
           |  +--ro fragment?             boolean
           +--ro ipv6
           |  +--ro dscp?                 boolean
           |  +--ro ecn?                  boolean
           |  +--ro length?               boolean
           |  +--ro hoplimit?             boolean
           |  +--ro protocol?             boolean
           |  +--ro destination-prefix?   boolean
           |  +--ro source-prefix?        boolean
           |  +--ro flow-label?           boolean
           |  +--ro fragment?             boolean
           +--ro tcp
           |  +--ro sequence-number?          boolean
           |  +--ro acknowledgement-number?   boolean
           |  +--ro data-offset?              boolean
           |  +--ro reserved?                 boolean
           |  +--ro flags?                    boolean
           |  +--ro window-size?              boolean
           |  +--ro urgent-pointer?           boolean
           |  +--ro options?                  boolean
           |  +--ro flags-bitmask?            boolean
           |  +--ro source-port?              boolean
           |  +--ro destination-port?         boolean
           |  +--ro port-range?               boolean
           +--ro udp
           |  +--ro length?             boolean
           |  +--ro source-port?        boolean
           |  +--ro destination-port?   boolean
           |  +--ro port-range?         boolean
           +--ro icmp
              +--ro type?             boolean
              +--ro code?             boolean
              +--ro rest-of-header?   boolean

                 Figure 10: Filtering Capabilities Subtree

4.3. YANG Module

Time for the YANG module 🌈 This one pulls in the common YANG types from [RFC6991] and the types from [RFC8519], so it's basically borrowing the good stuff from its friends 🫢

   <CODE BEGINS> file "ietf-dots-data-channel@2020-05-28.yang"
   module ietf-dots-data-channel {
     yang-version 1.1;
     namespace "urn:ietf:params:xml:ns:yang:ietf-dots-data-channel";
     prefix data-channel;

     import ietf-inet-types {
       prefix inet;
       reference
         "Section 4 of RFC 6991";
     }
     import ietf-access-control-list {
       prefix ietf-acl;
       reference
         "RFC 8519: YANG Data Model for Network Access
                    Control Lists (ACLs)";
     }
     import ietf-packet-fields {
       prefix packet-fields;
       reference
         "RFC 8519: YANG Data Model for Network Access
                    Control Lists (ACLs)";
     }

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

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

        Editor:  Konda, Tirumaleswar Reddy.K
                 <mailto:TirumaleswarReddy_Konda@McAfee.com>

        Author:  Jon Shallow
                 <mailto:jon.shallow@nccgroup.com>

        Author:  Kaname Nishizuka
                 <mailto:kaname@nttv6.jp>

        Author:  Liang Xia
                 <mailto:frank.xialiang@huawei.com>

        Author:  Prashanth Patil
                 <mailto:praspati@cisco.com>

        Author:  Andrew Mortensen
                 <mailto:amortensen@arbor.net>

        Author:  Nik Teague
                 <mailto:nteague@ironmountain.co.uk>";
     description
       "This module contains YANG definition for configuring
        aliases for resources and filtering rules using DOTS
        data channel.

        Copyright (c) 2020 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 Simplified BSD License
        set forth in Section 4.c of the IETF Trust's Legal Provisions
        Relating to IETF Documents
        (http://trustee.ietf.org/license-info).

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

     revision 2020-05-28 {
       description
         "Initial revision.";
       reference
         "RFC 8783: Distributed Denial-of-Service Open Threat
                    Signaling (DOTS) Data Channel Specification";
     }

Okay, the YANG is about to get spicy πŸ’…πŸŽ€

     typedef activation-type {
       type enumeration {
         enum activate-when-mitigating {
           value 1;
           description
             "The Access Control List (ACL) is installed only when
              a mitigation is active for the DOTS client.";
         }
         enum immediate {
           value 2;
           description
             "The ACL is immediately activated.";
         }
         enum deactivate {
           value 3;
           description
             "The ACL is maintained by the DOTS server, but it is
              deactivated.";
         }
       }
       description
         "Indicates the activation type of an ACL.";
     }

     typedef operator {
       type bits {
         bit not {
           position 0;
           description
             "If set, logical negation of operation.";
         }
         bit match {
           position 1;
           description
             "Match bit.  This is a bitwise match operation
              defined as '(data & value) == value'.";
         }
         bit any {
           position 3;
           description
             "Any bit.  This is a match on any of the bits in
              bitmask.  It evaluates to 'true' if any of the bits
              in the value mask are set in the data,
              i.e., '(data & value) != 0'.";
         }
       }
       description
         "Specifies how to apply the defined bitmask.
          'any' and 'match' bits must not be set simultaneously.";
     }

     grouping tcp-flags {
       leaf operator {
         type operator;
         default "match";
         description
           "Specifies how to interpret the TCP flags.";
       }
       leaf bitmask {
         type uint16;
         mandatory true;
         description
           "The bitmask matches the last 4 bits of byte 12
            and byte 13 of the TCP header.  For clarity, the 4 bits
            of byte 12 corresponding to the TCP data offset field
            are not included in any matching.";
       }
       description
         "Operations on TCP flags.";
     }

     typedef fragment-type {
       type bits {
         bit df {
           position 0;
           description
             "Don't fragment bit for IPv4.
              Must be set to 0 when it appears in an IPv6 filter.";
         }
         bit isf {
           position 1;
           description
             "Is a fragment.";
         }
         bit ff {
           position 2;
           description
             "First fragment.";
         }
         bit lf {
           position 3;
           description
             "Last fragment.";
         }
       }
       description
         "Different fragment types to match against.";
     }

     grouping target {
       description
         "Specifies the targets of the mitigation request.";
       leaf-list target-prefix {
         type inet:ip-prefix;
         description
           "IPv4 or IPv6 prefix identifying the target.";
       }
       list target-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;
           mandatory true;
           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.";
         }
       }
       leaf-list target-protocol {
         type uint8;
         description
           "Identifies the target protocol number.

            Values are taken from the IANA protocol registry:
            https://www.iana.org/assignments/protocol-numbers/

            For example, 6 for TCP or 17 for UDP.";
       }
       leaf-list target-fqdn {
         type inet:domain-name;
         description
           "FQDN identifying the target.";
       }
       leaf-list target-uri {
         type inet:uri;
         description
           "URI identifying the target.";
       }
     }

     grouping fragment-fields {
       leaf operator {
         type operator;
         default "match";
         description
           "Specifies how to interpret the fragment type.";
       }
       leaf type {
         type fragment-type;
         mandatory true;
         description
           "Indicates what fragment type to look for.";
       }
       description
         "Operations on fragment types.";
     }

     grouping aliases {
       description
         "Top-level container for aliases.";
       list alias {
         key "name";
         description
           "List of aliases.";
         leaf name {
           type string;
           description
             "The name of the alias.";
         }
         uses target;
         leaf pending-lifetime {
           type int32;
           units "minutes";
           config false;
           description
             "Indicates the pending validity lifetime of the alias
              entry.";
         }
       }
     }

     grouping ports {
       choice source-port {
         container source-port-range-or-operator {
           uses packet-fields:port-range-or-operator;
           description
             "Source port definition.";
         }
         description
           "Choice of specifying the source port or referring to
            a group of source port numbers.";
       }
       choice destination-port {
         container destination-port-range-or-operator {
           uses packet-fields:port-range-or-operator;
           description
             "Destination port definition.";
         }
         description
           "Choice of specifying a destination port or referring
            to a group of destination port numbers.";
       }
       description
         "Choice of specifying a source or destination port numbers.";
     }

     grouping access-lists {
       description
         "Specifies the ordered set of Access Control Lists.";
       list acl {
         key "name";
         ordered-by user;
         description
           "An ACL is an ordered list of Access Control Entries (ACE).
            Each ACE has a list of match criteria and a list of
            actions.";
         leaf name {
           type string {
             length "1..64";
           }
           description
             "The name of the access list.";
           reference
             "RFC 8519: YANG Data Model for Network Access
                        Control Lists (ACLs)";
         }
         leaf type {
           type ietf-acl:acl-type;
           description
             "Type of access control list.  Indicates the primary
              intended type of match criteria (e.g., IPv4, IPv6)
              used in the list instance.";
           reference
             "RFC 8519: YANG Data Model for Network Access
                        Control Lists (ACLs)";
         }
         leaf activation-type {
           type activation-type;
           default "activate-when-mitigating";
           description
             "Indicates the activation type of an ACL.  An ACL can be
              deactivated, installed immediately, or installed when
              a mitigation is active.";
         }
         leaf pending-lifetime {
           type int32;
           units "minutes";
           config false;
           description
             "Indicates the pending validity lifetime of the ACL
              entry.";
         }
         container aces {
           description
             "The Access Control Entries container contains
              a list of ACEs.";
           list ace {
             key "name";
             ordered-by user;
             description
               "List of access list entries.";
             leaf name {
               type string {
                 length "1..64";
               }
               description
                 "A unique name identifying this ACE.";
               reference
                 "RFC 8519: YANG Data Model for Network Access
                            Control Lists (ACLs)";
             }
             container matches {
               description
                 "The rules in this set determine what fields will be
                  matched upon before any action is taken on them.

                  If no matches are defined in a particular container,
                  then any packet will match that container.

okay so we're still deep in the YANG module, bestie πŸ’– and the ACE rules are giving main character energy πŸ’…

                  If no matches are specified at all in an ACE, then any
                  packet will match the ACE.";
               reference
                 "RFC 8519: YANG Data Model for Network Access
                            Control Lists (ACLs)";
               choice l3 {
                 container ipv4 {
                   when "derived-from(../../../../type, "
                      + "'ietf-acl:ipv4-acl-type')";
                   uses packet-fields:acl-ip-header-fields;
                   uses packet-fields:acl-ipv4-header-fields;
                   container fragment {
                     description
                       "Indicates how to handle IPv4 fragments.";
                     uses fragment-fields;
                   }
                   description
                     "Rule set that matches IPv4 header.";
                 }
                 container ipv6 {
                   when "derived-from(../../../../type, "
                      + "'ietf-acl:ipv6-acl-type')";
                   uses packet-fields:acl-ip-header-fields;
                   uses packet-fields:acl-ipv6-header-fields;
                   container fragment {
                     description
                       "Indicates how to handle IPv6 fragments.";
                     uses fragment-fields;
                   }
                   description
                     "Rule set that matches IPv6 header.";
                 }
                 description
                   "Either IPv4 or IPv6.";
               }
               choice l4 {
                 container tcp {
                   uses packet-fields:acl-tcp-header-fields;
                   container flags-bitmask {
                     description
                       "Indicates how to handle TCP flags.";
                     uses tcp-flags;
                   }
                   uses ports;
                   description
                     "Rule set that matches TCP header.";
                 }
                 container udp {
                   uses packet-fields:acl-udp-header-fields;
                   uses ports;
                   description
                     "Rule set that matches UDP header.";
                 }
                 container icmp {
                   uses packet-fields:acl-icmp-header-fields;
                   description
                     "Rule set that matches ICMP/ICMPv6 header.";
                 }
                 description
                   "Can be TCP, UDP, or ICMP/ICMPv6";
               }
             }
             container actions {
               description
                 "Definitions of action for this ACE.";
               leaf forwarding {
                 type identityref {
                   base ietf-acl:forwarding-action;
                 }
                 mandatory true;
                 description
                   "Specifies the forwarding action per ACE.";
                 reference
                   "RFC 8519: YANG Data Model for Network Access
                              Control Lists (ACLs)";
               }
               leaf rate-limit {
                 when "../forwarding = 'ietf-acl:accept'" {
                   description
                     "Rate-limit is valid only when accept action is
                      used.";
                 }
                 type decimal64 {
                   fraction-digits 2;
                 }
                 units "bytes per second";
                 description
                   "Specifies how to rate-limit the traffic.";
               }
             }
             container statistics {
               config false;
               description
                 "Aggregate statistics.";
               uses ietf-acl:acl-counters;
             }
           }
         }
       }
     }

     container dots-data {
       description
         "Main container for DOTS data channel.";
       list dots-client {
         key "cuid";
         description
           "List of DOTS clients.";
         leaf cuid {
           type string;
           description
             "A unique identifier that is generated by a DOTS client
              to prevent request collisions.";
           reference
             "RFC 8782: Distributed Denial-of-Service Open Threat
                     Signaling (DOTS) Signal Channel Specification";
         }
         leaf cdid {
           type string;
           description
             "A client domain identifier conveyed by a
              server-domain DOTS gateway to a remote DOTS server.";
           reference
             "RFC 8782: Distributed Denial-of-Service Open Threat
                     Signaling (DOTS) Signal Channel Specification";
         }
         container aliases {
           description
             "Set of aliases that are bound to a DOTS client.";
           uses aliases;
         }
         container acls {
           description
             "Access lists that are bound to a DOTS client.";
           uses access-lists;
         }
       }
       container capabilities {
         config false;
         description
           "Match capabilities";
         leaf-list address-family {
           type enumeration {
             enum ipv4 {
               description
                 "IPv4 is supported.";
             }
             enum ipv6 {
               description
                 "IPv6 is supported.";
             }
           }
           description
             "Indicates the IP address families supported by
              the DOTS server.";
         }
         leaf-list forwarding-actions {
           type identityref {
             base ietf-acl:forwarding-action;
           }
           description
             "Supported forwarding action(s).";
         }
         leaf rate-limit {
           type boolean;
           description
             "Support of rate-limit action.";
         }
         leaf-list transport-protocols {
           type uint8;
           description
             "Upper-layer protocol associated with a filtering rule.

              Values are taken from the IANA protocol registry:
              https://www.iana.org/assignments/protocol-numbers/

okay so we're still deep in the YANG module, bestie πŸ’… this chunk is all about the capability flags for IPv4, IPv6, TCP, UDP and ICMP, so a DOTS server can say exactly which filters it can enforce πŸ¦‹

              For example, this field contains 1 for ICMP, 6 for TCP
              17 for UDP, or 58 for ICMPv6.";
         }
         container ipv4 {
           description
             "Indicates IPv4 header fields that are supported to enforce
              ACLs.";
           leaf dscp {
             type boolean;
             description
               "Support of filtering based on Differentiated Services
                Code Point (DSCP).";
           }
           leaf ecn {
             type boolean;
             description
               "Support of filtering based on Explicit Congestion
                Notification (ECN).";
           }
           leaf length {
             type boolean;
             description
               "Support of filtering based on the Total Length.";
           }
           leaf ttl {
             type boolean;
             description
               "Support of filtering based on the Time to Live (TTL).";
           }
           leaf protocol {
             type boolean;
             description
               "Support of filtering based on protocol field.";
           }
           leaf ihl {
             type boolean;
             description
               "Support of filtering based on the Internet Header
                Length (IHL).";
           }
           leaf flags {
             type boolean;
             description
               "Support of filtering based on the 'flags'.";
           }
           leaf offset {
             type boolean;
             description
               "Support of filtering based on the 'offset'.";
           }
           leaf identification {
             type boolean;
             description
               "Support of filtering based on the 'identification'.";
           }
           leaf source-prefix {
             type boolean;
             description
               "Support of filtering based on the source prefix.";
           }
           leaf destination-prefix {
             type boolean;
             description
               "Support of filtering based on the destination prefix.";
           }
           leaf fragment {
             type boolean;
             description
               "Indicates the capability of a DOTS server to
                enforce filters on IPv4 fragments.  That is, the match
                functionality based on the Layer 3 'fragment' clause
                is supported.";
           }
         }
         container ipv6 {
           description
             "Indicates IPv6 header fields that are supported to enforce
              ACLs.";
           leaf dscp {
             type boolean;
             description
               "Support of filtering based on DSCP.";
           }
           leaf ecn {
             type boolean;
             description
               "Support of filtering based on ECN.";
           }
           leaf length {
             type boolean;
             description
               "Support of filtering based on the Payload Length.";
           }
           leaf hoplimit {
             type boolean;
             description
               "Support of filtering based on the Hop Limit.";
           }
           leaf protocol {
             type boolean;
             description
               "Support of filtering based on the Next Header field.";
           }
           leaf destination-prefix {
             type boolean;
             description
               "Support of filtering based on the destination prefix.";
           }
           leaf source-prefix {
             type boolean;
             description
               "Support of filtering based on the source prefix.";
           }
           leaf flow-label {
             type boolean;
             description
               "Support of filtering based on the Flow Label.";
           }
           leaf fragment {
             type boolean;
             description
               "Indicates the capability of a DOTS server to
                enforce filters on IPv6 fragments.";
           }
         }
         container tcp {
           description
             "Set of TCP fields that are supported by the DOTS server
              to enforce filters.";
           leaf sequence-number {
             type boolean;
             description
               "Support of filtering based on the TCP sequence number.";
           }
           leaf acknowledgement-number {
             type boolean;
             description
               "Support of filtering based on the TCP acknowledgement
                number.";
           }
           leaf data-offset {
             type boolean;
             description
               "Support of filtering based on the TCP data-offset.";
           }
           leaf reserved {
             type boolean;
             description
               "Support of filtering based on the TCP reserved field.";
           }
           leaf flags {
             type boolean;
             description
               "Support of filtering, as defined in RFC 8519, based
                on the TCP flags.";
           }
           leaf window-size {
             type boolean;
             description
               "Support of filtering based on the TCP window size.";
           }
           leaf urgent-pointer {
             type boolean;
             description
               "Support of filtering based on the TCP urgent pointer.";
           }
           leaf options {
             type boolean;
             description
               "Support of filtering based on the TCP options.";
           }
           leaf flags-bitmask {
             type boolean;
             description
               "Support of filtering based on the TCP flags bitmask.";
           }
           leaf source-port {
             type boolean;
             description
               "Support of filtering based on the source port number.";
           }
           leaf destination-port {
             type boolean;
             description
               "Support of filtering based on the destination port
                number.";
           }
           leaf port-range {
             type boolean;
             description
               "Support of filtering based on a port range.

                This includes filtering based on a source port range,
                destination port range, or both.  All operators
                (i.e, less than or equal to, greater than or equal to,
                equal to, and not equal to) are supported.

                In particular, this means that the implementation
                supports filtering based on
                source-port-range-or-operator and
                destination-port-range-or-operator.";
           }
         }
         container udp {
           description
             "Set of UDP fields that are supported by the DOTS server
              to enforce filters.";
           leaf length {
             type boolean;
             description
               "Support of filtering based on the UDP length.";
           }
           leaf source-port {
             type boolean;
             description
               "Support of filtering based on the source port number.";
           }
           leaf destination-port {
             type boolean;
             description
               "Support of filtering based on the destination port
                number.";
           }
           leaf port-range {
             type boolean;
             description
               "Support of filtering based on a port range.

                This includes filtering based on a source port range,
                destination port range, or both.  All operators
                (i.e, less than or equal, greater than or equal,
                equal to, and not equal to) are supported.

                In particular, this means that the implementation
                supports filtering based on
                source-port-range-or-operator and
                destination-port-range-or-operator.";
           }
         }
         container icmp {
           description
             "Set of ICMP/ICMPv6 fields that are supported by the DOTS
              server to enforce filters.";
           leaf type {
             type boolean;
             description
               "Support of filtering based on the ICMP/ICMPv6 type.";
           }
           leaf code {
             type boolean;
             description
               "Support of filtering based on the ICMP/ICMPv6 code.";
           }
           leaf rest-of-header {
             type boolean;
             description
               "Support of filtering based on the ICMP four-byte
                field / the ICMPv6 message body.";
           }
         }
       }
     }
   }
   <CODE ENDS>

5. Managing DOTS Clients ✨

5.1. Registering DOTS Clients πŸ’–

okay bestie, first things first: before a DOTS client can touch the DOTS data channel, it MUST register with its DOTS server(s) by creating a DOTS client (dots-client) resource ✨. To do that, DOTS clients SHOULD send a POST request, shown in Figure 11 πŸŽ€.

POST /restconf/data/ietf-dots-data-channel:dots-data HTTP/1.1
Host: {host}:{port}
Content-Type: application/yang-data+json

{
  "ietf-dots-data-channel:dots-client": [
    {
      "cuid": "string"
    }
  ]
}

Figure 11: POST to Register Schema

The cuid (client unique identifier) parameter is basically the client's ID card πŸͺͺ, so here's the tea:

  • cuid: A globally unique identifier that is meant to prevent collisions among DOTS clients. This attribute has the same meaning, syntax, and processing rules as the cuid attribute defined in [RFC8782].

DOTS clients MUST use the same cuid for both signal and data channels πŸ”₯. This is a mandatory attribute.

In deployments where server-domain DOTS gateways are enabled, identity info about the origin source client domain SHOULD be supplied to the DOTS server πŸ›‘οΈ. That info helps the server enforce policies, and those policies can be applied per client, per client domain, or both. Figure 12 shows a register request relayed by a server-domain DOTS gateway.

POST /restconf/data/ietf-dots-data-channel:dots-data HTTP/1.1
Host: {host}:{port}
Content-Type: application/yang-data+json

{
  "ietf-dots-data-channel:dots-client": [
    {
      "cuid": "string",
      "cdid": "string"
    }
  ]
}

Figure 12: POST to Register Schema (via a Server-Domain DOTS Gateway)

A server-domain DOTS gateway SHOULD add the following attribute πŸ’…:

  • cdid: This attribute has the same meaning, syntax, and processing rules as the cdid attribute defined in [RFC8782].

Here's the vibe: in deployments where server-domain DOTS gateways are enabled, cdid does not need to be inserted when relaying DOTS methods to manage aliases (Section 6) or filtering rules (Section 7). DOTS servers are responsible for keeping track of the association between cdid and cuid for policy enforcement purposes 🧚. This is an optional attribute.

An example request to create a dots-client resource is in Figure 13. This one gets relayed by a server-domain DOTS gateway, which you can tell from the cdid attribute showing up πŸ‘€.

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

{
  "ietf-dots-data-channel:dots-client": [
    {
      "cuid": "dz6pHjaADkaFTbjr0JGBpw",
      "cdid": "7eeaf349529eb55ed50113"
    }
  ]
}

Figure 13: POST to Register (DOTS gateway)

As a reminder 🌸, DOTS gateways may rewrite the cuid used by peer DOTS clients (Section 4.4.1 of [RFC8782]).

DOTS servers can identify the DOTS client domain using the cdid parameter, or using the client's DNS name specified in the Subject Alternative Name extension's dNSName type in the client certificate [RFC6125]. Iconic identification energy πŸ¦‹.

DOTS servers MUST limit the number of dots-client resources to be created by the same DOTS client to 1 per request. Requests with multiple dots-client resources MUST be rejected by DOTS servers. To that aim, the DOTS server MUST rely on the same procedure to unambiguously identify a DOTS client as discussed in Section 4.4.1 of [RFC8782]. No double-dipping allowed πŸ™…β€β™€οΈ.

The DOTS server tells you how the POST went using status-line codes. Status codes in the "2xx" range are success, "4xx" codes are some sort of invalid requests, and "5xx" codes come back if the DOTS server has erred or is incapable of accepting the creation of the dots-client resource. In particular:

  • 201 Created status-line is returned in the response if the DOTS server has accepted the request. Slay πŸŽ‰.
  • 400 Bad Request status-line is returned by the DOTS server if the request does not include a cuid parameter. The error-tag missing-attribute is used in this case 😭.
  • 409 Conflict status-line is returned to the requesting DOTS client if the data resource already exists. The error-tag resource-denied is used in this case πŸ’€.

Once a DOTS client registers itself with a DOTS server, it can create, delete, and retrieve aliases (Section 6) and filtering rules (Section 7). Main character energy πŸ‘‘.

A DOTS client MAY use the PUT request (Section 4.5 of [RFC8040]) to register a DOTS client within the DOTS server. An example is shown in Figure 14 πŸ“.

PUT /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-data-channel:dots-client": [
    {
      "cuid": "dz6pHjaADkaFTbjr0JGBpw"
    }
  ]
}

Figure 14: PUT to Register

Now the important bit 🚨: the DOTS gateway that inserted a cdid in a PUT request MUST strip the cdid parameter in the corresponding response before forwarding the response to the DOTS client. Clean up after yourself, periodt πŸ’….


5.2. De-registering DOTS Clients

Leaving the party is simple 🌈. A DOTS client de-registers from its DOTS server(s) by deleting the cuid resource(s). Resources bound to this DOTS client will be deleted by the DOTS server too. An example of a de-register request is in Figure 15.

DELETE /restconf/data/ietf-dots-data-channel:dots-data\
       /dots-client=dz6pHjaADkaFTbjr0JGBpw HTTP/1.1
Host: example.com

Figure 15: De-register a DOTS Client


6. Managing DOTS Aliases ✨

The following subsections define how a DOTS client creates aliases (Section 6.1), retrieves one alias or a list of aliases (Section 6.2), and deletes an alias (Section 6.3). Alias era, let's go πŸ§šβ€β™€οΈπŸ’œ.

6.1. Creating Aliases ✨

Okay so a POST or PUT request is how a DOTS client makes aliases for resources that might need a mitigation πŸ›‘οΈ. Those aliases can then show up in later DOTS signal channel exchanges so everyone can refer to the resources under attack way more efficiently πŸ’….

DOTS clients within the same domain can create different aliases for the same resource πŸ¦‹.

Figure 16 shows what a POST request for creating aliases looks like πŸ‘€.

POST /restconf/data/ietf-dots-data-channel:dots-data\
     /dots-client=cuid HTTP/1.1
Host: {host}:{port}
Content-Type: application/yang-data+json

{
 "ietf-dots-data-channel:aliases": {
   "alias": [
     {
       "name": "string",
       "target-prefix": [
         "string"
       ],
       "target-port-range": [
         {
           "lower-port": integer,
           "upper-port": integer
         }
       ],
       "target-protocol": [
         integer
       ],
       "target-fqdn": [
         "string"
       ],
       "target-uri": [
         "string"
       ]
     }
   ]
 }
}

         Figure 16: POST to Create Aliases (Request Schema)

Here are the parameters, and yes, they all matter πŸŽ€:

name: The name of the alias. This is a mandatory attribute, so you can't skip it πŸ™…β€β™€οΈ.

target-prefix: Prefixes are separated by commas, and they're written in Classless Inter-domain Routing (CIDR) notation [RFC4632]. As a reminder, the prefix length must be less than or equal to 32 for IPv4 or 128 for IPv6 🧠.

The prefix list MUST NOT include broadcast, loopback, or multicast addresses. Those are considered invalid values, so they're a hard no 🚫. On top of that, the DOTS server MUST validate that these prefixes are within the scope of the DOTS client domain. Other validation checks may be supported by DOTS servers too πŸ”. This is an optional attribute.

target-port-range: A range of port numbers. The range is defined by two bounds, a lower port number (lower-port) and an upper port number (upper-port), and it includes both bounds πŸ’œ. When only lower-port is present, it represents a single port number ☝️.

For TCP, UDP, Stream Control Transmission Protocol (SCTP) [RFC4960], or Datagram Congestion Control Protocol (DCCP) [RFC4340], the range of port numbers can be, for example, 1024-65535 🌈. This is an optional attribute.

target-protocol: A list of protocols, with values taken from the IANA protocol registry [IANA-PROTO] 🧚. If target-protocol is not specified, then the request applies to any protocol. This is an optional attribute.

target-fqdn: A list of Fully Qualified Domain Names (FQDNs) that identify resources under attack [RFC8499] 🌸.

How a name gets passed to an underlying name resolution library is implementation and deployment specific. Still, once the name is resolved into one or multiple IP addresses, DOTS servers MUST apply the same validation checks as those used for target-prefix βœ…. The use of FQDNs may be suboptimal, though, because it does not guarantee that the DOTS server will resolve a name to the same IP addresses that the DOTS client does πŸ™ˆ. This is an optional attribute.

target-uri: A list of Uniform Resource Identifiers (URIs) [RFC3986] πŸ”—.

The same validation checks used for target-fqdn MUST be followed by DOTS servers to validate a target URI. This is an optional attribute.

In POST or PUT requests, at least one of the target-prefix, target-fqdn, or target-uri attributes MUST be present. This is the one rule you can't bend 😀. DOTS agents can safely ignore vendor-specific parameters they don't understand, so no stress there 🫢.

If more than one target-* scope type is included in a POST or PUT request (for example, target-prefix and target-fqdn, or target-fqdn and target-uri), the DOTS server binds all resulting IP addresses and prefixes to the same resource 🎯.

Figure 17 shows a POST request that creates an alias called "https1" for HTTPS servers with IP addresses 2001:db8:6401::1 and 2001:db8:6401::2 listening on TCP port number 443 πŸ”.

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-data-channel:aliases": {
    "alias": [
      {
        "name": "https1",
        "target-protocol": [
          6
        ],
        "target-prefix": [
          "2001:db8:6401::1/128",
          "2001:db8:6401::2/128"
        ],
        "target-port-range": [
          {
            "lower-port": 443
          }
        ]
      }
    ]
  }
}

           Figure 17: Example of a POST to Create an Alias

Now for the responses πŸ“¬.

A "201 Created" status-line MUST be returned in the response if the DOTS server has accepted the alias πŸŽ‰.

A "409 Conflict" status-line MUST be returned to the requesting DOTS client if the request conflicts with an existing alias name πŸ’€. The error-tag "resource-denied" is used in this case.

If the request is missing a mandatory attribute, or it contains an invalid or unknown parameter, a "400 Bad Request" status-line MUST be returned by the DOTS server 😬. The error-tag is set to "missing-attribute", "invalid-value", or "unknown-element", depending on which error was encountered.

If the request is received via a server-domain DOTS gateway, but the DOTS server does not 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" πŸšͺ. Upon receipt of this message, the DOTS client MUST register (Section 5) πŸ“.

A DOTS client uses the PUT request to modify the aliases on the DOTS server. In particular, a DOTS client MUST update its alias entries upon a change of the prefix indicated in the target-prefix πŸ”„.

A DOTS server MUST maintain an alias for at least 10080 minutes (1 week) ⏳. If no refresh request is seen from the DOTS client, the DOTS server removes expired entries 🧹.


6.2. Retrieving Installed Aliases

A GET request retrieves one or all installed aliases that a DOTS client has on a DOTS server (Section 3.3.1 of [RFC8040]) πŸ”. If no name is included in the request, that means the DOTS client wants all the aliases it instantiated πŸ—‚οΈ.

Figure 18 shows an example of retrieving all the aliases that were instantiated by the requesting DOTS client. The "content" query parameter and its permitted values are defined in Section 4.8.1 of [RFC8040] πŸ€“.

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

           Figure 18: GET to Retrieve All Installed Aliases

Figure 19 shows an example of the response message body, which includes all the aliases that the DOTS server maintains for the DOTS client identified by the cuid parameter πŸ“‹.

{
  "ietf-dots-data-channel:aliases": {
    "alias": [
      {
        "name": "Server1",
        "target-protocol": [
          6
        ],
        "target-prefix": [
          "2001:db8:6401::1/128",
          "2001:db8:6401::2/128"
        ],
        "target-port-range": [
          {
            "lower-port": 443
          }
        ],
        "pending-lifetime": 3596
      },
      {
        "name": "Server2",
        "target-protocol": [
          6
        ],
        "target-prefix": [
          "2001:db8:6401::10/128",
          "2001:db8:6401::20/128"
        ],
        "target-port-range": [
          {
            "lower-port": 80
          }
        ],
        "pending-lifetime": 9869
      }
    ]
  }
}

    Figure 19: An Example of a Response Body Listing All Installed
                               Aliases

Figure 20 shows an example of a GET request that retrieves the alias "Server2" instantiated by the DOTS client πŸŽ€.

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

                 Figure 20: GET to Retrieve an Alias

If an alias name (name) is included in the request, but the DOTS server does not find that alias name for this DOTS client in its configuration data, the server MUST respond with a "404 Not Found" status-line πŸ™ƒ.


6.3. Deleting Aliases

A DELETE request is used to delete an alias maintained by a DOTS server πŸ—‘οΈ.

If the DOTS server does not find the alias name conveyed in the DELETE request in its configuration data for this DOTS client, it MUST respond with a "404 Not Found" status-line 🫠.

The DOTS server successfully acknowledges a DOTS client's request to remove the alias with a "204 No Content" status-line in the response βœ….

Figure 21 shows an example of a request to delete an alias πŸ’«.

  DELETE /restconf/data/ietf-dots-data-channel:dots-data\
         /dots-client=dz6pHjaADkaFTbjr0JGBpw\
         /aliases/alias=Server1 HTTP/1.1
  Host: example.com

                      Figure 21: Delete an Alias

7. Managing DOTS Filtering Rules πŸ›‘οΈ

The following subsections define the ways a DOTS client can retrieve DOTS filtering capabilities (Section 7.1), create filtering rules (Section 7.2), retrieve active filtering rules (Section 7.3), and delete a filtering rule (Section 7.4) πŸ’–.

7.1. Retrieving DOTS Filtering Capabilities

A DOTS client MAY send a GET request to retrieve the filtering capabilities supported by a DOTS server πŸ”Ž. Figure 22 shows an example of such a request.

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

     Figure 22: GET to Retrieve the Capabilities of a DOTS Server

A DOTS client that issued a GET request to retrieve the filtering capabilities supported by its DOTS server SHOULD NOT request filtering actions that the DOTS server does not support πŸ™…β€β™€οΈ.

Figure 23 shows an example of a response body received from a DOTS server that supports:

  • IPv4, IPv6, TCP, UDP, ICMP, and ICMPv6 mandatory match criteria listed in Section 4.2 🧩.
  • 'accept', 'drop', and 'rate-limit' actions 🚦.
{
 "ietf-dots-data-channel:capabilities": {
   "address-family": ["ipv4", "ipv6"],
   "forwarding-actions": ["drop", "accept"],
   "rate-limit": true,
   "transport-protocols": [1, 6, 17, 58],
   "ipv4": {
     "length": true,
     "protocol": true,
     "destination-prefix": true,
     "source-prefix": true,
     "fragment": true
   },
   "ipv6": {
     "length": true,
     "protocol": true,
     "destination-prefix": true,
     "source-prefix": true,
     "fragment": true
   },
   "tcp": {
     "flags-bitmask": true,
     "source-port": true,
     "destination-port": true,
     "port-range": true
   },
   "udp": {
     "length": true,
     "source-port": true,
     "destination-port": true,
     "port-range": true
   },
   "icmp": {
     "type": true,
     "code": true
   }
 }
}

     Figure 23: Reply to a GET Request with Filtering Capabilities
                             (Message Body)

7.2. Installing Filtering Rules ✨

okay bestie, so a POST or PUT request is how a DOTS client slides its filtering rules over to a DOTS server πŸ’Œ

Figure 24 shows a POST that blocks traffic coming from 192.0.2.0/24 and heading to 198.51.100.0/24 πŸ™ˆ Other examples are in Appendix A, so go peek if you want more πŸ¦‹

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-data-channel:acls": {
   "acl": [
     {
       "name": "sample-ipv4-acl",
       "type": "ipv4-acl-type",
       "activation-type": "activate-when-mitigating",
       "aces": {
         "ace": [
           {
             "name": "rule1",
             "matches": {
               "ipv4": {
                 "destination-ipv4-network": "198.51.100.0/24",
                 "source-ipv4-network": "192.0.2.0/24"
               }
             },
             "actions": {
               "forwarding": "drop"
             }
           }
         ]
       }
     }
   ]
 }
}

             Figure 24: POST to Install Filtering Rules

So here's what each parameter means πŸ’…

  • name: The name of the access list. πŸŽ€
    • This is a mandatory attribute.
  • type: Indicates the primary intended type of match criteria (e.g., IPv4, IPv6). It's set to 'ipv4-acl-type' in the Figure 24 example 🌈
    • This is an optional attribute.
  • activation-type: Indicates whether an ACL has to be activated (immediately or during mitigation time) or instantiated without being activated (deactivated) 🧚 Deactivated ACLs can be activated using a variety of means, such as manual configuration on a DOTS server or by using the DOTS data channel.
    • If this attribute is not provided, the DOTS server MUST use 'activate-when-mitigating' as the default value.
    • When a mitigation is in progress, the DOTS server MUST only activate 'activate-when-mitigating' filters that are bound to the DOTS client that triggered the mitigation.
    • This is an optional attribute.
  • matches: Defines criteria used to identify a flow on which to apply the rule. It can be "l3" (IPv4, IPv6) or "l4" (TCP, UDP, ICMP). The detailed match parameters are specified in Section 4. ⭐
    • In the example depicted in Figure 24, an IPv4 matching criteria is used.
    • This is an optional attribute.
  • destination-ipv4-network: The destination IPv4 prefix. DOTS servers MUST validate that these prefixes are within the scope of the DOTS client domain. Other validation checks may be supported by DOTS servers. If this attribute is not provided, the DOTS server enforces the ACL on any destination IP address that belongs to the DOTS client domain. πŸ‘‘
    • This is a mandatory attribute in requests with an 'activation-type' set to 'immediate'.
  • source-ipv4-network: The source IPv4 prefix. πŸ“
    • This is an optional attribute.
  • actions: Actions in the forwarding ACL category can be 'drop' or 'accept'. The 'accept' action is used to accept-list traffic. The "drop" action is used to drop-list traffic. πŸ’€
    • Accepted traffic may be subject to 'rate-limit'; the allowed traffic rate is represented in bytes per second. This unit is the same as the one used for "traffic-rate" in [RFC5575].
    • This is a mandatory attribute.

Now the response part, which is lowkey the important bit 😭 The DOTS server tells you how the POST went through the status-line. If the DOTS server has accepted the filtering rules, a "201 Created" status-line MUST be returned in the response. ✨ If the request is missing a mandatory attribute or has an invalid or unknown parameter (like a match field the DOTS server doesn't support), a "400 Bad Request" status-line MUST be returned by the DOTS server in the response. The error-tag is set to "missing-attribute", "invalid-value", or "unknown-element" depending on what went wrong 🫢

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". Once you get that message, the DOTS client MUST register (Figure 11). No skipping this step, periodt πŸ™…β€β™€οΈ

If the request conflicts with an existing filtering installed by another DOTS client of the domain, the DOTS server returns a "409 Conflict" status-line to the requesting DOTS client, absent any local policy. The error-tag "resource-denied" is used in this case. πŸ’€

The "insert" query parameter (Section 4.8.5 of [RFC8040]) MAY be used to specify how an access control entry is inserted within an ACL and how an ACL is inserted within an ACL set. 🌸

For changing things up, the DOTS client uses the PUT request to modify its filtering rules maintained by the DOTS server. In particular, a DOTS client MUST update its filtering entries upon change of the destination prefix. How such change is detected is out of scope. πŸ”₯

And finally, the lifetime situation 🧚 A DOTS server MUST maintain a filtering rule for at least 10080 minutes (1 week). If no refresh request is seen from the DOTS client, the DOTS server removes expired entries. Typically, a refresh request is a PUT request that echoes the content of a response to a GET request with all of the read-only parameters stripped out (e.g., 'pending-lifetime'). It's giving careful housekeeping, honestly πŸ’œ

7.3. Retrieving Installed Filtering Rules πŸ¦‹

okay so a DOTS client keeps checking in on its DOTS server to see the counters for the filtering rules it installed πŸ‘€ and the way it does that is with a GET request. πŸ’– To tell the server what kind of data it wants, the DOTS client sets the content query parameter appropriately ✨

if the DOTS server looks in its configuration data for this DOTS client and can't find the access list name from the GET request, it responds with "404 Not Found" πŸ’€

let's walk through an example πŸŽ€ In Figure 25, the DOTS client asks for an immediate ACL called test-acl-ipv6-udp to be created 🌸

PUT /restconf/data/ietf-dots-data-channel:dots-data\
    /dots-client=paL8p4Zqo4SLv64TLPXrxA/acls\
    /acl=test-acl-ipv6-udp HTTP/1.1
Host: example.com
Content-Type: application/yang-data+json

{
  "ietf-dots-data-channel:acls": {
    "acl": [
      {
        "name": "test-acl-ipv6-udp",
        "type": "ipv6-acl-type",
        "activation-type": "immediate",
        "aces": {
          "ace": [
            {
              "name": "my-test-ace",
              "matches": {
                "ipv6": {
                  "destination-ipv6-network": "2001:db8:6401::2/127",
                  "source-ipv6-network": "2001:db8:1234::/96",
                  "protocol": 17,
                  "flow-label": 10000
                },
                "udp": {
                  "source-port-range-or-operator": {
                    "operator": "lte",
                    "port": 80
                  },
                  "destination-port-range-or-operator": {
                    "operator": "neq",
                    "port": 1010
                  }
                }
              },
              "actions": {
                "forwarding": "accept"
              }
            }
          ]
        }
      }
    ]
  }
}

Figure 25: Example of a PUT Request to Create a Filtering

the peer DOTS server follows the procedure from Section 7.2 to process the request 🫢 For the rest of this, we're assuming a positive response goes back to the DOTS client, confirming that the test-acl-ipv6-udp ACL was successfully installed by the DOTS server πŸŽ‰

now the DOTS client can send a GET request to grab all of its filtering rules, plus the number of matches for the installed ones πŸ” That's shown in Figure 26, with the content query parameter set to 'all' πŸ’… The response body for that GET request is in Figure 27 ✨

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

Figure 26: Retrieve the Configuration Data and State Data for the Filtering Rules (GET Request)

{
  "ietf-dots-data-channel:acls": {
    "acl": [
      {
        "name": "test-acl-ipv6-udp",
        "type": "ipv6-acl-type",
        "activation-type": "immediate",
        "pending-lifetime":9080,
        "aces": {
          "ace": [
            {
              "name": "my-test-ace",
              "matches": {
                "ipv6": {
                  "destination-ipv6-network": "2001:db8:6401::2/127",
                  "source-ipv6-network": "2001:db8:1234::/96",
                  "protocol": 17,
                  "flow-label": 10000
                },
                "udp": {
                  "source-port-range-or-operator": {
                    "operator": "lte",
                    "port": 80
                  },
                  "destination-port-range-or-operator": {
                    "operator": "neq",
                    "port": 1010
                  }
                }
              },
              "actions": {
                "forwarding": "accept"
              }
            }
          ]
        }
      }
    ]
  }
}

Figure 27: Retrieve the Configuration Data and State Data for the Filtering Rules (Response Message Body)

a DOTS client can also send a GET request to pull up just the configuration data for one ACL πŸŽ€ It does that by setting the content query parameter to 'config', as in Figure 28 🌷

GET /restconf/data/ietf-dots-data-channel:dots-data\
    /dots-client=paL8p4Zqo4SLv64TLPXrxA/acls\
    /acl=test-acl-ipv6-udp?content=config HTTP/1.1
Host: example.com
Accept: application/yang-data+json

Figure 28: Retrieve the Configuration Data for a Filtering Rule (GET Request)

the response to that GET request is shown in Figure 29 🦒

{
  "ietf-dots-data-channel:acls": {
    "acl": [
      {
        "name": "test-acl-ipv6-udp",
        "type": "ipv6-acl-type",
        "activation-type": "immediate",
        "aces": {
          "ace": [
            {
              "name": "my-test-ace",
              "matches": {
                "ipv6": {
                  "destination-ipv6-network": "2001:db8:6401::2/127",
                  "source-ipv6-network": "2001:db8:1234::/96",
                  "protocol": 17,
                  "flow-label": 10000
                },
                "udp": {
                  "source-port-range-or-operator": {
                    "operator": "lte",
                    "port": 80
                  },
                  "destination-port-range-or-operator": {
                    "operator": "neq",
                    "port": 1010
                  }
                }
              },
              "actions": {
                "forwarding": "accept"
              }
            }
          ]
        }
      }
    ]
  }
}

Figure 29: Retrieve the Configuration Data for a Filtering Rule (Response Message Body)

a DOTS client can also send a GET request with the content query parameter set to 'non-config' 🧚 That gets it only the non-configuration data tied to a given ACL, as shown in Figure 30, and the response is in Figure 31 πŸ’œ

GET /restconf/data/ietf-dots-data-channel:dots-data\
    /dots-client=paL8p4Zqo4SLv64TLPXrxA/acls\
    /acl=test-acl-ipv6-udp?content=non-config HTTP/1.1
Host: example.com
Accept: application/yang-data+json

Figure 30: Retrieve the Non-Configuration Data for a Filtering Rule (GET Request)

{
  "ietf-dots-data-channel:acls":  {
    "acl": [
      {
        "name": "test-acl-ipv6-udp",
        "pending-lifetime": 8000,
        "aces": {
          "ace": [
            {
              "name": "my-test-ace"
            }
          ]
        }
      }
    ]
  }
}

Figure 31: Retrieve the Non-Configuration Data for a Filtering Rule (Response Message Body)

7.4. Removing Filtering Rules πŸ’…

okay this is the cleanup part 🧹 A DOTS client uses a DELETE request to delete filtering rules from a DOTS server πŸ—‘οΈ

if the DOTS server looks in its configuration data for this DOTS client and can't find the access list name in the DELETE request, it MUST respond with "404 Not Found" πŸ™ˆ When the DOTS server successfully acknowledges that the DOTS client wants to withdraw the filtering rules, it responds with "204 No Content" and removes the filtering rules accordingly 🫧

Figure 32 shows a request to remove the IPv4 ACL sample-ipv4-acl, which was created in Section 7.2 🌸

DELETE  /restconf/data/ietf-dots-data-channel:dots-data\
        /dots-client=dz6pHjaADkaFTbjr0JGBpw/acls\
        /acl=sample-ipv4-acl HTTP/1.1
Host: example.com

Figure 32: Remove a Filtering Rule (DELETE Request)

Figure 33 shows the response from the DOTS server confirming that sample-ipv4-acl was deleted πŸŽ€

HTTP/1.1 204 No Content
Server: Apache
Date: Fri, 27 Jul 2018 10:05:15 GMT
Cache-Control: no-cache
Content-Type: application/yang-data+json
Content-Length: 0
Connection: Keep-Alive

Figure 33: Remove a Filtering Rule (Response)

8. Operational Considerations 🌈

the following operational considerations should be taken into account 🧐

  • DOTS servers MUST NOT enable both DOTS data channel and direct configuration, to avoid race conditions and inconsistent configurations arising from simultaneous updates from multiple sources. πŸ™…β€β™€οΈ
  • DOTS agents SHOULD enable the DOTS data channel to configure aliases and ACLs, and only use direct configuration as a stop-gap mechanism to test DOTS signal channel with aliases and ACLs. Further, direct configuration SHOULD only be used when the on-path DOTS agents are within the same domain. 🫢
  • If a DOTS server has enabled direct configuration, it can reject the DOTS data channel connection using hard ICMP error [RFC1122] or RST (Reset) bit in the TCP header, or reject the RESTCONF request using an error response containing a "503 Service Unavailable" status-line. πŸ’€

9. IANA Considerations 🧾

IANA has registered the following URI in the "ns" subregistry within the "IETF XML Registry" [RFC3688] ✨

ID:  yang:ietf-dots-data-channel
URI:  urn:ietf:params:xml:ns:yang:ietf-dots-data-channel
Registrant Contact:  The IESG.
XML:  N/A; the requested URI is an XML namespace.
Reference:  RFC 8783

IANA has also registered the following YANG module in the "YANG Module Names" subregistry [RFC7950] within the "YANG Parameters" registry 🌟

Name:  ietf-dots-data-channel
Namespace:  urn:ietf:params:xml:ns:yang:ietf-dots-data-channel
Prefix:  data-channel
Reference:  RFC 8783

This module is not maintained by IANA πŸ”’

10. Security Considerations πŸ”’βœ¨

Okay bestie, this is the serious section, so grab your iced matcha πŸ΅πŸ’…. RESTCONF security lives over in [RFC8040], and DOTS agents MUST follow the security recommendations in Sections 2 and 12 of [RFC8040]. On top of that, DOTS agents MUST support the mutual authentication TLS profile discussed in Sections 7.1 and 8 of [RFC8782]. No skipping! πŸ™ˆ

Authenticated encryption MUST be used for data confidentiality and message integrity πŸ”. The DOTS agents talk to each other over Transport Layer Security (TLS) with a cipher suite that offers confidentiality protection, and the guidance in [RFC7525] MUST be followed to avoid attacks on TLS. Main character energy means doing the security homework πŸ“šπŸ’–.

Installing drop-list or accept-list rules over RESTCONF on TLS reveals the attacker IP addresses and the legitimate IP addresses, but only to the DOTS server that the DOTS client trusts πŸ‘€. The secure channel between DOTS agents gives privacy and stops a network eavesdropper from directly getting access to the drop-listed and accept-listed IP addresses. Nosy neighbours denied πŸ™…β€β™€οΈβœ¨.

An attacker may be able to inject RST packets, bogus application segments, and so on, whether or not TLS authentication is used πŸ’€. Because the application data is TLS protected, the application won't receive bogus data, but it still counts as a DoS on the connection. This can be countered by using TCP Authentication Option (TCP-AO) [RFC5925]. If TCP-AO is used, then any bogus packets an attacker injects get rejected by the TCP-AO integrity check, so they never reach the TLS layer. Rejected, iykyk 🫢.

To keep internal info from leaking outside a client domain, client-side DOTS gateways SHOULD NOT reveal the identity of internal DOTS clients (e.g., source IP address, client's hostname) unless they're explicitly configured to do so. Privacy is a whole vibe πŸ¦‹.

DOTS servers MUST verify that requesting DOTS clients are entitled to enforce filtering rules on a given IP prefix. Basically, only filtering rules on IP resources that belong to the DOTS client domain can be authorized by a DOTS server 🚫. How the DOTS servers check that the target prefixes are within the scope of the DOTS client domain is deployment specific, so it depends on how each network is set up πŸ› οΈ.

Rate-limiting DOTS requests, including the ones with new cuid values, from the same DOTS client defends against DoS attacks where someone varies the cuid to drain DOTS server resources 🚧. Rate-limit policies SHOULD be enforced on DOTS gateways (if deployed) and DOTS servers 🌸.

Applying resource quotas per DOTS client and/or per DOTS client domain (for example, limiting the number of aliases and filters that DOTS clients can install) stops some DOTS clients from hogging DOTS server resources 🍰. That keeps DDoS mitigation usage fair for everyone. Also, DOTS servers may limit the number of DOTS clients that can be enabled per domain. Fairness is giving πŸ‘‘.

When FQDNs are used as targets, the DOTS server MUST rely upon DNS privacy enabling protocols (e.g., DNS over TLS [RFC7858] or DNS over HTTPS (DoH) [RFC8484]) so eavesdroppers can't easily figure out which target resources are protected by the DDoS mitigation service πŸ•΅οΈβ€β™€οΈ. It also needs ways to make sure the FQDN resolution is authentic (e.g., DNSSEC [RFC4034]). Trust the source, bestie πŸ”₯.

The presence of DOTS gateways may lead to infinite forwarding loops, which is very much not it 😭. A mechanism to prevent and detect such loops is defined in Section 3.4, so go check it out 🧚.

The YANG module in this document defines a schema for data that's designed to be accessed via network management protocols such as NETCONF [RFC6241] or RESTCONF [RFC8040] πŸŽ€. The lowest NETCONF layer is the secure transport layer, and the mandatory-to-implement secure transport is Secure Shell (SSH) [RFC6242]. The lowest RESTCONF layer is HTTPS, and the mandatory-to-implement secure transport is TLS [RFC8446].

The Network Configuration Access Control Model (NACM) [RFC8341] gives you the tools to restrict access for particular NETCONF or RESTCONF users to a preconfigured subset of all the available NETCONF or RESTCONF protocol operations and content πŸ”‘. Very bouncer-at-the-club energy πŸ’œ.

Heads up, there are a bunch of data nodes in this YANG module that are writable, creatable, and deletable (that's config true, which is the default) 🚨. These can be considered sensitive or vulnerable in some network environments. Write operations (e.g., edit-config) to these data nodes without proper protection can have a negative effect on network operations 😬. The DOTS data channel is in charge of exchanging configuration data that affects traffic filtering during DDoS attack mitigation, in particular. Appropriate security measures are recommended to stop illegitimate users from invoking DOTS data channel primitives on writable data nodes. Even so, an attacker who can access a DOTS client is technically capable of launching various attacks, such as:

  • Setting an arbitrarily low rate-limit, which may prevent legitimate traffic from being forwarded (rate-limit).
  • Setting an arbitrarily high rate-limit, which may lead to the forwarding of illegitimate DDoS traffic (rate-limit).
  • Communicating invalid aliases to the server (alias), which will cause the failure of associating both data and signal channels.
  • Setting invalid ACL entries, which may prevent legitimate traffic from being forwarded. Likewise, invalid ACL entries may lead to forward DDoS traffic.

Ngl that list is a lot πŸ’€. This module reuses YANG structures from [RFC8519], and the security considerations for those nodes continue to apply for this usage πŸ¦‹.


11. References πŸ“šπŸ’…

11.1. Normative References

[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>.

[RFC4632]  Fuller, V. and T. Li, "Classless Inter-domain Routing
           (CIDR): The Internet Address Assignment and Aggregation
           Plan", BCP 122, RFC 4632, DOI 10.17487/RFC4632, August
           2006, <https://www.rfc-editor.org/info/rfc4632>.

[RFC6125]  Saint-Andre, P. and J. Hodges, "Representation and
           Verification of Domain-Based Application Service Identity
           within Internet Public Key Infrastructure Using X.509
           (PKIX) Certificates in the Context of Transport Layer
           Security (TLS)", RFC 6125, DOI 10.17487/RFC6125, March
           2011, <https://www.rfc-editor.org/info/rfc6125>.

[RFC6241]  Enns, R., Ed., Bjorklund, M., Ed., Schoenwaelder, J., Ed.,
           and A. Bierman, Ed., "Network Configuration Protocol
           (NETCONF)", RFC 6241, DOI 10.17487/RFC6241, June 2011,
           <https://www.rfc-editor.org/info/rfc6241>.

[RFC6242]  Wasserman, M., "Using the NETCONF Protocol over Secure
           Shell (SSH)", RFC 6242, DOI 10.17487/RFC6242, June 2011,
           <https://www.rfc-editor.org/info/rfc6242>.

[RFC6991]  Schoenwaelder, J., Ed., "Common YANG Data Types",
           RFC 6991, DOI 10.17487/RFC6991, July 2013,
           <https://www.rfc-editor.org/info/rfc6991>.

[RFC7230]  Fielding, R., Ed. and J. Reschke, Ed., "Hypertext Transfer
           Protocol (HTTP/1.1): Message Syntax and Routing",
           RFC 7230, DOI 10.17487/RFC7230, June 2014,
           <https://www.rfc-editor.org/info/rfc7230>.

[RFC7525]  Sheffer, Y., Holz, R., and P. Saint-Andre,
           "Recommendations for Secure Use of Transport Layer
           Security (TLS) and Datagram Transport Layer Security
           (DTLS)", BCP 195, RFC 7525, DOI 10.17487/RFC7525, May
           2015, <https://www.rfc-editor.org/info/rfc7525>.

[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>.

[RFC7951]  Lhotka, L., "JSON Encoding of Data Modeled with YANG",
           RFC 7951, DOI 10.17487/RFC7951, August 2016,
           <https://www.rfc-editor.org/info/rfc7951>.

[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>.

[RFC8259]  Bray, T., Ed., "The JavaScript Object Notation (JSON) Data
           Interchange Format", STD 90, RFC 8259,
           DOI 10.17487/RFC8259, December 2017,
           <https://www.rfc-editor.org/info/rfc8259>.

[RFC8341]  Bierman, A. and M. Bjorklund, "Network Configuration
           Access Control Model", STD 91, RFC 8341,
           DOI 10.17487/RFC8341, March 2018,
           <https://www.rfc-editor.org/info/rfc8341>.

[RFC8446]  Rescorla, E., "The Transport Layer Security (TLS) Protocol
           Version 1.3", RFC 8446, DOI 10.17487/RFC8446, August 2018,
           <https://www.rfc-editor.org/info/rfc8446>.

[RFC8519]  Jethanandani, M., Agarwal, S., Huang, L., and D. Blair,
           "YANG Data Model for Network Access Control Lists (ACLs)",
           RFC 8519, DOI 10.17487/RFC8519, March 2019,
           <https://www.rfc-editor.org/info/rfc8519>.

[RFC8782]  Reddy.K, T., Ed., Boucadair, M., Ed., Patil, P.,
           Mortensen, A., and N. Teague, "Distributed Denial-of-
           Service Open Threat Signaling (DOTS) Signal Channel
           Specification", RFC 8782, DOI 10.17487/RFC8782, May 2020,
           <https://www.rfc-editor.org/info/rfc8782>.

11.2. Informative References

Okay bestie, now for the extra reading list πŸ“šβœ¨ These are the informative refs, the "go deeper if you're curious" stuff, and I'm obsessed with how many of them there are 😭

[DOTS-ARCH] Mortensen, A., Reddy.K, T., Andreasen, F., Teague, N., and R. Compton, "Distributed-Denial-of-Service Open Threat Signaling (DOTS) Architecture", Work in Progress, Internet-Draft, draft-ietf-dots-architecture-18, 6 March 2020, https://tools.ietf.org/html/draft-ietf-dots-architecture-18.

[DOTS-SERVER-DISC] Boucadair, M. and T. Reddy.K, "Distributed-Denial-of-Service Open Threat Signaling (DOTS) Agent Discovery", Work in Progress, Internet-Draft, draft-ietf-dots-server-discovery-10, 7 February 2020, https://tools.ietf.org/html/draft-ietf-dots-server-discovery-10.

[IANA-PROTO] IANA, "Protocol Numbers", http://www.iana.org/assignments/protocol-numbers.

[RESTCONF-MODELS] Watsen, K., "RESTCONF Client and Server Models", Work in Progress, Internet-Draft, draft-ietf-netconf-restconf-client-server-19, 20 May 2020, https://tools.ietf.org/html/draft-ietf-netconf-restconf-client-server-19.

[RFC1122] Braden, R., Ed., "Requirements for Internet Hosts - Communication Layers", STD 3, RFC 1122, DOI 10.17487/RFC1122, October 1989, https://www.rfc-editor.org/info/rfc1122.

[RFC3986] Berners-Lee, T., Fielding, R., and L. Masinter, "Uniform Resource Identifier (URI): Generic Syntax", STD 66, RFC 3986, DOI 10.17487/RFC3986, January 2005, https://www.rfc-editor.org/info/rfc3986.

[RFC4034] Arends, R., Austein, R., Larson, M., Massey, D., and S. Rose, "Resource Records for the DNS Security Extensions", RFC 4034, DOI 10.17487/RFC4034, March 2005, https://www.rfc-editor.org/info/rfc4034.

[RFC4340] Kohler, E., Handley, M., and S. Floyd, "Datagram Congestion Control Protocol (DCCP)", RFC 4340, DOI 10.17487/RFC4340, March 2006, https://www.rfc-editor.org/info/rfc4340.

[RFC4960] Stewart, R., Ed., "Stream Control Transmission Protocol", RFC 4960, DOI 10.17487/RFC4960, September 2007, https://www.rfc-editor.org/info/rfc4960.

[RFC5575] Marques, P., Sheth, N., Raszuk, R., Greene, B., Mauch, J., and D. McPherson, "Dissemination of Flow Specification Rules", RFC 5575, DOI 10.17487/RFC5575, August 2009, https://www.rfc-editor.org/info/rfc5575.

[RFC5925] Touch, J., Mankin, A., and R. Bonica, "The TCP Authentication Option", RFC 5925, DOI 10.17487/RFC5925, June 2010, https://www.rfc-editor.org/info/rfc5925.

[RFC6520] Seggelmann, R., Tuexen, M., and M. Williams, "Transport Layer Security (TLS) and Datagram Transport Layer Security (DTLS) Heartbeat Extension", RFC 6520, DOI 10.17487/RFC6520, February 2012, https://www.rfc-editor.org/info/rfc6520.

[RFC7858] Hu, Z., Zhu, L., Heidemann, J., Mankin, A., Wessels, D., and P. Hoffman, "Specification for DNS over Transport Layer Security (TLS)", RFC 7858, DOI 10.17487/RFC7858, May 2016, https://www.rfc-editor.org/info/rfc7858.

[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.

[RFC8484] Hoffman, P. and P. McManus, "DNS Queries over HTTPS (DoH)", RFC 8484, DOI 10.17487/RFC8484, October 2018, https://www.rfc-editor.org/info/rfc8484.

[RFC8499] Hoffman, P., Sullivan, A., and K. Fujiwara, "DNS Terminology", BCP 219, RFC 8499, DOI 10.17487/RFC8499, January 2019, https://www.rfc-editor.org/info/rfc8499.

[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.


Appendix A. Examples: Filtering Fragments 🧩

Okay so the spec really, really wants you to use 'fragment' for handling fragments πŸ’…

Figure 34 shows the POST request a DOTS client sends to its DOTS server to allow traffic going to 198.51.100.0/24 on UDP port 53, but to drop all fragmented packets. The ACEs are defined in this order:

  • "drop-all-fragments" ACE: discards all fragments.
  • "allow-dns-packets" ACE: accepts DNS packets destined to 198.51.100.0/24.
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-data-channel:acls": {
    "acl": [
      {
        "name": "dns-fragments",
        "type": "ipv4-acl-type",
        "aces": {
          "ace": [
            {
              "name": "drop-all-fragments",
              "matches": {
                "ipv4": {
                  "fragment": {
                    "operator": "match",
                    "type": "isf"
                  }
                }
              },
              "actions": {
                "forwarding": "drop"
              }
            },
            {
              "name": "allow-dns-packets",
              "matches": {
                "ipv4": {
                  "destination-ipv4-network": "198.51.100.0/24"
                },
                "udp": {
                  "destination-port-range-or-operator": {
                    "operator": "eq",
                    "port": 53
                  }
                },
                "actions": {
                  "forwarding": "accept"
                }
              }
            }
          ]
        }
      }
    ]
  }
}

Figure 34: Filtering IPv4 Fragmented Packets

Figure 35 shows an example of a POST request a DOTS client sends to its DOTS server to allow traffic going to 2001:db8::/32 on UDP port 53, but to drop all fragmented packets. The ACEs are defined in this order:

  • "drop-all-fragments" ACE: discards all fragments (including atomic fragments). That is, IPv6 packets that include a Fragment header (44) are dropped.
  • "allow-dns-packets" ACE: accepts DNS packets destined to 2001:db8::/32.
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-data-channel:acls": {
    "acl": [
      {
        "name": "dns-fragments",
        "type": "ipv6-acl-type",
        "aces": {
          "ace": [
            {
              "name": "drop-all-fragments",
              "matches": {
                "ipv6": {
                  "fragment": {
                    "operator": "match",
                    "type": "isf"
                  }
                }
              },
              "actions": {
                "forwarding": "drop"
              }
            },
            {
              "name": "allow-dns-packets",
              "matches": {
                "ipv6": {
                  "destination-ipv6-network": "2001:db8::/32"
                },
                "udp": {
                  "destination-port-range-or-operator": {
                    "operator": "eq",
                    "port": 53
                  }
                }
              },
              "actions": {
                "forwarding": "accept"
              }
            }
          ]
        }
      }
    ]
  }
}

Figure 35: Filtering IPv6 Fragmented Packets


Appendix B. Examples: Filtering TCP Messages πŸ¦‹

This section gives examples of TCP-specific filtering based on the flag bits. Bestie, these examples should not be read as recommended filtering behaviors under specific DDoS attacks πŸ™ˆ

B.1. Discard TCP Null Attack

Figure 36 shows a DOTS request a DOTS client sends to its DOTS server to install a filter right away that discards incoming TCP messages with all flags unset. The bitmask can be set to 255 to check against the (CWR, ECE, URG, ACK, PSH, RST, SYN, FIN) flags.

PUT /restconf/data/ietf-dots-data-channel:dots-data\
    /dots-client=paL8p4Zqo4SLv64TLPXrxA/acls\
    /acl=tcp-flags-example HTTP/1.1
Host: example.com
Content-Type: application/yang-data+json

{
  "ietf-dots-data-channel:acls": {
    "acl": [{
      "name": "tcp-flags-example",
      "activation-type": "immediate",
      "aces": {
        "ace": [{
          "name": "null-attack",
          "matches": {
            "tcp": {
              "flags-bitmask": {
                "operator": "not any",
                "bitmask": 4095
              }
            }
          },
          "actions": {
            "forwarding": "drop"
          }
        }]
      }
    }]
  }
}

Figure 36: Example of a DOTS Request to Deny TCP Null Attack Messages

B.2. Rate-Limit SYN Flooding

Figure 37 shows an ACL example that rate-limits incoming SYNs during a SYN flood attack 🌊

PUT /restconf/data/ietf-dots-data-channel:dots-data\
    /dots-client=paL8p4Zqo4SLv64TLPXrxA/acls\
    /acl=tcp-flags-example HTTP/1.1
Host: example.com
Content-Type: application/yang-data+json

{
  "ietf-dots-data-channel:acls": {
    "acl": [{
      "name": "tcp-flags-example",
      "activation-type": "activate-when-mitigating",
      "aces": {
        "ace": [{
          "name": "rate-limit-syn",
          "matches": {
            "tcp": {
              "flags-bitmask": {
                "operator": "match",
                "bitmask": 2
              }
            }
          },
          "actions": {
            "forwarding": "accept",
            "rate-limit": "20.00"
          }
        }]
      }
    }]
  }
}

Figure 37: Example of DOTS Request to Rate-Limit Incoming TCP SYNs

B.3. Rate-Limit ACK Flooding

Figure 38 shows an ACL example that rate-limits incoming ACKs during an ACK flood attack πŸ’œ

PUT /restconf/data/ietf-dots-data-channel:dots-data\
    /dots-client=paL8p4Zqo4SLv64TLPXrxA/acls\
    /acl=tcp-flags-example HTTP/1.1
Host: example.com
Content-Type: application/yang-data+json

{
  "ietf-dots-data-channel:acls": {
    "acl": [{
      "name": "tcp-flags-example",
      "type": "ipv4-acl-type",
      "activation-type": "activate-when-mitigating",
      "aces": {
        "ace": [{
          "name": "rate-limit-ack",
          "matches": {
            "tcp": {
              "flags-bitmask": {
                "operator": "match",
                "bitmask": 16
              }
            }
          },
          "actions": {
            "forwarding": "accept",
            "rate-limit": "20.00"
          }
        }]
      }
    }]
  }
}

Figure 38: Example of DOTS Request to Rate-Limit Incoming TCP ACKs

Acknowledgements 🌸

okay bestie, the thank-you list is SO long and I love that everyone got a shoutout 🫢 Thanks to Christian Jacquenet, Roland Dobbins, Roman Danyliw, Ehud Doron, Russ White, Gilbert Clark, Kathleen Moriarty, Nesredien Suleiman, Roni Even, and Brian Trammel for the discussion and comments πŸ’–

The authors also gave super special thanks to Kaname Nishizuka and Jon Shallow for actually implementing the protocol and running interop testing at IETF Hackathons. like, they built it and tested it with other people's code, iconic πŸ‘‘

Many thanks to Benjamin Kaduk for the detailed AD review πŸŽ€

Thanks to Martin BjΓΆrklund for the guidance on RESTCONF πŸ¦‹

Thanks to Alexey Melnikov, Adam Roach, Suresh Krishnan, Mirja KΓΌhlewind, and Warren Kumari for the review πŸ’…


Contributors 🧚

The following people contributed substantially to the content of this document and should be considered coauthors. they really did the work, so they get the coauthor title ✨

Kaname Nishizuka NTT Communications GranPark 16F 3-4-1 Shibaura, Minato-ku, Tokyo 108-8118 Japan

Email: kaname@nttv6.jp

Liang Xia Huawei 101 Software Avenue, Yuhuatai District Nanjing Jiangsu, 210012 China

Email: frank.xialiang@huawei.com

Prashanth Patil Cisco Systems, Inc.

Email: praspati@cisco.com

Andrew Mortensen Arbor Networks, Inc. 2727 S. State Street Ann Arbor, Michigan 48104 United States of America

Email: andrew@moretension.com

Nik Teague Iron Mountain Data Centers United Kingdom

Email: nteague@ironmountain.co.uk

The following individuals have contributed to this document:

Dan Wing

Email: dwing-ietf@fuggles.com

Jon Shallow NCC Group

Email: jon.shallow@nccgroup.com


Authors' Addresses πŸ’Œ

Okay so these are the people you can actually reach out to about the document. Mohamed Boucadair is the editor, based in Rennes, France πŸ‡«πŸ‡·

Mohamed Boucadair (editor) Orange 35000 Rennes France

Email: mohamed.boucadair@orange.com

And Tirumaleswar Reddy.K is the other editor, over at McAfee in Bangalore, Karnataka, India 🌈

Tirumaleswar Reddy.K (editor) McAfee, Inc. Embassy Golf Link Business Park Bangalore 560071 Karnataka India

Email: kondtir@gmail.com

That's the whole RFC, bestie! πŸ¦‹ Thanks for hanging with me through all 14 parts πŸ«ΆπŸ’–

πŸ“¦ where this page comes from