设为首页 | 加入收藏
蜘蛛网站系统

高可用的政府网站建设解决方案 - 蜘蛛网站系统

摘要

 

高可用的政府网站建设解决方案 - 蜘蛛网站系统,解决目前困扰政府网站的信息安全,并发访问等问题。

本文从域名解析、负载均衡、内容分发、模块分离、健康检查、系统安全等角度论述高可用的政府网站需要解决的问题,并在上述几个方面进行针对性的开发,从而实现一整套的高可用解决方案。

 

 

1 蜘蛛网站系统简介

1.1 来自DDoS攻击的威胁

    社会信息化进程的发展,电子商务、电子政务等信息化工程的日益完善一直跟随着网络技术的发展而发展,然而从安全的角度来看,随着网络的逐步完善,电子商务网络所面临的网络安全问题却始终如挥之不去的梦魇。日益突出的安全问题面前,魔道双方的攻守角逐未曾也永远不会停止。其中有一种很难被彻底解决的电子商务网站安全问题——可造成网络延时甚至瘫痪的攻击DDoS(Distributed Deny of Service——分布式拒绝服务攻击)严重威胁着众多电子商务网站。甚至成为电子商务网站能否生存和发展的重大隐患。

    DDoS攻击手段是在传统的DoS攻击基础之上发展而来的一种攻击方式。DoS的攻击方式有很多种,最基本的DoS攻击就是利用合理的服务请求来占用过多的服务资源,从而使合法用户无法得到服务的响应,DoS(Deny of Service——拒绝服务)因此得名。

  单一的DoS攻击一般采用一对一的方式,当被攻击目标各项性能指标较低,如:低CPU速度、小内存或者网络带宽有限时,攻击效果是明显的。但随着硬件与网络技术的发展,硬件价格暴跌的情况下,计算机的内存增加,处理器能力大大提高,千兆级别的网络的出现,使得DoS攻击的难度增加不少,因为性能的增强使得目标机对恶意攻击包的化解能力也随之增强。此时分布式的拒绝服务攻击(DDoS)也随之应运而生。DDoS原理很简单,就是利用网络掌控并集结尽量多的傀儡机来攻击目标机以期达到比单机大得多杀伤力。但其危害却极大且难以防御。

  自从1999年第一次有报道的大规模DDoS攻击在美国明尼苏达大学出现以来,相当多的电子商务网站已经遭受到其暗算并且损失惨重。2000 年,雅虎、CNN等一批大型商业网站被DDoS攻陷并停止正常运营。有研究表明,在20012月中的3周时间内,DDoS有效攻击达12 000次并侵害了5 000多台主机。DDoS造成的数据流堵塞迫使路由器丢弃所有用户的请求。更严重的基于DNSDDoS攻击发生在2006年,但是这是一种新型的攻击方式,攻击者并不直接攻击DNS服务器而是利用其作为跳板进而发动更大规模的攻击,由于DNS协议的复杂性和各DNS服务器之间的联系,这种攻击更难以化解。两个月之内,曾有1 500多个IP地址被这种方式攻击过。

  在自第一次的DDoS攻击出现之后,各种侦测和应对的技术没有一种能够给受害者以真正的保护。原因之一是很难将DDoS攻击的数据流量和正常的数据流量区分开;原因之二是在分布式的网络结构中,DDoS攻击利用IP欺骗等手段很容易隐藏且不易被追溯,因此不能被有效的阻止。

1.2 蜘蛛网站系统

    抵抗DDoS攻击的主要挑战来自于对其高效的监测和当攻击发生时的迅速察觉并控制住攻击数据流以保证对合法用户提供正常的响应服务。虽然网络业界并没有任何措施可以彻底消除DDoS的攻击,并且没有任何软件可以有效地防范并完全阻止它,硬件设施也只是做到了降低攻击程度的级别,只能采用一些适当的方法和思路去防范DDoS,从而收到一定的效果,即可以把攻击带来的损失降低到最小。

  其实无论使用何种防范措施,单打独斗的方法永远不会奏效。既然DDoS攻击最难以防范的攻击力量来自于大量被控制的傀儡机所发出的巨量数据流,所以有效地防范力量也应是将流量进行有效的分流,蜘蛛网站系统就是将大量的访问节点部署在不同的地区甚至国家。从而避免单点故障,将攻击带来的损失降低到最低程度。

    一套蜘蛛系统的部署涉及到域名解析、负载均衡、内容分发、模块分离、健康检查、系统安全等六个方面,下面分六章内容分别介绍。

 

 

2 域名解析系统

2.1 DNS轮循

    传统的DNS解析都是一个域名对应一个IP地址,但是通过DNS轮循技术(负载平衡技术)可以做到一个域名对应到多个IP 上。DNS轮循是指将相同的域名解释到不同的IP,随机使用其中某台主机的技术,该项技术可以智能的调整网站的访问量到不同服务器上,减轻网站服务器的压力,实现负载匀衡;如果您感觉到单一的主机已经不堪负载你网站日益增长的访问,那么建议您采用我们的DNS轮循技术。 

  DNS轮循系统可以根据您的需求设置N台主机作为WEB服务器。目前已有越来多大型的WEB服务器使用DNS轮循来实现负载均衡,服务的分布规划更便捷,扩展性更好,从而提高了网站的稳定性和访问效率,那些大量数据文件请求的客户也得到了更快的响应。

  DNS轮循还将给您的网站提供这样的改进,诸如您的网站的数据使用量一直处于不断的增长当中,当达到服务器资源运行瓶颈的情况下,由于采用了DNS轮循技术,您只需要增加服务器数量就可以平滑升级,而且偶然故障或其他意外情况造成的损失得以避免,7×24小时可靠性的持续的运行成为可能。

2.2 CNAME

    CNAME记录,即:别名记录。这种记录允许您将多个名字映射到同一台计算机。 通常用于同时提供WWWMAIL服务的计算机。例如,有一台计算机名为“host.mydomain.com”(A记录)。 它同时提供WWWMAIL服务,为了便于用户访问服务。可以为该计算机设置两个别名(CNAME):WWWMAIL 这两个别名的全称就是www.mydomain.com和“mail.mydomain.com”。实际上他们都指向 host.mydomain.com”。通过CNAME记录,我们可以实现不用操作实际的域名记录就可以实现蜘蛛节点的更换操作。但是CNAME记录不能为空,这样我们就无法实现不带WWW的蜘蛛节点切换。目前搜索引擎对301永久性重定向非常友好,BAIDUGOOGLE对此都有很好的支持。为此我们专门部署一台URL转发服务器对不带WWW的主机进行301永久性重定向。服务器采用NGINX系统。配置文件非常简单即可完成我们的目的。运行非常稳定。配置文件如下:

    server {

        listen       173.192.122.40:80;

        server_name  localname;

        rewrite ^(.*)$ http://www.$host  permanent;

    }

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

