Mobile Computing · Mobile Networking
Open Connections When the Device Changes Its Address
A handover replaces the address under a live socket; why TCP cannot follow it, how QUIC connection identifiers and path validation allow migration, and what a rebinding costs.
A transport connection is identified by the pair of addresses and ports at its ends. That identification is not an implementation detail; it is the mechanism by which every packet in both directions is attributed to a connection, and by which a middlebox decides that two packets belong to the same flow. When a phone moves from a wireless network to a cellular one, its address changes, and the connection’s identity is no longer valid. Everything that happens next is a consequence of how the protocol handles that fact.
For TCP, the consequence is that the connection is dead. For QUIC, the consequence is that it can be migrated, at a cost that is paid in round trips and in the risk of an off-path attacker redirecting the flow. The difference is not a matter of tuning; it is a difference in what the protocols use as an identity, and it sits underneath the request-level costs counted in Counting round trips before the first payload byte.
Why the four-tuple is load-bearing
TCP’s connection state is keyed by the four-tuple of source and destination addresses and ports. A segment arriving with a different source address is not associated with the existing connection. It belongs to no connection at all, and the receiving host responds with a reset or silently drops it. The same is true at the network’s middleboxes: a stateful firewall or a network address translator maintains a mapping keyed by the same tuple, and a packet that does not match an existing mapping is treated as a new flow or refused.
This is not an accident of implementation. The tuple is what makes the connection distinguishable from every other connection on the internet, and the sequence-number space protects it against injection only from an attacker who can guess the tuple. If a connection could change its address, then an attacker who observed one packet could send a segment from a different address and have it accepted, and the sequence-number defence would be reduced to the attacker’s ability to guess a number that is chosen to be unguessable. The protocol’s identity and its security argument are the same mechanism, which is why the address cannot be allowed to change.
When the device moves, the old connection’s state persists on both ends until a timeout, and its packets are lost. The client discovers this when its next segment goes unanswered and its retransmission timer expires. The time to discovery is therefore a function of the retransmission timeout, which grows with each attempt, and it can be seconds.
What the network layer offers, and why it is not enough
The network layer has mechanisms for keeping an address across a move, and they are all variations on tunnelling or proxying.
A mobile IP arrangement gives the device a stable home address and a care-of address that changes as it moves, with a home agent forwarding packets to the current care-of address. The transport connection sees the home address and does not know it moved. The cost is triangular routing, since packets from the correspondent node go to the home agent and then to the device, which lengthens the path. The home agent also becomes a single point of failure and a capacity bottleneck.
A proxy arrangement terminates the transport connection at a point that does not move and relays it to the device over a second connection. This is what some enterprise mobility products do, and it works because the relay’s address is stable while the device’s is not. The cost is that the relay is now in the data path, adding latency and requiring trust.
Neither mechanism is available to an application. Both require network configuration, both are deployed in specific environments rather than generally, and neither is what a phone does when it moves between a wireless network and a cellular one. What a phone does is acquire a new address and lose its connections, which is why the application-level response to mobility is to expect connection failure and to reconnect.
Connection identifiers and path validation
QUIC separates the connection’s identity from its addresses. A packet carries a connection identifier, chosen by the receiver, in its short header, and the receiver maintains a mapping from identifier to connection. The addresses are then attributes of a path rather than of the connection, and a packet arriving on a new path with a valid connection identifier can be attributed to the existing connection.
The identifier is not a secret and is visible on the wire, so accepting a packet from a new address on the strength of the identifier alone would allow anyone who observed one packet to redirect the connection’s responses to themselves. The protocol therefore requires path validation before it will send data on a new path.
Validation is a challenge-response on the new path. The endpoint sends a PATH_CHALLENGE frame containing a random value, and the peer must echo that value in a PATH_RESPONSE frame sent on the same path. Only the party that can receive on the new address can complete the exchange, so success proves reachability. Until validation completes, the endpoint limits how much it sends on the new path, which bounds the amplification an attacker can obtain by spoofing an address.
The validation costs one round trip on the new path, which is the price of migration. That is a much smaller price than re-establishing a connection: the cryptographic keys, the congestion control state, and the stream state all survive, and no handshake occurs. It is also the reason migration is worth implementing, since a handover that would otherwise require a new connection and a new handshake, plus the application-level re-authentication on top, becomes one round trip.
The client’s address changes, and the server’s view of it
The common mobile case is client-initiated migration: the device’s address changes, and it sends from the new address with the same connection identifier. The server validates the new path and continues. The connection identifier the client uses must be one the server has issued and is willing to accept, which is why the protocol allows the peers to issue additional identifiers to each other: a client that expects to migrate can be given a fresh identifier for the new path, so that the old identifier is not reused across two addresses in a way that lets an observer correlate them.
The case that is not client-initiated is NAT rebinding. A translator between the client and the server may change its mapping, either because its idle timer expired or because it is under load, so that the client’s packets arrive at the server with a different source port or address even though the client did not move. From the server’s perspective this is indistinguishable from a migration, and the same validation applies. This is a significant practical benefit: a QUIC connection survives a translator’s rebinding, whereas a TCP connection is reset by it, and rebinding is common on cellular networks whose translators have short idle timers.
The server must be careful not to treat every apparent migration as a genuine one. A path that fails validation must not cause the connection to be abandoned if the old path still works, because an attacker who can spoof packets could otherwise force a migration to a black hole and terminate the connection. The protocol’s rule is that the endpoint keeps the old path until the new one is validated, and only then switches.
What survives and what does not
The state that survives migration is the state attached to the connection: keys, stream identifiers and their data, flow control credit, and the congestion controller. The state that does not survive, or that must be reset, is the state attached to the path.
The congestion controller is the important one. The new path has different characteristics, a wireless link where the old path was cellular or a cellular link where the old path was wireless, and the old path’s estimate of the bottleneck bandwidth and round-trip time is not a valid starting point. The protocol requires the congestion controller to be reset on migration, which means the connection begins again in slow start on the new path. The consequence is a throughput dip after every handover, proportional to the bandwidth-delay product of the new path, and it is unavoidable: there is no way to know the new path’s capacity without probing it.
The round-trip time estimate is reset for the same reason, and this has a second-order effect on retransmission timers. A connection that migrates to a path with a longer round trip will briefly use a timer derived from the old path’s estimate, and may retransmit prematurely. The protocol handles this by discarding the old samples, but the first few measurements on the new path are taken under uncertainty.
Flow control credit survives, which is usually desirable: a stream that had been blocked by the receiver’s window is still blocked, and the sender does not have to rediscover the limit. The exception is a migration that changes the path’s capacity so much that the credit is now the constraint, which is a design assumption rather than a protocol defect.
Choosing an address before the first packet
The other half of the mobility problem is the initial choice, and it is not about migration at all.
A device with both a wireless and a cellular interface, or with both IPv6 and IPv4 connectivity, has several candidate paths to a server, and the choice among them determines the latency of the first request and the cost of the connection. The general mechanism is to attempt candidates in parallel with a short stagger, so that a slow or broken path does not delay the attempt behind it, the approach standardised for dual-stack hosts as Happy Eyeballs. The client sorts candidates by preference, starts the first, and starts the next after a short delay if the first has not completed its handshake, taking whichever succeeds first and abandoning the rest.
On a phone the candidate set also includes the interface, and the platform’s network binding determines which interface a connection uses. An application that does not bind explicitly gets the default network, which is usually the one the platform considers best for the traffic; an application that binds to a specific network, for example to keep a large download on an unmetered interface, takes on the responsibility of rebinding when that network goes away.
Rebinding is the part that requires application involvement. A socket bound to an interface whose network disappears does not automatically move to another network; it fails, and the application must detect the failure, create a new socket on the new network, and re-establish whatever the old socket carried. This is the practical form that connection migration takes for most applications today: not a protocol feature but a reconnection policy, informed by the platform’s network callbacks described in What a connectivity callback can and cannot tell you.
The migration that does not happen
A protocol that can migrate is not a system that does migrate, and several practical obstacles keep migration rare in deployed traffic.
The first is middlebox tolerance. A translator that sees packets from a new address on an existing mapping may treat them as a new flow, and a firewall that has been configured to permit a specific tuple will drop the migrated packets. QUIC’s path validation detects the failure, but detection is not repair; the connection still has to be replaced.
The second is the server’s willingness. A server that is behind a load balancer which routes by address will send the migrated packets to the wrong backend, and the backend will not recognise the connection identifier. Migration therefore requires the load balancer to route by connection identifier, which is a deployment property rather than a protocol one.
The third is that migration is only useful when the new path is usable. A handover between two cellular cells does not change the device’s address, because the address is assigned by the core network rather than by the cell, so there is nothing to migrate. The address changes when the device moves between networks of different kinds or between translators, which is exactly the case where the old connection was going to fail anyway, and where the application’s reconnection policy, with its outbox and its retry classification, is what actually determines whether the user notices.