Killing idle TCP connections

Mar 15, 2017,
Categories: network,linux

Why

Let’s say you have some TCP connections to your local system that you
want to kill. You could kill the process that handles the connection,
but that may also kill other connections, so that’s not great. You
could also put in a firewall rule that will cause the connection to be
reset. But that won’t work on a connection that’s idle (also if one
side is initiator then using this method the other side would not tear
down its side of the connection). There’s
tcpkill, but it needs to
sniff the network to find the TCP sequence numbers, and again that
won’t work for an idle connection.

Ideally for these long-running connections TCP keepalive would be
enabled. But sometimes it’s not. (e.g. it’s not on by default for gRPC
TCP connections, and they certainly can be long-running and idle).

You could also do this by attaching a debugger and calling
shutdown(2) on the sockets, but having the daemon calling unexpected
syscalls thus getting into an unexpected state doesn’t really make for
a stable system. Also attaching a debugger hangs the daemon while
you’re attached to it.

This post documents how to do this on a Debian system.

No, really. Why?

If a client connects to a dual-stack hostname it’ll (usually, see
RFC3484) first try IPv6, and
then IPv4 if that fails.

If a server comes up after the client tries IPv6 then it’ll fall back
to IPv4, even though IPv6 would have worked at that time too.

I want to kick the IPv4 clients over to IPv6, since restarting the
server (or even rebooting the server) doesn’t change anything about
the race, and I don’t want to restart the clients because they’re
doing long-running compute work that I don’t want to lose state on.