删除打开的TCP连接而不发送RST
查看nginx:忽略一些没有正确主机头的请求让我觉得实际上不可能通过向另一端发送RST
(和/或FIN
)而没有OS正确终止底层TCP连接来close(2)
TCP连接。
一种解决方法是使用类似 tcpdrop(8)
东西,但是,从OpenBSD和FreeBSD 上的usr.sbin/tcpdrop/tcpdrop.c
可以看出,它是通过基于sysctl的接口实现的,并且可能有外部的可移植性问题BSD系统。(实际上,看起来甚至基于sysctl的实现在OpenBSD和FreeBSD之间可能不同,需要一个移植层 – OpenBSD使用 事实certificate,OpenBSD的tcp_ident_mapping
结构(随后,它包含两个sockaddr_storage
元素,加上一些其他信息),而FreeBSD , DragonFly和NetBSD直接使用两个sockaddr_storage
元素的数组。)tcpdrop
似乎确实根据tcpdump(8)
发送了R
数据包,并且可以通过查看/sys/netinet/tcp_subr.c :: tcp_drop()
来确认/sys/netinet/tcp_subr.c :: tcp_drop()
,最后调用tcp_close()
(并确认 tcp_close()
在其他地方发送RST
),因此,似乎它甚至都不起作用。
如果我自己通过C建立连接,有没有办法随后丢弃它而不确认另一方,例如,没有启动RST
?
如果我自己通过C建立连接,有没有办法随后丢弃它而不确认另一方,例如,没有启动RST?
不会。即使有,如果对方随后发送任何东西,它将由RST回答。
NB正常TCP终止使用FIN,而不是RST。
以这种方式欺骗攻击者可能是个好主意。 当然,在这种情况下,您已经为已建立的连接保留了服务器资源。 在最基本的模式下,您可以使用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函数挂起尽管KEEPALIVE我在其中提供测试结果,其中另一方不返回任何TCP段(甚至不是ACK)。 在我的配置中,套接字需要13分钟才能进入错误状态(这取决于Linux参数,如tcp_retries1和tcp_retries2)。
仅考虑DoS攻击通常意味着来自数千个不同设备的连接,并且不一定意味着来自同一设备的许多连接。 这很容易在防火墙中检测和阻止。 因此,您不太可能在客户端中产生资源耗尽。 此解决方案也不适用于半开连接攻击的情况。