[完成端口模型]关于AcceptEx的问题,如何防止拒绝服务攻击?

Hellboy 2004-08-31 09:35:07
在程序启动的时候,递交了10个AcceptEx.
如果恶意的客户端发送了10连接,但是不发送任何数据,那样就会耗尽所有的未完成的AccpetEx调用。
这时合法的客户端将无法正常连接。

参照Windows网络编程的代码,使用getsockopt()得到每个客户端的ConnectTime,然后关闭非法的连接。
我在程序里面设置了1分钟的超时,但是10个AceptEx还是很容易就被消耗完。

是否可以在一开始递交50个AcceptEx,然后设置一分钟的超时? (估计这样做会影响性能!)。
...全文
1340 38 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
38 条回复
切换为时间正序
请发表友善的回复…
发表回复
CompletionPort 2005-02-16
  • 打赏
  • 举报
回复
mark
banjo 2004-09-03
  • 打赏
  • 举报
回复
可以计算每ip单位时间的连接次数,超过的列为非法ip,直接拒绝好了,这样耗资源也是少的
coolFly19 2004-09-02
  • 打赏
  • 举报
回复
不管怎么,提交太多的Acceptex和建立太多的连接对你应用都是不利的,你提交的缓冲仅仅是页面缓冲,非页面缓冲是,一个AccepteEx占用1.5k,一个连接占用2k,即使服务器作了优化,这个也是有上限的,不会超过机器内存的一半,具体我记不清了,正如Hellboy说的那样,最好的可能是,调用失败,最坏的可能是系统出现终端错误而崩溃。刚开始看你说1000000个时让我吃惊,我看elssann说的防止恶心攻击的方法还是比较合理的,话说回来你想从根本上完全拒绝这种服务,拒绝这种攻击是不可能的,在此之前Cisco发现连IP协议有漏洞,
wwwsq 2004-09-02
  • 打赏
  • 举报
回复
回复人: wwwsq(wwwsq) ( ) 信誉:100 2004-9-1 17:17:48 得分: 0



to elssann() :

iocp_standard确实还不够实用,比如里面没有server端主动发数据的函数。但是iocp_standard绝对是最经典的iocp模型。在iocp_standard模型中CreateAcceptSocket()里面的“DEFAULT_IOCP_BUFF_SIZE - (2 * (sizeof(SOCKADDR_IN) + 16))”需要替换成“0”,这样AcceptEx就会在第一时间返回。

强行检查AcceptEx所post出去的iocp packet是不可取的。因为在iocp模型里面,post出去的iocp packet在返回之前都不应该被访问,他们处于kernel mode,而且访问的结果是不可靠的。

在收到任何数据之前,AcceptEx所post出去的iocp packet就已经仅仅因为client端的connect成功而返回了。此时server端就据此建立一个connection的上下文,并且post一个WSARecv的iocp packet。

之后,正如每个server程序所必须的,会有心跳机制。当一个connection超过若干时间都没有发送心跳过来,这个连接就会被server踢出。

如果这是一个易受攻击的服务器,那么建立connection上下文是最危险的工作,因为这地方可能导致内存不受控制。很简单,你限制connection上下文的个数就可以了,并且你可以预先开辟100000个connection上下文以避免内存的动态分配。
此外你可以改进心跳机制,要求connection上下文建立之后,第一份合法的数据必须在0.1秒之内到达,否则就踢掉。第一份合法数据到达之后,就认为是可信连接,心跳检验就可以以秒为单位进行了。




Hellboy 2004-09-02
  • 打赏
  • 举报
回复
初略的算了一下1000000个acceptex会锁定4G的内存。在x86体系中,页面以4K的倍数被锁定,即使提交的接收缓冲是1的字节,系统实际锁定将锁定一个4K的数据块。

另外,《MICROSOFT的WINDOWS网络编程》一书中提到,win2000及以后的系统,未分页内存的上限为256MB。如果系统用尽了未分页内存,会有两种可能性。最好的可能是,Winsock调用失败,最坏的可能是系统出现终端错误而崩溃。

所以提交1000000个acceptEx有点夸张,而且肯定是不可行的。

