#####################################################################
# 本程式由 fiend 編寫 轉貼請註明出處
#####################################################################

前言 :

這是一支小小的簡單程式 不過 網站被 dos 攻擊時還蠻好用的 ^^

小弟之前 被一個死香港駭客

不停的用 dos 對我的 網站傳送大量封包 同時傳送上百萬的 apache 請求 封包 .

害我的 apache 忙的要死 db loding 一直衝上來 ..

因為當時我是租用主機 主機商 又沒有能力處理這種攻擊 它們遇到這種狀況一律 鎖住我的網站的權限 這是不對的不公平!! .

使用它後 cpu 的 loding 從 70~90% 降到 2% , 被攻擊的情況也變少了 .

使用這支程式 請注意 session 數不要設太少 有的 user 電腦中毒了 也會被封鎖

經驗上 16 是最嚴格的 32 算中等 64 的話 剛剛好

所以大家在設定上 16 32 64 依自己需需求去判斷

有人會問我 這樣 loding 會不會很重 不會的大家放心 因為 netstats 的技術 不是分析封包

只是判斷 sources ip 對 sources port 及 destantion ip 對 destantion port 的連線數 每秒執行cpu用不到 0.1% .

其實還可以再加強 一點就是 apache 要送回封包時 會發現

要求回應 的 desctantion port 會一直找不到這個也可以列入判斷 dos 的 規則

不要要強調一點的是這支程式 不能擋 ddos 攻擊喔 不過 可以擋下不少 惡意的攻擊了

當初我也有想過 連異常封包我都要擋下來 .

不過 想想要擋 ddos攻擊 就真的要用 sniffer 了

不過用在 封包判斷可能 loding 蠻重的 web 服務我想 可能不需要 .

如果真的需要我 大楖會另外再放一台機器 獨立 撈 mirror port 或是 廣撥的封包 去 監聽 然後 再命令 web主機加以封鎖

會比較安全 也不會因為分析 sniffer 封包過多 主機會掛掉 而影響到 web 主機.

對網管不清礎的 user 看不懂 小弟的介紹也沒關係反正就照抄就對了

好啦 簡單介紹了一下 大家對 這支程式有什麼問題 可以在這發問 小弟會耐心解答 .

請將程式放在 /root/bin/block_http

#!/usr/local/bin/php -q
<?php
set_time_limit(0);
$exception[] ="220.132.104.8" ;
$exception[] ="206.225.95.61" ;

$path_log = "/var/log/http_err/err_log_".strftime("%Y-%m-%d",time()) ;
$alert_limit = "48"; // 連線數超過 發出警告
$flow_limit = "72"; // 連線數最多 ... 封鎖
$block_range = "1"; // 偵測間距
$restart_httpd_num = "100"; // 連線數達N筆時重新啟動 http ...
while(1==1){

        $msg = "";

        @exec("netstat -tn | grep \":80 \" | grep -v \"0:0:0:0\" | cut -d: -f8 | sort ",$ip_list) ;
        @exec("iptables -L INPUT -n | grep DROP | cut -d- -f3| cut -d/ -f1",$isblock_ip) ;
        // DROP       all  --  60.248.11.20         0.0.0.0/0
        if(count($isblock_ip) >= 1){
                foreach($isblock_ip as $ibv){
                        $isblock_ip_arr[] = trim(str_replace("0.0.0.0","",trim($ibv))) ;
                }
                $isblock_ip_arr = array_unique($isblock_ip_arr) ;
        }
        //print_r($isblock_ip_arr);

        $ip_list = @array_count_values($ip_list) ;

        foreach($ip_list as $ip => $num){
                if($ip != "" and $num >= $alert_limit){
                        //$msg = "TIME"."\t"."IP"."\t"."QUANTITY"."\n";
                        $msg .=  "ALERT\t".strftime("%Y-%m-%d %H:%M:%S",time())."\t".$ip."\t".$num."\n";
                }
                if($ip != "" and $num >= $flow_limit){
                        $block_ip[] =  $ip;
                }
        }

        /*
        if(is_array($block_ip)){
                foreach($block_ip as $kip){
                        echo "ALERT : ".$kip ." => ".$ip_list[$kip] . " -- ".strftime("%Y-%m-%d %H:%M:%S",time())." - amount than :".$flow_limit." \n";
                }
                unset($kip);
        }
        */
        if(is_array($block_ip)){
                $block_ip = array_diff($block_ip,$exception); // 過濾例外清單
                if(is_array($block_ip) and is_array($isblock_ip_arr)){
                        $block_ip = array_diff($block_ip,$isblock_ip_arr); // 過濾已封鎖清單
                }

                foreach($block_ip as $kip){
                        $msg .=  "BLOCK\t".strftime("%Y-%m-%d %H:%M:%S",time())."\t".$kip."\t".$ip_list[$kip]."\n";
                        system("iptables -I INPUT -s ".$kip." -j DROP");
                        //system("iptables-save");
                        if($ip_list[$kip] >= $restart_httpd_num){
                                //echo $kip ." => ".$ip_list[$kip] . " -- ".strftime("%Y-%m-%d %H:%M:%S",time())."\n";
                                system("killall /usr/local/apache2/bin/httpd");
                                system("/usr/local/apache2/bin/apachectl restart");
                        }
                }

        }
        //print_r($block_ip);
        //echo "Last second ...... \n";
        if(!is_dir(dirname($path_log))){
                $action = "/bin/mkdir -p ".dirname($path_log);
                system(escapeshellcmd($action));
        }
        $fp = fopen($path_log,"a+");
        fwrite($fp,$msg,strlen($msg));
        fclose($fp);



        sleep($block_range);  // 偵測間距
        unset($ip_list);
        unset($isblock_ip);
        unset($isblock_ip_arr);
        unset($num);
        unset($ip);
        unset($block_ip);
        unset($msg);
}



?>
然後將這行程式的路徑放入

/etc/rc.local

nohup /root/bin/block_http &
創作者介紹
創作者 kevin0523 的頭像
kevin0523

新‧夢想

kevin0523 發表在 痞客邦 留言(0) 人氣()