Rev 883 | 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~2024 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 -e -fMar 09 13:40:20 qbpwcf.org postfix/smtpd[1058247]: connect from unknown[194.48.251.15]Mar 09 13:40:21 qbpwcf.org postfix/smtpd[1058247]: disconnect from unknown[194.48.251.15] ehlo=1 auth=0/1 quit=1 commands=2/3Mar 09 13:40:45 qbpwcf.org postfix/smtpd[1050779]: connect from unknown[194.48.251.15]Mar 09 13:40:46 qbpwcf.org postfix/smtpd[1050779]: disconnect from unknown[194.48.251.15] ehlo=1 auth=0/1 quit=1 commands=2/3Mar 09 13:41:07 qbpwcf.org postfix/smtpd[1058247]: connect from unknown[194.48.251.15]Mar 09 13:41:08 qbpwcf.org postfix/smtpd[1058247]: disconnect from unknown[194.48.251.15] ehlo=1 auth=0/1 quit=1 commands=2/3*/#指派命名空間namespace qbpwcf;#以該檔案的實際位置的 lib path 為 include path 首位exec("cd ".pathinfo(__FILE__)["dirname"]."/../lib;pwd;",$output,$status);set_include_path($output[0].PATH_SEPARATOR.get_include_path());#匯入外部套件include("allInOne.php");#當前路徑$pwd=$output[0];#unix socket 的位置$unixSocket=$pwd."/".basename(__FILE__).".sock";#提示unix domain socket位置echo "unix domain socket used at ".$unixSocket;#初始化儲存上次各log的時間$preTimeFloat=array();#初始化記錄 http log 最後變更的時間$preTimeFloat["http"]=0;#初始化記錄 https log 最後變更的時間$preTimeFloat["https"]=0;#初始化記錄 smtpd log 最後變更的時間$preTimeFloat["smtp"]=0;#初始化記錄 dovecot/imap log 最後變更的時間$preTimeFloat["imap"]=0;#初始化記錄 named log 最後變更的時間$preTimeFloat["named"]=0;#初始化不啟用debug模式$debug=false;#預設暫存的白名單ip有效時間為1小時$tmp_white_ip_valid_time=1;#說明函式function help(){#印出指令說明echo "Usage of ".basename(__FILE__).":".PHP_EOL;echo "--debug [true/false] 代表是否要啟動 debug 模式".PHP_EOL;echo "--exclude [white list ip] 代表白名單IP,一次只能放一個IP.".PHP_EOL;echo "--tmp-white-ip-valid-time [white ip value time] 指定暫時白名單的有效小時".PHP_EOL;echo "--client [true/false] 代表是否為 client 端,而非 server 端".PHP_EOL;echo "--client-add-tmp-white-ip [while ip for while] client端指令,代表要增加的暫時白名單IP".PHP_EOL;echo "--client-update-tmp-white-ip-valid-time [white ip value time] client端指令,代表要更新暫時白名單的有效時間,單位為小時".PHP_EOL;#結束執行exit;}#function help end#函式說明:#解析參數.#回傳結果:#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.#$reuslt["error"],執行不正常結束的錯訊息陣列.#$result["function"],當前執行的函式名稱.#$result["content"],解析好的參數陣列.#$result["content"][$key][$i],參數 $key 的 $i+1 個參數數值內容.#$result["program"],字串,執行的程式名稱.#必填參數:#無.#可省略參數:#$conf["helpFunc"],如果解析的參數不成對,則要執行的函式名稱.$conf["helpFunc"]="help";#參考資料:#無.#備註:#僅能在命令列底下執行.#以後可將參數 --a--b 的名稱與後面的數值 $value 存成 $result["a"]["b"][$i]=$value .$parseArgu=cmd::parseArgu($conf);unset($conf);#如果執行失敗if($parseArgu["status"]==="false"){#設置執行失敗$result["status"]="false";#設置錯誤訊息$result["error"]=$parseArgu;#印出結果var_dump($result);#結束執行exit(1);}#if end#檢查參數#函式說明:#檢查必填與可省略的參數,可省略參數可指定預設要給與什麼數值內容.#回傳結果:#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.#$result["error"],執行不正常結束的錯訊息陣列.#$result["simpleError"],簡單表示的錯誤訊息.#$result["function"],當前執行的函式名稱.#$result["argu"],設置給予的參數.#$result["passed"],識別要檢查的全體變數是否存在以及型態是否正確的變數,"true"代表檢查全部通過;"false"代表檢查不通過#$result[$shouldBeCheckedVarName]["varExist"],所檢查的變數是否存在,"false"代表不存在;"true"代表存在#$result[$shouldBeCheckedVarName]["varType"],所檢查的變數型態是否正確,"false"代表錯誤;"true"代表正確#$result[$shouldBeCheckedVarName]["error"],每個參數設定的錯誤訊息#$result["shouldNotBeEmpty"],不應該為空字串或控陣列的變數.#$result["argu"],字串陣列,目前輸入的參數名稱陣列.#$result["legalVarName"],字串陣列,合法可用的參數名稱陣列.#$result["notNeedVar"],字串陣列,多餘的參數名稱.#必填參數:#$conf["varInput"],陣列變數,要檢查的陣列變數,請在要檢查的參數前面加上&,這樣變動的結果才能被套用。$conf["varInput"]=&$parseArgu["content"];#$conf["referenceVarKey"],字串,$conf參數後面的key值,用於移除不要的參考陣列.$conf["referenceVarKey"]="variableCheck::checkArguments";#可省略參數:#$conf["mustBeFilledVariableName"],爲必填參數的變數名稱陣列,形態爲陣列變數,元素數量需要跟"mustBeFilledVariableType"參數的元素數量一致,例如: $conf["mustBeFilledVariableName"] = array("id","account","password");#$conf["mustBeFilledVariableName"]=array();#$conf["mustBeFilledVariableType"],爲必填參數的變數陣列應該爲何種變數形態,形態爲陣列,元素數量需要跟"mustBeFilledVariableName"參數的元素數量一致,例如: $conf["mustBeFilledVariableType"] = array("string",integer,"double","resource","object"); , null代表不指定變數形態.#$conf["mustBeFilledVariableType"]=array();#$conf["canBeEmptyString"],字串,必填變數內容如果是空字串就不能算是有設置的話,請設為"false",預設爲"true",可以為空字串.#$conf["canBeEmptyString"]="false";#$conf["canNotBeEmpty"],字串陣列,哪些必填參數的內容不得為空字串或空陣列,僅當$conf["canBeEmptyString"]為"true"時會生效.#$conf["canNotBeEmpty"]=array();#$conf["canBeEmpty"],字串陣列,哪些必填參數的內容可為空字串或空陣列,僅當$conf["canBeEmptyString"]為"false"時會生效.#$conf["canBeEmpty"]=array();#$conf["skipableVariableCanNotBeEmpty"],字串陣列,哪些可省略參數不可以為空字串或空陣列.$conf["skipableVariableCanNotBeEmpty"]=array("debug","exclude","tmp-white-ip-valid-time","client","tmp-white-ip-valid-time","client-add-tmp-white-ip","client-update-tmp-white-ip-valid-time");#$conf["skipableVariableName"],陣列字串,爲可省略參數的變數名稱陣列,形態爲陣列變數,例如: $conf["skipableVariableName"] = array("id","account","password");$conf["skipableVariableName"]=array("debug","exclude","tmp-white-ip-valid-time","client","tmp-white-ip-valid-time","client-add-tmp-white-ip","client-update-tmp-white-ip-valid-time");#$conf["skipableVariableType"],陣列字串,爲可省略參數的變數名稱陣列,形態爲陣列變數,例如: $conf["skipableVariableType"] = array("string",integer,"double");$conf["skipableVariableType"]=array("array","array","array","array","array","array","array");#$conf["skipableVarDefaultValue"],字串陣列,每個不存在的可省略變數要初始化為什麼,null與代表不指定,若預設值是參數之一,請將$conf["mustBeFilledVar"]改成"\$conf["\mustBeFilledVar\"]".$conf["skipableVarDefaultValue"]=array(array("false"),null,array("1"),null,null,null,null);#$conf["disallowAllSkipableVarIsEmpty"],字串,是否允許每個可省略參數都為空字串,預設為"true"允許,反之為"false".$conf["disallowAllSkipableVarIsEmpty"]="false";#$conf["disallowAllSkipableVarIsEmptyArray"],字串,是否允許每個可省略參數都為空陣列,預設為"true"允許,反之為"false".$conf["disallowAllSkipableVarIsEmptyArray"]="false";#$conf["arrayCountEqualCheck"],字串陣列,為檢查哪些陣列參數的元素數量要一樣,$conf["arrayCountEqualCheck"][$i]=array()為第$i組key為哪些的變數其元素數量要相等.#$conf["arrayCountEqualCheck"][]=array();#參考資料:#array_keys=>http://php.net/manual/en/function.array-keys.php#備註:#無.$checkArguments=variableCheck::checkArguments($conf);unset($conf);#如果檢查參數失敗if($checkArguments["status"]==="false"){#設置執行失敗$result["status"]="false";#設置錯誤訊息$result["error"]=$checkArguments;#印出結果var_dump($result);#結束執行,跟回傳錯誤代碼.exit(1);}#if end#如果檢查參數不通過if($checkArguments["passed"]==="false"){#設置執行失敗$result["status"]="false";#設置錯誤訊息$result["error"]=$checkArguments;#印出結果var_dump($result);#結束執行,跟回傳錯誤代碼.exit(1);}#if end#如果有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#如果有client參數if(isset($parseArgu["content"]["client"])){#預設沒有id$clientId="";#如果第一個參數為 "--client true"if($parseArgu["content"]["client"][0]==="true"){#函式說明:#連線到 unixDomainSockServer 提供的 unix domain socket.#回傳結果:#$result["status"],"true"代表執行正常;"false"代表執行不正常.#$result["error"],錯誤訊息陣列.#$result["function"],當前執行的函式名稱.#$result["content"],取得的回應.#必填參數:#$conf["sock"],字串,要連線的unix domain socket.$conf["sock"]=$unixSocket;#可省略參數:#$conf["id"],字串,取得的id,若無此值,則會得到新的數值.#$conf["id"]="";#$conf["cmd"],字串,要執行的指令,當$conf["id"]參數合法時,才會執行.#$conf["cmd"]="";#$conf["param"],參數陣列.#$conf["param"]=array();#$conf["escaped"],字串,param參數是否已經escaped了,預設為"false",反之為"true".#$conf["escaped"]="true";#$conf["custom"],陣列,要客制化傳輸的內容,會覆蓋以上除了$conf["id"]以外的可省略參數.#$conf["custom"]=array();#參考資料:#http://php.net/manual/en/function.stream-socket-client.php#http://php.net/manual/en/function.stream-get-contents.php#備註:#無.$unixDomainSockClient=sock::unixDomainSockClient($conf);unset($conf);#如果執行失敗if($unixDomainSockClient["status"]==="false"){#設置執行失敗$result["status"]="false";#設置錯誤訊息$result["error"]=$unixDomainSockClient;#印出結果var_dump($result);#結束執行,跟回傳錯誤代碼.exit(1);}#if end#取得會應$res=$unixDomainSockClient["content"];#解析回應$res=(array)json_decode(trim($res));#debug#var_dump($res);#如果沒有給予 idif(!isset($res["id"])){#設置執行失敗$result["status"]="false";#設置錯誤訊息$result["error"][]="id not found";#設置錯誤訊息$result["error"][]=$res;#印出結果var_dump($result);#結束執行,跟回傳錯誤代碼.exit(1);}#if end#取得用戶端的id$clientId=$res["id"];}#if end#如果有要增加暫時的白名單if(isset($parseArgu["content"]["client-add-tmp-white-ip"])){#針對每個要增加暫時的白名單foreach($parseArgu["content"]["client-add-tmp-white-ip"] as $tmpWhilteIp){#要求 server 端增加暫時白名單 - start#產生要傳遞的陣列$request=array();#設置要新增暫時白名單的ip$request["add-tmp-white-ip"]=$tmpWhilteIp;#函式說明:#連線到 unixDomainSockServer 提供的 unix domain socket.#回傳結果:#$result["status"],"true"代表執行正常;"false"代表執行不正常.#$result["error"],錯誤訊息陣列.#$result["function"],當前執行的函式名稱.#$result["content"],取得的回應.#必填參數:#$conf["sock"],字串,要連線的unix domain socket.$conf["sock"]=$unixSocket;#可省略參數:#$conf["id"],字串,取得的id,若無此值,則會得到新的數值.$conf["id"]=$clientId;#$conf["cmd"],字串,要執行的指令,當$conf["id"]參數合法時,才會執行.#$conf["cmd"]="";#$conf["param"],參數陣列.#$conf["param"]=array();#$conf["escaped"],字串,param參數是否已經escaped了,預設為"false",反之為"true".#$conf["escaped"]="true";#$conf["custom"],陣列,要客制化傳輸的內容,會覆蓋以上除了$conf["id"]以外的可省略參數.$conf["custom"]=$request;#參考資料:#http://php.net/manual/en/function.stream-socket-client.php#http://php.net/manual/en/function.stream-get-contents.php#備註:#無.$unixDomainSockClient=sock::unixDomainSockClient($conf);unset($conf);#debug#var_dump($unixDomainSockClient);#如果執行失敗if($unixDomainSockClient["status"]==="false"){#設置執行失敗$result["status"]="false";#設置錯誤訊息$result["error"]=$unixDomainSockClient;#印出結果var_dump($result);#結束執行,跟回傳錯誤代碼.exit(1);}#if end#取得回應$res=$unixDomainSockClient["content"];#解析回應$res=(array)json_decode(trim($res));#要求 server 端增加暫時白名單 - end}#foreach end}#if end#如果有要更新暫存白名單的有效時間if(isset($parseArgu["content"]["client-update-tmp-white-ip-valid-time"])){#要求 server 端更新暫時白名單的期限 - start#產生要傳遞的陣列$request=array();#設置要更新暫時白名單ip的有效時間$request["update-tmp-white-ip-valid-time"]=$parseArgu["content"]["client-update-tmp-white-ip-valid-time"][0];#函式說明:#連線到 unixDomainSockServer 提供的 unix domain socket.#回傳結果:#$result["status"],"true"代表執行正常;"false"代表執行不正常.#$result["error"],錯誤訊息陣列.#$result["function"],當前執行的函式名稱.#$result["content"],取得的回應.#必填參數:#$conf["sock"],字串,要連線的unix domain socket.$conf["sock"]=$unixSocket;#可省略參數:#$conf["id"],字串,取得的id,若無此值,則會得到新的數值.$conf["id"]=$clientId;#$conf["cmd"],字串,要執行的指令,當$conf["id"]參數合法時,才會執行.#$conf["cmd"]="";#$conf["param"],參數陣列.#$conf["param"]=array();#$conf["escaped"],字串,param參數是否已經escaped了,預設為"false",反之為"true".#$conf["escaped"]="true";#$conf["custom"],陣列,要客制化傳輸的內容,會覆蓋以上除了$conf["id"]以外的可省略參數.$conf["custom"]=$request;#參考資料:#http://php.net/manual/en/function.stream-socket-client.php#http://php.net/manual/en/function.stream-get-contents.php#備註:#無.$unixDomainSockClient=sock::unixDomainSockClient($conf);unset($conf);#如果執行失敗if($unixDomainSockClient["status"]==="false"){#設置執行失敗$result["status"]="false";#設置錯誤訊息$result["error"]=$unixDomainSockClient;#印出結果var_dump($result);#結束執行,跟回傳錯誤代碼.exit(1);}#if end#取得回應$res=$unixDomainSockClient["content"];#解析回應$res=(array)json_decode(trim($res));#要求 server 端更新暫時白名單的期限 - end}#if end#client端程式結束,結束執行exit;}#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(1);}#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#暫時的白名單$excludeIpsTmp=array();#函式說明:#建立 unix domain socket server, 僅提供具備檔案存取權限的用戶使用,預設提供可以下達任何指令的功能.#回傳結果:#$result["status"],"true"代表執行正常;"false"代表執行不正常.#$result["error"],錯誤訊息陣列.#$result["function"],當前執行的函式名稱.#必填參數:#$conf["sock"],字串,socket檔案要放在哪邊,名稱為何.$conf["sock"]=$unixSocket;#$conf["fileArgu"],字串,變數__FILE__的內容.$conf["fileArgu"]=__FILE__;#可省略參數:#$conf["changeOwner"],字串,要將socket檔案的擁有着權限進行修改."user.group"代表擁有者帳號為user,群組為group.#$conf["changeOwner"]="";#$conf["changePermission"],字串,要將socket檔案的權限設為多少.ex: 0666(所有帳戶都有存取的權限) 或 0660(僅有擁有者與群組帳戶有存取的權限) 或 0600(只有擁有者有權限執行).$conf["changePermission"]="0666";#$conf["sessionTimeout"],字串,當連線結束後於下一次連線間隔多久就算session timeout,server端會將記錄移除,client端需要重新拿取id,預設為300秒.#$conf["sessionTimeout"]="300";#$conf["addOnProcessFunc"],字串陣列,增加用於處理 json request 的函式名稱,給予的參數為array("request"=>收到的json訊息,"sock"=>用戶的socket).$conf["addOnProcessFunc"]=array("\qbpwcf\addOnProcessFunc");#$conf["funcToRunWhenIdle"],字串陣列,當沒有事件產生時,要執行的函式名稱,給予參數為array("client"=>所有用戶).$conf["funcToRunWhenIdle"]=array("\qbpwcf\\funcToRunWhenIdle");#$conf["infoToFunction"],陣列,需要增加給addOnProcessFunc跟funcToRunWhenIdle函式的資訊,在函式中其參數的info鍵值.$conf["infoToFunction"]=array("debug"=>&$debug,"preTimeFloat"=>&$preTimeFloat,"excludeIpsTmp"=>&$excludeIpsTmp,"excludeIp"=>&$excludeIp,"tmp-white-ip-valid-time"=>&$tmp_white_ip_valid_time);#參考資料:#http://php.net/manual/en/function.stream-socket-server.php#備註:#無.$unixDomainSockServer=sock::unixDomainSockServer($conf);unset($conf);#當執行失敗if($unixDomainSockServer["status"]==="false"){#設置執行失敗$result["status"]="false";#設置錯誤訊息$result["error"]=$unixDomainSockServer;#印出結果var_dump($result);#結束執行,跟回傳錯誤代碼.exit(1);}#if end#收到訊息要怎麼處理的函式function addOnProcessFunc($params){#debug#var_dump(__LINE__,$params["request"]);#取得收到的訊息$receivedArray=$params["request"];#取得用戶的 socket$clientSock=$params["socket"];#預設不 debug$debug=false;#如果有debug鍵數值.if(isset($params["info"]["debug"])){#設置之$debug=$params["info"]["debug"];}#if end#debug modeif($debug){#debugvar_dump(__LINE__,$params);}#if end#如果解析 json 失敗if(json_last_error()!==JSON_ERROR_NONE){#初始化結果$result=array();#設置執行失敗$result["status"]="false";#記錄錯誤訊息$result["error"]=json_last_error_msg();#回覆錯誤訊息fwrite($clientSock,json_encode($result).PHP_EOL);#初始化要回傳的訊息$result=array();#設置不繼續執行$result["continue"]="false";#回傳結果return $result;}#if end#debug modeif($debug){#debugvar_dump(__LINE__,$receivedArray);}#if end#如果要新增暫時的ip白名單if(isset($receivedArray["add-tmp-white-ip"])){#函式說明:#將多個多維陣列串聯起來,key從0開始排序.#回傳的結果:#$result["status"],"true"表執行正常,"false"代表執行不正常.#$result["error"],錯誤訊息陣列.#$result["function"],當前執行的函數.#$result["content"],合併好的一維陣列.#必填參數#$conf["inputArray"],陣列,要合併的一維陣列變數,例如:=array($array1,$array2);$conf["inputArray"]=array($params["info"]["excludeIpsTmp"],array(array("ip"=>$receivedArray["add-tmp-white-ip"],"unixtime"=>time())));#可省略參數:#$conf["allowRepeat"],字串,預設為"false",不允許重複的結果;反之為"true".#$conf["allowRepeat"]="true";#$conf["equalKeyStruc"],字串陣列,若 allowRepeat 參數為 "false", 這該參數生效.該參數為用來判斷每個陣列的哪個鍵值路徑底下的數值相同時要進行取代,後者會取代前者.$conf["equalKeyStruc"]=array("ip");#參考資料:#無.#備註:#無.$mergeMultiDimensionArray=arrays::mergeMultiDimensionArray($conf);unset($conf);#debug modeif($debug){#debugvar_dump(__LINE__,$mergeMultiDimensionArray);}#if end#如果運行失敗if($mergeMultiDimensionArray["status"]==="false"){#設置執行失敗$result["status"]="false";#設置錯誤訊息$result["error"]=$mergeMultiDimensionArray;#印出結果var_dump($result);#結束執行exit(1);}#if end#更新白名單$params["info"]["excludeIpsTmp"]=$mergeMultiDimensionArray["content"];#debug modeif($debug){#debugvar_dump(__LINE__,$params["info"]["excludeIpsTmp"]);}#if end}#if end#反之收到 update-tmp-white-ip-valid-timeif(isset($receivedArray["update-tmp-white-ip-valid-time"])){#更新白名單有效時間$params["info"]["tmp-white-ip-valid-time"]=$receivedArray["update-tmp-white-ip-valid-time"];#debug modeif($debug){#debugvar_dump(__LINE__,$params["info"]["tmp-white-ip-valid-time"]);}#if end}#if end#初始化要回傳的結果$result=array();#設置執行正常$result["status"]="true";#設置可以繼續執行後面的函式$result["continue"]="true";#回傳結果return $result;}#function addOnProcessFunc end#沒事時要重複執行的函式function funcToRunWhenIdle($params){#預設不 debug$debug=false;#如果有debug鍵數值.if(isset($params["info"]["debug"])){#設置之$debug=$params["info"]["debug"];}#if end#debug modeif($debug){#commentecho "new round".PHP_EOL;}#if end#debug modeif($debug){#commentecho "\$preHttpTimeFloat:".$params["info"]["preTimeFloat"]["http"].PHP_EOL;echo "\$preHttpsTimeFloat:".$params["info"]["preTimeFloat"]["https"].PHP_EOL;echo "\$preSmtpTimeFloat:".$params["info"]["preTimeFloat"]["smtp"].PHP_EOL;echo "\$preImapTimeFloat:".$params["info"]["preTimeFloat"]["imap"].PHP_EOL;echo "\$preNamedTimeFloat:".$params["info"]["preTimeFloat"]["named"].PHP_EOL;}#if end#函式說明:#檢查多個檔案與資料夾是否存在.#回傳的結果:#$result["status"],執行正常與否,"true"代表正常,"false"代表不正常.#$result["error"],錯誤訊息陣列.#$resutl["function"],當前執行的涵式名稱.#$result["argu"],使用的參數.#$result["allExist"],所有檔案皆存在的識別,"true"代表皆存在,"false"代表沒有全部都存在.#$result["varName"][$i],爲第$i個資料夾或檔案的路徑與名稱。#$result["varNameFullPath"][$i],爲第$i個資料夾或檔案的完整檔案系統路徑與名稱,如果不存在則代表路徑是網址.#$result["varNameWebPath"][$i],為第$i個資料夾或檔案的網址,若"web"參數為"true",才會有該內容.#$result["varExist"][$i],爲第$i個資料夾或檔案是否存在,"true"代表存在,"false"代表不存在。#必填參數:#$conf["fileArray"],陣列字串,要檢查是否存在的檔案有哪些,須爲一維陣列數值。$conf["fileArray"]=array("/var/log/httpd/access_log");#$conf["fileArgu"],字串,php變數__FILE__的內容,亦即該檔案在檔案系統的絕對路徑$conf["fileArgu"]=__FILE__;#可省略參數:#$conf["disableWebSearch"],"字串",是否取消「當檔案找不到時,改用catchWebContent類別的wget函數來檢查檔案是否存在於網路上」的功能,"false"不取消,若要取消該功能請設為"true",若抓到的內容為空字串則會視為檔案不存在,預設為"true".#$conf["disableWebSearch"]="false";#$conf["userDir"],字串,網頁是否置放於家目錄底下,"true"為是,"false"為不是,預設為"true".$conf["userDir"]="false";#$conf["web"],字串,檔案是放在web就是"true",反之為檔案系統"false",預設為"true".$conf["web"]="false";#參考資料:#http://php.net/manual/en/function.file-exists.php#http://php.net/manual/en/control-structures.foreach.php#備註:#函數file_exists檢查的路徑為檔案系統的路徑#$result["varName"][$i]結果未實作$checkMultiFileExist=fileAccess::checkMultiFileExist($conf);unset($conf);#如果運行失敗if($checkMultiFileExist["status"]==="false"){#設置執行失敗$result["status"]="false";#設置錯誤訊息$result["error"]=$checkMultiFileExist;#印出結果var_dump($checkMultiFileExist);#結束執行exit(1);}#if end#初始化 http log 的最後變更時間$httpTimeFloat=0;#如果存在 http logif($checkMultiFileExist["allExist"]==="true"){#函數說明:#依據取得檔案的擁有着資訊#回傳結果:#$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(1);}#if end#debugif($debug){#commentecho "accessed file /var/log/httpd/access_log".PHP_EOL;}#if end#記錄 http log 的最後變更時間$httpTimeFloat=$httpFileInfo["content"]["modifyTimeFloat"];}#if end#函式說明:#檢查多個檔案與資料夾是否存在.#回傳的結果:#$result["status"],執行正常與否,"true"代表正常,"false"代表不正常.#$result["error"],錯誤訊息陣列.#$resutl["function"],當前執行的涵式名稱.#$result["argu"],使用的參數.#$result["allExist"],所有檔案皆存在的識別,"true"代表皆存在,"false"代表沒有全部都存在.#$result["varName"][$i],爲第$i個資料夾或檔案的路徑與名稱。#$result["varNameFullPath"][$i],爲第$i個資料夾或檔案的完整檔案系統路徑與名稱,如果不存在則代表路徑是網址.#$result["varNameWebPath"][$i],為第$i個資料夾或檔案的網址,若"web"參數為"true",才會有該內容.#$result["varExist"][$i],爲第$i個資料夾或檔案是否存在,"true"代表存在,"false"代表不存在。#必填參數:#$conf["fileArray"],陣列字串,要檢查是否存在的檔案有哪些,須爲一維陣列數值。$conf["fileArray"]=array("/var/log/httpd/ssl_access_log");#$conf["fileArgu"],字串,php變數__FILE__的內容,亦即該檔案在檔案系統的絕對路徑$conf["fileArgu"]=__FILE__;#可省略參數:#$conf["disableWebSearch"],"字串",是否取消「當檔案找不到時,改用catchWebContent類別的wget函數來檢查檔案是否存在於網路上」的功能,"false"不取消,若要取消該功能請設為"true",若抓到的內容為空字串則會視為檔案不存在,預設為"true".#$conf["disableWebSearch"]="false";#$conf["userDir"],字串,網頁是否置放於家目錄底下,"true"為是,"false"為不是,預設為"true".$conf["userDir"]="false";#$conf["web"],字串,檔案是放在web就是"true",反之為檔案系統"false",預設為"true".$conf["web"]="false";#參考資料:#http://php.net/manual/en/function.file-exists.php#http://php.net/manual/en/control-structures.foreach.php#備註:#函數file_exists檢查的路徑為檔案系統的路徑#$result["varName"][$i]結果未實作$checkMultiFileExist=fileAccess::checkMultiFileExist($conf);unset($conf);#如果運行失敗if($checkMultiFileExist["status"]==="false"){#設置執行失敗$result["status"]="false";#設置錯誤訊息$result["error"]=$checkMultiFileExist;#印出結果var_dump($checkMultiFileExist);#結束執行exit(1);}#if end#初始化 https log 的最後變更時間$httpsTimeFloat=0;#如果存在 https logif($checkMultiFileExist["allExist"]==="true"){#函數說明:#依據取得檔案的擁有着資訊#回傳結果:#$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(1);}#if end#debugif($debug){#commentecho "accessed file /var/log/httpd/ssl_access_log".PHP_EOL;}#if end#記錄 https log 的最後變更時間$httpsTimeFloat=$httpsFileInfo["content"]["modifyTimeFloat"];}#if end#透過運行以下指令取得最後變更時間#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(1);}#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(1);}#if end#記錄 smtpd log 最後變更的時間$smtpTimeFloat=$spiltMutiString["spiltString"][0]["dataArray"][2];}#if end#反之沒變動else{#沿用上次時間$smtpTimeFloat=$params["info"]["preTimeFloat"]["smtp"];}#else ebd#透過運行以下指令取得最後變更時間#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(1);}#if end#debugif($debug){#commentecho "accessed file dovecot/imap log".PHP_EOL;}#if end#取得行數$lineCount=count($callShell["output"]);#如果行數等於1if($lineCount===1){#debugif($debug){#最新一筆惡意IPecho "最新一筆惡意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(1);}#if end#記錄 smtpd log 最後變更的時間$imapTimeFloat=$spiltMutiString["spiltString"][0]["dataArray"][2];}#if end#反之沒變動else{#沿用上次時間$imapTimeFloat=$params["info"]["preTimeFloat"]["imap"];}#else ebd#透過 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(1);}#if end#debugif($debug){#commentecho "accessed file named log".PHP_EOL;}#if end#取得行數$lineCount=count($callShell["output"]);#如果行數等於1if($lineCount===1){#debugif($debug){#最新一筆惡意IPecho "最新一筆惡意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(1);}#if end#記錄 named log 最後變更的時間$namedTimeFloat=$spiltMutiString["spiltString"][0]["dataArray"][2];}#if end#反之無變動else{#沿用上次的時間$namedTimeFloat=$params["info"]["preTimeFloat"]["named"];}#else end#debug modeif($debug){#commentecho "\$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($params["info"]["preTimeFloat"]["http"]===0 && $params["info"]["preTimeFloat"]["https"]===0 && $params["info"]["preTimeFloat"]["smtp"]===0 && $params["info"]["preTimeFloat"]["imap"]===0 && $params["info"]["preTimeFloat"]["named"]===0){#將本次http記錄覆寫到上次的記錄$params["info"]["preTimeFloat"]["http"]=$httpTimeFloat;#將本次https記錄覆寫到上次的記錄$params["info"]["preTimeFloat"]["https"]=$httpsTimeFloat;#將本次smtps記錄覆寫到上次的記錄$params["info"]["preTimeFloat"]["smtp"]=$smtpTimeFloat;#將本次imaps記錄覆寫到上次的記錄$params["info"]["preTimeFloat"]["imap"]=$imapTimeFloat;#將本次nmaed記錄覆寫到上次的記錄$params["info"]["preTimeFloat"]["named"]=$namedTimeFloat;#睡一秒sleep(1);#debug modeif($debug){#commentecho "第一次運行,不做事".PHP_EOL;}#if end#結束執行return;}#if end#非第一次運行,且 http 與 https 與 imap 與 smtp 與 named log 都沒變動過.else if($params["info"]["preTimeFloat"]["http"]===$httpTimeFloat && $params["info"]["preTimeFloat"]["https"]===$httpsTimeFloat && $params["info"]["preTimeFloat"]["smtp"]===$smtpTimeFloat && $params["info"]["preTimeFloat"]["imap"]===$imapTimeFloat && $params["info"]["preTimeFloat"]["named"]===$namedTimeFloat ){#睡一秒sleep(1);#debug modeif($debug){#commentecho "Log檔無變動,不做事".PHP_EOL;}#if end#結束執行return;}#else end#debug modeif($debug){#commentecho "Log檔有變動,要做事".PHP_EOL;echo "\$preHttpTimeFloat:".$params["info"]["preTimeFloat"]["http"].PHP_EOL;echo "\$preHttpsTimeFloat:".$params["info"]["preTimeFloat"]["https"].PHP_EOL;echo "\$preSmtpTimeFloat:".$params["info"]["preTimeFloat"]["smtp"].PHP_EOL;echo "\$preImapTimeFloat:".$params["info"]["preTimeFloat"]["imap"].PHP_EOL;echo "\$preNamedTimeFloat:".$params["info"]["preTimeFloat"]["named"].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記錄覆寫到上次的記錄$params["info"]["preTimeFloat"]["http"]=$httpTimeFloat;#將本次https記錄覆寫到上次的記錄$params["info"]["preTimeFloat"]["https"]=$httpsTimeFloat;#初始化儲存暫時ip白名單的陣列$excludeIpsTmp=array();#針對每個暫時白名單ipforeach($params["info"]["excludeIpsTmp"] as $index=>$tmpIpInfo){#若暫存白名單已經過期if($tmpIpInfo["unixtime"]<time()-$params["info"]["tmp-white-ip-valid-time"]*3600){#卸除之unset($params["info"]["excludeIpsTmp"][$index]);}#if end#反之else{#變成 $excludeIpsTmp 的內容$excludeIpsTmp[]=$params["info"]["excludeIpsTmp"][$index]["ip"];}#else end}#foreach end#函式說明:#將多個多維陣列串聯起來,key從0開始排序.#回傳的結果:#$result["status"],"true"表執行正常,"false"代表執行不正常.#$result["error"],錯誤訊息陣列.#$result["function"],當前執行的函數.#$result["content"],合併好的一維陣列.#必填參數#$conf["inputArray"],陣列,要合併的一維陣列變數,例如:=array($array1,$array2);$conf["inputArray"]=array($params["info"]["excludeIp"],$excludeIpsTmp);#可省略參數:#$conf["allowRepeat"],字串,預設為"false",不允許重複的結果;反之為"true".#$conf["allowRepeat"]="true";#$conf["equalKeyStruc"],字串陣列,若 allowRepeat 參數為 "false", 這該參數生效.該參數為用來判斷每個陣列的哪個鍵值路徑底下的數值相同時要進行取代,後者會取代前者.#$conf["equalKeyStruc"]=array();#參考資料:#無.#備註:#無.$mergeMultiDimensionArray=arrays::mergeMultiDimensionArray($conf);unset($conf);#如果執行失敗if($mergeMultiDimensionArray["status"]==="false"){#設置執行失敗$result["status"]="false";#設置錯誤訊息$result["error"]=$mergeMultiDimensionArray;#回傳結果var_dump($result);#結束執行exit(1);}#if end#debug#var_dump(__LINE__,$mergeMultiDimensionArray);#涵式說明:#檢查 httpd 與 postfix/smtpd 的 log 與 named 的 log 與 sshd 的 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"]=$mergeMultiDimensionArray["content"];#$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(1);}#if end#如果有執行封鎖IP的情形if(isset($blockAcctackIp["content"])){#commentecho "本次封鎖IP的結果如下:".PHP_EOL;var_dump($blockAcctackIp["content"]);var_dump($blockAcctackIp["reason"]);}#if end#睡一秒sleep(1);#結束執行return;}//function funcToRunWhenIdle end?>