Chapters

18 CoAP Security: Protection and Application Fit

coap
security

18.1 Overview

This first route builds the CoAP security boundary and tests where constrained request-response communication fits real applications.

This is part 1 of 2. Continue with CoAP Security: Implementation and Operations for the second focused route.

  1. Broker Bex stands between a ward medicine sensor and a nurse while an exposed message path crosses an uncertain network boundary.

    How can the reading reach only the nurse who needs it?

CP-0128 pre-concept hook: How can the reading reach only the nurse who needs it?

18.2 Start With the Private Reading

Protect the Whole Exchange, Not Only the Number

Picture a ward sensor sending a medicine temperature to a nurse. The number is private, but the device name, request path, time, and pattern of use can also reveal patient care. The service owner must decide who may read or change the resource and what proof the small device can afford.

Draw one exchange from the sensor to the approved reader. Mark the device identity, the peer it trusts, the key or certificate in use, the protected fields, and the rule that grants access. Record when the proof starts, when it expires, and who can replace it after loss or repair.

Repeat the exchange with a false peer, an old key, a copied message, a delayed reply, a changed address, and a sleeping device. Check that private data stays hidden, changed data is rejected, and a failed check cannot turn into an unsafe command. Save enough detail to explain each refusal.

Keep any urgent safe response near the ward device or local care system. A distant security service can help issue and revoke trust, but loss of that link must not silently grant access or block a required local safeguard.

This opening does not size every packet or settle every legal duty. Practitioner builds the access and recovery test. Under the Hood follows message protection, key exchange, replay checks, constrained memory, and the limits of each security choice.

Use this private exchange check:

  • Name the small device.
  • Name the right peer.
  • Name the allowed read.
  • Name the allowed write.
  • Mark each trust root.
  • Mark the key owner.
  • Mark the key age.
  • Mark the key end.
  • Keep the source name.
  • Keep the event time.
  • Try the wrong peer.
  • Try the old key.
  • Try the copied note.
  • Try the late reply.
  • Try the changed path.
  • Try the lost link.
  • Try a deep sleep.
  • Check each clear refusal.
  • Check the safe fallback.
  • Save the failed trace.
  • Save the passed trace.
  • Reopen when trust changes.

Picture a wearable sensor sending a heart-rate value through a hospital gateway. The payload is sensitive, but so are the resource path, timing, identity, and repeated access pattern. CoAP security has to protect the exchange without spending so much energy that the device cannot do its job.

This page follows that practical tension: secure the datagrams, choose credentials, keep sessions alive when possible, and decide where application policy belongs in real deployments.

Chapter Roadmap

This is a long chapter, so read it as a sequence of design decisions:

  1. First we decide what DTLS protects, why CoAPs uses port 5684, and where payload-only encryption falls short.
  2. Then we size the security cost with the chapter’s handshake, header, MAC, and battery examples.
  3. Next we connect those choices to smart energy, building automation, industrial, healthcare, agriculture, and asset-tracking deployments.
  4. After that we turn to implementation failure modes: tokens, retransmission backoff, MTU limits, response codes, and CON/NON misuse.
  5. Finally we compare DTLS, OSCORE, credentials, proxies, and deep-sleep recovery before the summary quizzes.

Checkpoints recap the required decisions as you go. Deep-dive and interactive sections are optional on a first read, but they show the calculations behind the recommendations.

18.3 Learning Objectives

  • Explain how DTLS (Datagram TLS) provides encryption, authentication (PSK or certificates), and integrity protection for CoAP on port 5684
  • Distinguish between application-layer payload encryption and DTLS transport encryption, and justify why only DTLS satisfies HIPAA compliance for full metadata protection
  • Apply CoAP in real-world deployments including smart energy metering, building automation (HVAC/lighting), and industrial sensor networks
  • Select appropriate CoAP message types (CON vs NON) based on message criticality, battery constraints, and reliability requirements, and justify your choice
  • Diagnose common CoAP implementation issues including token matching failures, retransmission backoff misconfiguration, MTU size violations, and response code misinterpretation