3 负载均衡

  对于一套蜘蛛系统而言,如果将不同的节点协调在一起运行,从而构成一张网状的结构是整个系统正常运行的关键。

3.1 DNS轮循与分地区解析

    前一章我们提到的DNS轮循是一个非常简单的算法,如果我们把系统威胁逐步缩小范围还需要对访问用户进行更精确的定位。这就需要将DNS轮循和分地区的智能DNS结合起来。BIND9的版本开始支持多VIEW,从而将我们实现分地区的智能解析成为可能。我们根据电子商务网站统计的客户群按历史数据进行一个大致的划分,在重点的客户区域投入更多的节点资源,在不太重要的地区投入少量的资源,从而实现高可用性和经济性的平衡。

3.2 反向代理与负载均衡

    反向代理(Reverse Proxy)方式是指以代理服务器来接受internet上的连接请求,然后将请求转发给代理服务器,并将从服务器上得到的结果返回给internet上请求连接的客户端,此时代理服务器对外就表现为一个服务器。

  通常的代理服务器,只用于代理内部网络对Internet的连接请求,客户机必须指定代理服务器,并将本来要直接发送到Web服务器上的http请求发送到代理服务器中。由于外部网络上的主机并不会配置并使用这个代理服务器,普通代理服务器也被设计为在Internet上搜寻多个不确定的服务器,而不是针对Internet上多个客户机的请求访问某一个固定的服务器,因此普通的Web代理服务器不支持外部对内部网络的访问请求。当一个代理服务器能够代理外部网络上的主机,访问内部网络时,这种代理服务的方式称为反向代理服务。此时代理服务器对外就表现为一个Web服务器,外部网络就可以简单把它当作一个标准的Web服务器而不需要特定的配置。不同之处在于,这个服务器没有保存任何网页的真实数据,所有的静态网页或者CGI程序,都保存在内部的Web服务器上。因此对反向代理服务器的攻击并不会使得网页信息遭到破坏,这样就增强了Web服务器的安全性。

  当客户机向站点提出请求时,请求将转到代理服务器。然后,代理服务器通过防火墙中的特定通路,将客户机的请求发送到内容服务器。内容服务器再通过该通道将结果回传给代理服务器。代理服务器将检索到的信息发送给客户机,好像代理服务器就是实际的内容服务器。如果内容服务器返回错误消息,代理服务器会先行截取该消息并更改标头中列出的任何 URL,然后再将消息发送给客户机。如此可防止外部客户机获取内部内容服务器的重定向 URL

  这样,代理服务器就在安全数据库和可能的恶意攻击之间提供了又一道屏障。与有权访问整个数据库的情况相对比,就算是侥幸攻击成功,作恶者充其量也仅限于访问单个事务中所涉及的信息。未经授权的用户无法访问到真正的内容服务器,因为防火墙通路只允许代理服务器有权进行访问。

  Nginx ("engine x") 是一个高性能的 HTTP 反向代理 服务器,也是一个 IMAP/POP3/SMTP 代理服务器。 Nginx 是由 Igor Sysoev 为俄罗斯访问量第二的 Rambler.ru 站点开发的,它已经在该站点运行超过两年半了。Igor 将源代码以类BSD许可证的形式发布。尽管还是测试版,但是,Nginx 已经因为它的稳定性、丰富的功能集、示例配置文件和低系统资源的消耗而闻名了。

  Nginx 可以在大多数 Unix like OS 上编译运行,并有 Windows 移植版。目前 Nginx 的稳定版为 0.8.50

    NGINXCENTOS5上的安装非常简单。我们在安装的时候仅打开状态监视功能。让NGINX仅作为静态网页请求和方向代理使用,从而提高其运行的稳定性和效率。具体安装步骤为:

wget http://nginx.org/download/nginx-0.8.50.tar.gz

tar xvf nginx-0.8.50.tar.gz

cd nginx-0.8.50

yum -y install make gcc zlib zlib-devel openssl openssl-devel pcre pcre-devel

./configure --with-http_stub_status_module

make

make install  

    安装完成后编辑其默认配置文件:vi /usr/local/nginx/conf/nginx.conf,下面给出了一个典型的方向代理和负载均衡的配置如下:

worker_processes  8;

worker_rlimit_nofile   51200;

events {

    use epoll;

    worker_connections  51200;

}

 

http {

    include       mime.types;

    default_type  application/octet-stream;

    sendfile        on;

    keepalive_timeout  65;

   

    upstream php_server_pool {

       server 174.36.222.47:80   weight=5 max_fails=2 fail_timeout=30s;

       server 174.37.159.247:80  weight=5 max_fails=2 fail_timeout=30s;

    }

   

    # 1.domain1.com

    server

    {

           listen       80;

           server_name  .domain1.com;

           index index.html index.php;

           root /home/www/domain1.com_W4bwsyQm1UoioY8jzjIE/wwwroot;

        location / {

            root /home/www/domain1.com_W4bwsyQm1UoioY8jzjIE/wwwroot;

            index  index.html index.htm;

        }

 

        location ~ \.(php)$ {

             proxy_next_upstream  http_502 http_504  error timeout  invalid_header;

             proxy_pass http://php_server_pool;

             proxy_set_header Host $host;

             proxy_set_header X-Forwarded-For $remote_addr;

        }

    }

   

    # 2.domain2.com

    server

    {

       listen       80;

           server_name  .domain2.com;

           index index.html index.htm index.php;

           root /home/www/domain2.com_ahRfQfxEYYR0LQoaNWrY/wwwroot;

        location / {

            root /home/www/domain2.com_ahRfQfxEYYR0LQoaNWrY/wwwroot;

            index  index.html index.htm;

        }

 

        location ~ \.(php)$ {

             proxy_next_upstream  http_502 http_504  error timeout  invalid_header;

             proxy_pass http://php_server_pool;

             proxy_set_header Host $host;

             proxy_set_header X-Forwarded-For $remote_addr;

        }

    }

 

}

    在上述配置中采用了将静态文件放在代理服务器上,将动态的内容方向代理到php_server_pool 中去处理,其中php_server_pool 的两个IP各均衡50%的负载。

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

4 内容分发

    在我们部署了大量的节点之后,网站内容如何分发出去,将成为一个非常重要的工作内容,下面我们两种方式介绍内容分发的做法,在实施过程中,有时需要将两种方式结合起来运用。

41 网站管理系统实现内容分发

    在访问节点不是很多的情况下,我们可以考虑在网站管理系统中集成内容分发模块。内容分发考虑到通用性,我采用PHPFTP函数来实现。代码实现如下:

    配置文件:config.php

<?php

$ftp_server = "173.234.184.76";

$aExt = explode("|","/admin|/install|/log|/templates_c|/ftp");

$bExt = explode("|","install.php|robots.txt");

