D
delphiroad
Unregistered / Unconfirmed
GUEST, unregistred user!
使用完成端口实现了一个服务器程序,每成功建立一个连接,服务
器就必须分配一些内存。正常断开了再释放这些资源。
在我的监听线程中,如果有连接则得到一个Accept的socket:
Accept = WSAAccept(Listen,NULL,NULL,NULL,0);
然后马上在这个socket上投寄一个接收操作(就是马上就要求客户端上传数据):
WSARecv(Accept......
该操作马上完成,但接收还在等待。
现在的问题是,如果客户端不上传数据,我也没有办法断开这个Accept的连接。
假如,存心攻击我的人,建立了大量无用的连接(尽管不做传递任何数据),长时间
不断开,不久我的服务器就会资源耗尽!于是拒绝接受其它正常的连接请求。
我做了一点改进:
接收到非法的数据(比如信息头不正确等)则丢弃;
但这基本上对攻击者没什么意义,因为他不会发任何信息给我(以免发错了给我断开
了),也就是不给我断开连接的机会。
想过的第一个办法是:同一个IP只允许建立一个连接。
但是,第一是如何设计一个算法很快的查出这个Ip在之前已经建立一个连接了(因为
服务器被设计成可接收数以万计合法连接的,采用完成端口本身就是为了达到大响应)?
第二是好像用Ip判断也不可靠(如果Ip欺骗呢?尽管不容易)。
曾想过的第二个办法是:是否存在一种事件(超时事件)通知的模式
于是想到对每个建立起来的socket使用WSAEventSelect投寄事件,然后用在另一个线程
中用WSAWaitForMultipleEvents来等待事件发生,并且设一个超时,如果超时了,就代
表WSARecv超时了。
但WSAWaitForMultipleEvents一次只能等待60个socket的事件,如果多了我不是要建立
很多个线程来等待,这不单是线程多的关系,还有就是WSAWaitForMultipleEvents返回
的是事件对象在数组中的相对索引(而不是socket),那我就得自己去对应到socket对象,
还是在好几个数组(每个数组是最多60个事件Handle)中进行对应,这也加大了服务器的
负荷。
第三个办法是用另一个线程来隔一段时间就用getsockopt来判断每个socket连接有多长
时间没有动作了,但是用轮询的办法对成千上万的socket来判断开销也是可观的!
如果做这个事情需要系统付出很大的开销则是得不偿失的,因为攻击者同样可以利用这
一点来达到让服务器拒绝正常服务的目的。
在网上还看到原来拒绝服务攻击是很普遍的(并且象这种只建立连接不传递数据的攻击方
法又很简单,几乎不需要面对什么技术难题),同时还知道有分布式的拒绝服务攻击DDoS,
那就意味者攻击者可以利用互联网上所有的计算机来攻击我!就算我可以做到让一个Ip
只能建立一个连接,也没有办法阻止它啊!
有没有什么办法既可自动断开长时间不作为的连接同时开销又很小呢?
这帖子是200分,还有以前两个帖子(一直没有答案,现在自己已经知道了),如果回答得
精彩的,到时散分时,请“得奖”者到这两个帖子跟贴领分:
http://www.delphibbs.com/delphibbs/dispq.asp?lid=1700719
http://www.delphibbs.com/delphibbs/dispq.asp?lid=2239070
器就必须分配一些内存。正常断开了再释放这些资源。
在我的监听线程中,如果有连接则得到一个Accept的socket:
Accept = WSAAccept(Listen,NULL,NULL,NULL,0);
然后马上在这个socket上投寄一个接收操作(就是马上就要求客户端上传数据):
WSARecv(Accept......
该操作马上完成,但接收还在等待。
现在的问题是,如果客户端不上传数据,我也没有办法断开这个Accept的连接。
假如,存心攻击我的人,建立了大量无用的连接(尽管不做传递任何数据),长时间
不断开,不久我的服务器就会资源耗尽!于是拒绝接受其它正常的连接请求。
我做了一点改进:
接收到非法的数据(比如信息头不正确等)则丢弃;
但这基本上对攻击者没什么意义,因为他不会发任何信息给我(以免发错了给我断开
了),也就是不给我断开连接的机会。
想过的第一个办法是:同一个IP只允许建立一个连接。
但是,第一是如何设计一个算法很快的查出这个Ip在之前已经建立一个连接了(因为
服务器被设计成可接收数以万计合法连接的,采用完成端口本身就是为了达到大响应)?
第二是好像用Ip判断也不可靠(如果Ip欺骗呢?尽管不容易)。
曾想过的第二个办法是:是否存在一种事件(超时事件)通知的模式
于是想到对每个建立起来的socket使用WSAEventSelect投寄事件,然后用在另一个线程
中用WSAWaitForMultipleEvents来等待事件发生,并且设一个超时,如果超时了,就代
表WSARecv超时了。
但WSAWaitForMultipleEvents一次只能等待60个socket的事件,如果多了我不是要建立
很多个线程来等待,这不单是线程多的关系,还有就是WSAWaitForMultipleEvents返回
的是事件对象在数组中的相对索引(而不是socket),那我就得自己去对应到socket对象,
还是在好几个数组(每个数组是最多60个事件Handle)中进行对应,这也加大了服务器的
负荷。
第三个办法是用另一个线程来隔一段时间就用getsockopt来判断每个socket连接有多长
时间没有动作了,但是用轮询的办法对成千上万的socket来判断开销也是可观的!
如果做这个事情需要系统付出很大的开销则是得不偿失的,因为攻击者同样可以利用这
一点来达到让服务器拒绝正常服务的目的。
在网上还看到原来拒绝服务攻击是很普遍的(并且象这种只建立连接不传递数据的攻击方
法又很简单,几乎不需要面对什么技术难题),同时还知道有分布式的拒绝服务攻击DDoS,
那就意味者攻击者可以利用互联网上所有的计算机来攻击我!就算我可以做到让一个Ip
只能建立一个连接,也没有办法阻止它啊!
有没有什么办法既可自动断开长时间不作为的连接同时开销又很小呢?
这帖子是200分,还有以前两个帖子(一直没有答案,现在自己已经知道了),如果回答得
精彩的,到时散分时,请“得奖”者到这两个帖子跟贴领分:
http://www.delphibbs.com/delphibbs/dispq.asp?lid=1700719
http://www.delphibbs.com/delphibbs/dispq.asp?lid=2239070