Read these points as one connected sequence: start with CoAP: Constrained Application Protocol — REST-style request/response protocol using UDP instead of TCP; then Confirmable Message (CON): Requires ACK from recipient — provides reliable delivery over UDP at the cost of one roundtrip; then Non-confirmable Message (NON): Fire-and-forget UDP datagram — lowest latency, no delivery guarantee; then Observe Option: CoAP extension enabling publish/subscribe: client registers to receive notifications on resource changes; then Block-wise Transfer: Fragmentation mechanism for transferring payloads larger than a single CoAP datagram; then Token: Client-generated value matching responses to requests — enables concurrent request/response pairing; and finish with DTLS: Datagram TLS — CoAP’s security layer providing encryption and authentication over UDP.

  • CoAP: Constrained Application Protocol — REST-style request/response protocol using UDP instead of TCP
  • Confirmable Message (CON): Requires ACK from recipient — provides reliable delivery over UDP at the cost of one roundtrip
  • Non-confirmable Message (NON): Fire-and-forget UDP datagram — lowest latency, no delivery guarantee
  • Observe Option: CoAP extension enabling publish/subscribe: client registers to receive notifications on resource changes
  • Block-wise Transfer: Fragmentation mechanism for transferring payloads larger than a single CoAP datagram
  • Token: Client-generated value matching responses to requests — enables concurrent request/response pairing
  • DTLS: Datagram TLS — CoAP’s security layer providing encryption and authentication over UDP

18.4 For Beginners: CoAP Security

Securing CoAP means protecting the data that tiny IoT devices exchange. Since CoAP runs over UDP, it uses DTLS for encryption rather than the TLS used by web browsers. This chapter also covers real-world CoAP applications in smart buildings, industrial sensors, and wearable devices where security is essential.

“Wait — if CoAP sends data over UDP, can’t anyone listen in?” Temperature Terry asked nervously. “My medical sensor readings are private!”

the microcontroller nodded seriously. “That’s why we have DTLS — it’s like TLS (the lock on websites) but designed for UDP. It wraps your CoAP messages in encryption so nobody can read them in transit. Think of it as putting your letter in a locked box before mailing it.”

“But locking costs energy,” the battery pointed out. “The DTLS handshake — where devices exchange keys — takes several extra messages. That’s why you keep the connection open after the handshake so you don’t have to redo it every time. One handshake, then many encrypted messages.”

the LED shared a real example: “In a smart hospital, CoAP with DTLS protects patient data from sensors to the nurse’s station. Without encryption, a hacker with a radio could intercept heart rate data. With DTLS, all they see is scrambled nonsense. Security isn’t optional when lives are at stake!”

In 60 Seconds

CoAP uses DTLS (Datagram TLS) for security over UDP, providing encryption, authentication (via pre-shared keys or certificates), and integrity protection on port 5684. Unlike application-layer encryption which only protects the payload, DTLS encrypts the entire CoAP message including headers, URIs, and options — critical for compliance scenarios like healthcare (HIPAA) where metadata exposure is itself a privacy violation.

The mathematical gist. At a fixed 250 kbps and 20 mA transmit current, time is bits divided by bit rate and charge is current multiplied by time. The chapter’s 53-byte secured record therefore takes 1.696 ms and 0.00000942 mAh, while its 20-byte plain message takes 0.640 ms and 0.00000356 mAh: almost exactly the same 2.65x ratio as their byte counts. At 1,440 readings per day, add the 0.064 µAh handshake once, then keep self-discharge and derating separate from the radio ledger.

Math Bridge · guided foundationsHow do 53 secured bytes become a daily battery cost?Let Eddie connect bits, airtime, charge, session reuse, and cell limits.

18.5 Continue: CoAP DTLS and OSCORE Security Contracts

The main chapter below stays focused on CoAP security and application practice. For the deeper contract behind DTLS security modes, proxy termination, OSCORE inner and outer options, and replay protection, continue to CoAP DTLS and OSCORE Security Contracts.

18.6 Security with DTLS

Start with the security boundary. If the deployment needs privacy, the first question is not which CoAP method to call, but which fields must be hidden from the network.

CoAP uses DTLS (Datagram TLS) for security:

Features:

  • Encryption of messages
  • Authentication (Pre-Shared Keys or Certificates)
  • Integrity protection

DTLS vs TLS:

  • TLS = for TCP (HTTP)
  • DTLS = for UDP (CoAP)

Port:

  • CoAP: 5683
  • CoAPs (secure): 5684

Choosing DTLS for CoAP is about adapting security to datagrams, not borrowing TLS unchanged. Inspect Figure 18.1 to compare the transport assumptions first and the shared security outcomes second.