?>

    配置文件中指定FTP服务器,从而限制用户输入完整的FTP信息将网站代码窃取的威胁。同时在配置文件中指定不需要分发的文件夹和文件的列表。

    分发主文件:install.php

<?php

include_once './install/config.php';

 

function getMicroTime()

{

    $time = microtime();

    list($msec, $sec) = explode(" ", $time);

    return (float)$sec+(float)$msec;

}

 

function getRunTime($start, $end)

{

    return $end - $start;

 

}

 

if ($_GET['action']=='start'){

 

$ftp_user_name = $_POST['ftp_user'];

$ftp_pass = $_POST['ftp_pass'];

 

set_time_limit(0);

 

$startTime = getMicroTime();

 

$conn_id = ftp_connect ( $ftp_server ) or die ("can not connect to the server");

ftp_login ( $conn_id , $ftp_user_name , $ftp_pass ) or die ("can not login");

      

if (@ftp_chdir($conn_id, "/log")) {

           echo "<font color=red>文件夹 &nbsp;</font>[log] 已存在,跳过...<br/><br/>";

} else {

       ftp_mkdir($conn_id, "./log");

       ftp_site($conn_id,"CHMOD 777 /log");

}

 

if (@ftp_chdir($conn_id, "/templates_c")) {

           echo "<font color=red>文件夹 &nbsp;</font>[templates_c] 已存在,跳过...<br/><br/>";

} else {

       ftp_mkdir($conn_id, "./templates_c");

       ftp_site($conn_id,"CHMOD 777 /templates_c");

}

 

//ftp_chmod($conn_id,"777","templates_c");

//print_r (ftp_raw($conn_id,"SITE CHMOD 777 /templates_c"));

 

$id = 0;

$DOCUMENT_ROOT = $_SERVER["DOCUMENT_ROOT"];

//echo $DOCUMENT_ROOT;

//exit;

 

function traverseFile($dir){

       global $aExt ;

       global $bExt ;

        global $conn_id ;

        global $id;

        global $DOCUMENT_ROOT;

        //echo "id: ".++$id."\n";

       

       if(is_dir($dir)){

              if ($dh = opendir($dir)) {

                     while (($file= readdir($dh)) !== false){ //读取文件夹里面的所有东西

                            $nowfilepath=$dir.'/'.$file;//当前的目录

                            //var_dump($nowfilepath);

                            if(is_dir($nowfilepath)){

                                   //echo "file=".substr($nowfilepath,1,strlen($nowfilepath)-1)."|";

                                   if($file!='.' and $file!='..' and (!in_array(substr($nowfilepath,1,strlen($nowfilepath)-1),$aExt))){

                                          echo "<br/><br/><font color=red>文件夹 &nbsp;</font>[".$dir.'/'.$file."] ";

                                          //var_dump($nowfilepath);

                                          if (@ftp_chdir($conn_id, "/".$nowfilepath)) {

                                                     echo "<font color=red>已存在,跳过!</font><br/><br/>";

                                          } else {

                                                 ftp_chdir($conn_id,"/".$dir);

                                                 ftp_mkdir($conn_id, $file);

                                                 echo "<font color=blue>已创建!</font><br/><br/>";

                                          }

 

                                          traverseFile($nowfilepath); //递归

                                   }

                            }else{ //不是文件夹时,直接输出文件

                                   if(!in_array($file,$bExt)){

                                          echo "<font color=blue>文件:</font>".$dir.'/'.$file;

                                          if (ftp_size($conn_id,"/".$dir."/".$file)>0)

                                          {

                                                 echo " <font color=red>已存在,跳过!</font><br/>";

                                          }else{

                                                 ftp_chdir($conn_id,"/".$dir);

                                                 //echo ftp_pwd($conn_id)."<br/>";

                                                 ftp_put($conn_id, $file, $DOCUMENT_ROOT.$dir.'/'.$file, FTP_BINARY);

                                                 echo " <font color=blue>已上传!</font> <br/>";

                                          }

                                          flush();

                                   }

                            }

                     }

                     closedir($dh);

              }

       }

}

 

 

traverseFile(".");

 

$endTime = getMicroTime();

 

echo "完成!耗时".round(getRunTime($startTime, $endTime),4).". <br />";

 

}else{

       echo '

       <form method="POST" action="install.php?action=start">

      <p>FTP用户名:<input type="text" name="ftp_user" size="20"></p>

      <p>FTP&nbsp; 码:<input type="text" name="ftp_pass" size="20"></p>

      <p><input type="submit" value="开始上传" name="B1"></p>

       </form>

       ';

}

?>

    分发模块主要是根据本地文件的内容递归进行文件的FTP上传操作。同时可以根据不同的网站系统设置一些初始化的工作,比如创建日志文件夹并设置777权限。

42 使用同步软件实现内容分发

    使用网站管理系统进行分发适合节点比较少的情况,用户自主控制的灵活性非常高,但如果蜘蛛节点非常多,手工分发效率非常低下,在这种情况下,我们采用RSYNC同步软件进行自动同步。

    下面是在CENTOS5RSYNC的主从配置。

安装:

(一)yum install -y rsync xinetd

(二)rpm -ql rsync就可以看到rsync安装了哪些文件。

(三)编辑/etc/xinetd.d/rsync文件,修改disable=no,然后重启xinetd:

(四)/etc/init.d/xinetd restart

(五)创建文件 /etc/rsyncd.conf 内容如下:

pid file = /var/run/rsyncd.pid

port = 873

uid = root

gid = root

use chroot = yes

read only = yes

hosts allow=68.68.99.184/255.255.255.0 216.18.195.23/255.255.255.0

hosts deny=*

 

max connections = 5

motd file = /etc/rsyncd.motd

log file = /var/log/rsyncd.log

log format = %t %a %m %f %b

syslog facility = local3

timeout = 300

[www]

path = /home/pics/www

list=yes

ignore errors

auth users = pics

secrets file = /etc/rsyncd.secrets

comment = pics www

(六)创建文件 /etc/rsyncd.motd 内容随便写即可

(七)创建文件 /etc/rsyncd.secrets 内容是用户名和密码,比如:

syncuser: mypassword

然后执行如下命令:

chmod 700 /etc/rsyncd.secrets

这样就配置好了,在客户端就可以用rsync命令了,比如:

(八)注意:/etc/rsync.password需要600权限。rsync://pics@96.44.137.8/www这个后面的www就是服务器端文件 /etc/rsyncd.conf包含目录的括号内的内容

chmod 600 /etc/rsyncd.password

rsync rsync://syncuser@216.18.195.23/

rsync --password-file=/etc/rsync.password rsync://syncuser@216.18.195.23/www  /home/pics/www --recursive --times --links --hard-links --delete –av

将从服务器的命令写成一个脚本进行手工同步或者加进cron从而自动执行。

 

 

 

 

 

 

 

 

 

 

 

 

 

 

5 业务模块分离