很多东西书上,或者网上都有资料。我希望大家能够提供比较具体和实际一点的解决方法!
elssann 2004-09-02
  • 打赏
  • 举报
回复
别忘记了你是在回答别人的问题,你知道不知道你这样会误导别人?
这不是写小说,还用夸张的修辞手法。
Hellboy 2004-09-01
  • 打赏
  • 举报
回复
顶一下!
继续求更好的解决方案。
wwwsq 2004-09-01
  • 打赏
  • 举报
回复
我们测试iocp性能的时候,memcpy根本就没有被调用。

1000000是有点夸张的说法,不会有人真去投递1000000个吧?
elssann 2004-09-01
  • 打赏
  • 举报
回复
这种情况下,你有没有考虑过对memcpy优化?有没有考虑用类似NDIS_PACKET的那种包描述符和缓冲区描述符来代替单纯的缓冲区指针?

注意,投递AcceptEx耗用别的资源都不可怕,可怕的是每个AccepptEx会锁定一点未分页内存。你1000000个AcceptEx会锁定多少?算过没有?
wwwsq 2004-09-01
  • 打赏
  • 举报
回复
投递一个AceptEx确实会占用一定的资源,但是你的机器够好的话,这不是问题。而且占用的这点内存不会影响网络层的工作。

你去测试一下,客户端每次发送20个字节,服务器端收到20个字节立刻返回20个字节给客户端,客户端收到20个自己再发送20个字节。循环。

你看看这种高频率通讯的情况下,服务器的瓶颈是在哪里。
elssann 2004-09-01
  • 打赏
  • 举报
回复
递交1000000个AcceptEx。对于DOS就是拼谁的资源比较多。除非你想做个防火墙,一般的服务器程序,能做的就是拼资源。

另外,只要你内存够,你递交多少个AcceptEx理论上是不会影响性能的。
-----------------------------------------------------------------
我真的要怀疑你有没有写过高性能服务器程序了,你不知道每一个AcceptEx调用都会锁定一点未分页内存吗?




AcceptEx的时候要求对方送校验数据过来,无校验数据或者校验数据不对,就认为是恶意连接立刻踢开连接。强一点的话,甚至可以记住来源并进行计数和屏蔽。
---------------------------------------------------------------------------------
如果你在调用AcceptEx的时候同时传递了一个缓冲区,那么建立连接和接收数据成为一个原子操作,两项操作都完成了才会返回,你怎么去校验数据?如果你把缓冲区设置为0,那么不是和我那个方法一样了吗?




检查ip也没用,高级的dos攻击都是伪装ip的。
----------------------------------------------
伪装不存在的IP是到不了应用层来的,因为完成不了三次握手,只能进行syn flood攻击,于应用程序何干?根本不会给你有机会检测IP。

wwwsq 2004-09-01
  • 打赏
  • 举报
回复
随你吧。广泛听取意见,然后选择适合你的。

我并不觉得他的方法很好。
Hellboy 2004-09-01
  • 打赏
  • 举报
回复
to:wwwsq
1,如果设置了 “DEFAULT_IOCP_BUFF_SIZE - (2 * (sizeof(SOCKADDR_IN) + 16))”需要替换成“0”。 getsockopt函数就没必要了,否则可以用这个函数得到客户端连接了但是没发送任何数据的时间。
可以根据这个来知道客户端是否合法。
2,如果缓冲区设成0,那么accpetEx在接收到连接就立即返回。这时采用 elssann() 的方法也许比较适合。

我现在用了 elssann() 提供的方法,感觉用着还行。
如果需要更好的防止dos攻击,可以另外再提供一个网关的保护。
wwwsq 2004-09-01
  • 打赏
  • 举报
回复
to elssann() :

作为正式的项目开发,我想你们肯定是做过严格的性能测试的。请把你们的测试结果贴出来吧?让我见识一下你们开发的server有多高的效率。

elssann 2004-09-01
  • 打赏
  • 举报
回复
强行检查AcceptEx所post出去的iocp packet是不可取的。
--------------------------------------------------
怎么强行检查AcceptEx POST出去的iocp packet?我没这么做过。