Balanced comparison of DTLS over UDP and TLS over TCP. DTLS is shown with CoAP and CoAPS, datagram loss and reordering, a cookie anti-denial-of-service check, session reuse, and an explicit warning that DTLS does not make UDP reliable. TLS is shown with HTTPS and MQTT over TLS, TCP’s reliable ordered byte stream, and stream-based handshake records. A shared band lists confidentiality, integrity, and peer authentication.
Figure 18.1: DTLS and TLS can provide the same core security goals, but their transport and handshake mechanics differ.

In Figure 18.1, read the DTLS side through UDP loss, reordering, and the cookie check, then contrast it with TLS running over TCP’s ordered byte stream. Both can provide confidentiality, integrity, and peer authentication, but DTLS must handle datagram behavior explicitly and does not make UDP reliable. That boundary matters when the knowledge check asks what payload-only encryption leaves exposed.

Try It: DTLS Handshake Step Explorer

Explore each step of the DTLS handshake process. Adjust the security mode and network latency to see how the handshake timing and energy cost change for constrained IoT devices.

18.7 DTLS Setup: Pre-Shared Key Example

Setting up secure CoAP (CoAPs) with DTLS-PSK authentication using Python:

# pip install aiocoap[dtls]
# Requires: tinydtls library (pip install DTLSSocket)
import asyncio
import aiocoap
import aiocoap.credentials

# --- Server side: CoAPs on port 5684 ---
async def create_secure_server():
    """Start a CoAP server with DTLS-PSK on port 5684."""
    root = aiocoap.resource.Site()
    root.add_resource(['temperature'],
                      TemperatureResource())

    # Define server credentials: map client identities to PSKs
    server_credentials = aiocoap.credentials.CredentialsMap()
    server_credentials.load_from_dict({
        # Identity "sensor-042" uses this 16-byte pre-shared key
        ':dtls-psk': {
            'sensor-042': b'MySecret16ByteK!',
            'sensor-043': b'AnotherKey16Byt!',
        }
    })

    context = await aiocoap.Context.create_server_context(
        root,
        bind=('::', 5684),  # Secure CoAP port
    )
    context.client_credentials = server_credentials
    return context

# --- Client side: connect with PSK identity ---
async def secure_get_temperature():
    """GET coaps://server/temperature with DTLS-PSK."""
    context = await aiocoap.Context.create_client_context()

    # Set client identity and PSK
    context.client_credentials.load_from_dict({
        'coaps://server/*': {
            'dtls': {
                'psk': b'MySecret16ByteK!',
                'client-identity': b'sensor-042'
            }
        }
    })

    request = aiocoap.Message(
        code=aiocoap.GET,
        uri='coaps://server/temperature'  # Note: coaps:// not coap://
    )
    response = await context.request(request).response
    print(f"Secure response: {response.payload.decode()}")

# What to observe:
# - URI scheme is coaps:// (port 5684) vs coap:// (port 5683)
# - DTLS handshake adds ~200ms on first request (key exchange)
# - Subsequent requests reuse session (~5ms overhead)
# - If PSK doesn't match: handshake fails, no data exchanged

Testing DTLS with CLI tools:

# Generate a PSK identity file for coap-client
# coap-client supports DTLS-PSK natively

# Secure GET request
coap-client -m get coaps://localhost/temperature \
  -k "MySecret16ByteK!" \
  -u "sensor-042"

# Verify encryption with Wireshark:
# Filter: dtls && udp.port == 5684
# You should see:
#   ClientHello -> ServerHello -> ChangeCipherSpec
#   Then encrypted ApplicationData (CoAP payload not readable)

DTLS overhead comparison:

Plain CoAP (UDP port 5683):
  Request:  4-byte header + payload
  Response: 4-byte header + payload
  Latency:  1 RTT (~20ms LAN)

Secure CoAP (DTLS port 5684):
  First request:  DTLS handshake (4-6 messages) + encrypted payload
  Latency:  3 RTTs for handshake + 1 RTT for data = ~80ms first request
  Overhead: 13 bytes DTLS record header per message

  Subsequent requests (session reuse):
  Latency:  1 RTT + ~5ms DTLS overhead = ~25ms
  Overhead: 13 bytes header + 8-16 bytes MAC (integrity)

Energy cost of DTLS handshake (one-time per session):
  6 messages x 100 bytes avg x 10 mA TX = 0.6 mAs
  Amortized over 1000 messages: 0.0006 mAs each (negligible)
  Keep DTLS sessions alive to avoid repeated handshakes.

DTLS security has real cost, but it’s manageable with session reuse. Let’s quantify:

DTLS handshake energy (PSK mode):

  • ClientHello: 120 bytes @ 20 mA TX for 4.8 ms = 0.027 µAh
  • ServerHello + ChangeCipherSpec: 140 bytes RX = 0.024 µAh
  • Client Finished: 60 bytes TX = 0.013 µAh
  • Total handshake: 0.064 µAh (one-time cost)

Per-message overhead (after handshake):

  • DTLS record header: 13 bytes
  • Encrypted CoAP message: 20 bytes → 32 bytes (16-byte AES-CCM block alignment)
  • MAC tag: 8 bytes
  • Total: 13+32+8=5313 + 32 + 8 = 53 bytes vs 20 bytes plain CoAP

Amortization over 24 hours (1 reading/minute): Messages/day=24×60=1,440\text{Messages/day} = 24 \times 60 = 1{,}440 Handshake cost/message=0.0641,440=0.0000444 µAh (negligible)\text{Handshake cost/message} = \frac{0.064}{1{,}440} = 0.0000444 \text{ µAh (negligible)}

Per-message transmission (53 bytes secured vs 20 bytes plain, both @ 250 kbps, 20 mA TX; energy in µAh =ImA×tms/3,600= I_{mA}\times t_{ms}/3{,}600): tsecure=53×8250,000=1.696 ms20×1.6963,600=0.009422 µAht_{secure} = \frac{53 \times 8}{250{,}000} = 1.696 \text{ ms} \Rightarrow \frac{20\times1.696}{3{,}600} = 0.009422 \text{ µAh} tplain=20×8250,000=0.640 ms20×0.6403,600=0.003556 µAht_{plain} = \frac{20 \times 8}{250{,}000} = 0.640 \text{ ms} \Rightarrow \frac{20\times0.640}{3{,}600} = 0.003556 \text{ µAh}

Daily DTLS cost: 0.064+(1,440×0.009422)=13.630.064 + (1{,}440 \times 0.009422) = 13.63 µAh =0.01363= 0.01363 mAh Daily plain CoAP: 1,440×0.003556=5.121{,}440 \times 0.003556 = 5.12 µAh =0.00512= 0.00512 mAh (20-byte messages)

Security overhead: 0.013630.00512=2.66×\frac{0.01363}{0.00512} = 2.66\times or 166% more energy — tracking the 53:20 byte ratio, since energy at fixed rate/current is set by bytes moved. Still an acceptable trade-off for HIPAA compliance: on the chapter’s own 220 mAh CR2032 default, idealised life is 44.2 yr secured vs 118 yr plain — both far past any realistic deployment target.

Broker BexCheckpoint: Secure Transport

You now know:

  • Plain CoAP uses port 5683, while CoAPs uses DTLS on port 5684.
  • DTLS protects headers, URIs, options, payload, integrity, and authentication; application-layer encryption protects only the payload.
  • Session reuse matters: the chapter’s DTLS example amortizes a 0.064 µAh handshake over 1,440 messages/day, while each protected 20-byte reading grows to 53 bytes.

18.8 Interactive Security Calculators

Explore the energy costs and trade-offs of CoAP security options with these interactive calculators:

18.8.1 DTLS Energy Cost Calculator

18.8.2 Battery Life Estimator: CON vs NON

18.8.3 Protocol Overhead Comparison

18.8.4 Block Transfer Size Optimizer

18.8.5 Security vs Battery Trade-off Analyzer

Key Insights from Calculators:

Read these points as one connected sequence: start with DTLS Energy: Handshake is expensive (~0.064 mAh) but amortized over many messages becomes negligible; then CON vs NON: Confirmable messages use 2.5× more energy due to ACK requirement - use NON for telemetry; then Protocol Overhead: CoAP has 16.7% overhead vs HTTP’s 90.9% for small payloads - massive difference for IoT; then Block Transfer: Smaller MTUs (6LoWPAN) require smaller blocks but increase round trips - find the balance; and finish with Security Trade-off: DTLS adds 15-80% overhead depending on message frequency - but required for compliance.

  • DTLS Energy: Handshake is expensive (~0.064 mAh) but amortized over many messages becomes negligible
  • CON vs NON: Confirmable messages use 2.5× more energy due to ACK requirement - use NON for telemetry
  • Protocol Overhead: CoAP has 16.7% overhead vs HTTP’s 90.9% for small payloads - massive difference for IoT
  • Block Transfer: Smaller MTUs (6LoWPAN) require smaller blocks but increase round trips - find the balance
  • Security Trade-off: DTLS adds 15-80% overhead depending on message frequency - but required for compliance

18.9 Real-World Applications