51 生成静态实现动静分离

    通过内容分发将静态文件分发到不同的节点,从而将访问分散是大幅度提高系统性能的有效手段,但是不是所有的系统都能支持生成静态。为了解决这个问题,我们根据流行的电子商务网站管理系统设计了一个通用的静态生成模块,来满足动静分离的需要。下面是OSC系统的实现。

1index.html

<p><a href="createindex.php">生成首页</a>

<p><a href="createcategories.php">生成产品目录</a>

<p><a href="createproduct.php">生成产品详细页</a>

2config.php

<?php

$domain = "domain.com";

?>

3createindex.php

<?php

//生成首页文件

//空间开启allow_url_fopen。方法:编辑php.ini,设置allow_url_fopen = Onallow_url_fopen关闭时fopenfile_get_contents都不能打开远程文件

function getchar($SearchString,$SearchChar1,$SearchChar2)

{

       $mySearchStringLen = strlen($SearchString);

       $mySearchChar1Len = strlen($SearchChar1);

       $mySearchChar2Len = strlen($SearchChar2);

       $myCharpos1 = strpos($SearchString,$SearchChar1);

       $myCharpos2 = strpos($SearchString,$SearchChar2);

       $getchar = substr($SearchString,$myCharpos1+$mySearchChar1Len,$myCharpos2-$myCharpos1-$mySearchChar1Len);    

       return $getchar;

}

 

//error handler function

function customError($errno, $errstr, $errfile, $errline)

 {

 echo "<b>Custom error:</b> [$errno] $errstr<br />";

 echo " Error on line $errline in $errfile<br />";

 echo "Ending Script";

 die();

 }

 

//set error handler

set_error_handler("customError");

 

include_once "config.php";

$url = "http://www.".$domain."/index.php";

$htmlcontent = file_get_contents($url);

 

//处理分类链接

preg_match_all( '/\<a href="http:\/\/www.'.$domain.'\/Categories.php(.*?)\<\/a\>/s',$htmlcontent, $blocks );

//print_r($blocks);

foreach( $blocks[0] as $block )

{

       //链接样本:<a href="http://www.domain.com/Categories.php?cPath=63_64&osCsid=163irov54l1sdame7eaiq8qo45">UGG Classic Tall Boots 5815</a>

       $Categories_url = getchar($block,'<a href="','">');

       $Categories_name = getchar($block,'">','</a>');

       if ($Categories_name=='All Products'){

              $cPath = "_".getchar($block,'cPath=','?osCsid=');

       }else{

              $cPath = "";

       }

       $Categories_name = str_replace(" ","_",$Categories_name);

       //echo 'Categories_url='.$Categories_url.'|Categories_name='.$Categories_name.'<br>';

       //$htmlcontent = str_replace($Categories_url,"http://www.domain.com/".$Categories_name.$cPath.".html",$htmlcontent);

       $htmlcontent = str_replace($Categories_url,"/".$Categories_name.$cPath.".html",$htmlcontent);

}

 

//处理产品链接

//http://www.domain.com/product_info.php?products_id=545&osCsid=70sdl9m1kanqu2ad6166o74sk1

preg_match_all( '/\<a href="http:\/\/www.'.$domain.'\/product_info.php(.*?)\<\/a\>/s',$htmlcontent, $blocks );

//print_r($blocks);

//exit;

$product_name = "";

foreach( $blocks[0] as $block )

{

       //链接样本: <a href="http://www.domain.com/product_info.php?products_id=545&osCsid=m6adoscq20qqm4o0olm68jmsg4"><img alt="UGG 5818 Classic Tall Roxy Boots Sand" src="ImgsZoom.after.php?s=images/yuyouipoui9888999999.jpg&w=90&h=90&f=1&q=100" title="UGG 5818 Classic Tall Roxy Boots Sand" /></a>

       $product_url = getchar($block,'<a href="','">');

       $product_name_new = getchar($block,'alt="','" title=');

       if ( substr($product_name_new,0,3)== "ef=" ){

              if (strpos($product_name_new,"buy")>0){

                     $product_name_new = $product_name;

              }else{

                     $product_name_new = getchar($block,'">','</a>');

              }

       }elseif (strpos($product_name_new,"src")>0){

              //echo strpos($product_name_new,"src");

              //echo "src-".$product_name_new."<br>";

              $product_name_new = substr($product_name_new,0,strpos($product_name_new,"src")-4);

              //echo 'Categories_url='.$Categories_url.'|Categories_name='.$Categories_name.'<br>';

              //$htmlcontent = str_replace($Categories_url,"http://www.domain.com/".$Categories_name.$cPath.".html",$htmlcontent);

       }

       //echo "product_name=".$product_name_new."<br>";

       $product_name = str_replace(" ","_",$product_name_new);

       $htmlcontent = str_replace($product_url,"/".$product_name.".html",$htmlcontent);

}

 

//exit;

//在测试空间上可用,正式程序中请删除

//$htmlcontent = str_replace('<base href="http://www.'.$domain.'/"></base>','<base href="http://'.$domain.'.l4.i35.cn/"></base>',$htmlcontent);

 

 

//echo $htmlcontent;

$fp = fopen("../index.html","w");

fwrite($fp,$htmlcontent);

fclose($fp);

echo "<p>create index.html succ!";

echo "<p><a href='index.html'>返回</a>";

?>

4createcategories.php

<?php

//error handler function

function customError($errno, $errstr, $errfile, $errline)

 {

 echo "<b>Custom error:</b> [$errno] $errstr<br />";

 echo " Error on line $errline in $errfile<br />";

 echo "Ending Script";

 //die();

 }

 

function getchar($SearchString,$SearchChar1,$SearchChar2)

{

       $mySearchStringLen = strlen($SearchString);

       $mySearchChar1Len = strlen($SearchChar1);

       $mySearchChar2Len = strlen($SearchChar2);

       $myCharpos1 = strpos($SearchString,$SearchChar1);

       $myCharpos2 = strpos($SearchString,$SearchChar2);

       $getchar = substr($SearchString,$myCharpos1+$mySearchChar1Len,$myCharpos2-$myCharpos1-$mySearchChar1Len);    

       return $getchar;

}

 

function createcategories($cPath,$categories_name)

