Summary

  • RFC 2385 authenticated each protected TCP segment with a shared secret and silently discarded failures, reducing the risk of forged resets against long-lived BGP sessions.
  • To fit scarce TCP option space, the deployed format carried neither an algorithm identifier nor a key identifier; validation proved one segment matched local configuration, not which security epoch, peer authority or route truth stood behind it.

A reset could erase more than a connection

BGP ran over TCP because TCP already supplied ordered, reliable delivery. That inheritance also created a narrow attack surface. An off-path attacker who guessed a connection’s endpoints and sequence space could inject a reset. TCP would close; the routing process might reconnect, or it might temporarily withdraw what it had learned from the peer. A small forged segment could therefore create an effect far larger than its own bytes.

RFC 2385 answered that problem at the transport boundary. Every protected segment received TCP option Kind 19, a length byte and a 16-byte digest. The digest covered the IPv4 pseudo-header, the TCP header with its checksum treated as zero and its options excluded, the payload, and a secret already known to both endpoints. An attacker now needed more than a plausible sequence number. The attacker also needed the shared secret.

The receiver recomputed the digest. If the values did not match, it dropped the segment and sent nothing back. That silence was part of the defense: a forged packet did not earn a useful protocol response. Logging was advisable, but not a receipt visible to the sender.

The IESG note was unusually candid. This was existing practice against certain simple attacks, with weaknesses against concerted ones. RFC 2385 did not claim to solve BGP security. It protected a specific TCP transition from a specific class of false input.

What the digest actually witnessed

The option’s name invited a larger interpretation than its evidence supported. “Signature” could sound like a certificate of identity or an endorsement of the routing information inside the stream. On the wire, the claim was thinner.

A matching digest showed that the received segment bytes, the endpoint addresses in the pseudo-header and one locally selected secret produced the same MD5 result at both ends. It did not identify the human operator. It did not establish that a particular autonomous system was entitled to originate a prefix. It did not show that a BGP UPDATE passed import policy, reached the routing table, entered forwarding hardware or delivered packets.

Even the key identity was absent. The segment carried no label saying which shared secret the receiver should try. Configuration supplied that fact. If several operational records disagreed about the current password, the digest could not resolve the disagreement; it could only pass or fail under whichever local state the implementation selected.

That makes the receipt chain important. Segment emission, option presence, key selection, digest validation, TCP acceptance, BGP session continuity, UPDATE acceptance, RIB selection, FIB installation and packet delivery are separate events. A valid digest closes only the first part of that chain.

Security was policy, not negotiation

RFC 2385 deliberately avoided negotiating whether the option would be used. Site policy and the application decided. The remote peer could not make a protected sender downgrade simply by omitting the option from its SYN/ACK. The sender continued to require signatures; the unsigned response was ignored and the connection did not form.

That was a strong local boundary. It also meant that operational agreement existed outside the packets. Both sides had to know that protection was required, choose the same secret and activate it at compatible times. A silent discard did not say which assumption was wrong. An absent option, a bad secret, a damaged segment and a peer that never enabled the feature could all appear as failure without a signed explanation.

RFC 2385 allowed the password to change during a live connection if both sides synchronized the change. It immediately admitted the difficult edge: retransmitted segments could become problematic in implementations that changed passwords. A segment created under the old secret could arrive after the receiver had moved to the new one. With no key identifier in the option, the packet could not tell the receiver which verification state belonged to it.

The specification had made validation deterministic only after local configuration supplied the missing epoch.

The byte that was not there

TCP’s header-length field caps the complete TCP header at 60 bytes. After the fixed 20-byte header, only 40 bytes remain for options. RFC 2385 illustrated how narrow that budget was. A SYN carrying MSS, window scale, timestamps, the MD5 option and padding consumed the entire allowance.

The MD5 option itself occupied 18 bytes: Kind, Length and the 16-byte digest. By the time the RFC was issued, collision-search concerns about MD5 were already known. Yet the option stayed fixed to MD5. The mechanism was deployed, and the format had no algorithm-type field.

Why omit it? The RFC recorded the arithmetic. An algorithm field would require at least one more byte, producing a 19-byte option that implementations would likely pad to 20. In a 40-byte option budget, those two effective bytes competed with other TCP capabilities. A local optimization made sense: protect the BGP session with the mechanism routers already ran and avoid consuming more of a scarce common header.

The cost appeared later. Because no algorithm could be named inside Kind 19, a stronger algorithm could not simply be selected in the same format. Migration required another option and a new compatibility contract. One saved byte was not the sole reason TCP MD5 persisted, but it made cryptographic choice invisible exactly where endpoints needed interoperable evidence of that choice.

Held Errata 4432 later corrected “32-byte words” to “32-bit words” in the header-length explanation. RFC 6691 corrected a different point: RFC 2385 had said the receiver should reduce its advertised MSS for the option, while the later rule made the sender subtract actual option bytes from its own data length. Those corrections sharpen the engineering record. They do not change the central 40-byte constraint or the missing algorithm field.

A key without a lifecycle

RFC 2385 left the nature of the shared key to applications and implementations. That kept the wire mechanism small, but the key-management surface did not disappear. It moved into router configuration, operator procedure and bilateral timing.

RFC 3562 made the displaced work visible. It recommended keys between 12 and 24 bytes, limited sharing across peering arrangements and changes at least every 90 days. The practical concern was not only abstract MD5 collision research. Weak or reused secrets could be guessed; a leaked key shared across many sessions enlarged the blast radius; a rotation could reset a session if the two sides changed at different times.

The option had no key number, no “next key” signal and no replay separation for a later connection that reused the same socket pair and master secret. A valid segment therefore proved possession of some configured secret, not that the secret was fresh, unique or still inside the intended operational boundary.

This is the difference between removing a decision from the common layer and pretending the decision no longer exists. The RFC kept the packet format thin, but it provided no portable state for the choices that operators still had to coordinate.

TCP-AO made the missing state explicit

RFC 5925 eventually obsoleted TCP MD5 with the TCP Authentication Option. TCP-AO separated algorithms into an extensible specification, added a KeyID and a receive-next-key identifier, derived traffic keys for particular connections and protected against replay across long-lived and repeated connections. It could coordinate a key change without asking every received segment to try an unnamed set of secrets.

TCP-AO still did not distribute master secrets or dynamically negotiate its own use. Operators or an external key-management system remained responsible for that. The replacement did not turn transport authentication into route authorization, encryption or a complete BGP security system.

That distinction matters because there is already a separate history to tell about TCP-AO key epochs. RFC 2385’s history ends earlier. It is the history of a deployed defense whose compact wire image could say “this segment matches our shared state” but could not say which replaceable algorithm and key state the endpoints meant.

The historical boundary

RFC 2385 was not foolish because it was later obsoleted. It solved an urgent, bounded problem with the option space and deployed equipment available in 1998. Its restraint helped prevent remote downgrade: local policy, not an unauthenticated peer hint, decided whether protection was mandatory.

The durable lesson is about evidence design. A minimum common mechanism must be thin enough to deploy, but it must expose enough state for independent implementations to replace it. If algorithm and key identity remain entirely outside the packet, a successful digest can validate present compatibility while giving no portable path to future compatibility.

The Internet did receive a stronger option later. It needed a new one. RFC 2385 had protected the segment, but the missing selector meant running code could not change the algorithm without changing the protocol surface around it.

Sources