删除打开的TCP连接而不发送RST

时间:2017-09-11 01:13:58

标签: c sockets tcp network-programming tcp-rst

调查nginx: ignore some requests without proper Host header让我觉得,如果没有操作系统通过发送RST(和/或{{)正确终止底层TCP连接,close(2) TCP连接实际上是不可能的1}})到另一端。

一种解决方法是使用类似tcpdrop(8)的内容,但是,从usr.sbin/tcpdrop/tcpdrop.c on OpenBSDFreeBSD可以看出,它是通过基于sysctl的界面实现的,并且可能在BSD之外有可移植性问题。 (实际上,看起来甚至基于sysctl的实现在OpenBSD和FreeBSD之间也可能不同,需要一个移植层 - OpenBSD uses tcp_ident_mapping结构(随后包含两个{{1} } {}},FreeBSDDragonFly直接使用两个FIN元素的数组。)事实证明, OpenBSD的sockaddr_storage似乎确实按照NetBSD发送了sockaddr_storage个数据包,并且可以通过查看最后调用tcpdrop的{​​{3}}来确认({3}}和R tcpdump(8)),似乎它甚至都不起作用。

如果我通过C自己建立连接,有没有办法随后丢弃它而不向另一方发送确认,例如,没有启动tcp_close()

2 个答案:

答案 0 :(得分:1)

  

如果我自己通过C建立连接,有没有办法在没有确认到另一方的情况下将其丢弃,例如,不启动RST?

没有。即使有,如果对方随后发送任何东西,它将由RST回答。

NB正常TCP终止使用FIN,而不是RST。

答案 1 :(得分:0)

以这种方式欺骗攻击者可能是个好主意。当然,在这种情况下,您已经为已建立的连接保留了服务器资源。在最基本模式下,您可以使用netfilter删除任何设置了RST或FIN标志的TCP传出段。这条规则iptables规则可以是一个例子:

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

当然,此规则会影响您的所有TCP连接。我写这篇文章只是为了提供你如何做到这一点。转到https://www.netfilter.org/,了解有关解决方案的更多想法。基本上,您应该只能对选定的连接执行相同的操作。

由于TCP如何工作,如果您能够实现它,客户端(或攻击者)将保持连接打开很长时间。要理解它在客户端中的效果,请阅读:TCP, recv function hanging despite KEEPALIVE其中我提供了测试结果,其中另一方没有返回任何TCP段(甚至不是ACK)。在我的配置中,套接字需要13分钟才能进入错误状态(这取决于Linux参数,如tcp_retries1和tcp_retries2)。

仅考虑DoS攻击通常意味着来自数千个不同设备的连接,并且不一定意味着来自同一设备的许多连接。这很容易在防火墙中检测和阻止。因此,您不太可能在客户端中产生资源耗尽。此解决方案也不适用于半开连接攻击的情况。