{

       global $domain;

      //echo "<b>cPath:</b> $cPath<br />";

      //echo "<b>categories_name:</b> $categories_name<br />";

      $url = "http://www.".$domain."/Categories.php?cPath=".$cPath;

      $htmlcontent = file_get_contents($url);

 

preg_match_all( '/\<a href="http:\/\/www.'.$domain.'\/Categories.php(.*?)\<\/a\>/s',$htmlcontent, $blocks );

//print_r($blocks);

foreach( $blocks[0] as $block )

{

       //链接样本:<a href="http://www.domain.com/Categories.php?cPath=63_64&osCsid=163irov54l1sdame7eaiq8qo45">UGG Classic Tall Boots 5815</a>

       $Categories_url = getchar($block,'<a href="','">');

       $Categories_name = getchar($block,'">','</a>');

       if ($Categories_name=='All Products'){

              $cPath = "_".getchar($block,'cPath=','?osCsid=');

       }else{

              $cPath = "";

       }

       $Categories_name = str_replace(" ","_",$Categories_name);

       //echo 'Categories_url='.$Categories_url.'|Categories_name='.$Categories_name.'<br>';

       //$htmlcontent = str_replace($Categories_url,"http://www.domain.com/".$Categories_name.$cPath.".html",$htmlcontent);

       $htmlcontent = str_replace($Categories_url,"/".$Categories_name.$cPath.".html",$htmlcontent);

}

 

 

//处理产品链接

//http://www.domain.com/product_info.php?products_id=545&osCsid=70sdl9m1kanqu2ad6166o74sk1

preg_match_all( '/\<a href="http:\/\/www.'.$domain.'\/product_info.php(.*?)\<\/a\>/s',$htmlcontent, $blocks );

//print_r($blocks);

//exit;

$product_name = "";

foreach( $blocks[0] as $block )

{

       //链接样本: <a href="http://www.domain.com/product_info.php?products_id=545&osCsid=m6adoscq20qqm4o0olm68jmsg4"><img alt="UGG 5818 Classic Tall Roxy Boots Sand" src="ImgsZoom.after.php?s=images/yuyouipoui9888999999.jpg&w=90&h=90&f=1&q=100" title="UGG 5818 Classic Tall Roxy Boots Sand" /></a>

       $product_url = getchar($block,'<a href="','">');

       $product_name_new = getchar($block,'alt="','" title=');

       if ( substr($product_name_new,0,3)== "ef=" ){

              if (strpos($product_name_new,"buy")>0){

                     $product_name_new = $product_name;

              }else{

                     $product_name_new = getchar($block,'">','</a>');

              }

       }elseif (strpos($product_name_new,"src")>0){

              //echo strpos($product_name_new,"src");

              //echo "src-".$product_name_new."<br>";

              $product_name_new = substr($product_name_new,0,strpos($product_name_new,"src")-2);

              //echo 'Categories_url='.$Categories_url.'|Categories_name='.$Categories_name.'<br>';

              //$htmlcontent = str_replace($Categories_url,"http://www.domain.com/".$Categories_name.$cPath.".html",$htmlcontent);

       }

       //echo "product_name=".$product_name_new."<br>";

       $product_name = str_replace(" ","_",$product_name_new);

       $htmlcontent = str_replace($product_url,"/".$product_name.".html",$htmlcontent);

}

 

 

       //在测试空间上可用,正式程序中请删除

       //$htmlcontent = str_replace('<base href="http://www.'.$domain.'/"></base>','<base href="http://'.$domain.'.l4.i35.cn/"></base>',$htmlcontent);

 

     

      $fp = fopen("../".$categories_name.".html","w");

       fwrite($fp,$htmlcontent);

       fclose($fp);

       echo "create ".$categories_name.".html succ!<br>";

       ob_flush();

       flush();

}

 

include_once 'config.php';

set_time_limit(0);

ob_flush();

flush();         //将输出发送给客户端浏览器

//set error handler

//set_error_handler("customError");

      require('includes/application_top.php');

     

       $qq="select c.categories_id, cd.categories_name, c.parent_id from " . TABLE_CATEGORIES . " c, " . TABLE_CATEGORIES_DESCRIPTION . " cd where c.parent_id = '0' and c.categories_id = cd.categories_id and cd.language_id='" . (int)$languages_id ."' order by c.sort_order  asc";

       $category_query = tep_db_query($qq);

       $number = tep_db_num_rows($category_query);

       while($category = tep_db_fetch_array($category_query)){

              $id=$category['categories_id'];

              $image=$category['categories_image'];

              $paress="SELECT count(*) FROM  categories WHERE parent_id =$id ";

              $paress_query = tep_db_query($paress);

              $parecc = tep_db_fetch_array($paress_query);

              $num=$parecc['count(*)'];

              if($num>0){

 

                     $cate_de="select c.categories_id, cd.categories_name, c.parent_id from " . TABLE_CATEGORIES . " c, " . TABLE_CATEGORIES_DESCRIPTION . " cd where c.parent_id = $id and c.categories_id = cd.categories_id and cd.language_id='" . (int)$languages_id ."' order by sort_order, cd.categories_name";

                     $cate_de_query = tep_db_query($cate_de);

                     while($de = tep_db_fetch_array($cate_de_query)){

                            createcategories($category['categories_id'] . '_' . $de['categories_id'],str_replace(" ","_",$de['categories_name']));

                     }

                     createcategories($category['categories_id'],"All_Products"."_".$category['categories_id']);

              }else{

                     createcategories($category['categories_id'],str_replace(" ","_",$de['categories_name']));

              }

       }

       echo 'all categories create succ!';

       echo "<p><a href='index.html'>返回</a>";

?>

5createproduct.php

<?php

//error handler function

function customError($errno, $errstr, $errfile, $errline)

 {

 echo "<b>Custom error:</b> [$errno] $errstr<br />";

 echo " Error on line $errline in $errfile<br />";

 echo "Ending Script";

 //die();

 }

 

function getchar($SearchString,$SearchChar1,$SearchChar2)

{

       $mySearchStringLen = strlen($SearchString);

       $mySearchChar1Len = strlen($SearchChar1);

       $mySearchChar2Len = strlen($SearchChar2);

       $myCharpos1 = strpos($SearchString,$SearchChar1);

       $myCharpos2 = strpos($SearchString,$SearchChar2);

       $getchar = substr($SearchString,$myCharpos1+$mySearchChar1Len,$myCharpos2-$myCharpos1-$mySearchChar1Len);

       return $getchar;

}

 

function product($products_id,$products_name)

