内容


自动关闭网络中的空闲计算机

通过自动检测并关闭网络中的非活动系统节省电力、带宽和磨损

Comments

“绿色” 技术最近的动向主要集中在口头上,而很少对典型的家庭办公环境或小型办公环境采取行动。许多用户由于偷懒或不小心而使系统保持连续在线,因而导致消耗大量电力资源,并且为恶意传播提供了更多可能性。本文提供的工具和代码允许您查找非活动的系统并安全地关闭它们。通过使用 Argus 和一些自定义 Perl 代码监视网络连接的 Linux® box,任何一个支持 Perl 的系统都可以设置为在满足主要的非活动规则时被远程关闭。

硬件要求

虽然控制安全通信和关闭系统的代码是跨平台的,但是需要有能够运行 Linux 以监视计算机的硬件,我们称之为 控制节点。这样的节点可以是 Linksys NSLU2 或类似的运行 Linux 的低功率设备。控制节点需要具有在整个网络内监视网络连接的方法。只需要最低程度的处理能力、RAM 和存储,除非您打算在一个高带宽通道中监视成百上千的计算机。事实上,任何在 2000 年以后制造、拥有适当网络适配器并且能够运行 Linux 的 PC,都足以监视小型办公或家庭网络。控制节点使用一个网络适配器便足以满足低流量设置,但是对于繁忙的网络来说,有两个网络适配器更好。有关所选系统放置位置的建议,请参阅 “硬件布置” 小节。

软件要求

在理论上来说,Snort、Tcpdump 或许多网络监视软件包都可以用于测量。本文将使用 Argus 和 racluster(Argus 客户机)的组合,因为它十分简单并且是跟踪连接状态的轻量级软件。除了大部分工作由 Argus 完成之外,您还需要 Perl 和相关模块以进行网络通信、生成任意字符串和加密。这些模块分别是 POE、String::MkPasswd 和 Crypt::Blowfish。有关查找和安装这些模块的详细信息,请参阅 参考资料

硬件布置

为全网络监视连接点选择适当的位置是一个复杂的主题,因为其中存在很多依赖具体网络属性的变化因素。假定您对网络拓扑有一定的了解,并且能够识别所有网络流量流经的上游连接点(upstream connection point)。

例如,考虑一个典型的家庭网络,其中有四台计算机连接到无线访问点(WAP),或者通过电缆或 DSL 调制解调器向外连接的路由器。(我发现在这里使用 “调制解调器” 一词并不精确,但是由于整个行业默认了这个词,因此我也将使用它 — 虽然不情愿)。将控制节点网络连接放在 WAP 与调制解调器之间将允许通过网络中的任意一台计算机监视与 Internet 的所有连接。此外,许多家庭办公 WAP 也是配有有线以太网端口的路由器,因此直接连接到 WAP 的有线端口可以满足要求。

请牢记,正确放置控制节点(配有适当的网络接口)、网络适配器或控制节点中适配器的关联性配置,会为偶然的访问者带来巨大的挑战。有关帮助您开始了解网络监视的教程和研究资料,请参阅 参考资料

控制节点上的 Argus 设置

对于本文来说,最理想的目的是通过最小的资源损耗对网络连接属性进行简单测试。本文并没有编写 Snort 规则或分析 Tcpdump 输出,而是使用 Argus 和一些命令行转换来提供最少的网络连接列表。在控制节点上,安装 Argus 并运行以下命令。

清单 1. 控制节点上的 Argus 命令
argus -w /tmp/argusOutput -i eth0

Argus 记录的事务记录将被附加到 /tmp/argusOutput 文件中,并且将 eth0 接口指定为在 promiscuous 模式下搜索包。现在 Argus 已被设为监视网络中每台主机的连接,使用其中一台 Argus 客户机输出这些连接的信息。使用 racluster -L0 -M -u -r /tmp/argusOutput tcp 命令显示网络中的当前连接,包括诸如总传输字节数和连接开始时间之类的信息。注意,此命令可以生成大量信息,因此请考虑用 racluster -L0 -M -u -r /tmp/argusOutput tcp -w - | rasort -m bytes | head 命令隔离大多数活动连接。

结合使用 rasorthead 命令将按照传输字节数列出前 10 个连接。

注意,需要以拥有在 promiscuous 模式下访问网络适配器的相应权限的用户身份运行 Argus 和 process_racluster.pl 程序(下面列出)。在大多数情况下,这指的是根用户。

选择计算机和带宽使用量

将要进行监视的每台计算机需要有标识符、表示非活动状态的字节数和检测到非活动状态时要运行的命令。清单 2 显示了示例 activityRules 文件。

清单 2. 示例 activityRules 文件
192.168.1.30_#_10_#_xmessage "Elena's laptop inactive"
192.168.1.35_#_400_#_xmessage "Alexander's desktop inactive"