With the transport and battery costs in mind, the next step is matching message type and security mode to the application domain.

18.9.1 Smart Energy

Smart Meters:

  • Read consumption (GET)
  • Update tariffs (PUT)
  • Control load (POST)
coap://meter.home/consumption
coap://meter.home/tariff
coap://meter.home/switch

18.9.2 Building Automation

HVAC Control:

  • Read temperature
  • Set thermostat
  • Schedule modes

Lighting:

  • Query status
  • Control brightness
  • Manage groups (multicast)

18.9.3 Industrial IoT

Industrial CoAP designs should separate observation from control. A sensor network may poll values frequently with replaceable NON traffic, but a sampling-rate change needs an authenticated, authorized, confirmable write and a traceable 2.04 Changed outcome. Firmware update metadata and blocks add integrity, rollback, and power requirements beyond delivery alone. Asset tracking follows the same consequence test: a periodic location or status update may tolerate loss, whereas an alert notification can require confirmable delivery, deduplication, and escalation evidence. The protocol choice stays connected to the operational risk of each resource.

Try It: CoAP Application Scenario Builder

Select a real-world IoT application domain and configure CoAP parameters. The tool recommends optimal message types, security modes, and observe patterns based on your deployment requirements.

Broker BexCheckpoint: Application Fit

You now know:

  • Smart energy readings need CON when missed billing data would cause financial errors.
  • Building automation can mix NON readings with CON setpoint changes, while industrial firmware blocks need CON with Block2.
  • The scenario builder keeps the same deployment questions visible: device count, messages per day, security mode, observe pattern, and battery estimate.

18.10 Lab Exercise

Goal: Build CoAP temperature monitoring system

Hardware (or simulate):

Read these points as one connected sequence: start with ESP32 board; and finish with DHT22 sensor.

  • ESP32 board
  • DHT22 sensor

Tasks:

Read these points as one connected sequence: start with Setup CoAP Server (on Raspberry Pi or PC):; then Install aiocoap; then Create temperature resource; then Add humidity resource; and finish with Implement GET and PUT methods.

  1. Setup CoAP Server (on Raspberry Pi or PC):
    • Install aiocoap
    • Create temperature resource
    • Add humidity resource
    • Implement GET and PUT methods

Read these points as one connected sequence: start with Create ESP32 CoAP Client:; then Connect to Wi-Fi; then Send GET requests every 30s; and finish with Display responses on Serial Monitor.

  1. Create ESP32 CoAP Client:
    • Connect to Wi-Fi
    • Send GET requests every 30s
    • Display responses on Serial Monitor

Read these points as one connected sequence: start with Add Observe Pattern:; then Server notifies on temperature change; then Client receives push updates; and finish with No polling needed.

  1. Add Observe Pattern:
    • Server notifies on temperature change
    • Client receives push updates
    • No polling needed

Read these points as one connected sequence: start with Implement Multicast Discovery:; then Client broadcasts to find servers; and finish with Servers respond with capabilities.

  1. Implement Multicast Discovery:
    • Client broadcasts to find servers
    • Servers respond with capabilities

Challenge: Add CoAP-to-MQTT bridge for cloud integration

18.11 When to Use CoAP

18.11.1 Choose CoAP when:

Read these points as one connected sequence: start with Constrained devices (8-bit MCU, limited RAM); then Low power critical (battery-operated); then Request/Response pattern fits your needs; then RESTful API desired; then Multicast needed for device discovery; then IPv6 networks (6LoWPAN); and finish with Direct device-to-device communication.

  • Constrained devices (8-bit MCU, limited RAM)
  • Low power critical (battery-operated)
  • Request/Response pattern fits your needs
  • RESTful API desired
  • Multicast needed for device discovery
  • IPv6 networks (6LoWPAN)
  • Direct device-to-device communication

18.11.2 Choose HTTP when:

  • Web browser access needed
  • Infrastructure already HTTP-based
  • Devices not constrained
  • Complex authentication required

18.11.3 Choose MQTT when:

  • Publish/Subscribe pattern needed
  • Central broker acceptable
  • Many-to-many communication
  • QoS levels important
  • Topic-based routing preferred

18.12 Common Implementation Pitfalls

Once the protocol choice is made, reliability depends on small implementation details that UDP will not fix for you.

Pitfall: Forgetting to Handle CoAP Token Matching in Observe Responses

The Mistake: Implementing CoAP Observe without properly tracking tokens, causing clients to misattribute notifications to the wrong resources when observing multiple endpoints simultaneously.