{

       global $domain;

      //echo "<b>cPath:</b> $cPath<br />";

      //echo "<b>categories_name:</b> $categories_name<br />";

      $url = 'http://www.'.$domain.'/product_info.php?products_id='.$products_id;

      $htmlcontent = file_get_contents($url);

 

preg_match_all( '/\<a href="http:\/\/www.'.$domain.'\/Categories.php(.*?)\<\/a\>/s',$htmlcontent, $blocks );

//print_r($blocks);

foreach( $blocks[0] as $block )

{

       //链接样本:<a href="http://www.domain.com/Categories.php?cPath=63_64&osCsid=163irov54l1sdame7eaiq8qo45">UGG Classic Tall Boots 5815</a>

       $Categories_url = getchar($block,'<a href="','">');

       $Categories_name = getchar($block,'">','</a>');

       if ($Categories_name=='All Products'){

              $cPath = "_".getchar($block,'cPath=','?osCsid=');

       }else{

              $cPath = "";

       }

       $Categories_name = str_replace(" ","_",$Categories_name);

       //echo 'Categories_url='.$Categories_url.'|Categories_name='.$Categories_name.'<br>';

       //$htmlcontent = str_replace($Categories_url,"http://www.domain.com/".$Categories_name.$cPath.".html",$htmlcontent);

       $htmlcontent = str_replace($Categories_url,"/".$Categories_name.$cPath.".html",$htmlcontent);

}

 

//处理产品链接

//http://www.uggsonsaleusa.com/product_info.php?products_id=545&osCsid=70sdl9m1kanqu2ad6166o74sk1

preg_match_all( '/\<a href="http:\/\/www.'.$domain.'\/product_info.php(.*?)\<\/a\>/s',$htmlcontent, $blocks );

//print_r($blocks);

//exit;

$product_name = "";

foreach( $blocks[0] as $block )

{

       //链接样本: <a href="http://www.domain.com/product_info.php?products_id=545&osCsid=m6adoscq20qqm4o0olm68jmsg4"><img alt="UGG 5818 Classic Tall Roxy Boots Sand" src="ImgsZoom.after.php?s=images/yuyouipoui9888999999.jpg&w=90&h=90&f=1&q=100" title="UGG 5818 Classic Tall Roxy Boots Sand" /></a>

       $product_url = getchar($block,'<a href="','">');

       $product_name_new = getchar($block,'alt="','" title=');

       if ( substr($product_name_new,0,3)== "ef=" ){

              if (strpos($product_name_new,"buy")>0){

                     $product_name_new = $product_name;

              }else{

                     $product_name_new = getchar($block,'">','</a>');

              }

       }elseif (strpos($product_name_new,"src")>0){

              //echo strpos($product_name_new,"src");

              //echo "src-".$product_name_new."<br>";

              $product_name_new = substr($product_name_new,0,strpos($product_name_new,"src")-4);

              //echo 'Categories_url='.$Categories_url.'|Categories_name='.$Categories_name.'<br>';

              //$htmlcontent = str_replace($Categories_url,"http://www.domain.com/".$Categories_name.$cPath.".html",$htmlcontent);

       }

       //echo "product_name=".$product_name_new."<br>";

       $product_name = str_replace(" ","_",$product_name_new);

       $htmlcontent = str_replace($product_url,"/".$product_name.".html",$htmlcontent);

}

 

 

       //在测试空间上可用,正式程序中请删除

       //$htmlcontent = str_replace('<base href="http://www.'.$domain.'/"></base>','<base href="http://'.$domain.'.l4.i35.cn/"></base>',$htmlcontent);

 

     

      $fp = fopen("../".$products_name.".html","w");

       fwrite($fp,$htmlcontent);

       fclose($fp);

       echo "create ".$products_name.".html succ!<br>";

       ob_flush();

       flush();

}

include_once 'config.php';

set_time_limit(0);

ob_flush();

flush();         //将输出发送给客户端浏览器

//set error handler

//set_error_handler("customError");

 

  require('includes/application_top.php');

 

  $new_products_query = tep_db_query("select distinct p.products_id,pd.products_name from " . TABLE_PRODUCTS . " p, " . TABLE_PRODUCTS_DESCRIPTION . " pd WHERE  p.products_id = pd.products_id AND  pd.products_name <> '' order by p.products_date_added desc ");

 

  while ($new_products = tep_db_fetch_array($new_products_query)) {

      product($new_products['products_id'],str_replace(" ","_",$new_products['products_name']));

  }

 

  echo 'all products create succ!';

  echo "<p><a href='index.html'>返回</a>";

?>

    上述文件中包含的application_top.php文件是OSC系统标准的文件,是初始化数据库连接及通用函数,这里仅仅是调用,所以这里没有给出相应的代码,我们只需在系统中包含就可以实现我们需要的功能。

52 按业务模块进行分离

    通过动静分离已经大幅度降低WEB服务器的负担,但对于一些要求比较苛刻的系统。我们可以基于二级域名将不同的业务模块分离到不同的服务器上,从而实现内部管理和外部访问的分离,图片服务器和业务逻辑服务器的分离。通过一系列的功能划分,达到业务的高度伸缩性和扩展性。典型的例子是将站点所有的图片分配独立的IMG.DOMAIN.COM域名。将后台管理分配单独的MANAGE.DOMAIN.COM,而在后台管理中用户上传的图片按照上述PHPFTP函数进行实时分发到图片服务器上。这样即使网站被攻击瘫痪,内部业务人员仍然可以登录后台管理服务器进行业务的处理。

 

 

 

 

 

 

 

 

 

 

 

 

 

6 健康检查

61 前端运行状态监控

Nginx 监控

需要注意的是,Nginx默认安装不包含状态模块stub_status,所以,在编译Nginx的时候,需要添加以下参数:

--with-http_stub_status_module

一旦包含stub_status模块后,我们就可以在配置文件nginx.conf中开启状态页面:

http {

    server {

        listen       80;

        server_name  localhost;

        location / {

            root   html;

            index  index.html index.htm;

        }

        location /nginx-status {

            stub_status on;

            access_log  off;

        }

    }

}

以上配置文件中,我们实际增加的部分是:

        location /nginx-status {

            stub_status on;

            access_log  off;

        }

同样,假如Nginx所在服务器的IP10.0.0.1,同时指向它的域名为www.domain.com,这样一来,Nginx的状态页面便是:

http://10.0.0.1/nginx-status

或者

http://www.domain.com/nginx-status

同样,建议您将以上示例中的nginx-status修改为其它字符串。

另外,Nginxstub_status也支持授权IP的配置,比如我们可以授权仅在下面的IP地址可以查看状态:

60.195.252.106

60.195.249.83

62 后端运行状态监控

    后端的健康检查在NGINX的配置文件中指定,例如:

        location ~ \.(php)$ {

             proxy_next_upstream  http_502 http_504  error timeout  invalid_header;

             proxy_pass http://php_server_pool;

             proxy_set_header Host $host;

             proxy_set_header X-Forwarded-For $remote_addr;

        }

    如果后端服务器出现502504错误,则自动转向下一个地址池中的服务器,同时后端服务器也可以采用简单网络管理协议进行CPU,内存等的监控。以下介绍在CENTOS系统中开启SNMP的方法。

编译和安装

    首先我们需要下载Net-SNMP的源代码,选择当前最新的版本5.4.2.1,地址如下:

http://sourceforge.net/projects/net-snmp/files/net-snmp/5.4.2.1/

    接下来对下载的源代码包进行解压缩,如下:

# tar xzvf net-snmp-5.4.2.1.tar.gz

    然后通过configure来生成编译规则,如下:

# cd net-snmp-5.4.2.1

# ./configure --prefix=/usr/local/snmp --with-openssl=/usr/ --with-mib-modules=ucd-snmp/diskio

    注意,以上的