注意,这些数字只是示例,并且需要针对网络中的计算机的具体使用情况进行调整。第一行将在控制节点的界面上弹出消息(如果 X Window System 处于活动状态),从而让用户知道笔记本处于非活动状态并且需要关闭。

用于监视非活动状态的 process_racluster.pl

读取 activityRules 文件、处理 racluster 输出和执行命令都是由 process_racluster.pl 程序执行的。清单 3 列出了 process_racluster.pl 的第 1 部分。

清单 3. process_racluster.pl 的第 1 部分
#!/usr/bin/perl -w
# process_racluster.pl - run commands if inactivity conditions are met
use strict;

my $sleepTime     = 600; # seconds between network activity reads
my $argusFile     = "/tmp/argusOutput";
my $raclusterFile = "/tmp/raclusterOutput";
my %rules         = (); # store commands, thresholds for each ip

open( INFILE, "activityRules" )  or die "can't open rules file";
  while(my $line = <INFILE> )
  {
    my( $ip, $threshold, $command ) = split "_#_", $line;
    $rules{ $ip }{ threshold } = $threshold;
    $rules{ $ip }{ command   } = $command;

  }#while in file

close( INFILE );

在变量声明和读取 activityRules 文件后,下一步是主逻辑循环。

清单 4. process_racluster.pl 的第 2 部分
while( 1 )
{
  # check if Argus is running 
  my $cmd = qq{ps -aef | grep argus | wc -l };
  die "argus no longer running" unless ( `$cmd` ne "1\n" );

  # transform the argus data into human readable form
  $cmd = qq{racluster -L0 -M -u  -r $argusFile tcp > $raclusterFile};
  $cmd = `$cmd`;

  my %hosts = ();
  open( INFILE, "$raclusterFile" ) or die "can't open argus output file";
    while(my $line = <INFILE> )
    {
      # grab destination addr, port, total packets, bytes, connection status
      $line = substr($line,68);
   
      my( $ipAndPort, undef, $bytes ) = split " ", $line;
      my _cnnew1@parts = split '\.', $ipAndPort;

      # skip if there is no port associated (probably not tcp)
      next unless( $#parts  == 4 );
  
      # get just the ip address 
      my $ip = substr($ipAndPort, 0, rindex($ipAndPort,".") );
   
      $hosts{$ip} += $bytes;
    
    }#while linein
  close(INFILE);

在每次经过主逻辑时,系统都将运行简单的过程检查以确保 Argus 网络连接监视器处于活动状态。如果是这样,则运行上面所述的 racluster 命令,并且将把 IP 地址和该地址的所有连接的关联字节计数记录到 %hosts 散列中。清单 5 显示了主逻辑循环的其余部分。

清单 5. process_racluster.pl 的第 3 部分
  for my $key( keys %rules )
  {
    my $foundKey = 0;
    $foundKey = 1 if( ! exists($hosts{$key}) );

    if( exists($hosts{$key}) && ($hosts{$key} < $rules{$key}{threshold})  )
    {
      $foundKey = 1;
    }#if key is not found

    next unless ( $foundKey == 1 );

    # run the command, remove the entry from processing
    system( $rules{$key}{command} );
    delete $rules{$key};

  }#for each key in the rules

  # delete the processed files, wait for next pass
  $cmd = qq{ rm $argusFile $raclusterFile };
  $cmd = `$cmd`;

  sleep($sleepTime);

}#while 1 loop

将检查规则数据集中每个定义的 IP 是否存在于 %hosts 散列中。如果未找到 IP,或者字节阈值小于规则文件中指定的值,则运行 inactive 命令。在找到一个非活动状态后,系统将删除规则数据集中的条目以防止对已经处于非活动状态的主机进行进一步处理。/tmp/argusOutput 将被删除以重置已记录的连接状态,并且删除临时 racluster 输出文件以节省空间。在休眠 10 分钟后,此过程将重复执行。

要开始进行对非活动状态的处理,用拥有运行 Argus 的权限的 ID(通常为根用户)运行命令 perl process_racluster.pl。当 “笔记本” 系统和 “桌面型” 系统转为非活动状态时,您将在控制节点上看到一条弹出消息,向您说明是哪些人让这些计算机处于非活动状态。

远程关闭系统

提供远程关闭系统的方法容易产生对计算机的控制和滥用。为了避免这样的一些较简单的攻击,以下客户机和服务器将实现一个简单的请求-响应系统。这种方法将帮助确保在使用了正确的加密密钥时系统只响应关闭命令。

侦听关闭请求:shutdownListener.pl

响应远程关闭请求的每个系统都需要运行 shutdownListener.pl 程序。

清单 6. shutdownListener.pl
#!/usr/bin/perl -w
# shutdownListener.pl - manage challenge/response, shutdown if authenticated
use strict;
use POE qw(Component::Server::TCP Filter::Reference);
use Crypt::Blowfish;
use String::MkPasswd qw(mkpasswd);

my $key = "<enter your key of choice here>";
my $random = substr(mkpasswd,0,8);
my $cipher = new Crypt::Blowfish $key;
my $cipherText = "";

# heavily influenced by the POE cookbook:
POE::Component::Server::TCP->new
  ( Alias => "shutdownListener",
    Port         => 11211,
    ClientFilter => "POE::Filter::Reference",
    ClientInput  => sub {
        my ( $sender, $heap, $input ) = @_[ SESSION, HEAP, ARG0 ];

        if( $cipherText eq "" )
        { 
          # send the challenge text back to client
          $heap->{client}->put( \$random );
          $cipherText = $cipher->encrypt( $random );

        }elsif( $cipherText eq $$input )
        { 
          print "challenge response match, shutting down\n";
          # uncomment this line to actually shutdown the system
          # system(`shutdown -h now`);   # linux
          # system(`shutdown -s -t 01`); # windows
          exit(0);
        }else
        { 
          print "challenge response does not match, exiting server";
          exit(1);
        }#if cipher text not generated
    },
  );

$poe_kernel->run();
exit 0;

POE 模块提供了一种使用 Perl 创建双向 TCP 通信的最简单方法。在收到关闭请求时,当前的任意字符串将被发送回客户机。如果客户机的加密过的返回字符串与本地加密的字符串匹配,则运行关闭命令。注意,应当把密钥替换为匹配下面的 clientShutdown.pl 中定义的密钥的惟一值。除了关闭系统之外,如果不能阻止重复的连接尝试,则 shutdownListener.pl 将终止系统执行。

在应当支持远程关闭的每台计算机中保存 shutdownListener.pl 代码。应当以拥有关闭计算机和访问所选端口的相应权限的用户身份运行 shutdownListener.pl。

发送关闭请求:clientShutdown.pl

要关闭的每台计算机都将侦听控制节点以捕获关闭连接请求。这些请求均来自 clientShutdown.pl 程序。

清单 7. clientShutdown.pl
#!/usr/bin/perl -w
# clientShutdown.pl - compute challenge request, send response
use strict;
use POE qw( Component::Client::TCP Filter::Reference);
use Crypt::Blowfish;

die "specify hostname " unless @ARGV == 1;

my $host    = $ARGV[0];
my $key     = "<enter your key of choice here>";
my $cipher  = new Crypt::Blowfish $key;
my $port    = 11211;
my $sendStr = "getChallenge";

# heavily influenced by the POE cookbook:
POE::Component::Client::TCP->new
  ( RemoteAddress => $host,
    RemotePort    => $port,
    Filter        => "POE::Filter::Reference",
    Connected     => sub {
        $_[HEAP]->{server}->put( \$sendStr );
    },
    ConnectError => sub {
        die "could not connect to $host:$port ...\n";
    },
    ServerInput => sub {

      # get the server response
      my ( $input ) = @_[ ARG0 ];

      # encrypt the response, send back
      my $cipherText = $cipher->encrypt( $$input );
      $_[HEAP]->{server}->put( \$cipherText );

    },
  );
$poe_kernel->run();
exit 0;

类似于 shutdownListener.pl,clientShutdown.pl 程序将连接到要关闭的计算机、检索随机文本、用共享密钥加密该文本并返回加密文本。同样,客户机与服务器之间的加密密钥必须匹配。通过插入清单 8 中所示的代码行来修改 activityRules 文件。

清单 8. activityRules 中的远程关闭
192.168.1.33_#_5555554_#_perl clientShutdown.pl 192.168.1.33

现在,当 process_racluster.pl 被重新启动并且 192.168.1.33 计算机的网络总使用量在 10 分钟内降低到大约 5.5 MB 以下,则发送关闭命令。

用法

重新概况一下用法:修改 activityRules 文件以对每台计算机运行适当的命令。在应当远程关闭的每台计算机中启动 shutdownListener.pl。在控制节点上启动 Argus 和 process_racluster.pl 程序。

结束语

使用本文中的工具和代码,您可以设置网络监视器以跟踪网络中特定计算机的总使用量。当网络中的系统变为非活动状态时,使用本文提供的程序强制执行自动关闭。考虑修改 Argus 以搜索特定连接类型或主机。当计算机中只有历时 15 分钟的电子邮件检查处于活动状态时,或者如果流音频连接在几个小时内一直处于静音播放状态,则关闭系统。监视使用的协议或连接开始时间,进一步增强对触发关闭操作的非活动状态的检测。


下载资源


相关主题


评论

添加或订阅评论,请先登录注册

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=10
Zone=Open source
ArticleID=356323
ArticleTitle=自动关闭网络中的空闲计算机
publish-date=12042008