TCP connection reset: causes and fixes
Published 26 September 2026
A TCP connection reset means a device sent a packet with the RST flag to abort the connection. The peer application may have sent it, but a firewall, load balancer or operating system can send the same packet. Capture the reset at both ends and use its direction and timing to find the sender. Retrying without that evidence often hides the fault until the next long-lived flow.
What a TCP connection reset means
TCP has two very different ways to end a connection. A FIN is an orderly close: one endpoint says it has no more data to send, and the other side can finish its half of the exchange. A reset is an abort. RFC 9293 permits an application to issue one at any time, and TCP itself generates one when a segment appears to belong to no current connection.
Operating systems normally report a received reset as
ECONNRESET, often rendered as Connection reset by
peer. The wording is narrower than the evidence. It proves that a
reset arrived from the network path. It does not prove the remote
application deliberately closed the socket.
| Result | What happened on the wire | First place to look |
|---|---|---|
| Connection reset | An RST aborted an existing or attempted TCP flow. | The device that sent the RST and the event immediately before it. |
| Connection refused | The destination usually reset the opening SYN because no listener accepted the port. | Service state, bind address and host firewall. |
| Connection timed out | No usable answer arrived before the client gave up. | Packet loss, filtering, routing and the far endpoint. |
| Orderly close | FIN and ACK packets completed the normal shutdown. | Application logs if the close was unexpected. |
Refused, reset and timed out are not interchangeable. If the error is no route to host, the failure happened before this TCP conversation could exist. If a new connection opens but later resets, reachability has already been proved.
Read the reset by timing
The packet before the RST is usually more useful than the error string. Sort the incident into one of these patterns before changing a timeout or opening a firewall rule.
| When the reset arrives | Likely explanations | Check next |
|---|---|---|
| Immediately after SYN | No listener, an active reject rule, or a device answering on behalf of the host | Destination port, bind address, host firewall and source address |
| Just after TLS ClientHello | TLS policy, SNI routing, an inspection device, or a non-TLS service on that port | openssl s_client, server TLS logs and the SSL checker |
| After an HTTP request | Application crash, proxy policy, malformed request, body limit or upstream failure | Proxy and application logs with the same timestamp |
| After a repeatable idle period | Firewall, NAT or load-balancer idle timeout | Idle timers and TCP keepalive behavior on every stateful hop |
| During a large transfer | Application abort, resource pressure, inspection limit or a path fault exposed by sustained traffic | Both-side captures, process logs, interface errors and transfer size |
| After failover or maintenance | Lost connection state, target deregistration or an intentional reset that forces reconnection | Load-balancer events, firewall state sync and drain settings |
Capture the packet that settles it
Start with a capture on the client. Replace the host and port with the real destination so a busy interface does not bury the flow.
sudo tcpdump -ni any 'host 203.0.113.20 and tcp port 443'
# Show only packets with the TCP RST flag set
sudo tcpdump -ni any 'host 203.0.113.20 and tcp port 443 and tcp[tcpflags] & tcp-rst != 0'
Record the source address, destination address, timestamp, sequence and ACK values, and the packets directly before the reset. Then take a capture at the server or its nearest observable hop. The comparison is decisive:
- If the same RST leaves the server, inspect the server process and kernel.
- If the client receives an RST that never left the server, a middlebox generated it.
- If the server sent an RST that never reached the client, investigate filtering or asymmetric paths.
- If neither side sees an RST, the application may be translating a different lower-level error.
Do not identify a middlebox from TTL alone. A surprising TTL is a lead, not proof, because the sender's initial TTL and return path may differ. Two synchronized captures are stronger evidence.
Check the application before tuning TCP
A process can reset a socket by closing it abortively, exiting while data is outstanding, or asking the operating system to discard unread data. A server may do that because the request is invalid, too large, sent to the wrong protocol, or rejected by policy. Look for an application event at the packet timestamp before changing retransmission or keepalive settings.
Protocol mismatch is easy to prove. Use a client that exposes each stage:
curl -v --connect-timeout 5 https://example.com/
openssl s_client -connect example.com:443 -servername example.com
nc -vz -w 5 example.com 443
A successful external port check proves a new TCP handshake can complete from one vantage point. It cannot prove a long-lived connection survives an idle timer or that the application will accept the next protocol message.
Stateful devices can be the peer
Firewalls, NAT gateways and load balancers track a TCP flow using addresses, ports and protocol state. If that state expires or disappears during a failover, later packets no longer match a known connection. The device may drop them silently or send a reset. Both outcomes break the application, but the reset fails fast while silence waits for retransmission timers.
AWS made that tradeoff explicit in September 2026. Gateway Load Balancer can now send resets when a target becomes unhealthy, is deregistered after its drain period, or reaches a configured idle timeout. AWS reports that this can reduce an interruption from minutes to seconds because the endpoint can open a fresh flow through a healthy target. The feature is off by default and conflicts with some stickiness and rebalance settings.
Raising every idle timeout is not a general fix. Longer timers retain more connection state and delay cleanup. Match the timeout to the application's expected idle period, or send an application heartbeat and prove it crosses every stateful hop.
A short troubleshooting order
- Preserve the exact error, endpoint pair and timestamp.
- Confirm whether the failure occurs during connect, negotiation, active transfer or idle time.
- Capture on the client and identify the RST direction.
- Capture at the server side and compare the same flow.
- Match the preceding packet to application, proxy, firewall and load-balancer logs.
- Change one policy or timer, then reproduce the original sequence.
A retry restores one flow. A diagnosis identifies which component terminated it and why, so the same condition can be fixed.
Sources
- RFC 9293, section 3.5.2: TCP reset generation and processing rules
- Reduce traffic interruptions with Gateway Load Balancer TCP Reset: AWS feature announcement published 2 September 2026
- AWS Gateway Load Balancer now supports TCP Reset: availability note posted 3 September 2026
- Gateway Load Balancer target group attributes: reset triggers, defaults and configuration constraints
Protocol and AWS behavior were checked on 26 September 2026.