--with-mib-modules=ucd-snmp/diskio

    选项,可以让服务器支持磁盘I/O监控。

    接下来,开始编译和安装:

# make

# make install

    到现在为止,我们已经有了可以运行的SNMP代理程序,它位于/usr/local/snmp/sbin/snmpd,在启动它之前,我们还要进行一些必要的设置。

设置安全的验证方式

    SNMP代理程序暴露给网络上的所有主机是很危险的,为了防止其它主机访问你的SNMP代理程序,我们需要在SNMP代理程序上加入身份验证机制。 SNMP支持不同的验证机制,这取决于不同的SNMP协议版本,监控宝目前支持v2cv3两个版本,其中v2c版本的验证机制比较简单,它基于明文密码和授权IP来进行身份验证,而v3版本则通过用户名和密码的加密传输来实现身份验证,我们建议使用v3,当然,只要按照以下的介绍进行配置,不论是v2c 版本还是v3版本,都可以保证一定的安全性,你可以根据情况来选择。

    注意一点,SNMP协议版本和SNMP代理程序版本是两回事,刚才说的v2cv3是指SNMP协议的版本,而Net-SNMP是用来实现SNMP协议的程序套件,目前它的最新版本是刚才提到的5.4.2.1

v2c

    先来看如何配置v2c版本的SNMP代理,我们来创建snmpd的配置文件,默认情况下它是不存在的,我们来创建它,如下:

# vi /usr/local/snmp/share/snmp/snmpd.conf

    然后我们需要创建一个只读帐号,也就是read-only community,在snmpd.conf中添加以下内容:

    rocommunity jiankong 60.195.249.83

    注意,这里的“rocommunity”表示这是一个只读的访问权限,监控只可以从你的服务器上获取信息,而不能对服务器进行任何设置。

    紧接着的“jiankong”相当于密码,很多平台喜欢使用“public”这个默认字符串。这里的“jiankong”只是一个例子,你可以设置其它字符串作为密码。

    最右边的“60.195.249.83”代表指定的监控点IP,这个IP地址是监控专用的监控点,这意味着只有监控有权限来访问你的SNMP代理程序。

    所以,以上这段配置中,只有“jiankong”是需要你进行修改的,同时在监控宝上添加服务器的时候,需要提供这个字符串。

v3

    当然,我们建议您使用v3版本来进行身份验证。对于一些早期版本的Linux分发版,其内置的SNMP代理程序可能并不支持v3,所以我们建议您按照前边介绍的方法,编译和安装最新的Net-Snmp

    v3支持另一种验证方式,需要创建一个v3的帐号,我们同样修改以下配置文件:

 # vi /usr/local/snmp/share/snmp/snmpd.conf

    然后添加一个只读帐号,如下:

rouser jiankong auth

 

    可以看到,在v3中,“rouser”用于表示只读帐号类型,随后的“jiankong”是指定的用户名,后边的“auth”指明需要验证。

    接下来,我们还要添加“jiankong”这个用户,这就是v3中的特殊机制,我们打开以下配置文件:

# vi /var/net-snmp/snmpd.conf

    这个文件会在snmpd启动的时候被自动调用,我们需要在它里边添加创建用户的指令,如下:

    createUser jiankong MD5 mypassword

    这行配置的意思是创建一个名为“jiankong”的用户,密码为“mypassword”,并且用MD5进行加密传输。这里要提醒的是:

    密码至少要有8个字节

    这是SNMP协议的规定,如果小于8个字节,通信将无法进行。

    值得注意的是,一旦snmpd启动后,出于安全考虑,以上这行配置会被snmpd自动删除,当然,snmpd会将这些配置以密文的形式记录在其它文件中,重新启动snmpd是不需要再次添加这些配置的,除非你希望创建新的用户。

    以上配置中的用户名、密码和加密方式,在监控添加服务器的时候需要添加。

启动SNMP代理程序

    经过配置后,现在可以启动snmpd,如下:

    /usr/local/snmp/sbin/snmpd

    如果要关闭,则可以直接kill这个进程,如下:

    killall -9 snmpd

    增强的安全机制

    有了以上的验证机制,你就可以放心的使用SNMP代理了。但是,如果你的SNMP代理程序版本较低,可能会有一些别有用心的破坏者利用一些固有的漏洞进行破坏,比如发送较长的数据导致SNMP代理程序内存泄漏或者拒绝服务等,为此,你还可以使用防火墙(iptables)来进行增强的安全过滤。

    Linux中,我们用iptables来实现防火墙,一般情况下,除了流入指定端口的数据包以外,我们应该将其它流入的IP数据包抛弃。你可能已经配置了一定的防火墙规则,那么只要增加针对SNMP的规则即可。

 

    SNMP代理程序默认监控在udp161端口,为你的iptables增加以下规则:

    iptables -A INPUT -i eth0 -p udp -s 60.195.249.83 --dport 161 -j ACCEPT

    以上设置中假设服务器外网网卡是eth0,你可以根据实际情况来修改。

    这样一来,只有监控的专用监控器可以发送UDP数据包到你的服务器的161端口,与SNMP代理程序进行通信。

 

7 系统安全

71 数据库安全

    在电子商务系统中,数据库是关键的关键,如果保证业务数据不丢失,除了做好备份计划外,我们还需要将数据库进行实时的同步。

    MySQLReplication功能可以自动同步主MySQL服务器的更新到若干个辅MySQL服务器上,这个功能能把MySQL的数据实时分布到多台机器上,提交了MySQL的数据安全性。

    配置MySQL Replication并不是个简单的工作,如果配置的不好,回导致MySQL的同步性能不好,或者不能同步,甚至导致主辅服务器的数据不一致。

    下面主服务器为master,辅助服务器为slave

    master的配置

    第一步保证master能单机正常工作,略。

    master上创建一个MySQL用户,这个用户专门用于Replication

    grant replication slave on *.* to 'repluser'@'%' identified by 'mypassword';

 

    编辑MySQL的配置文件,允许log-bin,并且给master分配一个ID

[mysqld]

skip-name-resolve

server-id=10

log-bin=mysql-bin

sync_binlog=1

#innodb_flush_logs_at_trx_commit=1

#innodb_support_xa=1

slave的配置

配置ID

[mysqld]

server-id=20

log_bin = mysql-bin

relay_log = mysql-relay-bin

skip_slave_start

log_slave_updates = 1

read_only

skip-name-resolve

replicate-ignore-db=information_schema

replicate-ignore-db=horde_groupware

replicate-ignore-db=kloxo

replicate-ignore-db=mysql

replicate-ignore-db=popuser

replicate-ignore-db=roundcubemail

replicate-ignore-db=vpopmail
   
同步数据

    master上把数据导出,并记录当前数据位置。用一个用户连接mysql并运行:

flush tables with read lock;

show master status;

显示:file:mysql-bin.000003

position:18874

