Rev 556 | Rev 565 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed
#!/usr/bin/php<?php/*QBPWCF, Quick Build PHP website Component base on Fedora Linux.Copyright (C) 2015~2023 Min-Jhin,ChenThis file is part of QBPWCF.QBPWCF is free software: you can redistribute it and/or modifyit under the terms of the GNU General Public License as published bythe Free Software Foundation, either version 3 of the License, or(at your option) any later version.QBPWCF is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See theGNU General Public License for more details.You should have received a copy of the GNU General Public Licensealong with QBPWCF. If not, see <http://www.gnu.org/licenses/>.*//*封鎖來自http、https、smtp、named的惡意ip.*//*bug log:journalctl -a | grep ipBlockerd.phpApr 29 20:03:38 ip-172-31-33-199.ap-northeast-1.compute.internal ipBlockerd.php[2362579]: 內建白名單:169.254.1.1Apr 29 20:03:38 ip-172-31-33-199.ap-northeast-1.compute.internal ipBlockerd.php[2362579]: 附加白名單:169.254.1.1Apr 29 20:03:38 ip-172-31-33-199.ap-northeast-1.compute.internal ipBlockerd.php[2362579]: array(2) {Apr 29 20:03:38 ip-172-31-33-199.ap-northeast-1.compute.internal ipBlockerd.php[2362579]: ["status"]=>Apr 29 20:03:38 ip-172-31-33-199.ap-northeast-1.compute.internal ipBlockerd.php[2362579]: string(5) "false"Apr 29 20:03:38 ip-172-31-33-199.ap-northeast-1.compute.internal ipBlockerd.php[2362579]: ["error"]=>Apr 29 20:03:38 ip-172-31-33-199.ap-northeast-1.compute.internal ipBlockerd.php[2362579]: array(4) {Apr 29 20:03:38 ip-172-31-33-199.ap-northeast-1.compute.internal ipBlockerd.php[2362579]: ["function"]=>Apr 29 20:03:38 ip-172-31-33-199.ap-northeast-1.compute.internal ipBlockerd.php[2362579]: string(8) "fileInfo"Apr 29 20:03:38 ip-172-31-33-199.ap-northeast-1.compute.internal ipBlockerd.php[2362579]: ["argu"]=>Apr 29 20:03:38 ip-172-31-33-199.ap-northeast-1.compute.internal ipBlockerd.php[2362579]: array(3) {Apr 29 20:03:38 ip-172-31-33-199.ap-northeast-1.compute.internal ipBlockerd.php[2362579]: ["fileArgu"]=>Apr 29 20:03:38 ip-172-31-33-199.ap-northeast-1.compute.internal ipBlockerd.php[2362579]: string(47) "/usr/lib/20230429/qbpwcf/usr/bin/ipBlockerd.php"Apr 29 20:03:38 ip-172-31-33-199.ap-northeast-1.compute.internal ipBlockerd.php[2362579]: ["file"]=>Apr 29 20:03:38 ip-172-31-33-199.ap-northeast-1.compute.internal ipBlockerd.php[2362579]: string(25) "/var/log/httpd/access_log"Apr 29 20:03:38 ip-172-31-33-199.ap-northeast-1.compute.internal ipBlockerd.php[2362579]: ["web"]=>Apr 29 20:03:38 ip-172-31-33-199.ap-northeast-1.compute.internal ipBlockerd.php[2362579]: string(5) "false"Apr 29 20:03:38 ip-172-31-33-199.ap-northeast-1.compute.internal ipBlockerd.php[2362579]: }Apr 29 20:03:38 ip-172-31-33-199.ap-northeast-1.compute.internal ipBlockerd.php[2362579]: ["status"]=>Apr 29 20:03:38 ip-172-31-33-199.ap-northeast-1.compute.internal ipBlockerd.php[2362579]: string(5) "false"Apr 29 20:03:38 ip-172-31-33-199.ap-northeast-1.compute.internal ipBlockerd.php[2362579]: ["error"]=>Apr 29 20:03:38 ip-172-31-33-199.ap-northeast-1.compute.internal ipBlockerd.php[2362579]: array(7) {Apr 29 20:03:38 ip-172-31-33-199.ap-northeast-1.compute.internal ipBlockerd.php[2362579]: ["function"]=>Apr 29 20:03:38 ip-172-31-33-199.ap-northeast-1.compute.internal ipBlockerd.php[2362579]: string(19) "checkMultiFileExist"Apr 29 20:03:38 ip-172-31-33-199.ap-northeast-1.compute.internal ipBlockerd.php[2362579]: ["argu"]=>Apr 29 20:03:38 ip-172-31-33-199.ap-northeast-1.compute.internal ipBlockerd.php[2362579]: array(3) {Apr 29 20:03:38 ip-172-31-33-199.ap-northeast-1.compute.internal ipBlockerd.php[2362579]: ["fileArray"]=>Apr 29 20:03:38 ip-172-31-33-199.ap-northeast-1.compute.internal ipBlockerd.php[2362579]: array(1) {Apr 29 20:03:38 ip-172-31-33-199.ap-northeast-1.compute.internal ipBlockerd.php[2362579]: [0]=>Apr 29 20:03:38 ip-172-31-33-199.ap-northeast-1.compute.internal ipBlockerd.php[2362579]: string(25) "/var/log/httpd/access_log"Apr 29 20:03:38 ip-172-31-33-199.ap-northeast-1.compute.internal ipBlockerd.php[2362579]: }Apr 29 20:03:38 ip-172-31-33-199.ap-northeast-1.compute.internal ipBlockerd.php[2362579]: ["fileArgu"]=>Apr 29 20:03:38 ip-172-31-33-199.ap-northeast-1.compute.internal ipBlockerd.php[2362579]: string(47) "/usr/lib/20230429/qbpwcf/usr/bin/ipBlockerd.php"Apr 29 20:03:38 ip-172-31-33-199.ap-northeast-1.compute.internal ipBlockerd.php[2362579]: ["web"]=>Apr 29 20:03:38 ip-172-31-33-199.ap-northeast-1.compute.internal ipBlockerd.php[2362579]: string(5) "false"Apr 29 20:03:38 ip-172-31-33-199.ap-northeast-1.compute.internal ipBlockerd.php[2362579]: }Apr 29 20:03:38 ip-172-31-33-199.ap-northeast-1.compute.internal ipBlockerd.php[2362579]: ["varName"]=>Apr 29 20:03:38 ip-172-31-33-199.ap-northeast-1.compute.internal ipBlockerd.php[2362579]: array(1) {Apr 29 20:03:38 ip-172-31-33-199.ap-northeast-1.compute.internal ipBlockerd.php[2362579]: [0]=>Apr 29 20:03:38 ip-172-31-33-199.ap-northeast-1.compute.internal ipBlockerd.php[2362579]: string(25) "/var/log/httpd/access_log"Apr 29 20:03:38 ip-172-31-33-199.ap-northeast-1.compute.internal ipBlockerd.php[2362579]: }Apr 29 20:03:38 ip-172-31-33-199.ap-northeast-1.compute.internal ipBlockerd.php[2362579]: ["varExist"]=>Apr 29 20:03:38 ip-172-31-33-199.ap-northeast-1.compute.internal ipBlockerd.php[2362579]: array(1) {Apr 29 20:03:38 ip-172-31-33-199.ap-northeast-1.compute.internal ipBlockerd.php[2362579]: [0]=>Apr 29 20:03:38 ip-172-31-33-199.ap-northeast-1.compute.internal ipBlockerd.php[2362579]: string(5) "false"Apr 29 20:03:38 ip-172-31-33-199.ap-northeast-1.compute.internal ipBlockerd.php[2362579]: }Apr 29 20:03:38 ip-172-31-33-199.ap-northeast-1.compute.internal ipBlockerd.php[2362579]: ["varNameFullPath"]=>Apr 29 20:03:38 ip-172-31-33-199.ap-northeast-1.compute.internal ipBlockerd.php[2362579]: array(1) {Apr 29 20:03:38 ip-172-31-33-199.ap-northeast-1.compute.internal ipBlockerd.php[2362579]: [0]=>Apr 29 20:03:38 ip-172-31-33-199.ap-northeast-1.compute.internal ipBlockerd.php[2362579]: string(25) "/var/log/httpd/access_log"Apr 29 20:03:38 ip-172-31-33-199.ap-northeast-1.compute.internal ipBlockerd.php[2362579]: }Apr 29 20:03:38 ip-172-31-33-199.ap-northeast-1.compute.internal ipBlockerd.php[2362579]: ["allExist"]=>Apr 29 20:03:38 ip-172-31-33-199.ap-northeast-1.compute.internal ipBlockerd.php[2362579]: string(5) "false"Apr 29 20:03:38 ip-172-31-33-199.ap-northeast-1.compute.internal ipBlockerd.php[2362579]: ["status"]=>Apr 29 20:03:38 ip-172-31-33-199.ap-northeast-1.compute.internal ipBlockerd.php[2362579]: string(4) "true"Apr 29 20:03:38 ip-172-31-33-199.ap-northeast-1.compute.internal ipBlockerd.php[2362579]: }Apr 29 20:03:38 ip-172-31-33-199.ap-northeast-1.compute.internal ipBlockerd.php[2362579]: }Apr 29 20:03:38 ip-172-31-33-199.ap-northeast-1.compute.internal ipBlockerd.php[2362579]: }*/#指派命名空間namespace qbpwcf;#以該檔案的實際位置的 lib path 為 include path 首位exec("cd ".pathinfo(__FILE__)["dirname"]."/../../;pwd;",$output,$status);set_include_path($output[0].PATH_SEPARATOR.get_include_path());#匯入外部套件include("allInOne.php");#初始化記錄 http log 最後變更的時間$preHttpTimeFloat=0;#初始化記錄 https log 最後變更的時間$preHttpsTimeFloat=0;#初始化記錄 smtpd log 最後變更的時間$preSmtpTimeFloat=0;#初始化記錄 dovecot/imap log 最後變更的時間$preImapTimeFloat=0;#初始化記錄 named log 最後變更的時間$preNamedTimeFloat=0;#初始化不啟用debug模式$debug=false;#取得參數/*#函式說明:#解析參數.#回傳結果:#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.#$reuslt["error"],執行不正常結束的錯訊息陣列.#$result["function"],當前執行的函式名稱.#$result["content"],解析好的參數陣列.#$result["content"][$key][$i],參數 $key 的 $i+1 個參數數值內容.#$result["program"],字串,執行的程式名稱.#必填參數:#無#可省略參數:#無#備註:#僅能在命令列底下執行.#建議:#以後可將參數 --a--b 的名稱與後面的數值 $value 存成 $result["a"]["b"][$i]=$value .*/$conf=array();$parseArgu=cmd::parseArgu($conf);unset($conf);#如果有debug參數if(isset($parseArgu["content"]["debug"])){#如果第一個參數為 "--debug true"if($parseArgu["content"]["debug"][0]==="true"){#設置debug模式$debug=true;#commentecho "debug mode".PHP_EOL;}#if end}#if end#取得自己對外的ip#函式說明:#依據提供查詢IP服務的網站取得伺服器對外的IP.#回傳結果:#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.#$result["function"],當前執行的函數名稱.#$result["error"],錯誤訊息陣列.#$result["content"],伺服端對外的IP.#必填參數:#$conf["fileArgu"],字串,php變數__FILE__的內容,亦即該檔案在檔案系統的絕對路徑$conf["fileArgu"]=__FILE__;#可省略參數:#無.#備註:#需要有網站支援此服務.$getServerRealIP=csInformation::getServerRealIP($conf);unset($conf);#如果執行失敗if($getServerRealIP["status"]==="false"){#設置執行失敗$result["status"]="false";#設置錯誤訊息$result["error"]=$getServerRealIP;#印出結果var_dump($result);#結束執行exit;}#if end#預設的白名單為自己對外的IP$excludeIp=array($getServerRealIP["content"][0]);#提示內建白名單echo "內建白名單:".$excludeIp[0].PHP_EOL;#如果有 exclude 參數if(isset($parseArgu["content"]["exclude"])){#針對每個白名單 IPforeach($parseArgu["content"]["exclude"] as $whiteIp){#提示內建白名單echo "附加白名單:".$whiteIp.PHP_EOL;#取得每個指定要排除的ip$excludeIp[]=$whiteIp;}#foreach end}#if end#永久執行while(true){#debug modeif($debug){#commentecho "while loop".PHP_EOL;}#if end#函數說明:#依據取得檔案的擁有着資訊#回傳結果:#$result["status"],"true"爲建立成功,"false"爲建立失敗.#$result["error"],錯誤訊息陣列.#$result["function"],函數名稱.#$result["content"],檔案資訊陣列.#$result["content"]["is_folder"],是否為目錄,"true"代表是,"false"代表不是.#$result["content"]["ownerPerm"],檔案擁有者權限資訊.#$result["content"]["groupPerm"],檔案歸屬群組權限資訊.#$result["content"]["otherPerm"],檔案對於其他身份使用者的權限資訊.#$result["content"]["subElementCount"],目錄底下的檔案目錄數量.#$result["content"]["ownerName"],檔案擁有着資訊.#$result["content"]["groupName"],檔案所屬擁有着資訊.#$result["content"]["size"],檔案大小.#$result["content"]["modifyDate"],檔案變更年月日.#$result["content"]["modifyTime"],檔案變更時分秒.#$result["content"]["modifyTimeFloat"],檔案變更時間秒的float數值.#$result["content"]["timezone"],檔案變更時間的時區與UTC的差距.#必填參數:#$conf["fileArgu"],字串,當前檔案的位置亦即__FILE__的內容.$conf["fileArgu"]=__FILE__;#$conf["file"],字串,要查看擁有者資訊的檔案.$conf["file"]="/var/log/httpd/access_log";$conf["web"]="false";#參考資料:#fileowner=>http://php.net/manual/en/function.fileowner.php#posix_getpwuid=>http://php.net/manual/en/function.posix-getpwuid.php$httpFileInfo=fileAccess::fileInfo($conf);unset($conf);#如果運行失敗if($httpFileInfo["status"]==="false"){#設置執行失敗$result["status"]="false";#設置錯誤訊息$result["error"]=$httpFileInfo;#印出結果var_dump($result);#結束執行exit;}#if end#debugif($debug){#commentecho "accessed file /var/log/httpd/access_log".PHP_EOL;}#if end#記錄 http log 的最後變更時間$httpTimeFloat=$httpFileInfo["content"]["modifyTimeFloat"];#函數說明:#依據取得檔案的擁有着資訊#回傳結果:#$result["status"],"true"爲建立成功,"false"爲建立失敗.#$result["error"],錯誤訊息陣列.#$result["function"],函數名稱.#$result["content"],檔案資訊陣列.#$result["content"]["is_folder"],是否為目錄,"true"代表是,"false"代表不是.#$result["content"]["ownerPerm"],檔案擁有者權限資訊.#$result["content"]["groupPerm"],檔案歸屬群組權限資訊.#$result["content"]["otherPerm"],檔案對於其他身份使用者的權限資訊.#$result["content"]["subElementCount"],目錄底下的檔案目錄數量.#$result["content"]["ownerName"],檔案擁有着資訊.#$result["content"]["groupName"],檔案所屬擁有着資訊.#$result["content"]["size"],檔案大小.#$result["content"]["modifyDate"],檔案變更年月日.#$result["content"]["modifyTime"],檔案變更時分秒.#$result["content"]["modifyTimeFloat"],檔案變更時間秒的float數值.#$result["content"]["timezone"],檔案變更時間的時區與UTC的差距.#必填參數:#$conf["fileArgu"],字串,當前檔案的位置亦即__FILE__的內容.$conf["fileArgu"]=__FILE__;#$conf["file"],字串,要查看擁有者資訊的檔案.$conf["file"]="/var/log/httpd/ssl_access_log";$conf["web"]="false";#參考資料:#fileowner=>http://php.net/manual/en/function.fileowner.php#posix_getpwuid=>http://php.net/manual/en/function.posix-getpwuid.php$httpsFileInfo=fileAccess::fileInfo($conf);unset($conf);#如果運行失敗if($httpsFileInfo["status"]==="false"){#設置執行失敗$result["status"]="false";#設置錯誤訊息$result["error"]=$httpsFileInfo;#印出結果var_dump($result);#結束執行exit;}#if end#debugif($debug){#commentecho "accessed file /var/log/httpd/ssl_access_log".PHP_EOL;}#if end#記錄 https log 的最後變更時間$httpsTimeFloat=$httpsFileInfo["content"]["modifyTimeFloat"];#透過運行以下指令取得最後變更時間#journalctl -a -e | grep postfix/smtpd | grep " connect from unknown" | tail -n 1#涵式說明:#呼叫shell執行系統命令,並取得回傳的內容.#回傳的結果:#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.#$result["error"],錯誤訊息陣列.#$result["function"],當前執行的函數名稱.#$result["argu"],使用的參數.#$result["cmd"],執行的指令內容.#$result["fullCmd"],如果參數 $conf["inBackGround"] 為 "true" 則會回傳該值.#$result["output"],爲執行完二元碼後的輸出陣列,若 $conf["inBackGround"] 為 "true",則為當下的輸出.#$result["tmpFileOutput"],儲存輸出的暫存檔案名稱,若 $conf["inBackGround"] 為 "true" 則會回傳該值.#$result["running"],是否還在執行.#$result["pid"],pid.#$result["statusCode"],執行結束後的代碼.#必填的參數#$conf["command"],字串,要執行的指令與.$conf["external::callShell"]["command"]="journalctl";#$conf["fileArgu"],字串,變數__FILE__的內容.$conf["external::callShell"]["fileArgu"]=__FILE__;#可省略參數:#$conf["argu"],陣列字串,指令搭配的參數,預設為空陣列.$conf["external::callShell"]["argu"]=array("-a","-e","|","grep","postfix/smtps/smtpd","|","grep"," connect from unknown","|","tail","-n","1");#$conf["arguIsAddr"],陣列字串,指令搭配的哪些參數為路徑,為路徑的參數會進行轉換以便符合呼叫當前函數的位置,預設不指定,若有3個參數,其中第3個參數為路徑,則表示為array("false","false","true").#$conf["arguIsAddr"]=array();#$conf["pre"],陣列,要在本指令前執行的每個指令與參數.#$conf["pre"][$i]["cmd"],字串,要在本指令前執行的第$i+1個指令.#$conf["pre"][$i]["param"],陣列字串,要在本指令前執行的第$i+1個指令的參數.#$conf["enablePrintDescription"],字串,是否要印出$conf["printDescription"]的內容,"true"代表要,"false"代表不要,預設為"false".#$conf["enablePrintDescription"]="true";#$conf["printDescription"],字串,執行該外部程式前要印出來的的文字,預設為$conf["command"]的內容加上使用的$conf["argu"]參數.#$conf["printDescription"]="";#$conf["escapeshellarg"],字串,是否要啟用過濾參數,用了比較安全,但可能會出錯,"true"為啟用,"false"為不啟用,預設為"false".$conf["external::callShell"]["escapeshellarg"]="true";#$conf["username"],字串,要用什麼使用者來執行,預設為執行php的使用者,該參數不適用於apache環境.#$conf["username"]="";#$conf["password"],字串,root的使用者密碼,預設不使用密碼,該參數不適用於apache環境.#$conf["password"]="";#$conf["useScript"],字串,是否要啟用Linux的script指令來記錄輸出,"true"代表要,Fedora的selinux會擋住該操作;"false"代表不要,預設為"false".#$conf["useScript"]="";#$conf["logFilePath"],字串,當 $conf["useScript"] 為 "true" 時,輸出的內容要暫存到哪裡,預設為 "/tmp/.qbpwcf_tmp/external/callShell/".#$conf["logFilePath"]=".qbpwcf_tmp/external/callShell/";#$conf["inBackGround"],字串,是否要在背景執行,且不會等待程式執行結束再執行下一個指令,"true"代表是,"false"代表不要,預設為"false",如果$conf["command"]有用「;」區隔的多個指令將會出錯.#$conf["inBackGround"]="";#$conf["getErr"],字串,"true"代表將錯誤輸出變成標準輸出,反之"false"為不變動.#$conf["getErr"]="false";#備註:#不是所有指令都能用apache的身份執行,目前已知java,javac指令無法執行,使用root身份可能會被selinux阻擋.#參考資料:#exec=>http://php.net/manual/en/function.exec.php#escapeshellcmd=>http://php.net/manual/en/function.escapeshellcmd.php#escapeshellarg=>http://php.net/manual/en/function.escapeshellarg.php$callShell=external::callShell($conf["external::callShell"]);unset($conf["external::callShell"]);#如果執行失敗if($callShell["status"]==="false"){#設置執行失敗$result["status"]="false";#設置錯誤訊息$result["error"]=$callShell;#回傳結果var_dump($result);#結束執行exit;}#if end#debugif($debug){#commentecho "accessed file postfix/smtp log".PHP_EOL;}#if end#取得行數$lineCount=count($callShell["output"]);#如果行數等於1if($lineCount===1){#debugif($debug){#最新一筆惡意IP#echo "最新一筆惡意IP:".PHP_EOL;#var_dump($callShell["output"]);}#if end#Aug 09 07:12:09 www.qbpwcf.org postfix/smtpd[20829]: connect from unknown[185.234.219.62]#Apr 04 15:11:16 mail.qbpwcf.org postfix/smtps/smtpd[10145]: connect from unknown[212.70.149.72]$unProcesedStr=$callShell["output"];#分割字串#涵式說明:#將多個固定格式的字串分開,並回傳分開的結果#回傳的參數:#$result["status"],執行成功與否,若爲"true",代表執行成功,若爲"false"代表執失敗。#$result["error"],錯誤訊息陣列.#$result["function"],當前執行的函數名稱.#$result["spiltString"][$i]["oriStr"],爲第i個字串的原始內容#$result["spiltString"][$i]["dataArray"],爲第($i+1)個字串分割後的字串陣列#$result["spiltString"][$i]["dataArray"][$j],爲第($i+1)的分割好的字串的第($j+1)段內容#$result["spiltString"][$i]["dataCounts"],爲第($i+1)個字串分割後總共分成幾段#必填的參數:#$conf["stringIn"],字串陣列,要處理的字串陣列.$conf["stringProcess::spiltMutiString"]["stringIn"]=$unProcesedStr;#$conf["spiltSymbol"],字串,爲要以哪個符號作爲分割.$conf["stringProcess::spiltMutiString"]["spiltSymbol"]=" ";$spiltMutiString=stringProcess::spiltMutiString($conf["stringProcess::spiltMutiString"]);unset($conf["stringProcess::spiltMutiString"]);#如果分割失敗if($spiltMutiString["status"]==="false"){#設置執行失敗$result["status"]="false";#設置錯誤訊息$result["error"]=$spiltMutiString;#印出結果var_dump($result);#停止執行exit;}#if end#記錄 smtpd log 最後變更的時間$smtpTimeFloat=$spiltMutiString["spiltString"][0]["dataArray"][2];}#if end#反之else{#記錄 smtpd log 最後變更的時間爲0$smtpTimeFloat=0;}#else end#透過運行以下指令取得最後變更時間#journalctl -a -e | grep dovecot | grep " failed" | tail -n 1#涵式說明:#呼叫shell執行系統命令,並取得回傳的內容.#回傳的結果:#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.#$result["error"],錯誤訊息陣列.#$result["function"],當前執行的函數名稱.#$result["argu"],使用的參數.#$result["cmd"],執行的指令內容.#$result["fullCmd"],如果參數 $conf["inBackGround"] 為 "true" 則會回傳該值.#$result["output"],爲執行完二元碼後的輸出陣列,若 $conf["inBackGround"] 為 "true",則為當下的輸出.#$result["tmpFileOutput"],儲存輸出的暫存檔案名稱,若 $conf["inBackGround"] 為 "true" 則會回傳該值.#$result["running"],是否還在執行.#$result["pid"],pid.#$result["statusCode"],執行結束後的代碼.#必填的參數#$conf["command"],字串,要執行的指令與.$conf["external::callShell"]["command"]="journalctl";#$conf["fileArgu"],字串,變數__FILE__的內容.$conf["external::callShell"]["fileArgu"]=__FILE__;#可省略參數:#$conf["argu"],陣列字串,指令搭配的參數,預設為空陣列.$conf["external::callShell"]["argu"]=array("-a","-e","|","grep","dovecot","|","grep"," failed","|","tail","-n","1");#$conf["arguIsAddr"],陣列字串,指令搭配的哪些參數為路徑,為路徑的參數會進行轉換以便符合呼叫當前函數的位置,預設不指定,若有3個參數,其中第3個參數為路徑,則表示為array("false","false","true").#$conf["arguIsAddr"]=array();#$conf["pre"],陣列,要在本指令前執行的每個指令與參數.#$conf["pre"][$i]["cmd"],字串,要在本指令前執行的第$i+1個指令.#$conf["pre"][$i]["param"],陣列字串,要在本指令前執行的第$i+1個指令的參數.#$conf["enablePrintDescription"],字串,是否要印出$conf["printDescription"]的內容,"true"代表要,"false"代表不要,預設為"false".#$conf["enablePrintDescription"]="true";#$conf["printDescription"],字串,執行該外部程式前要印出來的的文字,預設為$conf["command"]的內容加上使用的$conf["argu"]參數.#$conf["printDescription"]="";#$conf["escapeshellarg"],字串,是否要啟用過濾參數,用了比較安全,但可能會出錯,"true"為啟用,"false"為不啟用,預設為"false".$conf["external::callShell"]["escapeshellarg"]="true";#$conf["username"],字串,要用什麼使用者來執行,預設為執行php的使用者,該參數不適用於apache環境.#$conf["username"]="";#$conf["password"],字串,root的使用者密碼,預設不使用密碼,該參數不適用於apache環境.#$conf["password"]="";#$conf["useScript"],字串,是否要啟用Linux的script指令來記錄輸出,"true"代表要,Fedora的selinux會擋住該操作;"false"代表不要,預設為"false".#$conf["useScript"]="";#$conf["logFilePath"],字串,當 $conf["useScript"] 為 "true" 時,輸出的內容要暫存到哪裡,預設為 "/tmp/.qbpwcf_tmp/external/callShell/".#$conf["logFilePath"]=".qbpwcf_tmp/external/callShell/";#$conf["inBackGround"],字串,是否要在背景執行,且不會等待程式執行結束再執行下一個指令,"true"代表是,"false"代表不要,預設為"false",如果$conf["command"]有用「;」區隔的多個指令將會出錯.#$conf["inBackGround"]="";#$conf["getErr"],字串,"true"代表將錯誤輸出變成標準輸出,反之"false"為不變動.#$conf["getErr"]="false";#備註:#不是所有指令都能用apache的身份執行,目前已知java,javac指令無法執行,使用root身份可能會被selinux阻擋.#參考資料:#exec=>http://php.net/manual/en/function.exec.php#escapeshellcmd=>http://php.net/manual/en/function.escapeshellcmd.php#escapeshellarg=>http://php.net/manual/en/function.escapeshellarg.php$callShell=external::callShell($conf["external::callShell"]);unset($conf["external::callShell"]);#如果執行失敗if($callShell["status"]==="false"){#設置執行失敗$result["status"]="false";#設置錯誤訊息$result["error"]=$callShell;#回傳結果var_dump($result);#結束執行exit;}#if end#debugif($debug){#commentecho "accessed file dovecot/imap log".PHP_EOL;}#if end#取得行數$lineCount=count($callShell["output"]);#如果行數等於1if($lineCount===1){#debugif($debug){#最新一筆惡意IP#echo "最新一筆惡意IP:".PHP_EOL;#var_dump($callShell["output"]);}#if end#Feb 23 07:44:29 localhost.localdomain dovecot[1427]: imap-login: Disconnected (no auth attempts in 0 secs): user=<>, rip=101.136.215.61, lip=169.254.1.1, TLS handshaking: SSL_accept() failed: error:14094416:SSL routines:ssl3_read_bytes:sslv3 alert certificate unknown: SSL alert number 46, session=<9oMMYvW7ihhliNc9>$unProcesedStr=$callShell["output"];#分割字串#涵式說明:#將多個固定格式的字串分開,並回傳分開的結果#回傳的參數:#$result["status"],執行成功與否,若爲"true",代表執行成功,若爲"false"代表執失敗。#$result["error"],錯誤訊息陣列.#$result["function"],當前執行的函數名稱.#$result["spiltString"][$i]["oriStr"],爲第i個字串的原始內容#$result["spiltString"][$i]["dataArray"],爲第($i+1)個字串分割後的字串陣列#$result["spiltString"][$i]["dataArray"][$j],爲第($i+1)的分割好的字串的第($j+1)段內容#$result["spiltString"][$i]["dataCounts"],爲第($i+1)個字串分割後總共分成幾段#必填的參數:#$conf["stringIn"],字串陣列,要處理的字串陣列.$conf["stringProcess::spiltMutiString"]["stringIn"]=$unProcesedStr;#$conf["spiltSymbol"],字串,爲要以哪個符號作爲分割.$conf["stringProcess::spiltMutiString"]["spiltSymbol"]=" ";$spiltMutiString=stringProcess::spiltMutiString($conf["stringProcess::spiltMutiString"]);unset($conf["stringProcess::spiltMutiString"]);#如果分割失敗if($spiltMutiString["status"]==="false"){#設置執行失敗$result["status"]="false";#設置錯誤訊息$result["error"]=$spiltMutiString;#印出結果var_dump($result);#停止執行exit;}#if end#記錄 smtpd log 最後變更的時間$imapTimeFloat=$spiltMutiString["spiltString"][0]["dataArray"][2];}#if end#反之else{#記錄 imap log 最後變更的時間爲0$imapTimeFloat=0;}#else end#透過 journalctl -a -e | grep named | tail -n 1 來取得最後一筆 dns 查詢記錄#涵式說明:#呼叫shell執行系統命令,並取得回傳的內容.#回傳的結果:#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.#$result["error"],錯誤訊息陣列.#$result["function"],當前執行的函數名稱.#$result["argu"],使用的參數.#$result["cmd"],執行的指令內容.#$result["fullCmd"],如果參數 $conf["inBackGround"] 為 "true" 則會回傳該值.#$result["output"],爲執行完二元碼後的輸出陣列,若 $conf["inBackGround"] 為 "true",則為當下的輸出.#$result["tmpFileOutput"],儲存輸出的暫存檔案名稱,若 $conf["inBackGround"] 為 "true" 則會回傳該值.#$result["running"],是否還在執行.#$result["pid"],pid.#$result["statusCode"],執行結束後的代碼.#必填的參數#$conf["command"],字串,要執行的指令與.$conf["external::callShell"]["command"]="journalctl";#$conf["fileArgu"],字串,變數__FILE__的內容.$conf["external::callShell"]["fileArgu"]=__FILE__;#可省略參數:#$conf["argu"],陣列字串,指令搭配的參數,預設為空陣列.$conf["external::callShell"]["argu"]=array("-a","-e","|","grep"," named","|","tail","-n","1");#$conf["arguIsAddr"],陣列字串,指令搭配的哪些參數為路徑,為路徑的參數會進行轉換以便符合呼叫當前函數的位置,預設不指定,若有3個參數,其中第3個參數為路徑,則表示為array("false","false","true").#$conf["arguIsAddr"]=array();#$conf["pre"],陣列,要在本指令前執行的每個指令與參數.#$conf["pre"][$i]["cmd"],字串,要在本指令前執行的第$i+1個指令.#$conf["pre"][$i]["param"],陣列字串,要在本指令前執行的第$i+1個指令的參數.#$conf["enablePrintDescription"],字串,是否要印出$conf["printDescription"]的內容,"true"代表要,"false"代表不要,預設為"false".#$conf["enablePrintDescription"]="true";#$conf["printDescription"],字串,執行該外部程式前要印出來的的文字,預設為$conf["command"]的內容加上使用的$conf["argu"]參數.#$conf["printDescription"]="";#$conf["escapeshellarg"],字串,是否要啟用過濾參數,用了比較安全,但可能會出錯,"true"為啟用,"false"為不啟用,預設為"false".$conf["external::callShell"]["escapeshellarg"]="true";#$conf["username"],字串,要用什麼使用者來執行,預設為執行php的使用者,該參數不適用於apache環境.#$conf["username"]="";#$conf["password"],字串,root的使用者密碼,預設不使用密碼,該參數不適用於apache環境.#$conf["password"]="";#$conf["useScript"],字串,是否要啟用Linux的script指令來記錄輸出,"true"代表要,Fedora的selinux會擋住該操作;"false"代表不要,預設為"false".#$conf["useScript"]="";#$conf["logFilePath"],字串,當 $conf["useScript"] 為 "true" 時,輸出的內容要暫存到哪裡,預設為 "/tmp/.qbpwcf_tmp/external/callShell/".#$conf["logFilePath"]=".qbpwcf_tmp/external/callShell/";#$conf["inBackGround"],字串,是否要在背景執行,且不會等待程式執行結束再執行下一個指令,"true"代表是,"false"代表不要,預設為"false",如果$conf["command"]有用「;」區隔的多個指令將會出錯.#$conf["inBackGround"]="";#$conf["getErr"],字串,"true"代表將錯誤輸出變成標準輸出,反之"false"為不變動.#$conf["getErr"]="false";#備註:#不是所有指令都能用apache的身份執行,目前已知java,javac指令無法執行,使用root身份可能會被selinux阻擋.#參考資料:#exec=>http://php.net/manual/en/function.exec.php#escapeshellcmd=>http://php.net/manual/en/function.escapeshellcmd.php#escapeshellarg=>http://php.net/manual/en/function.escapeshellarg.php$callShell=external::callShell($conf["external::callShell"]);unset($conf["external::callShell"]);#如果執行失敗if($callShell["status"]==="false"){#設置執行失敗$result["status"]="false";#設置錯誤訊息$result["error"]=$callShell;#回傳結果var_dump($result);#結束執行exit;}#if end#debugif($debug){#commentecho "accessed file named log".PHP_EOL;}#if end#取得行數$lineCount=count($callShell["output"]);#如果行數等於1if($lineCount===1){#debugif($debug){#最新一筆惡意IP#echo "最新一筆惡意IP:".PHP_EOL;#var_dump($callShell["output"]);}#if end#Aug 09 07:12:09 www.qbpwcf.org postfix/smtpd[20829]: connect from unknown[185.234.219.62]$unProcesedStr=$callShell["output"];#分割字串#涵式說明:#將多個固定格式的字串分開,並回傳分開的結果#回傳的參數:#$result["status"],執行成功與否,若爲"true",代表執行成功,若爲"false"代表執失敗。#$result["error"],錯誤訊息陣列.#$result["function"],當前執行的函數名稱.#$result["spiltString"][$i]["oriStr"],爲第i個字串的原始內容#$result["spiltString"][$i]["dataArray"],爲第($i+1)個字串分割後的字串陣列#$result["spiltString"][$i]["dataArray"][$j],爲第($i+1)的分割好的字串的第($j+1)段內容#$result["spiltString"][$i]["dataCounts"],爲第($i+1)個字串分割後總共分成幾段#必填的參數:#$conf["stringIn"],字串陣列,要處理的字串陣列.$conf["stringProcess::spiltMutiString"]["stringIn"]=$unProcesedStr;#$conf["spiltSymbol"],字串,爲要以哪個符號作爲分割.$conf["stringProcess::spiltMutiString"]["spiltSymbol"]=" ";$spiltMutiString=stringProcess::spiltMutiString($conf["stringProcess::spiltMutiString"]);unset($conf["stringProcess::spiltMutiString"]);#如果分割失敗if($spiltMutiString["status"]==="false"){#設置執行失敗$result["status"]="false";#設置錯誤訊息$result["error"]=$spiltMutiString;#印出結果var_dump($result);#停止執行exit;}#if end#記錄 named log 最後變更的時間$namedTimeFloat=$spiltMutiString["spiltString"][0]["dataArray"][2];}#if end#反之else{#記錄 named log 最後變更的時間爲0$namedTimeFloat=0;}#else end#debug modeif($debug){#commentecho "\$preHttpTimeFloat:".$preHttpTimeFloat.PHP_EOL;echo "\$preHttpsTimeFloat:".$preHttpsTimeFloat.PHP_EOL;echo "\$preSmtpTimeFloat:".$preSmtpTimeFloat.PHP_EOL;echo "\$preImapTimeFloat:".$preImapTimeFloat.PHP_EOL;echo "\$preNamedTimeFloat:".$preNamedTimeFloat.PHP_EOL;echo "\$httpTimeFloat:".$httpTimeFloat.PHP_EOL;echo "\$httpsTimeFloat:".$httpsTimeFloat.PHP_EOL;echo "\$smtpTimeFloat:".$smtpTimeFloat.PHP_EOL;echo "\$imapTimeFloat:".$imapTimeFloat.PHP_EOL;echo "\$namedTimeFloat:".$namedTimeFloat.PHP_EOL;}#if end#第一次運行,不做事.if($preHttpTimeFloat===0 && $preHttpsTimeFloat===0 && $preSmtpTimeFloat===0 && $preImapTimeFloat===0 && $preNamedTimeFloat===0){#將本次http記錄覆寫到上次的記錄$preHttpTimeFloat=$httpTimeFloat;#將本次https記錄覆寫到上次的記錄$preHttpsTimeFloat=$httpsTimeFloat;#將本次smtps記錄覆寫到上次的記錄$preSmtpTimeFloat=$smtpTimeFloat;#將本次imaps記錄覆寫到上次的記錄$preImapTimeFloat=$imapTimeFloat;#將本次nmaed記錄覆寫到上次的記錄$preNamedTimeFloat=$namedTimeFloat;#睡一秒sleep(1);#debug modeif($debug){#commentecho "第一次運行,不做事".PHP_EOL;}#if end#下一輪continue;}#if end#非第一次運行,且 http 與 https log 都沒變動過.else if( $preHttpTimeFloat===$httpTimeFloat && $preHttpsTimeFloat===$httpsTimeFloat && $preSmtpTimeFloat===$smtpTimeFloat && $preImapTimeFloat===$imapTimeFloat && $preNamedTimeFloat===$namedTimeFloat ){#睡一秒sleep(1);#debug modeif($debug){#commentecho "Log檔無變動,不做事".PHP_EOL;}#if end#下一輪continue;}#else end#debug modeif($debug){#commentecho "Log檔有變動,要做事".PHP_EOL;echo "\$preHttpTimeFloat:".$preHttpTimeFloat.PHP_EOL;echo "\$preHttpsTimeFloat:".$preHttpsTimeFloat.PHP_EOL;echo "\$preSmtpTimeFloat:".$preSmtpTimeFloat.PHP_EOL;echo "\$preImapTimeFloat:".$preImapTimeFloat.PHP_EOL;echo "\$preNamedTimeFloat:".$preNamedTimeFloat.PHP_EOL;echo "\$httpTimeFloat:".$httpTimeFloat.PHP_EOL;echo "\$httpsTimeFloat:".$httpsTimeFloat.PHP_EOL;echo "\$smtpTimeFloat:".$smtpTimeFloat.PHP_EOL;echo "\$imapTimeFloat:".$imapTimeFloat.PHP_EOL;echo "\$namedTimeFloat:".$namedTimeFloat.PHP_EOL;}#if end#將本次http記錄覆寫到上次的記錄$preHttpTimeFloat=$httpTimeFloat;#將本次https記錄覆寫到上次的記錄$preHttpsTimeFloat=$httpsTimeFloat;#將本次smtps記錄覆寫到上次的記錄$preSmtpTimeFloat=$smtpTimeFloat;#涵式說明:#檢查 httpd 與 postfix/smtpd 的 log 與 named 的log 把惡意連線的 IP 用防火牆阻阻擋#回傳結果:#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.#$result["error"],錯誤訊息.#$result["function"],當前執行的函數名稱.#$result["argu"],所使用的參數.#$result["found"],是否有找到符合的檔案,"true"代表有;"false"代表沒有.#$result["content"],找到的檔案陣列.#必填參數:#$conf["fileArgu"],字串,php變數__FILE__的內容,亦即該檔案在檔案系統的絕對路徑$conf["fileArgu"]=__FILE__;#可省略參數:#$conf["excludeIp"],字串陣列,白名單ip陣列.$conf["excludeIp"]=$excludeIp;#$conf["logPath"],字串,httpd的log位置,預設為 "/var/log/httpd"#$conf["logPath"]="";#$conf["username"],字串,要用什麼使用者來執行,預設為root使用者#$conf["username"]="";#$conf["password"],字串,root使用者的密碼,#$conf["password"]="";#$conf["getIplistOnly"],字串,是否不阻擋IP只取得有問題的IP,預設為"false",要阻擋IP;"true"代表只取得有問題的IP.#$conf["getIplistOnly"]="true";$blockAcctackIp=cmd::blockAcctackIp($conf);unset($conf);#如果執行失敗if($blockAcctackIp["status"]==="false"){#設置執行失敗$result["status"]="false";#設置錯誤訊息$result["error"]=$blockAcctackIp;#印出結果var_dump($result);#結束執行exit;}#if end#如果有執行封鎖IP的情形if(isset($blockAcctackIp["content"])){#commentecho "本次封鎖IP的結果如下:".PHP_EOL;var_dump($blockAcctackIp["content"]);var_dump($blockAcctackIp["reason"]);}#if end#睡一秒sleep(1);#下一輪continue;}//while end?>