skip to content

In DTLS, what lets a receiver select the right security association when a peer reappears from a different source address?

level: seniorimportance: nice to knowfreq 30%

answer

  1. the address stopped being the name
  2. something in the record names it
  3. you advertise what you want to receive
  4. fixed until a new handshake
  5. in the clear, therefore linkable

basics

~20 s

The connection_id(54) extension. Each party advertises a ConnectionId it wishes to receive, the peer stamps that value on records it sends, and the receiver selects the association by that identifier instead of by the source address and port.

solid answer

~50 s

Without help, a receiver demultiplexes by the address and port tuple, so an address change — a rebound mapping, a different backhaul, a device that slept for hours — makes the records unmatchable and costs a fresh handshake. The `connection_id(54)` extension fixes that. The direction is the part people invert: **each party sends the `ConnectionId` value it wishes to RECEIVE**, so the value you advertise is the one your peer stamps on records addressed to you, and a zero-length value means you want none yourself. In DTLS 1.2 a record carrying one uses the `tls12_cid` content type, with the real content type moved inside the protected payload; DTLS 1.3 flags its presence in the unified header. The identifier is fixed for the association — changing it requires a fresh handshake — and a receiver must not move the peer's address until a record from the new one authenticates.

code

pseudocode · 15 lines
pseudocode
the value each side advertises is the value it wants to RECEIVE

  ClientHello   connection_id: (empty)   -- the buoy needs none on records sent to it
  ServerHello   connection_id: 0x4A2F    -- stamp this on records you send me

the buoy wakes hours later behind a different public address:

  record arrives at the server:
      content type  tls12_cid
      connection id 0x4A2F
      protected payload (the real content type is inside)

  select the association named by 0x4A2F, not the source address
  attempt authenticated decryption and the replay check
  update the stored peer address ONLY if both succeed

go deeper

for a junior

Know that DTLS normally finds an association by the source address and port, and that an extension exists so a peer whose address changes can still be recognised.

for a middle

Get the direction right: a party advertises the identifier it wants stamped on records sent to it, and a record carrying one is marked at the record layer so the receiver knows where to look.

for a senior

Show the handling rules: select by identifier, authenticate, and only then move the peer's address, and be able to say why a cleartext identifier does not hand an attacker anything beyond correlation.

for a principal

Frame it as a trade for the fleet. Surviving address changes saves a handshake on every wake for battery-powered devices, at the price of a stable clear identifier that cannot be rotated without a new handshake.

## What normally selects an association A receiver holding many DTLS associations has to decide which keys to apply to an arriving datagram, and by default it decides on the only thing it has: the source address and port. That works as long as the tuple is stable — and for a marine buoy uplink it is not. A device that sleeps for hours loses its address mapping; a device that reconnects through a different backhaul gets a different public address; a translation device rewrites the port whenever it pleases. When the tuple changes, the records look like traffic for an association the receiver cannot find, so it discards them, and recovery means a whole new handshake — expensive on a link where the handshake is already the costly part. ## The extension, and the direction that trips everyone The `connection_id(54)` extension carries a `ConnectionId`, an opaque value that names an association independently of any address. The rule to memorise: > **The value a party sends is the value it wishes to RECEIVE.** So if the server advertises `0x4A2F`, the **buoy** stamps `0x4A2F` on every record it sends **to the server**, and the server uses it to find the association. A zero-length value means 'I do not want one on records sent to me', and a party willing to stamp the peer's value still sends the extension to say so. Both sides must send the extension for either to be used, and the two directions are independent: it is perfectly normal for only the side behind the moving address to be named. This matters because the deployment asymmetry is real. It is the **server** that struggles to find an association for a moving client, so it is the server that needs a connection ID it can recognise — even though the client is the one whose address moves. ## How a record carries it - **DTLS 1.2.** A record carrying a connection ID uses the `tls12_cid` content type in the record header, and the record's real content type travels inside the protected payload. The outer type therefore says 'there is a connection ID here', and the true type is only visible after decryption. - **DTLS 1.3.** Presence is signalled by a flag bit in the variable-length unified header, alongside the low-order epoch bits and the protected sequence number. In both cases the identifier itself is in the clear. It has to be — it is what selects the keys, so nothing can decrypt the record before reading it. ## The rules that keep it from becoming a hijack primitive An identifier in the clear that makes a receiver accept records from a new address is obviously interesting to an attacker, so the handling rules matter as much as the mechanism: 1. **Select the association by the identifier; do not move the peer's address on the strength of it.** The address is updated only after a record from the new address passes authenticated decryption and the replay check. 2. **Prefer to confirm the new path before sending much to it**, so that a forged record cannot redirect a stream of traffic at a victim. 3. **A copied identifier gains nothing on its own.** Without the keys, an attacker who replays or forges a record with the right identifier produces something that fails authentication and is discarded. 4. **The identifier is fixed for the association's life.** It cannot be renegotiated mid-flight; a new value requires a fresh handshake. That simplicity is deliberate, and it is also the mechanism's main cost. ## The privacy cost, stated honestly A stable identifier in the clear is a **linkable** identifier. Anyone on the path can follow it across address changes and across networks and say with certainty that two flows are the same association — which is precisely the correlation that changing addresses would otherwise have hidden. The trade is explicit: | | With a connection ID | Without one | |---|---|---| | Address change | association survives | records are discarded, new handshake needed | | Cost per change | none | a full handshake, plus the cookie round trip | | Observer on the path | can link flows across addresses | must correlate by address, which just changed | | Changing the identifier | needs a fresh handshake | not applicable | For a battery-powered sensor that wakes, sends a burst and sleeps, surviving the address change is usually worth the linkability, because the alternative is paying for a handshake on every wake. For a device whose movements are themselves sensitive, the calculus can go the other way — and because the value is fixed until a new handshake, 'rotate it occasionally' is not available as a middle path.

  • Which value does a peer put in the connection_id extension it sends?
    The one it wants to receive. Advertising a value tells the peer to stamp that value on records it sends to you, so the side that struggles to find an association for a moving peer is the side that must advertise. A zero-length value says you want none yourself while remaining willing to stamp the peer's.
  • A record with a known connection ID arrives from an address you have never seen. What now?
    Use the identifier to select the association and attempt authenticated decryption plus the replay check, but do not move the stored peer address until both succeed. Moving first would let anyone who copied a cleartext identifier redirect the traffic, turning the mechanism into a way to point a stream at a victim.
  • Can a connection ID be rotated without a new handshake?
    No. The value is fixed for the life of the association, and a different one requires a fresh handshake. That is why the linkability cost cannot be mitigated by rotation: the identifier travels in the clear on every record for as long as the association lasts, and an observer on the path can follow it across address changes.

saying these in an interview costs you the question

  • Says a peer advertises the identifier it will send on its own records
  • Claims the connection ID is encrypted and therefore unlinkable
  • Thinks a copied identifier lets an attacker read or inject data
  • Moves the stored peer address before the record authenticates
  • Believes the identifier can be renegotiated mid-association
  • Assumes both directions must use an identifier if either does