/usr/bin/mysql -uuggonboots -pwrkOSIYOQ2

    然后该连接不要退出,否则read lock就失效了,记录下当前日志的文件名和位置。在另外一个窗口运行如下命令导出数据:

mysqldump -uroot -prRWJS0ZFME1M  test |gzip -c > db.sql.gz

   然后把数据文件拷贝到slave上,解压缩:

gunzip db.sql.gz

MySQL导入:

source db.sql;

    这时候slave上的数据已经同步到master的导出时刻的数据了,下面就启动自动同步的线程就可以了:

change master to master_host='96.44.137.8', master_user='repluser', master_password=' mypassword ',master_log_file='mysql-bin.000004',master_log_pos=142319;

show slave status;

start slave;

show slave status;

    从上面的show slave status命令的输出可以看到,IO线程和SQL线程都开始工作了。过几分钟后比较一下slavemaster上的日志文件及其位置,应该就是一样的了。

    注意事项

    应用程序不要使用数据库的root用户,一定要创建普通用户供应用程序使用,因为root用户可以在slave上进行写操作,容易导致数据不一致。

grant replication slave on *.* to 'repluser'@'%' identified by 'mypassword';

mysqldump -uroot -prRWJS0ZFME1M  --all-databases |gzip -c > db.sql.gz

unlock tables;

72 防火墙技术

对于DDOS攻击,首先需要提升TCP连接能力

vi /etc/sysctl.conf

在最后增加三行

net.ipv4.tcp_max_syn_backlog = 2048

net.ipv4.tcp_synack_retries = 1

net.ipv4.tcp_syn_retries = 1

通过实际的工作经验,我总结出了一个比较有效的规则:

#!/bin/bash

modprobe ipt_recent ip_list_tot = 16384

iptables -N SYN_FLOODING

iptables -t filter -F

iptables -A INPUT

#=========================================

iptables -A INPUT -p tcp --syn --dport 80 -mlimit --limit 1/m --limit-burst 300 -j ACCEPT

iptables -A INPUT -p tcp --syn --dport 80 -j SYN_FLOODING

#=========================================

iptables -A SYN_FLOODING -p tcp --syn --dport 80 -m recent --name SYN_FLOOD --update --second 120 --hitcount 1 -j ACCEPT

iptables -A SYN_FLOODING -p tcp --syn --dport 80 -m recent --name SYN --set

iptables -A SYN_FLOODING -p tcp --syn -j DROP

73 安全升级和维护

    对于存在大量节点的蜘蛛系统来说,如果进行系统的升级和维护是一个很大问题。为此我们开发了一套系统指令下发系统来实现通过WEB端下发LINUX的指令,从而完成任何我们需要完成的功能。比如一台服务器受到攻击,我们检测到攻击来源,在所有的蜘蛛系统中我们都可以将他屏蔽掉。

    接受并执行指令的脚本:

#!/bin/bash

LANG=C

id=`awk '{a=$0} END {print a}' cron.log|cut -d ":" -f 1`

ip=`/sbin/ifconfig -a|grep inet|grep -v 127.0.0.1|grep -v inet6|awk '{print $2}'|tr -d "addr:"`

TEST=`php /usr/local/ddos/cron.php $id $ip`

line=`echo $TEST|cut -d ":" -f 1`

if ((line==0));then

   echo "nothing"

else

   echo $TEST >> /usr/local/ddos/cron.log

   line=`awk '{a=$0} END {print a}' /usr/local/ddos/cron.log|cut -d ":" -f 2`

   $line

fi

相应的PHP文件,实现数据检索等功能cron.php

<?php

if($argc==3)

{

        $id = $argv[1];

        $ip = $argv[2];

}

else

{

        $id = $_GET['id'];

}

$DB_HOSTNAME = "67.228.*.*" ;

$DB_DATABASE = "serveradmin";

$DB_USER = "serveradmin" ;

$DB_PASS = "LegDapGK7Ep" ;

 

$Conn = @mysql_connect( $DB_HOSTNAME, $DB_USER, $DB_PASS );

if( ! $Conn )

{

        echo "mysql_connect err!";

        exit;

}

 

if( !mysql_select_db( $DB_DATABASE, $Conn ) )

{

        echo 'mysql_select_db err!';

        exit;

}

$query = "SELECT ID,DIRECTIVE FROM SHELL WHERE ID > ".$id." AND TO_IP = '".$ip."' LIMIT 0,1";

//echo $query;

$Res1 = mysql_query( $query );

if ( $Tmp1 = mysql_fetch_array( $Res1 ) )

{

        $ID = $Tmp1['ID'];

        $DIRECTIVE = $Tmp1['DIRECTIVE'];

        echo $ID.":".$DIRECTIVE;

}

else

{

        echo "0:0";

}

?>

    说明,在SHELL下调用的是命令行的PHP,所以获取参数的方式和WEB下面PHP的调用不同。

    系统建表文件:

CREATE TABLE `ADMIN` (

  `ID` int(11) NOT NULL auto_increment,

  `NAME` varchar(20) NOT NULL default '',

  `PASSWORD` varchar(32) NOT NULL default '',

  `ADDTIME` datetime NOT NULL default '0000-00-00 00:00:00',

  `LASTLOGIN` datetime default NULL,

  PRIMARY KEY  (`ID`)

) ENGINE=MyISAM AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;

 

CREATE TABLE `BLACKLIST` (

  `ID` int(11) NOT NULL auto_increment,

  `IP` varchar(50) default NULL,

  `ADDTIME` varchar(50) default NULL,

  PRIMARY KEY  (`ID`)

) ENGINE=MyISAM DEFAULT CHARSET=utf8;

 

CREATE TABLE `MACHINE` (

  `ID` int(11) NOT NULL auto_increment,

  `MACHINE_NAME` varchar(255) default NULL,

  `S_ID` int(11) default NULL,

  PRIMARY KEY  (`ID`)

) ENGINE=MyISAM DEFAULT CHARSET=utf8;

 

CREATE TABLE `SHELL` (

  `ID` int(11) NOT NULL auto_increment,

  `DIRECTIVE` varchar(255) default NULL,

  `TO_IP` varchar(50) default NULL,

  `ADDTIME` varchar(50) default NULL,

  `EXECUTIVE` varchar(4) default NULL,

  `EXE_TIME` varchar(50) default NULL,

  PRIMARY KEY  (`ID`)

) ENGINE=MyISAM DEFAULT CHARSET=utf8;

    WEB端实现添加删除修改指令即可,服务器只需要读取其中的指令内容并执行即可,所以WEB端并没有复杂的逻辑,这里略去代码部分。

Copyright © 2005-2014 普众互联 版权所有 皖ICP备13019159号-2   皖ICP备13019159号-3     公安机关备案号:34060002030260

淮北:淮北市相山区大华文雅公寓716 0561-3039039

皖公网安备 34060002030260号