在收到任何数据之前,AcceptEx所post出去的iocp packet就已经仅仅因为client端的connect成功而返回了。此时server端就据此建立一个connection的上下文,并且post一个WSARecv的iocp packet。
-------------------------------------------------------------
不懂你说的是什么意思。



并且你可以预先开辟100000个connection上下文以避免内存的动态分配。
-----------------------------------
这个是肯定的,在服务器程序开发中,池的使用是必须的,




此外你可以改进心跳机制,要求connection上下文建立之后,第一份合法的数据必须在0.1秒之内到达,否则就踢掉。第一份合法数据到达之后,就认为是可信连接,心跳检验就可以以秒为单位进行了。
----------------------------------------
你说的这个心跳机制是指WINDOWS本身的还是自己做的?如果是自己做的没有必要。
我觉得我的那种做法:每建立一个连接就插入到一个链表,当收到第一份数据后就从链表中删除掉是可行的,而且在我的实际使用中,也很正常有效。

至于对于那些大规模的DOS攻击,任何方法都是徒劳的。



之后,正如每个server程序所必须的,会有心跳机制。当一个connection超过若干时间都没有发送心跳过来,这个连接就会被server踢出。
----------------------------------------------------
我们的心跳机制是业务层做的。我们有两套心跳机制,一套是WINSOCK本身提供的。在下面底层由完成端口来使用。一套是上面业务层的。。。。

wwwsq 2004-09-01
  • 打赏
  • 举报
回复
to elssann():

另外,iocp_standard模型里面,只有一个AcceptEx,如果你没有修改AcceptEx的dwReceivedDataLength,我相信只要一个不发数据的连接就可以把这个模型block住,我不知道你所说的:“1000个client”用了“2分钟”使它“崩溃”是怎么回事。
wwwsq 2004-09-01
  • 打赏
  • 举报
回复
to elssann() :

iocp_standard确实还不够实用,比如里面没有server端主动发数据的函数。但是iocp_standard绝对是最经典的iocp模型。在iocp_standard模型中CreateAcceptSocket()里面的“DEFAULT_IOCP_BUFF_SIZE - (2 * (sizeof(SOCKADDR_IN) + 16))”需要替换成“0”,这样AcceptEx就会在第一时间返回。

强行检查AcceptEx所post出去的iocp packet是不可取的。因为在iocp模型里面,post出去的iocp packet在返回之前都不应该被访问,他们处于kernel mode,而且访问的结果是不可靠的。

在收到任何数据之前,AcceptEx所post出去的iocp packet就已经仅仅因为client端的connect成功而返回了。此时server端就据此建立一个connection的上下文,并且post一个WSARecv的iocp packet。

之后,正如每个server程序所必须的,会有心跳机制。当一个connection超过若干时间都没有发送心跳过来,这个连接就会被server踢出。

如果这是一个易受攻击的服务器,那么建立connection上下文是最危险的工作,因为这地方可能导致内存不受控制。很简单,你限制connection上下文的个数就可以了,并且你可以预先开辟100000个connection上下文以避免内存的动态分配。
此外你可以改进心跳机制,要求connection上下文建立之后,第一份合法的数据必须在0.1秒之内到达,否则就踢掉。第一份合法数据到达之后,就认为是可信连接,心跳检验就可以以秒为单位进行了。
wwwsq 2004-08-31
  • 打赏
  • 举报
回复
检查ip也没用,高级的dos攻击都是伪装ip的。
wwwsq 2004-08-31
  • 打赏
  • 举报
回复
如果你是要做防火墙,我建议不要用软件做了,还是用硬件防火墙吧。软件防火墙基本上是personal的玩具。
tcp协议底层的半开连接,软件是解决不了的,硬件防火墙也多半解决不了。
高级的异步dos攻击,目前几乎就是无法抵挡的。
Hellboy 2004-08-31
  • 打赏
  • 举报
回复
Windows网络编程的的例子里面,有这样类似的代码.
我看了iocp的例子,他们不是去检查AcceptEx,而是用了getsockopt()函数去获得sock的connecttime.根据这个来判断是否恶意连接.
但是这样做也是需要遍历所有的连接,速度也会慢的.

加载更多回复(18)

18,363

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 网络编程
c++c语言开发语言 技术论坛(原bbs)
社区管理员
  • 网络编程
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