Why It Happens: Developers familiar with HTTP assume response correlation is automatic. In CoAP, the token (0-8 bytes) links requests to responses. When observing /temperature and /humidity concurrently, both notification streams arrive on the same UDP socket and must be matched by token.

The Fix: Maintain a token-to-resource mapping for all active observations:

# BAD: Ignoring tokens
def on_notification(response):
    print(f"Got value: {response.payload}")  # Which resource?

# GOOD: Token-based dispatch
observations = {}  # token -> resource_uri mapping

def observe_resource(uri):
    token = generate_unique_token()
    observations[token] = uri
    send_observe_request(uri, token)

def on_notification(response):
    uri = observations.get(response.token)
    if uri:
        print(f"Resource {uri} = {response.payload}")
    else:
        print(f"Unknown token, sending RST")
        send_reset(response.mid)

Use unique tokens per observation (e.g., 4-byte random values) and clean up mappings when observations are cancelled or reset.

Pitfall: CoAP Retransmission Backoff Flooding the Network

The Mistake: Using aggressive fixed-interval retransmissions for CON messages instead of exponential backoff, causing network congestion when packet loss occurs.

Why It Happens: Developers implement simple “retry every 2 seconds” logic without realizing that CoAP specifies exponential backoff (RFC 7252). On a lossy wireless network with 20% packet loss, aggressive retries amplify traffic by 5x and worsen congestion.

The Fix: Implement RFC 7252 compliant retransmission with exponential backoff:

# BAD: Fixed interval retry (network flooding)
RETRY_INTERVAL = 2.0  # seconds
for attempt in range(MAX_RETRIES):
    send_message(msg)
    if wait_for_ack(RETRY_INTERVAL):
        break

# GOOD: Exponential backoff per RFC 7252
ACK_TIMEOUT = 2.0      # Initial timeout (2 seconds)
ACK_RANDOM_FACTOR = 1.5  # Randomization factor
MAX_RETRANSMIT = 4      # Maximum retries

def coap_transmit(msg):
    timeout = ACK_TIMEOUT * (1 + random.random() * (ACK_RANDOM_FACTOR - 1))
    for attempt in range(MAX_RETRANSMIT + 1):
        send_message(msg)
        if wait_for_ack(timeout):
            return True
        timeout *= 2  # Double timeout each retry: 2s, 4s, 8s, 16s
    return False  # Give up after ~45 seconds total

With proper backoff: first retry at 2-3s, second at 4-6s, third at 8-12s, fourth at 16-24s. Total worst-case wait: ~45 seconds before declaring failure.

Pitfall: An Open CoAP Server Becomes a DDoS Reflector
  1. Broker Bex crosses out an open public server equals only eavesdropping claim in red; the same panel shows a tiny forged request with a victim return address, a larger reply hitting the victim, and a firewall blocking it.

    Wrong: An open device server risks only its own data. Fake return addresses can make it flood someone else.

CP-0064 misconception buster: Leaving a NoSec coap:// endpoint reachable from the public internet, on the assumption that CoAP's security risk starts and ends with eavesdropping on the device's own traffic.

The Mistake: Leaving a NoSec coap:// endpoint reachable from the public internet, on the assumption that CoAP’s security risk starts and ends with eavesdropping on the device’s own traffic.

Why It Happens: CoAP inherits UDP’s connectionless model, so there is no handshake like TCP’s SYN/ACK for a server to confirm that a request’s source address is genuine. An attacker can put a victim’s IP address in the source field of a small spoofed CoAP request and send it to any publicly reachable CoAP server. The server replies as designed, but the reply goes to the spoofed address, not to the attacker. Because a CoAP response — a discovery listing, a sensor reading with options, an error payload — is often several times larger than the one-line request that triggered it, published measurements put the resulting amplification factor at roughly 10-50x: the victim receives 10 to 50 times more traffic than the attacker sent. The device is not the target; it becomes an unwitting reflector in a DDoS attack against someone else.

The Fix: Do not place a NoSec CoAP resource directly on the public internet. Put it behind a gateway or firewall that only forwards requests from known client addresses, or require a DTLS mode (PreSharedKey or Certificate; see CoAP DTLS and OSCORE Security Contracts) whose handshake cookie exchange makes a client prove it owns its source address before the server does any real work. Where a public-facing endpoint is unavoidable, rate-limit responses per source address and cap response size so a spoofed request cannot draw an outsized reply.

18.13 Continue to Part 2

Continue with CoAP Security: Implementation and Operations.