简体   繁体   中英

Drop an open TCP connection without sending RST

Looking into nginx: ignore some requests without proper Host header got me thinking that it's not actually possible to close(2) a TCP connection without the OS properly terminating the underlying TCP connection by sending an RST (and/or FIN ) to the other end.

One workaround would be to use something like tcpdrop(8) , however, as can be seen from usr.sbin/tcpdrop/tcpdrop.c on OpenBSD and FreeBSD , it's implemented through a sysctl-based interface, and may have portability issues outside of BSDs. (In fact, it looks like even the sysctl-based implementation may be different enough between OpenBSD and FreeBSD to require a porting layer -- OpenBSD uses the tcp_ident_mapping structure (which, subsequently, contains two sockaddr_storage elements, plus some other info), whereas FreeBSD , DragonFly and NetBSD use an array of two sockaddr_storage elements directly.) It turns out, that OpenBSD's tcpdrop does appear to send the R packet as per tcpdump(8) , and can be confirmed by looking at /sys/netinet/tcp_subr.c :: tcp_drop() , which calls tcp_close() in the end (and tcp_close() is confirmed to send RST elsewhere on SO ), so, it appears that it wouldn't even work, either.

If I'm establishing the connection myself through C, is there a way to subsequently drop it without an acknowledgement to the other side, eg, without initiating RST ?

If I'm establishing the connection myself through C, is there a way to subsequently drop it without an acknowledgement to the other side, eg, without initiating RST?

No. Even if there was, if the peer subseqently sent anything it would be answered by an RST.

NB Normal TCP termination uses a FIN, not an RST.

Cheating an attacker in this way could be a good idea. Of course, in this case you are already reserving server resources for the established connection. In the most basic mode you can use netfilter to drop any TCP outgoing segment with RST or FIN flags set. This rule iptables rule could be an example:

sudo iptables -A OUTPUT -p tcp --tcp-flags FIN,RST SYN -j DROP

Of course, this rule will affect all your TCP connections . I wrote it just to provide a lead of how you can do it. Go to https://www.netfilter.org/ for getting more ideas working on your solution. Basically you should be able to do the same only for the selected connections.

Because of how TCP works, if you're able to implement it, the client (or attacker) will keep the connection open for a long time. To understand the effect it would have in a client read here: TCP, recv function hanging despite KEEPALIVE where I provide results of a test in which the other side doesn't return any TCP segment (not even an ACK). In my configuration, it takes 13 minutes for the socket to enter an error state (that depends on Linux parameters like tcp_retries1 and tcp_retries2).

Just consider a DoS attack will usually imply connections from thousands of different devices and not necessarily many connections from the same device. This is very easy to detect and block in the firewall. So, it's very improbable that you are going to generate resources exhaustion in the client. Also this solution will not work for cases of half-open connection attack.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM