12

Is there a way to programmatically close a TCP connection in C/C++ ungracefully on Linux?

For testing, I would like to simulate the case when an endpoint is just powered down without transmitting any FIN and/or RST, and neither flushing any buffers.

Andre K
  • 185
  • 1
  • 10
  • 3
    I reopened this because it was not a duplicate of the linked question. That question asks how to generate an RST; this question asks how to not generate any packets at all. – user253751 Feb 01 '23 at 17:28
  • 5
    Here's a possible solution using iptables to completely block the connection like a firewall https://unix.stackexchange.com/questions/136642/how-to-make-a-tcp-socket-time-out – user253751 Feb 01 '23 at 17:28
  • I don't know much about this, but what if you start another process and kill it? – HolyBlackCat Feb 01 '23 at 17:34
  • If you can spoof incoming RST packet, Linux will kill the connection without transmitting anything back. I have used `scapy` to terminate TIME_WAIT connections using that before but it required to match the sequence numbers. – Quimby Feb 01 '23 at 17:46
  • 1
    @HolyBlackCat the kernel knows it's killed and will react the same as if the process `close`s the socket (I think usually this means it sends RST) – user253751 Feb 01 '23 at 17:50
  • 2
    @Quimby the next incoming packet would get an RST response, as is usual for unknown incoming packets – user253751 Feb 01 '23 at 17:50
  • @user253751 Yes, I was just answering the "close TCP connection" part, if OP wants to make the host unavailable, your link with iptables seems like a way to go. – Quimby Feb 01 '23 at 17:52
  • @Quimby the point is to pretend the host disappeared, without actually pulling the plug out, just for testing. – user253751 Feb 01 '23 at 17:53
  • Possible solution using `ss` tool: https://stackoverflow.com/a/69685818/72178 – ks1322 Feb 01 '23 at 19:11
  • I think calling `ifdown` on the network interface that the TCP connection is using would have the desired effect (although it might also have undesired effects, since it would disable all traffic on that network interface, not just the TCP connection under test) – Jeremy Friesner Feb 04 '23 at 01:29
  • Maybe is an overkill, but what about running your endpoint program inside a virtual machine. You can put it in rc.local to run at boot time. Just force a "power off" the virtual machine to reproduce the conditions you want. – Miguel Feb 09 '23 at 08:44

4 Answers4

1

If you're opening a socket via socket(AF_INET, SOCK_STREAM, 0); then its unpredictable to implement an ungraceful shutdown sense even killing the process will still give the kernel domain over closing the socket.

You can either externally block network access to that socket (ie ifdown, iptables), which you can call from your program. Or you'll have to implement custom TCP code using socket(AF_INET, SOCK_RAW, 0); so that the kernal doesn't try to close it gracefully (as it wouldn't know it's even a TCP socket).

1

The easiest way to simulate the machine with the connection "going away" without notice is probably to block(drop) the incoming packets on the connection. A netfilter command like

iptables -A INPUT -p tcp --dport $PORT -j DROP

will do that -- replace $PORT with the connections local port number. The won't block outgoing packets (which may be an issue if you have keepalives or periodically send stuff.) You can do that with

iptables -A OUTPUT -p tcp --sport $PORT -j DROP

Be sure to remove these filtering rules when you're done, as otherwise they'll stick around and cause problems.

Chris Dodd
  • 119,907
  • 13
  • 134
  • 226
0

I would prefer To act on the net driver irq processing. The Linux kernel provides a way to set the affinity of an IRQ to specific CPUs, so that the IRQ can only be processed by those CPUs. By setting the affinity of an IRQ to an empty set of CPUs, you can effectively disable the IRQ.

disable irqbalance daemon . then check which interrupts your nic driver uses .

cat /proc/interrupts

then forbids any cpu To process the nic irq : echo 0 > /proc/irq/N/smp_affinity

sancelot
  • 1,905
  • 12
  • 31
0

You can use the close function from the unistd.h library to close the file descriptor associated with the socket. However, it is important to note that this method may not immediately terminate the connection, as the underlying TCP protocol has its own mechanisms for closing connections, and these mechanisms may take some time to complete.

Mihaimyh
  • 1,262
  • 1
  • 13
  • 35
  • 1
    It is the execution of those underlying mechanisms that the questioner is specifically trying to avoid -- s/he wants to simulate an *ungraceful* disconnect (i.e. someone pulling out the Ethernet cable), not a controlled shutdown of the connection. – Jeremy Friesner Feb 10 '23 at 20:47