<?xml version="1.0" encoding="US-ASCII"?>
<!-- edited with XMLSPY v5 rel. 3 U (http://www.xmlspy.com)
     by Daniel M Kohn (private) -->
<!DOCTYPE rfc SYSTEM "rfc2629.dtd" [
<!ENTITY rfc2119 PUBLIC "" "http://xml.resource.org/public/rfc/bibxml/reference.RFC.2119.xml">
]>
<?rfc toc="yes"?>
<?rfc tocompact="yes"?>
<?rfc tocdepth="3"?>
<?rfc tocindent="yes"?>
<?rfc symrefs="yes"?>
<?rfc sortrefs="yes"?>
<?rfc comments="yes"?>
<?rfc inline="yes"?>
<?rfc compact="yes"?>
<?rfc subcompact="no"?>
<rfc category="std" docName="draft-wang-tls-service-affinity-04"
     ipr="trust200902">
  <front>
    <title abbrev="tls-service-affinity">Service Affinity Solution
    based on Transport Layer Security (TLS)</title>

    <author fullname="Wei Wang" initials="W" surname="Wang">
      <organization>China Telecom</organization>

      <address>
        <postal>
          <street>Beiqijia Town, Changping District</street>

          <city>Beijing</city>

          <region>Beijing</region>

          <code>102209</code>

          <country>China</country>
        </postal>

        <email>weiwang94@foxmail.com</email>
      </address>
    </author>

    <author fullname="Aijun Wang" initials="A" surname="Wang">
      <organization>China Telecom</organization>

      <address>
        <postal>
          <street>Beiqijia Town, Changping District</street>

          <city>Beijing</city>

          <region>Beijing</region>

          <code>102209</code>

          <country>China</country>
        </postal>

        <email>wangaj3@chinatelecom.cn</email>
      </address>
    </author>

    <author fullname="Zongbin Wang" initials="Z" surname="Wang">
      <organization>Beijing Infosec Technologies Co., LTD.</organization>

      <address>
        <postal>
          <street>No. 2 Building, Jinyu Science and Technology Park, Xisanqi</street>
          <street>No. 6 Jianfeng Road (Nanyan), Haidian District</street>

          <city>Beijing</city>

          <region/>

          <code/>

          <country>China</country>
        </postal>

        <phone/>

        <facsimile/>

        <email>wangzb@infosec.com.cn</email>

        <uri/>
      </address>
    </author>

    <author fullname="Mohit Sahni" initials="M" surname="Sahni">
      <organization>Palo Alto Networks</organization>

      <address>
        <postal>
          <street/>

          <city>San Francisco</city>

          <region/>

          <code/>

          <country>U.S.</country>
        </postal>

        <phone/>

        <facsimile/>

        <email>msahni@paloaltonetworks.com</email>

        <uri/>
      </address>
    </author>

    <author fullname="Ketul Sheth" initials="K" surname="Sheth">
      <organization>Palo Alto Networks</organization>

      <address>
        <postal>
          <street/>

          <city>San Francisco</city>

          <region/>

          <code/>

          <country>U.S.</country>
        </postal>

        <phone/>

        <facsimile/>

        <email>ksheth@paloaltonetworks.com</email>

        <uri/>
      </address>
    </author>

    <date day="6" month="July" year="2026"/>

    <area>SEC Area</area>

    <workgroup>TLS Working Group</workgroup>

    <keyword>RFC</keyword>

    <abstract>
      <t>This draft proposes a service affinity solution between client and
      server based on Transport Layer Security (TLS). It defines a minimal
      extension to TLS 1.3 by which a server instance can authorize a client to
      resume an established session on a different instance of the same service
      (for example, another node of a load-balanced cluster) and request, in
      band, that the client do so. The relocation authorization is carried
      inside the server's own session ticket, so it inherits the security
      properties of TLS 1.3 ticket-based resumption; the relocation target is an
      opaque identifier resolved by the application or control plane rather than
      an address carried in TLS.</t>

      <t>This document also introduces a Reliable Framing Layer that operates
      above the TLS record layer to provide message framing, sequence
      numbering, acknowledgment tracking, and automatic retransmission. The
      Framing Layer ensures zero application data loss during TLS session
      migration by buffering unacknowledged data frames and retransmitting
      them to the new server endpoint after migration completes.</t>
    </abstract>
  </front>

  <middle>
    <section anchor="intro" title="Introduction">
      <t>The rapid growth of internet services and the increasing complexity
      of network architectures have created a demand for more flexible and
      resilient connections between clients and servers. Modern service
      deployments often utilize multi-homed servers. These are systems that
      are equipped with multiple network interfaces and IP addresses. This
      architecture enhances availability, balances loads, and optimizes
      routing based on dynamic network conditions.</t>

      <t>In such environments, clients often need to relocate an established
      session from one server instance to another. Service continuity must be
      maintained during this migration. This necessity can arise from changes
      in network topology, server maintenance requirements, or the need to
      balance computational resources across different service nodes.</t>

      <t>In traditional solutions for maintaining service affinity or
      facilitating migration, each device needs to maintain a customer-based
      connection status table. This table will not change dynamically with the
      change of network status and computing resources. Moreover, the network
      devices should keep large amounts of status table to keep the service
      affinity for every customer flow. As the number of sessions increases,
      this table will grow in size, and an excessive number of sessions will
      impose pressure on the device.</t>

      <t>Besides, in the load balance scenario, a load balancer is usually put
      in front of all the physical servers so that all the packets sent and
      received by the physical servers should pass through the load balancer.
      This deployment may lead to the load balancer becoming the bottleneck
      when the traffic increases.</t>

      <t>HTTP redirection enables automatic page jumps by having the browser
      automatically send a new request based on the specific response status
      code and the value of the Location field returned by the server. It
      mainly involves the communication between client and server. Both client
      and server do not perceive changes in network status and cannot achieve
      comprehensive optimization based on network status and computing
      resource status.</t>

      <t>DNS redirection can redirect customer requests from one domain name
      to another by modifying DNS resolution records, or change the resolution
      result of a domain name to point to a different server IP address.
      However, due to the caching time of DNS records, it takes some time for
      the modification to take effect, which may result in customers still
      accessing servers that have been taken offline, thereby affecting
      customer experience.</t>

      <t>We propose a solution for the service affinity between client and
      server by extending TLS 1.3. This proposal is designed for environments
      where operational simplicity and migration speed are paramount. The server
      authorizes relocation by marking its session ticket, and triggers a move
      with a dedicated post-handshake message carrying an opaque target. The
      client then performs ordinary PSK-based resumption on the new instance;
      because only an instance holding the session's resumption keys can
      complete that resumption, a client that is steered to an endpoint outside
      the trust domain fails closed rather than exposing data (see Security
      Considerations).</t>

      <t>While the TLS session migration mechanism described in Sections 4-5
      ensures cryptographic session continuity, it does not by itself
      guarantee that in-flight application data is preserved during the
      reconnection. To address this, Section 6 introduces a Reliable Framing
      Layer that provides message framing, sequence tracking, and automatic
      retransmission to ensure zero application data loss across
      migrations.</t>
    </section>

    <section title="Conventions used in this document">
      <t>The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
      "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this
      document are to be interpreted as described in BCP 14 <xref
      target="RFC2119"/> <xref target="RFC8174"/> when, and only when, they
      appear in all capitals, as shown here.</t>
    </section>

    <section title="Motivation and design rationale">
      <t>In distributed cloud and edge computing architectures, traditional
      session identification based on static IP addresses can no longer meet
      the demands of dynamic networks. This proposal chooses to implement
      service affinity at the TLS layer, rather than through redirection at
      the application layer (e.g., HTTP) or the network layer, based on the
      following three core dimensions:</t>

      <t>First, TLS 1.3 <xref target="RFC8446"/> provides a secure channel for
      negotiating connection parameters without exposing sensitive data to
      network intermediaries. By conveying migration instructions and
      cryptographic material within the handshake, the solution avoids the
      visibility and interference issues associated with in-band
      application-layer signaling (e.g., HTTP redirects) or out-of-band
      network-layer mechanisms.</t>

      <t>Second, the TLS session resumption framework offers a natural
      abstraction for session continuity. The proposed extension leverages the
      existing NewSessionTicket message to carry the relocation authorization
      inside the server's opaque ticket, which is already encrypted,
      integrity-protected, and bound to the session by TLS 1.3. This inherits
      the resumption security properties directly, without introducing a new
      key schedule or a separately verified credential.</t>

      <t>Third, resumption on the new endpoint reuses the standard PSK-based
      abbreviated handshake. When a client relocates, it presents the ticket it
      already holds, allowing the new instance to recover the session, confirm
      it is authorized to relocate, and resume without a full cryptographic
      handshake. This minimizes the latency impact of migration, which is
      critical for real-time applications.</t>

      <t>Critically, this design does not require changes to the application
      data flow. It is transparent to both the application and the network
      path, making it compatible with any protocol running over TLS.</t>

      <t/>
    </section>

    <section title="Procedures of the proposed solution">
      <section title="Message flow of the overall procedure">
        <t>The message flow of the procedures of service affinity mechanism
        based on TLS are shown in Figure 1.<figure>
            <artwork><![CDATA[Phase 1: Initial handshake and authorization
       Client                                           Server(IP A)

Key  ^ ClientHello
Exch | + key_share*
     | + signature_algorithms*
     | + psk_key_exchange_modes*
     | + pre_shared_key*
     v + migration_support   -------->
                                                  ServerHello  ^ Key
                                                 + key_share*  | Exch
                                            + pre_shared_key*  v
                                        {EncryptedExtensions}  ^  Server
                                        {CertificateRequest*}  v  Params
                                               {Certificate*}  ^
                                         {CertificateVerify*}  | Auth
                               <--------           {Finished}  v
     ^ {Certificate*}
Auth | {CertificateVerify*}
     v {Finished}              -------->
                                           [NewSessionTicket]
                                    (+ migration_allowed; relocation
                                     authorization sealed in the ticket)
                               <--------             Finished

         Application Data         <------->         Application Data

Phase 2: Migration trigger (server-initiated; optional)
         Client                                        Server (IP A)
                     <--------    {migrate_request: opaque target}
         (resolve target via app/control plane -> IP B)

Phase 3: Reconnection and resumption
         Client                                        Server (IP B)
         ClientHello (to IP B)
         + key_share*
         + psk_key_exchange_modes* (psk_dhe_ke)
         + pre_shared_key* (ticket from IP A) -------->

                                       (B recovers session from ticket,
                                     confirms migration_allowed+scope)
                                                          ServerHello
                                                         + key_share*
                                                    + pre_shared_key*
                                                {EncryptedExtensions}
                                                   [NewSessionTicket]
                               <--------                   {Finished}

         Application Data         <------->         Application Data


        Figure 1: service affinity mechanism based on TLS
]]></artwork>
          </figure></t>

        <t/>
      </section>

      <section title="Phase 1: initial handshake and authorization">
        <t>1. A client supporting this mechanism includes the
        `migration_support` extension in its initial `ClientHello` message to
        the server at IP A. This extension is empty and serves only to signal
        capability.</t>

        <t>2. The server at IP A completes a standard TLS 1.3 handshake.</t>

        <t>3. After the handshake is complete, the server sends a
        `NewSessionTicket` message to enable standard Pre-Shared Key-based
        (PSK-based) session resumption. For a session it wishes to make
        relocatable, the server includes the zero-length `migration_allowed`
        extension in the NewSessionTicket and encodes the relocation
        authorization (and any operator-defined scope) inside the opaque ticket
        itself. The ticket is already encrypted, integrity-protected, and bound
        to the session, so no separate credential or new key schedule is
        introduced. The client treats the ticket as opaque.</t>
      </section>

      <section title="Phase 2: migration trigger">
        <t>a) If the session migration is triggered by the client, the client
        can directly switch the session to the new server according to
        business requirements.</t>

        <t>b) If the session migration is triggered by the server, it performs
        as follow:</t>

        <t>1. At a later point, the server at IP A initiates the
        migration.</t>

        <t>2. The server sends a `migrate_request` post-handshake message over
        the encrypted and authenticated connection, carrying an opaque target
        that identifies where the client should relocate. Because it travels
        inside the established channel it cannot be forged or injected by a
        network attacker, and the target can be chosen at this moment to reflect
        current conditions. The client SHOULD initiate relocation but MAY defer
        or decline per local policy; receipt is not an error and does not by
        itself invalidate the current connection.</t>
      </section>

      <section title="Phase 3: reconnection and resumption">
        <t>1. The client resolves the opaque target (from the `migrate_request`,
        or from its own policy for a client-initiated move) to a concrete
        endpoint that MUST represent the same server identity as the original
        session. It terminates its connection to IP A and initiates a new TLS
        connection to IP B.</t>

        <t>2. The client sends a `ClientHello` message to IP B carrying the
        standard `pre_shared_key` extension with the ticket it received from IP
        A. To preserve forward secrecy, the client MUST offer `psk_dhe_ke`; the
        `psk_ke` (PSK-only) mode MUST NOT be used for relocation. No
        migration-specific data is sent in the ClientHello.</t>

        <t>3. The server at IP B uses the PSK identity to recover the session,
        confirms from the ticket that the session is authorized to relocate and
        that IP B is within any encoded scope, and completes the abbreviated
        handshake. Mutual possession of the resumption secret is proven by the
        client PSK binder and the server Finished, as in TLS 1.3.</t>

        <t>4. If the ticket does not authorize relocation, if IP B is out of
        scope, or if PSK validation fails, the server MUST NOT apply migration
        semantics and proceeds per normal resumption or full-handshake rules. An
        endpoint outside the trust domain cannot recover the session, so the
        client's resumption fails and it MUST abort without sending application
        data.</t>
      </section>
    </section>

    <section title="Detailed formats">
      <t>This section defines the structure of the new protocol elements,
      following the presentation language of <xref target="RFC8446"/>.</t>

      <section anchor="migration_support" title="migration_support extension">
        <t>This extension is sent in the `ClientHello` to indicate support for
        this protocol. The `extension_data` field of this extension is zero-
        length. <figure>
            <artwork><![CDATA[        struct { } MigrationSupport;
]]></artwork>
          </figure></t>
      </section>

      <section title="migration_allowed extension">
        <t>This zero-length extension is sent by the server in the
        `NewSessionTicket` message to indicate that the accompanying ticket MAY
        be presented to a sibling instance under this mechanism.<figure>
            <artwork><![CDATA[        struct { } MigrationAllowed;
]]></artwork>
          </figure></t>

        <t>The authorization itself -- that the session may be relocated, and
        any operator-defined scope limiting which instances may accept it -- is
        carried INSIDE the opaque ticket, which is already encrypted,
        integrity-protected with the server's ticket key, and bound to the
        session by <xref target="RFC8446"/>. Any sibling instance that can
        already resume the session can therefore recover and check it. The
        internal ticket format is a server implementation matter and is not
        standardized; the client treats the ticket as opaque. The
        authorization's validity is bounded by the ticket's existing lifetime
        (ticket_lifetime); no separate expiry, nonce, or signature field is
        defined, and no new key schedule is introduced.</t>
      </section>

      <section title="migrate_request post-handshake message">
        <t>This proposal introduces a new post-handshake handshake message to
        request relocation. It carries an opaque target that identifies where
        the client should relocate (see below for how the client obtains the
        address).<figure>
            <artwork><![CDATA[        struct {
            opaque target<0..2^16-1>;  /* opaque; empty = client
                                          uses its own policy */
        } MigrateRequest;
]]></artwork>
          </figure></t>

        <t>A server MAY send `migrate_request` only after the handshake has
        completed and only on a connection whose ClientHello contained
        `migration_support`; it MUST NOT be sent during the handshake or as
        early data. It may be sent more than once (e.g. to update the target).
        A client that offered `migration_support` MUST accept it; receipt is not
        an error. A client that did not offer `migration_support` MUST treat
        receipt as an `unexpected_message` alert. `migrate_request` is processed
        independently of NewSessionTicket and KeyUpdate and does not change
        traffic keys.</t>

        <t>The `target` is opaque to TLS: TLS does not define its internal
        structure, assign it semantics, or act on it. The client obtains the
        concrete transport address for the new connection from the `target`
        without relying on TLS to interpret it. Two encodings are supported:<list
            style="symbols">
            <t>Self-contained address (default). The `target` directly encodes
            the switchover transport address (for example, an IP address and
            port). The client parses it and connects, requiring no DNS lookup
            and no external control plane or other infrastructure. This is the
            RECOMMENDED encoding for deployments that want the client to extract
            the address automatically from the message alone.</t>

            <t>Indirect identifier. The `target` is a label or name that the
            client resolves (via a control plane or DNS) to the specific
            instance. This suits environments such as Computing-Aware Traffic
            Steering (Section 7) that already operate such a resolver and want
            the mapping chosen at relocation time.</t>
          </list>In both cases the client ends up with a specific address to
        open the new TCP connection to. Because the `target` travels only inside
        the encrypted, authenticated `migrate_request` post-handshake message,
        carrying the address there does not expose it on the wire (beyond the
        unavoidable visibility of the subsequent TCP connection to that
        address) and cannot be forged or altered by a network attacker. Keeping
        the `target` opaque avoids defining a network-layer address type in TLS
        while preserving the switchover address for the client. An empty
        `target` indicates the client should apply its own relocation
        policy.</t>
      </section>
    </section>

    <section title="Reliable Framing Layer">
      <section title="Overview and Motivation">
        <t>The TLS session migration mechanism described in Sections 4-5
        provides cryptographic session continuity, enabling a client to
        seamlessly resume a TLS session on a new server endpoint. However,
        during the migration process, there is a period where the client has
        sent application data to the original server (Server A) that has not
        yet been acknowledged by the application layer. If the client
        disconnects from Server A before receiving acknowledgments for all
        sent data, that data may be lost.</t>

        <t>This section defines a Reliable Framing Layer that operates above
        the TLS record layer (as shown in Figure 2) to provide: <list
            style="symbols">
            <t>Message Framing: Delineation of application-level messages
            within the continuous TLS byte stream, independent of TLS record
            boundaries.</t>

            <t>Sequence Numbering: Unique, monotonically increasing sequence
            numbers for each sent frame, enabling ordered delivery and gap
            detection.</t>

            <t>Acknowledgment Tracking: Explicit ACK frames that allow the
            receiver to confirm receipt of specific data frames, giving the
            sender visibility into which data has been processed.</t>

            <t>Automatic Retransmission: Upon migration to a new server
            endpoint, the client automatically retransmits all data frames
            that were not acknowledged by the previous server, ensuring zero
            application data loss.</t>
          </list><figure>
            <artwork><![CDATA[    +------------------------------------------+
    |          Application Layer               |
    +------------------------------------------+
    |       Reliable Framing Layer             | 
    |  (framing, sequencing, ACK, retransmit)  |
    +------------------------------------------+
    |          TLS Record Layer                |
    |  (encryption, authentication, MAC)       |
    +------------------------------------------+
    |          TCP / Transport                 |
    +------------------------------------------+
Figure 2: Protocol Stack with Reliable Framing Layer]]></artwork>
          </figure>The Framing Layer is designed to be:<list style="symbols">
            <t>Transparent to TLS: It operates on top of the established TLS
            connection and does not modify TLS handshake behavior.</t>

            <t>Transport-agnostic: While specified here in the context of TLS
            session migration, the framing protocol can operate over any
            reliable byte-stream transport.</t>

            <t>Minimal overhead: The frame header is compact (11 bytes), and
            the protocol does not require additional round trips beyond those
            needed for TLS session migration.</t>

            <t>Application-controlled ACK policy: The receiver decides when to
            send ACKs, enabling strategies such as immediate ACK, delayed ACK,
            or selective ACK based on application requirements.</t>
          </list></t>
      </section>

      <section title="Frame Format">
        <t>Every frame transmitted over the Framing Layer has the following
        structure:<figure>
            <artwork><![CDATA[    enum {
        FRAME_MAGIC(0x4652),  // "FR" in ASCII
    } FrameMagic;

    enum {
        FRAME_FLAG_DATA(0x00),
        FRAME_FLAG_ACK(0x01),
        FRAME_FLAG_FIN(0x02),
        FRAME_FLAG_RETRANSMIT(0x04),
    } FrameFlag;

    struct {
        uint16 magic;            // Frame magic number (0x4652)
        uint8  flags;            // Bitwise OR of FrameFlag values
        uint32 sequence_number;  // Sequence number of this frame
        uint32 length;           // Length of payload in bytes
        opaque payload[length];  // Frame payload (0 for ACK/FIN)
    } Frame;]]></artwork>
          </figure>The total header size is 11 bytes:</t>

        <figure>
          <artwork><![CDATA[+--------+----------+---------------+--------------------------------+
| Offset |   Size   |     Field     |          Description           |
+--------+----------+---------------+--------------------------------+
|   0    |    2     |     magic     | Frame magic number 0x4652 (FR) |
+--------+----------+---------------+--------------------------------+
|   2    |    1     |     flags     | Bitwise OR of frame type flags |
+--------+----------+---------------+--------------------------------+
|   3    |    4     |sequence_number| Sequence number of this frame  |
+--------+----------+---------------+--------------------------------+
|   7    |    4     |    length     | Payload length (0 for ACK/FIN) |
+--------+----------+---------------+--------------------------------+
|   11   | variable |    payload    |       Frame payload data       |
+--------+----------+---------------+--------------------------------+
]]></artwork>
        </figure>

        <t>Constants:<figure>
            <artwork><![CDATA[    const uint16 FRAME_MAGIC       = 0x4652;
    const uint8  FRAME_FLAG_DATA   = 0x00;
    const uint8  FRAME_FLAG_ACK    = 0x01;
    const uint8  FRAME_FLAG_FIN    = 0x02;
    const uint8  FRAME_FLAG_RETRANSMIT = 0x04;
    const uint16 FRAME_HEADER_SIZE = 11;
    const uint32 FRAME_MAX_PAYLOAD = 4096;
    const uint32 FRAME_MAX_QUEUE   = 1024;]]></artwork>
          </figure></t>
      </section>

      <section title="Frame Types and Flags">
        <section title="DATA Frame (0x00)">
          <t>DATA frame carries application data from the sender to the
          receiver. Its format is shown in Figure 3.</t>

          <t><figure>
              <artwork><![CDATA[    +------+------+----------+--------+----------+
    | 0x46 | 0x52 | 0x00     | seq#   | length   |
    +------+------+----------+--------+----------+
    |                   payload                  |
    +--------------------------------------------+
        Figure 3: The format of DATA frame]]></artwork>
            </figure>Where:<list style="symbols">
              <t>sequence_number: The sender's monotonically increasing
              sequence number for this data frame.</t>

              <t>length: The length of the application data payload.</t>

              <t>payload: The application data bytes, up to 4096 bytes.</t>
            </list>The receiver SHOULD send an ACK frame for each received
          DATA frame, according to its ACK policy.</t>
        </section>

        <section title="ACK Frame (0x01)">
          <t>ACK frame is the acknowledges receipt of a specific DATA frame.
          Its format is shown in Figure 4.</t>

          <t><figure>
              <artwork><![CDATA[    +------+------+----------+--------+-----------+
    | 0x46 | 0x52 | 0x01     | 0x0000 | 0x00000004|
    +------+------+----------+--------+-----------+
    |        ack_sequence_number (4 bytes)        |
    +---------------------------------------------+
        Figure 4: The format of ACK frame]]></artwork>
            </figure>Where:<list style="symbols">
              <t>sequence_number field in header: MUST be set to 0 (unused for
              ACK).</t>

              <t>length: MUST be 4.</t>

              <t>payload: A 4-byte big-endian unsigned integer containing the
              sequence number of the DATA frame being acknowledged.</t>
            </list>Upon receiving an ACK frame, the sender marks the
          corresponding entry in its send queue as acknowledged.</t>
        </section>

        <section title="FIN Frame (0x02)">
          <t>FIN frame signals the graceful end of the framing session. No
          payload. Its format is shown in Figure 5.</t>

          <figure>
            <artwork><![CDATA[    +------+------+----------+--------+--------+
    | 0x46 | 0x52 | 0x02     | seq#   | 0x0000 |
    +------+------+----------+--------+--------+
        Figure 5: The format of FIN frame]]></artwork>
          </figure>

          <t>Where:<list style="symbols">
              <t>sequence_number: The sender's next expected send sequence
              number.</t>

              <t>length: MUST be 0.</t>
            </list>The receiver of a FIN frame SHOULD respond with its own FIN
          frame and then close the connection.</t>
        </section>

        <section title="RETRANSMIT Flag (0x04)">
          <t>RETRANSMIT flag is combined with FRAME_FLAG_DATA using bitwise OR
          to indicate that a DATA frame is a retransmission of a previously
          sent frame.</t>

          <t><figure>
              <artwork><![CDATA[    flags = FRAME_FLAG_DATA | FRAME_FLAG_RETRANSMIT  // 0x04]]></artwork>
            </figure>The receiver SHOULD process retransmitted frames in the
          same manner as new frames. If the frame has already been processed
          (i.e., its sequence number is less than the receiver's
          next_recv_seq), the receiver MAY silently discard it but MUST still
          send an ACK.</t>
        </section>
      </section>

      <section title="Sequence Numbering and Acknowledgment">
        <section title="Sequence Number Space">
          <t>Each endpoint maintains two sequence counters:<list
              style="symbols">
              <t>next_send_seq: The sequence number to assign to the next DATA
              frame sent. Initialized to 1 and incremented after each DATA
              frame is queued for sending.</t>

              <t>next_recv_seq: The sequence number expected for the next DATA
              frame received. Initialized to 1 and incremented when a new
              (non- duplicate) DATA frame is successfully received.</t>
            </list>Sequence numbers are 32-bit unsigned integers. They MUST be
          initialized to 1 at the start of each framing session (i.e., when a
          new TLS connection is established).</t>
        </section>

        <section title="Send Queue">
          <t>The sender maintains a send queue that stores metadata for each
          sent DATA frame until it is acknowledged:<figure>
              <artwork><![CDATA[    struct {
        uint32 sequence_number;   // Sequence number of the frame
        uint32 length;            // Payload length
        opaque data[length];      // Copy of the payload data
        boolean acked;            // Whether this frame has been ACKed
        uint8  retransmit_count;  // Number of times retransmitted
    } SendQueueEntry;]]></artwork>
            </figure>The send queue has a maximum capacity of FRAME_MAX_QUEUE
          (1024) entries. If the queue is full, the sender MUST stop accepting
          new application data until space becomes available (i.e., until some
          frames are acknowledged).</t>
        </section>

        <section title="Acknowledgment Processing">
          <t>When the sender receives an ACK frame with ack_sequence_number
          equal to N, it searches its send queue for the entry with
          sequence_number == N and marks it as acked = true.</t>

          <t>The sender MAY prune acknowledged entries from the send queue to
          reclaim memory, but MUST retain all unacknowledged entries for
          potential retransmission.</t>
        </section>

        <section title="Duplicate Detection">
          <t>When the receiver receives a DATA frame with sequence_number &lt;
          next_recv_seq, it identifies the frame as a duplicate
          (retransmission). The receiver:<list style="symbols">
              <t>MUST still send an ACK for the frame.</t>

              <t>SHOULD discard the payload without delivering it to the
              application.</t>
            </list></t>
        </section>
      </section>

      <section title="Send Queue and Retransmission">
        <section title="Retransmission Trigger">
          <t>Retransmission is performed in two scenarios:<list
              style="symbols">
              <t>Migration-triggered retransmission: After completing TLS
              session migration to a new server (Section 4.4), the client MUST
              retransmit all unacknowledged DATA frames from its send queue to
              the new server. This is the primary use case addressed by this
              specification.</t>

              <t>Timer-based retransmission (optional): Implementations MAY
              support a retransmission timer that triggers retransmission of
              unacknowledged frames after a configurable timeout. This is
              useful for handling packet loss within a single connection but
              is OPTIONAL for the migration use case.</t>
            </list></t>
        </section>

        <section title="Retransmission Procedure">
          <t>To retransmit unacknowledged frames, the sender:</t>

          <t>1. Iterates through the send queue from the oldest to the newest
          entry.</t>

          <t>2. For each entry where acked == false:<list style="symbols">
              <t>Constructs a new DATA frame with flags = FRAME_FLAG_DATA |
              FRAME_FLAG_RETRANSMIT.</t>

              <t>Sets sequence_number to the original frame's sequence
              number.</t>

              <t>Copies the original payload data.</t>

              <t>Sends the frame over the current TLS connection.</t>

              <t>Increments the entry's retransmit_count.</t>
            </list></t>

          <t>3. The sender MUST preserve the original sequence numbers during
          retransmission. The receiver uses sequence numbers to detect and
          deduplicate retransmitted frames.<figure>
              <artwork><![CDATA[    RetransmitAllUnacked():
        for each entry in send_queue:
            if entry.acked == false:
                frame = Frame {
                    magic: 0x4652,
                    flags: DATA | RETRANSMIT,
                    sequence_number: entry.sequence_number,
                    length: entry.length,
                    payload: entry.data
                }
                send(frame)
                entry.retransmit_count++]]></artwork>
            </figure></t>
        </section>
      </section>

      <section title="Framing Layer State Machine">
        <section title="Sender State">
          <t><figure>
              <artwork><![CDATA[    +------------------+
    |     ACTIVE       |  Normal operation: sending DATA frames,
    |  (next_send_seq) |  receiving ACKs, managing send queue.
    +--------+---------+
             |
             | Migration initiated
             v
    +------------------+
    |   MIGRATING      |  TLS connection to old server closed.
    |   (queue intact) |  Send queue preserved for retransmission.
    +--------+---------+
             |
             | New TLS connection established
             v
    +------------------+
    |  RETRANSMITTING  |  Sending all unacknowledged frames to
    |                  |  new server, then resuming normal send.
    +--------+---------+
             |
             | All unacked frames retransmitted
             v
    +------------------+
    |     ACTIVE       |  Resume normal operation on new server.
    +------------------+

                  Figure 6: Sender state machine]]></artwork>
            </figure></t>
        </section>

        <section title="Receiver State">
          <t><figure>
              <artwork><![CDATA[    +------------------+
    |     ACTIVE       |  Normal operation: receiving DATA frames,
    |  (next_recv_seq) |  sending ACKs, delivering to application.
    +--------+---------+
             |
             | Connection closed (server shutdown or migration)
             v
    +------------------+
    |      CLOSED      |
    +------------------+

                  Figure 7: Receiver state machine]]></artwork>
            </figure>On the new server, the receiver initializes next_recv_seq
          = 1 and processes both retransmitted and new frames normally. The
          receiver does not need to be aware that some frames are
          retransmissions from a previous server.</t>
        </section>

        <section title="State Reset on New Connection">
          <t>When a new TLS connection is established (after migration), the
          sender:<list style="symbols">
              <t>MUST reset next_recv_seq to 1 (for receiving ACKs and data
              from the new server).</t>

              <t>MUST preserve the send queue intact (for retransmission).</t>

              <t>MUST preserve next_send_seq (to avoid sequence number
              collisions with retransmitted frames).</t>
            </list>The receiver on the new server:<list style="symbols">
              <t>MUST initialize next_recv_seq to 1.</t>

              <t>MUST initialize an empty send queue.</t>
            </list></t>
        </section>
      </section>

      <section title="Framing Layer Procedures During Migration">
        <section title="Pre-Migration (Phase 1)">
          <t>During normal data transfer with Server A:<list style="symbols">
              <t>The client sends DATA frames via the Framing Layer. Each
              frame is assigned a monotonically increasing sequence number and
              added to the send queue.</t>

              <t>Server A receives DATA frames and sends ACK frames according
              to its ACK policy. The application on Server A processes the
              data and decides whether to acknowledge each frame.</t>

              <t>The client processes incoming ACK frames and marks
              corresponding send queue entries as acknowledged.</t>
            </list></t>
        </section>

        <section title="Migration (Phase 2)">
          <t>When migration is triggered:<list style="symbols">
              <t>The client records the current state of its send queue,
              noting which frames remain unacknowledged.</t>

              <t>The client disconnects from Server A. The send queue is
              preserved in memory.</t>

              <t>The client initiates a new TLS connection to Server B,
              performing PSK-based session resumption as described in Section
              4.4.</t>
            </list></t>
        </section>

        <section title="Post-Migration (Phase 3)">
          <t>After the new TLS connection is established with Server B:<list
              style="symbols">
              <t>The client resets its receive state (next_recv_seq = 1) for
              the new connection.</t>

              <t>The client calls RetransmitAllUnacked() to resend all
              unacknowledged DATA frames to Server B. These frames carry the
              RETRANSMIT flag.</t>

              <t>Server B receives the retransmitted frames. Since Server B
              initializes next_recv_seq = 1, it processes them as new frames,
              sends ACKs, and delivers the data to the application.</t>

              <t>The client resumes normal data transfer, sending new DATA
              frames with sequence numbers continuing from where it left
              off.<figure>
                  <artwork><![CDATA[    Phase 1 (Server A):          Phase 3 (Server B):
    +----+-------+------+       +----+-------+------+
    | #1 | DATA  | ACKED|       | #1 | DATA  | ACKED|  (no retransmit)
    | #2 | DATA  | ACKED|       | #2 | DATA  | ACKED|  (no retransmit)
    | #3 | DATA  | ACKED|       | #3 | DATA  | ACKED|  (no retransmit)
    | #4 | DATA  | UNACK|  -->  | #4 | DATA  | ACKED|  (retransmitted)
    | #5 | DATA  | UNACK|  -->  | #5 | DATA  | ACKED|  (retransmitted)
    +----+-------+------+       +----+-------+------+
                                | #6 | DATA  | NEW  |  (post-migration)
                                +----+-------+------+

    Figure 8: Send Queue State Transition During Migration]]></artwork>
                </figure></t>
            </list></t>
        </section>
      </section>

      <section title="Message Flow with Framing Layer">
        <t>The following diagram illustrates the complete message flow
        including the Framing Layer during a migration scenario where Server A
        acknowledges only the first 3 of 5 data frames:<figure>
            <artwork><![CDATA[    Client                                              Server A
      |                                                    |
      |          === Phase 1: Data Transfer ===            |
      |                                                    |
      |  DATA(seq=1, "msg-1") -------------------------->  |
      |  DATA(seq=2, "msg-2") -------------------------->  |
      |  DATA(seq=3, "msg-3") -------------------------->  |
      |  DATA(seq=4, "msg-4") -------------------------->  |
      |  DATA(seq=5, "msg-5") -------------------------->  |
      |                                                    |
      |  ACK(seq=1) <------------------------------------  |  
      |  ACK(seq=2) <------------------------------------  |  
      |  ACK(seq=3) <------------------------------------  |  
      |                                                    |
      |  Note: seq=4 and seq=5 are NOT acknowledged        |
      |                                                    |
      |  NewSessionTicket(+migration_allowed) <----------  |
      |                                                    |
      |         === Phase 2: Migration Trigger ===         |
      |                                                    |
      |  {migrate_request: opaque target} <-------------   |                                                      
         Client disconnects from Server A                  
         Send queue preserved: seq#4, seq#5 unacknowledged 
       
    Client                                              Server B
      |                                                    |
      |   === Phase 3: Reconnection + Retransmission ===   |
      |                                                    |
      |  ClientHello + PSK (ticket, psk_dhe_ke) -------->  |
      |  ServerHello + PSK (abbreviated handshake)         |
      |  <---------------------------------------------->  |
      |                                                    |
      |  DATA|R(seq=4, "msg-4") ------------------------>  | 
      |  DATA|R(seq=5, "msg-5") ------------------------>  |
      |  DATA(seq=6, "msg-new") ------------------------>  | 
      |                                                    |
      |  ACK(seq=4) <------------------------------------  | 
      |  ACK(seq=5) <------------------------------------  | 
      |  ACK(seq=6) <------------------------------------  | 
   
         Result: All 6 messages delivered, zero loss      

    Figure 9: Framing Layer Message Flow During Migration]]></artwork>
          </figure></t>
      </section>
    </section>

    <section title="Use case">
      <t>Computing-Aware Traffic Steering (CATS) <xref
      target="I-D.ietf-cats-usecases-requirements"/> provides a compelling use
      case for TLS-layer session migration. In CATS architectures, traffic is
      dynamically steered to optimal endpoints based on real-time network
      conditions, server load, and computational resource availability. The
      scenario is shown as Figure 10, and the transmission process of packets
      is shown in Figure 11.</t>

      <t><figure>
          <artwork><![CDATA[
     +-----------------------------------------------------------------+
     |                Anycast IP/IP4                                   |
     |                +------------+                                   |
     |                |Service node|                                   |
     |                +-----+------+                                   |
     |                      |                                          |
     |                 +----+-----+                                    |
     |                 |    R4    |                                    |
     |   +-------------+  Egress  +------------+                       |
     |   |             +----------+            |                       |
     |   |                                     |        Anycast IP/IP3 |
    +----+-----+                          +----+-----+  +------------+ |
 A -+    R1    |                          |    R3    +--+Service node| |
 B -+ Ingress  +--------------------------+  Egress  |  +------------+ |
    +----+-----+                          +----+-----+                 |
     |   |                                     |                       |
     |   |              +----------+           |                       |
     |   +--------------+    R2    +-----------+                       |
     |                  |  Egress  |                                   |
     |                  +----+-----+                                   |
     |                       |                                         |
     |                 +-----+------+                                  |
     |                 |Service node|                                  |
     |                 +------------+                                  |
     |                 Anycast IP/IP2                                  |
     +-----------------------------------------------------------------+

       Figure 10: The Computing-Aware Traffic Steering (CATS) scenario
]]></artwork>
        </figure></t>

      <t>Customer A and customer B want to access the same service. For
      customer A, the packet will firstly be transmitted to the corresponding
      anycast IP address. The ingress will determine the optimal service node
      for customer A based on the access cost, computing resources of each
      service node, and the scheduled computing resource scheduling algorithm.
      Similar processing will be performed when customer B accesses the same
      service.</t>

      <t>When customer A accesses to the service, it presents the following
      steps:<list style="symbols">
          <t>Step 1: Customer A access to the service. It sends an initial
          `ClientHello` message which includes the `migration_support`
          extension to R1. The destination address of this packet is set to
          the anycast IP address of this service (IPs).</t>

          <t>Step 2: R1 schedules the customer A's service connection request
          according to the real-time status of the network and computing
          resources, and determine that the server (IP address = IP4) will
          provide services to customer A.</t>

          <t>Step 3: the server completes a standard TLS 1.3 handshake.</t>

          <t>Step 4: the server sends a `NewSessionTicket` message to enable
          standard PSK-based session resumption, marked `migration_allowed` with
          the relocation authorization sealed inside the ticket.</t>

          <t>Step 5: when steering dictates, the server sends a
          `migrate_request` with an opaque target; the control plane resolves it
          to IP4 and customer A re-establishes the session on IP4 via PSK
          resumption.</t>
        </list></t>

      <t><figure>
          <artwork><![CDATA[+----------+  +----------+                    +----------+  
|Customer A|  |    R1    |                    |server(IP4|  
+-----+----+  +-----+----+                    +-----+----+  
      | Step 1(IPs) |       Step 2: (IPs)           |
      |------------>|------------------------------>|
      |    Step 3: A standard TLS 1.3 handshake     |
      |<------------------------------------------->|
      |  Step 4: NewSessionTicket(+migration_allowed)|
      |<--------------------------------------------|
      |            Step 5: resume on IP4            |
      |-------------------------------------------->|
      |                                             |

         Figure 11: Procedures for the service affinity solution
]]></artwork>
        </figure>In the whole process, devices in the network only need to
      broadcast the information of the computing network &lt;Anycast IP
      Address, Service node Status&gt;, and perform optimized scheduling of
      computing network resources according to this information.</t>

      <t>Comparing to the existing solutions such as maintaining the
      customer-based connection status table in network devices, HTTP
      redirection and DNS redirection, this solution can avoid the waste of
      resources caused by saving a large amount of customer status data in the
      network devices, and realize the optimized scheduling of resources based
      on network conditions and computing resources in the computing-aware
      traffic steering scenario, so as to realize the reasonable operation of
      network resources, cloud resources and computing resources.</t>
    </section>

    <section title="Security Considerations">
      <section title="Threat model">
        <t>The mechanism operates within a single trust domain: a set of server
        instances of one administrative service that share the resumption keying
        material needed to accept a session. This sharing is already a
        prerequisite for ordinary TLS 1.3 resumption across a cluster; this
        document adds no new key-distribution requirement.</t>

        <t>Adversaries considered:<list style="symbols">
            <t>On-path network attacker: may observe, drop, reorder, delay, and
            inject records, but cannot break TLS 1.3 and holds no private or
            shared resumption keys.</t>

            <t>Off-path attacker: may inject spoofed packets only.</t>

            <t>Malicious client: holds a legitimate session and attempts to be
            relocated to an instance it should not reach, to replay a relocation
            authorization, or to exhaust resources.</t>

            <t>Foreign server: a TLS server outside the trust domain (no shared
            resumption keys) to which a client might be steered by DNS
            poisoning, BGP hijack, a compromised control plane, or a malicious
            application-layer redirect.</t>
          </list></t>

        <t>Out of scope (pre-existing assumptions of cluster resumption):
        compromise of an in-domain instance or of the shared resumption keys,
        either of which already defeats ticket-based resumption generally.</t>
      </section>

      <section title="Security goals">
        <t><list style="numbers">
            <t>Relocation authorization integrity: an attacker MUST NOT cause a
            client to treat a session as relocatable, or alter the permitted
            instances, without detection.</t>

            <t>Trust-domain authentication (anti-redirection): a client that
            acts on a relocation MUST end up resuming on an instance within the
            trust domain; a foreign server MUST NOT complete the relocation.</t>

            <t>Request authenticity: a relocation request MUST be attributable
            to the server of the current authenticated session and MUST NOT be
            forgeable or injectable by network attackers.</t>

            <t>Freshness / replay bound: reuse of a relocation authorization
            MUST be bounded by the same policy that bounds ticket reuse.</t>

            <t>Forward secrecy: data exchanged after relocation MUST remain
            confidential even if the shared resumption key is later
            compromised.</t>

            <t>No new linkability: the mechanism MUST NOT add cross-connection
            linkability beyond TLS 1.3 ticket resumption.</t>
          </list></t>
      </section>

      <section title="How the design meets the goals">
        <t><list style="symbols">
            <t>Goals 1 and 4. Whether a session is relocatable and any scope is
            carried inside the server's ticket, which is encrypted,
            integrity-protected, and already bound to the session by <xref
            target="RFC8446"/>. A client or network attacker can neither forge
            nor modify it. No new key schedule is introduced. Reuse is bounded by
            the server's existing anti-replay and ticket_lifetime policy.</t>

            <t>Goal 2. Phase 3 is ordinary PSK resumption. Only an instance
            holding the session's resumption keys can recover the session and
            produce a valid Finished; a foreign server cannot, so the client's
            normal resumption verification fails and the client MUST abort
            without sending application data (fail-closed). This provides, at the
            TLS layer, the anti-redirection assurance that path validation
            provides in QUIC. It is an inherited property of RFC 8446
            resumption, not a new cryptographic guarantee.</t>

            <t>Goal 3. `migrate_request` is a post-handshake message inside the
            established, authenticated, encrypted channel; it inherits TLS
            record-layer authenticity and carries no secret.</t>

            <t>Goal 5. Relocation MUST use `psk_dhe_ke`; `psk_ke` MUST NOT be
            used. Each relocated session establishes fresh (EC)DHE keys.</t>

            <t>Goal 6. The client sends no migration-specific secret in
            cleartext; Phase 3 is ordinary PSK resumption.</t>
          </list></t>
      </section>

      <section title="Residual risks">
        <t><list style="symbols">
            <t>Target resolution. The target is opaque to TLS and resolved by
            the application/control plane; regardless of how it is resolved, an
            endpoint that cannot complete the resumption is rejected (Goal 2).
            Implementations SHOULD still validate that the resolved endpoint
            represents the same server identity as the original session.</t>

            <t>Downgrade. `migration_support` is in the ClientHello and covered
            by the handshake transcript; a network attacker that strips or
            alters it causes the handshake to fail, so the feature cannot be
            silently downgraded. At worst it is simply not offered, which is
            fail-safe.</t>

            <t>Denial of service. Verifying a relocation costs one session
            recovery plus the normal resumption handshake. Instances SHOULD
            rate-limit failed relocation attempts per source.</t>
          </list></t>
      </section>

      <section title="Framing Layer Security">
        <section title="Confidentiality and Integrity">
          <t>The Framing Layer operates entirely within the TLS encrypted
          channel. All frame headers and payloads are protected by TLS
          record-layer encryption and authentication. An attacker who cannot
          break the TLS cipher suite cannot read, modify, or inject
          frames.</t>
        </section>

        <section title="Sequence Number Manipulation">
          <t>Sequence numbers are transmitted in the clear within the TLS
          record (i.e., they are encrypted but the receiver must be able to
          read them). Since the entire frame is protected by TLS, an attacker
          cannot modify sequence numbers without detection. Implementations
          SHOULD verify that received sequence numbers are within an
          acceptable window to detect potential protocol-level attacks.</t>
        </section>

        <section title="Denial of Service via Send Queue Exhaustion">
          <t>A malicious receiver could refuse to send ACK frames, causing the
          sender's send queue to grow until it reaches FRAME_MAX_QUEUE. At
          that point, the sender MUST stop accepting new application data. To
          mitigate this, implementations SHOULD:<list style="symbols">
              <t>Monitor send queue utilization and log warnings when it
              approaches capacity.</t>

              <t>Provide a configurable maximum queue size appropriate for the
              deployment environment.</t>

              <t>Consider a timeout after which unacknowledged frames are
              discarded and the connection is terminated with an error.</t>
            </list></t>
        </section>

        <section title="Retransmission Flooding">
          <t>A malicious client could retransmit a large number of frames to a
          new server after migration. The new server SHOULD apply rate
          limiting to retransmitted frames and SHOULD validate that
          retransmitted frame sequence numbers are within the expected range.
          Since retransmitted frames carry the RETRANSMIT flag, the server can
          apply differentiated rate limiting policies for new vs.
          retransmitted frames.</t>
        </section>
      </section>
    </section>

    <section anchor="iana" title="IANA Considerations">
      <t>This document requires IANA to allocate new codepoints from the
      following TLS registries, as defined in <xref target="RFC8446"/>:</t>

      <t>1. From the "TLS ExtensionType Values" registry for
      `migration_support` (ClientHello) and `migration_allowed`
      (NewSessionTicket). This document suggests the values TBD1 and TBD2.</t>

      <t>2. From the "TLS HandshakeType" registry for the `migrate_request`
      post-handshake message. This document suggests the value TBD3. Note that
      the TLS HandshakeType registry has no range reserved for private or
      experimental use; the value is TBD until assigned by IANA and MUST NOT be
      shipped in production before assignment.</t>

      <t>3. From the "TLS ExtensionType Values" registry for `framing_layer`.
      This document suggests the value TBD4. This extension, when present in
      ClientHello, indicates that the client supports the Reliable Framing
      Layer defined in Section 6. The extension_data is zero-length:<figure>
          <artwork><![CDATA[    struct { } FramingSupport;]]></artwork>
        </figure></t>
    </section>
  </middle>

  <back>
    <references title="Normative References">
      <?rfc include="reference.RFC.2119"?>

      <?rfc include="reference.RFC.8174"?>

      <?rfc include="reference.RFC.8446"?>
    </references>

    <references title="Informative References">
      <?rfc include='reference.I-D.ietf-cats-usecases-requirements'?>
    </references>
  </back>
</rfc>
