What is the difference between a connection closed with FIN and one reset with RST, and what causes resets?
Show the answer
Say this first
FIN is a graceful close of one direction: all data sent before it is delivered and acknowledged, and the other side can keep sending. RST aborts the whole connection at once: unsent and unread data is thrown away and the application gets "connection reset by peer". Resets come from a SYN to a closed port, an application closing with unread data or with linger set to zero, a segment that matches no connection (for example after a reboot), and middleboxes such as firewalls and load balancers that kill sessions.
Go deeper
Common sources of RST
| Cause | What you see |
|---|---|
| SYN to a port with no listener | [R.] right after the SYN, client error "connection refused" |
| Peer rebooted or lost state | Our next data segment gets a RST (the half-open case) |
| App closed with data still unread in its receive buffer | Linux sends RST instead of FIN |
| SO_LINGER with timeout 0 | Deliberate abortive close |
| Firewall or IPS policy | RST injected toward one or both ends |
| Load balancer or firewall idle timeout | Next packet after idle hits no state; some devices send RST |
Who really sent it
Compare the RST with the real peer's packets. A RST forged by a middlebox often has a different IP TTL, a different IP ID pattern, or arrives faster than the peer's RTT allows. Capturing on both sides of the firewall settles it.
RST validation
A RST is only accepted if its sequence number matches exactly what the receiver expects next. If it is merely inside the window, the receiver sends a challenge ACK instead (RFC 5961). That makes blind reset attacks much harder.
They will ask next
What is the difference between "connection refused" and "connection timed out"?
Refused means a RST came back to the SYN: the host is reachable and nothing listens on that port, or a device rejected it. Timed out means nothing came back at all: a silent drop, a dead host or a broken route.
A long-lived database connection dies with "connection reset" every morning. Where do you look?
At idle timeouts on firewalls, NAT and load balancers in the path. The connection sat idle overnight, the middlebox removed its state, and the first query in the morning hit nothing. Enabling TCP keepalive at an interval shorter than the shortest idle timeout, or a pool that validates connections, fixes it.
Traps
- Assuming every RST came from the server. Middleboxes send them too, and the capture must prove who did.