Rev 376 | Blame | Compare with Previous | Last modification | View Log | RSS feed
<?php/*QBPWCF, Quick Build PHP website Component base on Fedora Linux.Copyright (C) 2014~2026 MIN ZHI, 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/>.*/namespace qbpwcf;/*類別說明:跟網頁、資訊安全性有關的類別.備註:無.*/class security{/*#函式說明:#當前類別被呼叫的靜態方法不存在時,將會執行該函數,回報該方法不存在.#回傳結果:#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.#$reuslt["error"],執行不正常結束的錯訊息陣列.#$result["function"],當前執行的函式名稱.#必填參數:#$method,物件,為物件實體或類別名稱,會自動置入該參數.#$arguments,陣列,為呼叫方法時所用的參數.#可省略參數:#無.#參考資料:#__call=>http://php.net/manual/en/language.oop5.overloading.php#object.callstatic#備註:#無.*/public function __call($method,$arguments){#取得當前執行的函式$result["function"]=__FUNCTION__;#設置執行不正常$result["status"]="false";#設置執行錯誤$result["error"][]=__NAMESPACE__ ."/".$method."() 不存在!";#設置所丟入的參數$result["error"][]=$arguments;#回傳結果return $result;}#function __call end/*#函式說明:#當前類別被呼叫的靜態方法不存在時,將會執行該函數,回報該方法不存在.#回傳結果:#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.#$reuslt["error"],執行不正常結束的錯訊息陣列.#$result["function"],當前執行的函式名稱.#必填參數:#$method,物件,為物件實體或類別名稱,會自動置入該參數.#$arguments,陣列,為呼叫方法時所用的參數.#可省略參數:#無.#參考資料:#__callStatic=>http://php.net/manual/en/language.oop5.overloading.php#object.callstatic#備註:#無.*/public static function __callStatic($method,$arguments){#取得當前執行的函式$result["function"]=__FUNCTION__;#設置執行不正常$result["status"]="false";#設置執行錯誤$result["error"][]="欲呼叫的". __NAMESPACE__ ."/".$method."() 不存在!";#設置所丟入的參數$result["error"][]=$arguments;#回傳結果return $result;}#function __callStatic end/*#函式說明:#禁止特定的angent訪問我們的網站,例如google與百度的搜尋引擎。#回傳結果:#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.#$result["error"],錯誤訊息.#$result["function"],當前執行的函數名稱.#必填參數:#$conf["disableAngentName"],字串,要禁止拜訪的用戶端資訊,代表要禁止哪些瀏覽器/搜尋引擎瀏覽,格式爲 /(含有哪些關鍵字,若有多個請用「|」隔開。)/i.$conf["disableAngentName"]="/(Chrome|Mozilla|Internet)/i";#可省略參數:#$conf["transferLocation"],字串,如果是要禁止搜尋引擎,要轉址到那個地方?,若沒設定,則預設爲資安素養網的臉書(https://zh-tw.facebook.com/isafemoe).#$conf["transferLocation"]="";#參考資料:#http://php.net/manual/en/function.preg-match.php#備註:#無.*/public static function preventSerchEngine(&$conf){#初始化要回傳的內容$result=array();#取得當前執行的函式$result["function"]=__FUNCTION__;#如果 $conf 不為陣列if(gettype($conf)!="array"){#設置執行失敗$result["status"]="false";#設置執行錯誤訊息$result["error"][]="\$conf變數須為陣列形態";#如果傳入的參數為 nullif($conf==null){#設置執行錯誤訊息$result["error"][]="\$conf變數不得為null,請檢查函數「".$result["function"]."」的參數設置有無正確!";}#if end#回傳結果return $result;}#if end#debug,檢查 $_SERVER["HTTP_USER_AGENT"] 的內容#var_dump($_SERVER['HTTP_USER_AGENT']);#檢查參數#函式說明:#檢查必填與可省略的參數,可省略參數可指定預設要給與什麼數值內容。#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.#$reuslt["error"],執行不正常結束的錯訊息陣列.#$result["function"],當前執行的函式名稱.#$result["passed"],識別要檢查的全體變數是否存在以及型態是否正確的變數,"true"代表檢查全部通過;"false"代表檢查不通過#$result[$shouldBtCheckedVarName]["varExist"],所檢查的變數是否存在,"false"代表不存在;"true"代表存在#$result[$shouldBtCheckedVarName]["varType"],所檢查的變數型態是否正確,"false"代表錯誤;"true"代表正確#$result[$shouldBtCheckedVarName]["error"],每個參數設定的錯誤訊息#$result["argu"],字串陣列,目前輸入的參數名稱陣列.#$result["legalVarName"],字串陣列,合法可用的參數名稱陣列.#$result["notNeedVar"],字串陣列,多餘的參數名稱.#必填寫的參數:#$conf["variableCheck::checkArguments"]["varInput"],陣列變數,要檢查的陣列變數,請在要檢查的參數前面加上&,這樣變動的結果才能被套用。$conf["variableCheck::checkArguments"]["varInput"]=&$conf;#$conf["variableCheck::checkArguments"]["mustBeFilledVariableName"],爲必填參數的變數名稱陣列,形態爲陣列變數,元素數量需要跟"mustBeFilledVariableType"參數的元素數量一致,例如: $conf["mustBeFilledVariableName"] = array("id","account","password");$conf["variableCheck::checkArguments"]["mustBeFilledVariableName"]=array("disableAngentName");#$conf["variableCheck::checkArguments"]["mustBeFilledVariableType"],爲必填參數的變數陣列應該爲何種變數形態,形態爲陣列,元素數量需要跟"mustBeFilledVariableName"參數的元素數量一致,例如: $conf["mustBeFilledVariableType"] = array("string",integer,"double","resource","object");$conf["variableCheck::checkArguments"]["mustBeFilledVariableType"]=array("string");#$conf["variableCheck::checkArguments"]["referenceVarKey"],字串,$conf參數後面的key值,用於移除不要的參考陣列.$conf["variableCheck::checkArguments"]["referenceVarKey"]="variableCheck::checkArguments";#可以省略的參數:#$conf["canBeEmptyString"],必填變數內容如果是空字串就不能算是有設置的話,請設為"false",預設爲"true"。#$conf["canBeEmptyString"]="false";#$conf["variableCheck::checkArguments"]["skipableVariableName"],爲可省略參數的變數名稱陣列,形態爲陣列變數,例如: $conf["skipableVariableName"] = array("id","account","password");$conf["variableCheck::checkArguments"]["skipableVariableName"]=array("transferLocation");#$conf["variableCheck::checkArguments"]["skipableVariableType"],爲可省略參數的變數名稱陣列,形態爲陣列變數,例如: $conf["skipableVariableType"] = array("string",integer,"double");$conf["variableCheck::checkArguments"]["skipableVariableType"]=array("string");#$conf["variableCheck::checkArguments"]["skipableVarDefaultValue"],字串陣列,每個不存在的可省略變數要初始化為什麼,null與代表不指定,若預設值是參數之一,請將$conf["mustBeFilledVar"]改成"\$conf["\mustBeFilledVar\"]".$conf["variableCheck::checkArguments"]["skipableVarDefaultValue"]=array("https://zh-tw.facebook.com/isafemoe");#$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["variableCheck::checkArguments"]);unset($conf["variableCheck::checkArguments"]);#如果檢查失敗if($checkArguments["status"]=="false"){#設置執行失敗$result["status"]="false";#設置執行錯誤訊息$result["error"]=$checkArguments;#回傳結果return $result;}#if end#如果檢查不通過if($checkArguments["passed"]=="false"){#設置執行失敗$result["status"]="false";#設置執行錯誤訊息$result["error"]=$checkArguments;#回傳結果return $result;}#if end#如果使用者的瀏覽器出現變數 $conf["disableAngentName"] 裡面的關鍵字if(preg_match($conf["disableAngentName"],$_SERVER["HTTP_USER_AGENT"])){#則轉址特定頁面#函式說明:#設定session變數後,立即轉址.#回傳結果:#$result["status"],執行是否成功,"true"代表成功,"false"代表不成功.#$result["function"],當前執行的函數名稱.#$result["error"],錯誤訊息陣列.#必填的參數:#$conf["header::redirectionNow"]["headerLocation"],為要轉址到的地方,若爲 $_SERVER["PHP_SELF"],則爲回到目前頁面,全民資安素養網爲 https://isafe.moe.edu.tw/.$conf["header::redirectionNow"]["headerLocation"]=$conf["transferLocation"];#可省略的參數:#$conf["sessionName"],字串陣列,可以指派session變數的名稱.#$conf["sessionName"]=array("");#$conf["sessionValue"]字串陣列,可以指派session變數的內容.#$conf["sessionValue"]=array("");#參靠資料來源:#http://php.net/manual/en/reserved.variables.server.php$redirectionNow=header::redirectionNow($conf["header::redirectionNow"]);unset($conf["header::redirectionNow"]);#如果轉址失敗if($redirectionNow["status"]=="false"){#設置執行失敗$result["status"]="false";#設置執行錯誤訊息$result["error"]=$redirectionNow;#回傳結果return $result;}#if end}#if end#執行到這邊代表是可以拜訪的網頁瀏覽器$result["status"]="true";#回傳結果return $result;}#function preventSerchEngine end/*#函式說明:#禁止做任違反版權的事情,禁止在網頁按下滑鼠右鍵,禁止複製圖片,禁止開新分頁(失敗), 版權所有、Power by訊息.#回傳的內容:#保護版權的語法#必填參數:#無#可省略參數:#$conf["name"],字串,公司、組織、單位的名稱,預設不指定.#$conf["name"]="";#$conf["powerBy"],字串,由誰提供,預設爲QBPWCF.#$conf["powerBy"]="";#$conf["powerByLink"],字串,power by字串的連結目標,預設爲"https://www.qbpwcf.org".#$conf["powerByLink"]="";#$conf["bgColor"],字串,背景顏色,預設爲淡藍色.#$conf["bgColor"]="";#參考資料:#http://www.w3schools.com/jsref/dom_obj_event.asp#備註:#無.*/public static function copyRight(&$conf){#初始化要回傳的結果$result=array();#取得當前執行的函數名稱$result["function"]=__FUNCTION__;#取得參數$result["argu"]=$conf;#如果 $conf 不為陣列if(gettype($conf)!="array"){#設置執行失敗$result["status"]="false";#設置執行錯誤訊息$result["error"][]="\$conf變數須為陣列形態";#如果傳入的參數為 nullif(is_null($conf)){#設置執行錯誤訊息$result["error"][]="\$conf變數不得為null,請檢查函數「".$result["function"]."」的參數設置有無正確!";}#if end#回傳結果return $result;}#if end#初始化 content$result["content"]="";#函式說明:#檢查必填與可省略的參數,可省略參數可指定預設要給與什麼數值內容。#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.#$reuslt["error"],執行不正常結束的錯訊息陣列.#$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["variableCheck::checkArguments"]["varInput"]=&$conf;#$conf["referenceVarKey"],字串,$conf參數後面的key值,用於移除不要的參考陣列.$conf["variableCheck::checkArguments"]["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["variableCheck::checkArguments"]["skipableVariableCanNotBeEmpty"]=array("powerBy","powerByLink","bgColor");#$conf["skipableVariableName"],陣列字串,爲可省略參數的變數名稱陣列,形態爲陣列變數,例如: $conf["skipableVariableName"] = array("id","account","password");$conf["variableCheck::checkArguments"]["skipableVariableName"]=array("name","powerBy","powerByLink","bgColor");#$conf["skipableVariableType"],陣列字串,爲可省略參數的變數名稱陣列,形態爲陣列變數,例如: $conf["skipableVariableType"] = array("string",integer,"double");$conf["variableCheck::checkArguments"]["skipableVariableType"]=array("string","string","string","string");#$conf["skipableVarDefaultValue"],字串陣列,每個不存在的可省略變數要初始化為什麼,null與代表不指定,若預設值是參數之一,請將$conf["mustBeFilledVar"]改成"\$conf["\mustBeFilledVar\"]".$conf["variableCheck::checkArguments"]["skipableVarDefaultValue"]=array("","QBPWCF","https://www.qbpwcf.org","#DDDDFF");#$conf["disallowAllSkipableVarIsEmpty"],字串,是否允許每個可省略參數都為空字串,預設為"true"允許,反之為"false".#$conf["disallowAllSkipableVarIsEmpty"]="";#$conf["disallowAllSkipableVarIsEmptyArray"],字串,是否允許每個可省略參數都為空陣列,預設為"true"允許,反之為"false".#$conf["disallowAllSkipableVarIsEmptyArray"]="";#$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["variableCheck::checkArguments"]);unset($conf["variableCheck::checkArguments"]);#如果檢查失敗if($checkArguments["status"]=="false"){#設置錯誤狀態$result["status"]="false";#設置錯誤提示$result["error"]=$checkArguments;#回傳結果return $result;}#if end#如果檢查不通過if($checkArguments["passed"]=="false"){#設置錯誤狀態$result["status"]="false";#設置錯誤提示$result["error"]=$checkArguments;#回傳結果return $result;}#if end#函式說明:#將要執行的script語法透過該函式執行(會在程式外層用<script></script>包起來).#回傳結果:#$result["status"],執行是否正常,"true"為正常,"false"為不正常.#$result["error"],錯誤訊息陣列#$result["function"],當前執行的函數名稱#$result["content"],要執行的javaScript語法#必填參數:#$conf["script"],字串,要執行的javaScript語法.$conf["javaScript::toScript"]["script"]="var copyRightSpan=document.createElement('span');var copyRightText=document.createTextNode('".$conf["name"]."');copyRightSpan.appendChild(copyRightText);//建立power by spanvar powerBySpan=document.createElement('span');var powerByA=document.createElement('a');powerByA.href='".$conf["powerByLink"]."';powerByA.target='_blank';var powerByText=document.createTextNode('Powered by '+'".$conf["powerBy"]."');powerByA.appendChild(powerByText);powerBySpan.appendChild(powerByA);//建立 copy right divvar copyRightDiv=document.createElement('div');copyRightDiv.appendChild(copyRightSpan);copyRightDiv.appendChild(powerBySpan);copyRightDiv.style.backgroundColor='".$conf["bgColor"]."';copyRightDiv.style.textAlign='center';//顯現 copy rightdocument.body.appendChild(copyRightDiv);";#可省略參數:#$conf["onReady"],字串,是否要在網頁完全載入後再執行,"false"為不等載入完就先執行,預設為"true"要等載入完再執行.#$conf["onReady"]="true";#$conf["globalJs"],字串陣列,為要放入<script>標籤的js全域變數.#$conf["globalJs"]=array();#$conf["jsFunciton"],字串陣列,為要放入<script>標籤的js函數.#$conf["jsFunciton"]=array();#參考資料:#http://stackoverflow.com/questions/9899372/pure-javascript-equivalent-to-jquerys-ready-how-to-call-a-function-when-the$toScript=javaScript::toScript($conf["javaScript::toScript"]);unset($conf["javaScript::toScript"]);#如果建立 javascript 語法失敗if($toScript["status"]==="false"){#設置執行失敗$result["status"]="false";#設置執行錯誤訊息$result["error"]=$toScript;#回傳結果return $result;}#if end#傳接 content$result["content"]=$result["content"].$toScript["content"];#保護版權的語法#oncontextmenu,按下滑鼠右鍵#onContextMenu,按下滑鼠右鍵#ondragstart,開始拖曳#onselsect,選取區塊時#onselectstart,開始選取區塊#onkeydown='if(event.tKey && event.ctrlKey),按下ctrl+t開分頁時$result["content"]=$result["content"]."<htmloncontextmenu=\"return false\"onContextMenu=\"window.event.returnValue=false\"onselect=\"return false\"onselectstart=\"return false\"ondragstart=\"return false\"oncopy=\"return false\"onbeforeprint=\"return false\">\r\n";#設置執行正常$result["status"]="true";#回傳語法return $result;}#函式結束/*#函式說明:#放置用空白圖片擋住要呈現的圖片#回傳結果:#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.#$result["error"],錯誤訊息.#$result["function"],當前執行的函數名稱.#$result["content"],語法.#必填參數:$conf["imgAddress"],字串,要放的圖片位置和名稱.$conf["imgAddress"]="";$conf["imgWidth"],字串,爲圖片的寬.$conf["imgWidth"]="";$conf["imgHeight"],字串,爲圖片的高.$conf["imgHeight"]="";$conf["imgLeft"]=,字串,爲圖片放置的位置距離網頁左邊多少.$conf["imgLeft"]="";$conf["imgTop"]=,字串,爲圖片放置的位置距離網頁頂端多少.$conf["imgTop"]="";#可省略參數:#$conf["useBase64"],字串,是否要用base64的方式呈現圖片,預設為"true"代表要用base64的方式呈現,反之可用"false".#$conf["useBase64"]="true";#參考資料:#無.#備註:#無.*/public static function imgProtect(&$conf){#初始化要回傳的內容$result=array();#取得當前執行的函式$result["function"]=__FUNCTION__;#如果 $conf 不為陣列if(gettype($conf)!="array"){#設置執行失敗$result["status"]="false";#設置執行錯誤訊息$result["error"][]="\$conf變數須為陣列形態";#如果傳入的參數為 nullif($conf==null){#設置執行錯誤訊息$result["error"][]="\$conf變數不得為null,請檢查函數「".$result["function"]."」的參數設置有無正確!";}#if end#回傳結果return $result;}#if end#初始化程式碼$result["content"]="";#檢查參數#函式說明:#檢查必填與可省略的參數,可省略參數可指定預設要給與什麼數值內容。#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.#$reuslt["error"],執行不正常結束的錯訊息陣列.#$result["function"],當前執行的函式名稱.#$result["passed"],識別要檢查的全體變數是否存在以及型態是否正確的變數,"true"代表檢查全部通過;"false"代表檢查不通過#$result[$shouldBtCheckedVarName]["varExist"],所檢查的變數是否存在,"false"代表不存在;"true"代表存在#$result[$shouldBtCheckedVarName]["varType"],所檢查的變數型態是否正確,"false"代表錯誤;"true"代表正確#$result[$shouldBtCheckedVarName]["error"],每個參數設定的錯誤訊息#$result["argu"],字串陣列,目前輸入的參數名稱陣列.#$result["legalVarName"],字串陣列,合法可用的參數名稱陣列.#$result["notNeedVar"],字串陣列,多餘的參數名稱.#必填寫的參數:#$conf["variableCheck::checkArguments"]["varInput"],陣列變數,要檢查的陣列變數,請在要檢查的參數前面加上&,這樣變動的結果才能被套用。$conf["variableCheck::checkArguments"]["varInput"]=&$conf;#$conf["variableCheck::checkArguments"]["mustBeFilledVariableName"],爲必填參數的變數名稱陣列,形態爲陣列變數,元素數量需要跟"mustBeFilledVariableType"參數的元素數量一致,例如: $conf["mustBeFilledVariableName"] = array("id","account","password");$conf["variableCheck::checkArguments"]["mustBeFilledVariableName"]=array("imgAddress","imgWidth","imgHeight","imgLeft","imgTop");#$conf["variableCheck::checkArguments"]["mustBeFilledVariableType"],爲必填參數的變數陣列應該爲何種變數形態,形態爲陣列,元素數量需要跟"mustBeFilledVariableName"參數的元素數量一致,例如: $conf["mustBeFilledVariableType"] = array("string",integer,"double","resource","object");$conf["variableCheck::checkArguments"]["mustBeFilledVariableType"]=array("string","string","string","string","string");#$conf["variableCheck::checkArguments"]["referenceVarKey"],字串,$conf參數後面的key值,用於移除不要的參考陣列.$conf["variableCheck::checkArguments"]["referenceVarKey"]="variableCheck::checkArguments";#可以省略的參數:#$conf["canBeEmptyString"],必填變數內容如果是空字串就不能算是有設置的話,請設為"false",預設爲"true"。#$conf["canBeEmptyString"]="false";#$conf["variableCheck::checkArguments"]["skipableVariableName"],爲可省略參數的變數名稱陣列,形態爲陣列變數,例如: $conf["skipableVariableName"] = array("id","account","password");$conf["variableCheck::checkArguments"]["skipableVariableName"]=array("useBase64");#$conf["variableCheck::checkArguments"]["skipableVariableType"],爲可省略參數的變數名稱陣列,形態爲陣列變數,例如: $conf["skipableVariableType"] = array("string",integer,"double");$conf["variableCheck::checkArguments"]["skipableVariableType"]=array("string");#$conf["variableCheck::checkArguments"]["skipableVarDefaultValue"],字串陣列,每個不存在的可省略變數要初始化為什麼,null與代表不指定,若預設值是參數之一,請將$conf["mustBeFilledVar"]改成"\$conf["\mustBeFilledVar\"]".$conf["variableCheck::checkArguments"]["skipableVarDefaultValue"]=array("true");#$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["variableCheck::checkArguments"]);unset($conf["variableCheck::checkArguments"]);#如果檢查失敗if($checkArguments["status"]=="false"){#設置執行失敗$result["status"]="false";#設置執行錯誤訊息$result["error"]=$checkArguments;#回傳結果return $result;}#if end#如果檢查不通過if($checkArguments["passed"]=="false"){#設置執行失敗$result["status"]="false";#設置執行錯誤訊息$result["error"]=$checkArguments;#回傳結果return $result;}#if end#建立要放置的圖片樣式#函式說明:#創建 css 樣式#回傳結果:#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.#$result["css"],css設定內容#$result["function"],當前執行的函數#$result["error"],涵式錯誤訊息,若爲""則表示沒有錯誤$conf["css"]["createCssStyle"]["cssStyleName"]="imgStyle-".$conf["imgLeft"].$conf["imgTop"];$conf["css"]["createCssStyle"]["attributes"]=array("width","height","position","top","left");$conf["css"]["createCssStyle"]["content"]=array($conf["imgWidth"],$conf["imgHeight"],"absolute",$conf["imgTop"],$conf["imgLeft"]);$css=css::createCssStyle($conf["css"]["createCssStyle"]);unset($conf["css"]["createCssStyle"]);#清空變數避免出錯#如果建立css樣式失敗if($css["status"]=="false"){#設置執行失敗$result["status"]="false";#設置執行錯誤訊息$result["error"]=$css;#回傳結果return $result;}#if end#串接css語法$result["content"]=$result["content"].$css["css"];#如果要用base64顯示圖片if($conf["useBase64"]=="true"){#將圖片用base64加密呈現#函數說明:#用data:mimeType;base64,imgVar的形式來提供圖片的連結,亦即圖片儲存在變數裡面,本函式包含顯示圖片的語法.#回傳結果:#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.#$result["error"],錯誤訊息#$result["content"],圖片的連結資訊#$result["function"],當前執行的函數名稱#必填參數:#$conf["img::data"]["imgPosition"],要轉存成2元碼的圖片檔案位置與名稱$conf["img::data"]["imgPosition"]=$conf["imgAddress"];#可省略參數:#$conf["img::data"]["alt"],若沒有圖片要用什麼文字顯示。$conf["img::data"]["alt"]="not found";#$conf["img::data"]["class"],圖片要套用的css樣式名稱.$conf["img::data"]["class"]="imgStyle-".$conf["imgLeft"].$conf["imgTop"];#$conf["mimeType"],2元碼的內容是什麼,預設為"image/*".#$conf["mimeType"]="image/*";#$conf["compressType"],2元碼壓縮的方式,預設為"base64".#$conf["compressType"]="base64";#$conf["delImg"],讀取完圖片檔案後,要移除圖片嗎?"true"代表要移除,"false"代表不要移除,預設為"false".#$conf["delImg"]="false";#參考資料:#將檔案用字串變數儲存起來=>http://php.net/manual/en/function.file-get-contents.php#壓縮2元碼=>http://php.net/manual/en/function.base64-encode.php$data=img::data($conf["img::data"]);unset($conf["img::data"]);#將圖片用base64加密呈現失敗if($data["status"]=="false"){#設置執行失敗$result["status"]="false";#設置執行錯誤訊息$result["error"]=$data;#回傳結果return $result;}#if end#取得用base64放置圖片的語法$result["content"]=$result["content"].$data["content"];}#if end#反之為一般放置圖片的方式else{#放置要放的圖片#函式說明:#放置可以套用css樣式的圖片#回傳結果:#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.#$result["error"],錯誤訊息陣列#$result["function"],當前函數執行的名稱#$result["content"],印出圖片的語法。$conf["img"]["show"]["position"]=$conf["imgAddress"];$conf["img"]["show"]["alt"]="not found";$conf["img"]["show"]["class"]="imgStyle-".$conf["imgLeft"].$conf["imgTop"];$show=img::show($conf["img"]["show"]);unset($conf["img"]["show"]);#清空變數避免出錯#如果放置圖片的語法建立失敗if($show["status"]=="false"){#設置執行失敗$result["status"]="false";#設置執行錯誤訊息$result["error"]=$show;#回傳結果return $result;}#if end#串接顯示圖片的語法$result["content"]=$result["content"].$show["content"];}#else end#建立圖片隔離層樣式$conf["css"]["createCssStyle"]["cssStyleName"]="imgIsolationLayerStyle".$conf["imgLeft"].$conf["imgTop"];$conf["css"]["createCssStyle"]["attributes"]=array("width","height","opacity","position","top","left");$conf["css"]["createCssStyle"]["content"]=array($conf["imgWidth"],$conf["imgHeight"],".0","absolute",$conf["imgTop"],$conf["imgLeft"]);$css=css::createCssStyle($conf["css"]["createCssStyle"]);unset($conf["css"]["createCssStyle"]);#清空變數避免出錯#如果建立css樣式失敗if($css["status"]=="false"){#設置執行失敗$result["status"]="false";#設置執行錯誤訊息$result["error"]=$css;#回傳結果return $result;}#if end#取得圖片隔離層樣式程式碼$result["content"]=$result["content"].$css["css"];#放置隔離層#函式說明:#放置可以套用css樣式的圖片#回傳結果:#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.#$result["error"],錯誤訊息陣列#$result["function"],當前函數執行的名稱#$result["content"],印出圖片的語法。#必填參數:$conf["img"]["show"]["position"]="copyRight.png";#圖片位置#可省略參數:#$conf["img"]["show"]["alt"]="not found";#若沒有圖片要用什麼文字顯示。$conf["img"]["show"]["class"]="imgIsolationLayerStyle".$conf["imgLeft"].$conf["imgTop"];#要套用的css樣式類別名稱。$show=img::show($conf["img"]["show"]);unset($conf["img"]["show"]);#如果放置圖片的語法建立失敗if($show["status"]=="false"){#設置執行失敗$result["status"]="false";#設置執行錯誤訊息$result["error"]=$show;#回傳結果return $result;}#if end#串接顯示隔離層圖片的語法$result["content"]=$result["content"].$show["content"];#執行到這邊代表執行成功$result["status"]="true";#回傳語法return $result;}#function imgProtect end/*#函式說明:#加密php檔案的內容將結果輸出.#回傳結果:#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.#$result["error"],錯誤訊息陣列.#$result["function"],當前執行的函式名稱.#$result["content"],加密好的php內容字串.#必填參數:#$conf["phpFile"],字串,要加密的php檔案位置與名稱.$conf["phpFile"]="";#$conf["fileArgu"],字串,php變數__FILE__的內容,亦即該檔案在檔案系統的絕對路徑$conf["fileArgu"]=__FILE__;#可省略參數:#無.#參考資料:#無.#備註:#僅支援單行只出現<?php、?>、其他內容的PHP檔案格式內容.*/public static function encodePHP(&$conf){#初始化要回傳的內容$result=array();#取得當前執行的函式$result["function"]=__FUNCTION__;#如果 $conf 不為陣列if(gettype($conf)!="array"){#設置執行失敗$result["status"]="false";#設置執行錯誤訊息$result["error"][]="\$conf變數須為陣列形態";#如果傳入的參數為 nullif($conf==null){#設置執行錯誤訊息$result["error"][]="\$conf變數不得為null,請檢查函數「".$result["function"]."」的參數設置有無正確!";}#if end#回傳結果return $result;}#if end#初始加密好的php程式內容$result["content"]="";#檢查參數#函式說明:#檢查必填與可省略的參數,可省略參數可指定預設要給與什麼數值內容。#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.#$reuslt["error"],執行不正常結束的錯訊息陣列.#$result["function"],當前執行的函式名稱.#$result["passed"],識別要檢查的全體變數是否存在以及型態是否正確的變數,"true"代表檢查全部通過;"false"代表檢查不通過#$result[$shouldBtCheckedVarName]["varExist"],所檢查的變數是否存在,"false"代表不存在;"true"代表存在#$result[$shouldBtCheckedVarName]["varType"],所檢查的變數型態是否正確,"false"代表錯誤;"true"代表正確#$result[$shouldBtCheckedVarName]["error"],每個參數設定的錯誤訊息#$result["argu"],字串陣列,目前輸入的參數名稱陣列.#$result["legalVarName"],字串陣列,合法可用的參數名稱陣列.#$result["notNeedVar"],字串陣列,多餘的參數名稱.#必填寫的參數:#$conf["variableCheck::checkArguments"]["varInput"],陣列變數,要檢查的陣列變數,請在要檢查的參數前面加上&,這樣變動的結果才能被套用。$conf["variableCheck::checkArguments"]["varInput"]=&$conf;#$conf["variableCheck::checkArguments"]["mustBeFilledVariableName"],爲必填參數的變數名稱陣列,形態爲陣列變數,元素數量需要跟"mustBeFilledVariableType"參數的元素數量一致,例如: $conf["mustBeFilledVariableName"] = array("id","account","password");$conf["variableCheck::checkArguments"]["mustBeFilledVariableName"]=array("phpFile","fileArgu");#$conf["variableCheck::checkArguments"]["mustBeFilledVariableType"],爲必填參數的變數陣列應該爲何種變數形態,形態爲陣列,元素數量需要跟"mustBeFilledVariableName"參數的元素數量一致,例如: $conf["mustBeFilledVariableType"] = array("string",integer,"double","resource","object");$conf["variableCheck::checkArguments"]["mustBeFilledVariableType"]=array("string","string");#$conf["variableCheck::checkArguments"]["referenceVarKey"],字串,$conf參數後面的key值,用於移除不要的參考陣列.$conf["variableCheck::checkArguments"]["referenceVarKey"]="variableCheck::checkArguments";#可以省略的參數:#$conf["canBeEmptyString"],必填變數內容如果是空字串就不能算是有設置的話,請設為"false",預設爲"true"。#$conf["canBeEmptyString"]="false";#$conf["variableCheck::checkArguments"]["skipableVariableName"],爲可省略參數的變數名稱陣列,形態爲陣列變數,例如: $conf["skipableVariableName"] = array("id","account","password");#$conf["variableCheck::checkArguments"]["skipableVariableName"]=array("useBase64");#$conf["variableCheck::checkArguments"]["skipableVariableType"],爲可省略參數的變數名稱陣列,形態爲陣列變數,例如: $conf["skipableVariableType"] = array("string",integer,"double");#$conf["variableCheck::checkArguments"]["skipableVariableType"]=array("string");#$conf["variableCheck::checkArguments"]["skipableVarDefaultValue"],字串陣列,每個不存在的可省略變數要初始化為什麼,null與代表不指定,若預設值是參數之一,請將$conf["mustBeFilledVar"]改成"\$conf["\mustBeFilledVar\"]".#$conf["variableCheck::checkArguments"]["skipableVarDefaultValue"]=array("true");#$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["variableCheck::checkArguments"]);unset($conf["variableCheck::checkArguments"]);#如果檢查失敗if($checkArguments["status"]=="false"){#設置執行失敗$result["status"]="false";#設置執行錯誤訊息$result["error"]=$checkArguments;#回傳結果return $result;}#if end#如果檢查不通過if($checkArguments["passed"]=="false"){#設置執行失敗$result["status"]="false";#設置執行錯誤訊息$result["error"]=$checkArguments;#回傳結果return $result;}#if end#函式說明:#依據行號分隔抓取檔案的內容,結果會回傳一個陣列#回傳的變數說明:#$result["status"],執行是否成功,"true"代表成功;"fasle"代表失敗.#$result["error"],錯誤訊息提示.#$result["warning"],警告訊息.#$result["function"],當前執行的函數名稱.#$result["fileContent"],爲檔案的內容陣列.#$result["lineCount"],爲檔案內容總共的行數.#$result["fullContent"],為檔案的完整內容.#$result["base64data"],為檔案的base64內容.#$result["mimeType"],為檔案的mime type.#必填參數:#$conf["filePositionAndName"],字串,爲檔案的位置以及名稱.$conf["fileAccess::getFileContent"]["filePositionAndName"]=$conf["phpFile"];#$conf["fileArgu"],字串,php變數__FILE__的內容,亦即該檔案在檔案系統的絕對路徑$conf["fileAccess::getFileContent"]["fileArgu"]=$conf["fileArgu"];#可省略參數:#$conf["web"],是要取得網路上的檔案則為"true";反之則為"false".$conf["fileAccess::getFileContent"]["web"]="false";#參考資料:#file(),取得檔案內容的行數.#file=>http:#php.net/manual/en/function.file.php#rtrim(),剔除透過file()取得每行內容結尾的換行符號.#filesize=>http://php.net/manual/en/function.filesize.php$getFileContent=fileAccess::getFileContent($conf["fileAccess::getFileContent"]);unset($conf["fileAccess::getFileContent"]);#如果讀取檔案內容失敗if($getFileContent["status"]==="false"){#設置執行失敗$result["status"]="false";#設置執行錯誤訊息$result["error"]=$getFileContent;#回傳結果return $result;}#if end#加密過後的php內容$contentWithoutPhpTagArray=array();#識別是否開始php語法了.$isPHP=false;#識別是否讀取到php tag開頭$phpStart=false;#識別是否讀取到php tag結尾$phpEed=true;#針對每行內容foreach($getFileContent["fileContent"] as $index=>$line){#debug#echo "處理第".($index+1)."行".PHP_EOL;#函式說明:#將固定格式的字串分開,並回傳分開的結果。#回傳結果:#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.#$result["error"],錯誤訊息陣列#$result["function"],當前執行的函數名稱.#$result["argu"],使用的參數.#$result["oriStr"],要分割的原始字串內容#$result["dataArray"],爲分割好字串的陣列內容,$result["dataArray"][$i]爲第($i+1)段的內容。#$result["dataCounts"],爲總共分成幾段#$result["found"],是否有在$conf["stringIn"]找到$conf["spiltSymbol"],"true"代表有找到,"false"代表沒有找到.#必填的參數:#$conf["stringIn"],字串,要處理的字串.$conf["stringProcess::spiltString"]["stringIn"]=$line;#$conf["spiltSymbol"],字串,爲以哪個符號作爲分割.$conf["stringProcess::spiltString"]["spiltSymbol"]="<?php";#可省略參數:#$conf["allowEmptyStr"],是否允許分割出來空字串,預設為"false"不允許;"true"代表允許.$conf["stringProcess::spiltString"]["allowEmptyStr"]="false";$spiltString=stringProcess::spiltString($conf["stringProcess::spiltString"]);unset($conf["stringProcess::spiltString"]);#如果執行失敗if($spiltString["status"]==="false"){#設置執行失敗$result["status"]="false";#設置執行錯誤訊息$result["error"]=$spiltString;#回傳結果return $result;}#if end#初始化該行的資訊描述$lineInfo=array();#如果沒有關鍵字if($spiltString["found"]==="false" && $isPHP===false){#初始化暫存的資訊$tempLineInfo=array();#預設該行不是php的內容$tempLineInfo["isPHP"]=false;#放置內容$tempLineInfo["content"]=$line;#儲存一行資訊描述$lineInfo[]=$tempLineInfo;}#if end#反之有關鍵字且 現在是屬於 php 的範圍else if($spiltString["found"]==="false" && $isPHP===true){#確認該段目前沒有 "?".">" 結尾#函式說明:#將固定格式的字串分開,並回傳分開的結果。#回傳結果:#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.#$result["error"],錯誤訊息陣列#$result["function"],當前執行的函數名稱.#$result["argu"],使用的參數.#$result["oriStr"],要分割的原始字串內容#$result["dataArray"],爲分割好字串的陣列內容,$result["dataArray"][$i]爲第($i+1)段的內容。#$result["dataCounts"],爲總共分成幾段#$result["found"],是否有在$conf["stringIn"]找到$conf["spiltSymbol"],"true"代表有找到,"false"代表沒有找到.#必填的參數:#$conf["stringIn"],字串,要處理的字串.$conf["stringProcess::spiltString"]["stringIn"]=$line;#$conf["spiltSymbol"],字串,爲以哪個符號作爲分割.$conf["stringProcess::spiltString"]["spiltSymbol"]="?>";#可省略參數:#$conf["allowEmptyStr"],是否允許分割出來空字串,預設為"false"不允許;"true"代表允許.$conf["stringProcess::spiltString"]["allowEmptyStr"]="false";$spiltString=stringProcess::spiltString($conf["stringProcess::spiltString"]);unset($conf["stringProcess::spiltString"]);#如果執行失敗if($spiltString["status"]==="false"){#設置執行失敗$result["status"]="false";#設置執行錯誤訊息$result["error"]=$spiltString;#回傳結果return $result;}#if end#反之有關鍵字且 現在是屬於 php 的範圍if($spiltString["found"]==="false" && $isPHP===true){#初始化暫存的資訊$tempLineInfo=array();#預設該行不是php的內容$tempLineInfo["isPHP"]=true;#放置內容$tempLineInfo["content"]=$line;#儲存一行資訊描述$lineInfo[]=$tempLineInfo;}#if end#反之有找到關鍵字,且現在屬於 php 的範圍else if($spiltString["found"]==="true" && $isPHP===true){#如果分割成0段if($spiltString["dataCounts"]===0){#識別是否開始php語法了.$isPHP=false;#識別是否讀取到php tag開頭$phpStart=false;#識別是否讀取到php tag結尾$phpEed=true;}#if end#如果分割成其他段落else{#設置執行錯誤訊息$result["error"][]="not supported now";}#else end}#if end}#if end#反之有關鍵字else if($spiltString["found"]==="true"){#識別是否開始php語法了.$isPHP=true;#識別是否讀取到php tag開頭$phpStart=true;#識別是否讀取到php tag結尾$phpEed=false;#如果切成兩段if($spiltString["dataCounts"]===2){#儲存非 php 的字串$noPHPstr=$spiltString["dataArray"][0];#初始化暫存的資訊$tempLineInfo=array();#預設該行不是php的內容$tempLineInfo["isPHP"]=false;#放置內容$tempLineInfo["content"]=$noPHPstr;#儲存屬於 php 的字串$phpStr=$spiltString["dataArray"][1];#初始化暫存的資訊$tempLineInfo=array();#預設該行不是php的內容$tempLineInfo["isPHP"]=true;#放置內容$tempLineInfo["content"]=$noPHPstr;}#if end#反之切成一段else if($spiltString["dataCounts"]===1){#設置執行失敗$result["status"]="false";#設置執行錯誤訊息$result["error"][]="not supported now";#回傳結果return $result;}#else end#反之切成0段else if($spiltString["dataCounts"]===0){#do nothing}#else end#反之else{#設置執行失敗$result["status"]="false";#設置執行錯誤訊息$result["error"][]="not supported now";#回傳結果return $result;}#else end}#else end#真對每個字串foreach($lineInfo as $linfo){#記錄起來$contentWithoutPhpTagArray[]=$linfo;}#foreach end}#foreach end#debug#var_dump($contentWithoutPhpTagArray);#儲存每行的檔案內容$res=array();#php段落$phpSection="";#針對每行程式foreach($contentWithoutPhpTagArray as $lineInfo){#如果不是 phpif($lineInfo["isPHP"]===false){#如果有php段落if(!empty($phpSection)){#加密php程式$encodedPHP=base64_encode($phpSection);#串接內容$res[]="<?php eval(base64_decode(\"".$encodedPHP."\")); ?>";}#if end#清空php段落$phpSection="";#串接內容$res[]=$lineInfo["content"].PHP_EOL;}#if end#反之是 PHP 內容else{#有內容才處理if(!empty($lineInfo["content"])){#串接php語法$phpSection=$phpSection.$lineInfo["content"].PHP_EOL;}#if end}#else end}#foreach end#如果有php段落if(!empty($phpSection)){#加密php程式$encodedPHP=base64_encode($phpSection);#串接內容$res[]="<?php eval(base64_decode(\"".$encodedPHP."\")); ?>";}#if end#var_dump($res);exit;#針對每個要寫入的行內容foreach($res as $line){$result["content"]=$result["content"].$line;}#foreach end#設置執行正常$result["status"]="true";#回傳結果return $result;}#function encodePHP end/*#函式說明:#檢查 apache http(s) log 中疑似攻擊的記錄.#回傳結果:#$result["status"],字串,執行是否正常,"true"代表正常,"false"代表不正常.#$result["error"],錯誤訊息陣列.#$result["function"],字串,當前執行的函式名稱.#$result["content"],陣列,攻擊記錄資訊,每個元素為陣列key為"ip"者為攻擊者的ip;key為info者為其資訊陣列,其key為"log"者代表log的行內容;key為"time"者代表時間點;key為ip者代表ip.#必填參數:#無.#可省略參數:#$conf["logPath"],http log的路徑,預設為"/var/log/httpd".#$conf["logPath"]="/var/log/httpd";#$conf["https"],字串,是否為要查https的log,預設為"false",代表為http.#$conf["https"]="false";#參考資料:#無.#備註:#目前僅支援 apache 提供的 http(s) 服務.#攻擊者的定義包含http回應的code為4開頭或用戶使用 HTTP/1.0 協定或用戶使用 CONNECT method,且時間間隔不超過1秒鐘,次數達到3次.*/public static function checkHttpAttackLog(&$conf){#初始化要回傳的結果$result=array();#取得當前執行的函數名稱$result["function"]=__FUNCTION__;#取得參數$result["argu"]=$conf;#如果 $conf 不為陣列if(gettype($conf)!="array"){#設置執行失敗$result["status"]="false";#設置執行錯誤訊息$result["error"][]="\$conf變數須為陣列形態";#如果傳入的參數為 nullif(is_null($conf)){#設置執行錯誤訊息$result["error"][]="\$conf變數不得為null,請檢查函數「".$result["function"]."」的參數設置有無正確!";}#if end#回傳結果return $result;}#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["variableCheck::checkArguments"]["varInput"]=&$conf;#$conf["referenceVarKey"],字串,$conf參數後面的key值,用於移除不要的參考陣列.$conf["variableCheck::checkArguments"]["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、any代表不指定變數形態.其中 resource也包含"resource (closed)".#$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["variableCheck::checkArguments"]["skipableVariableCanNotBeEmpty"]=array("logPath","https");#$conf["skipableVariableName"],陣列字串,爲可省略參數的變數名稱陣列,形態爲陣列變數,例如: $conf["skipableVariableName"] = array("id","account","password");$conf["variableCheck::checkArguments"]["skipableVariableName"]=array("logPath","https");#$conf["skipableVariableType"],陣列字串,爲可省略參數的變數名稱陣列,形態爲陣列變數,例如: $conf["skipableVariableType"] = array("string",integer,"double");$conf["variableCheck::checkArguments"]["skipableVariableType"]=array("string","string");#$conf["skipableVarDefaultValue"],字串陣列,每個不存在的可省略變數要初始化為什麼,null與代表不指定,若預設值是參數之一,請將$conf["mustBeFilledVar"]改成"\$conf["\mustBeFilledVar\"]".$conf["variableCheck::checkArguments"]["skipableVarDefaultValue"]=array("/var/log/httpd","false");#$conf["disallowAllSkipableVarIsEmpty"],字串,是否允許每個可省略參數都為空字串,預設為"true"允許,反之為"false".#$conf["disallowAllSkipableVarIsEmpty"]="";#$conf["disallowAllSkipableVarIsEmptyArray"],字串,是否允許每個可省略參數都為空陣列,預設為"true"允許,反之為"false".#$conf["disallowAllSkipableVarIsEmptyArray"]="";#$conf["disallowAllSkipableVarNotExist"],字串,是否不允許每個可省略參數都不存在,預設為"false"代表允許,反之為"true".#$conf["disallowAllSkipableVarNotExist"]="";#$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["variableCheck::checkArguments"]);unset($conf["variableCheck::checkArguments"]);#預設為http的log$logFile="access_log";#如果 https 為 "true"if($conf["https"]==="true"){#設置為 https 的 log$logFile="ssl_access_log";}#if end#取得 http 存取記錄的 log#函式說明:#依據行號分隔抓取檔案的內容,結果會回傳一個陣列#回傳的變數說明:#$result["status"],執行是否成功,"true"代表成功;"fasle"代表失敗.#$result["error"],錯誤訊息提示.#$result["fileNotExist"],字串,"true"代表目標檔案不存在;"false"代表目標檔案存在.#$result["fileCreated"],字串,"true"代表目標檔案被本函式建立;"false"代表檔案不是透過本函式建立.#$result["function"],當前執行的函數名稱.#$result["fileContent"],爲檔案的內容陣列.#$result["lineCount"],爲檔案內容總共的行數.#$result["fullContent"],為檔案的完整內容.#$result["base64dataOnly"],檔案的base64data.#$result["base64data"],為在網頁上給予src參數的數值.#$result["mimeType"],為檔案的mime type.#必填參數:#$conf["filePositionAndName"],字串,爲檔案的位置以及名稱.$conf["fileAccess::getFileContent"]["filePositionAndName"]=$conf["logPath"]."/".$logFile;#$conf["fileArgu"],字串,php變數__FILE__的內容,亦即該檔案在檔案系統的絕對路徑$conf["fileAccess::getFileContent"]["fileArgu"]=__FILE__;#可省略參數:#$conf["web"],是要取得網路上的檔案則為"true";反之預設為"false".#$conf["web"]="true";#$conf["createIfnotExist"],字串,預設為"false"代表檔案不存在也不需要建立;反之為"true".#$conf["createIfnotExist"]="false";#$conf["autoDeleteSpaceOnEachLineStart"],字串,預設為"false",不做額外處理;反之為"true"#$conf["autoDeleteSpaceOnEachLineStart"]="false";#$conf["disableReturnBase64"],字串,預設為"false"代表要回傳base64結果,反之為"true".$conf["fileAccess::getFileContent"]["disableReturnBase64"]="true";#參考資料:#file(),取得檔案內容的行數.#file=>http:#php.net/manual/en/function.file.php#rtrim(),剔除透過file()取得每行內容結尾的換行符號.#filesize=>http://php.net/manual/en/function.filesize.php#參考資料:#無.#備註:#無.$getFileContent=fileAccess::getFileContent($conf["fileAccess::getFileContent"]);unset($conf["fileAccess::getFileContent"]);#如果執行失敗if($getFileContent["status"]==="false"){#如果檔案不存在if($getFileContent["fileNotExist"]==="true"){#設置結果$result["content"]=array();#設置執行正常$result["status"]="true";#回傳結果return $result;}#if end#設置執行失敗$result["status"]="false";#設置錯誤訊息$result["error"]=$getFileContent;#回傳結果return $result;}#if end/*http log 範例:36.149.205.198 - - [22/Jun/2026:15:49:21 +0800] "CONNECT api.ipapi.is:443 HTTP/1.1" 200 -36.149.205.198 - - [22/Jun/2026:15:49:24 +0800] "CONNECT ipwho.is:443 HTTP/1.1" 200 -36.149.205.198 - - [22/Jun/2026:15:49:18 +0800] "CONNECT push.services.mozilla.com:443 HTTP/1.1" 200 -120.48.6.159 - - [22/Jun/2026:15:49:20 +0800] "CONNECT ifconfig.me:443 HTTP/1.1" 200 -36.149.205.198 - - [22/Jun/2026:15:49:24 +0800] "CONNECT ipwho.is:443 HTTP/1.1" 200 -36.149.205.198 - - [22/Jun/2026:15:49:25 +0800] "CONNECT api.ipapi.is:443 HTTP/1.1" 200 -36.149.205.198 - - [22/Jun/2026:15:49:28 +0800] "CONNECT ipwho.is:443 HTTP/1.1" 200 -36.149.205.198 - - [22/Jun/2026:15:49:30 +0800] "CONNECT nexus.officeapps.live.com:443 HTTP/1.1" 200 -172.238.244.28 - - [22/Jun/2026:15:49:31 +0800] "GET / HTTP/1.0" 400 40236.149.205.198 - - [22/Jun/2026:15:49:29 +0800] "CONNECT api.ipapi.is:443 HTTP/1.1" 200 -36.149.205.198 - - [22/Jun/2026:15:49:33 +0800] "CONNECT qaz23.com:2869 HTTP/1.1" 403 35336.149.205.198 - - [22/Jun/2026:15:49:34 +0800] "CONNECT qaz23.com:2869 HTTP/1.1" 403 353*/#初始化給予 search::getMatchFormatsStrings 使用的 formats 參數$formatsParamsOfsearchGetMatchFormatsStrings=array();$formatsParamsOfsearchGetMatchFormatsStrings[]="\${ip} \${doNotNeed} [\${day}/\${month}/\${year}:\${hour}:\${min}:\${sec} \${timezone}] \${method} \${path} \${protocol} \${responseCode} \${bytesSend}";#尋找 http code 為 4xx 的內容行#函式說明:#尋找多個字串中是否含有符合多個格式之一的內容,且回傳解析好的變數數值.#回傳結果:#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.#$reuslt["error"],執行不正常結束的錯訊息陣列.#$result["function"],當前執行的函式名稱.#$result["argu"],所使用的參數.#$result["found"],是否有找到符合格式的字串內容,"true"代表有找到,"false"代表沒有找到.#$result["content"],陣列,第一維為對應formats參數的索引,第二維的key為lineNo者為inputs參數的索引;第二維的key為content者為符合的資訊,若為n個${*},則當found為"true"時,就會回傳n個元素;第二維的key為parsedVar者為符合的資訊,其數值以變數名稱作為索引,元素的索引為0~N,代表有幾個符合的同名變數.#必填參數:#$conf["inputs"],字串陣列,要檢查的字串集合.$conf["search::getMatchFormatsStrings"]["inputs"]=$getFileContent["fileContent"];#$conf["format"],格式字串陣列,要尋找的可能格式字串集合.格式為固定的字串("fixedStr format")與變數("${keyWordVarName}")組成.$conf["search::getMatchFormatsStrings"]["formats"]=$formatsParamsOfsearchGetMatchFormatsStrings;#可省略參數:#無.#參考資料:#無.#備註:#無.$getMatchFormatsStrings=search::getMatchFormatsStrings($conf["search::getMatchFormatsStrings"]);unset($conf["search::getMatchFormatsStrings"]);#如果執行異常if($getMatchFormatsStrings["status"]==="false"){#設置執行失敗$result["status"]="false";#設置錯誤訊息$result["error"]=$getMatchFormatsStrings;#回傳結果return $result;}#if end#如果沒有符合的項目if($getMatchFormatsStrings["found"]==="false"){#設置結果$result["content"]=array();#設置執行正常$result["status"]="true";#回傳結果return $result;}#if end#初始化要處理的ip資訊$ips=array();#初始化用 ip 為索引來儲存資料行$ips_byIp=array();#針對每個符合的規則foreach($getMatchFormatsStrings["content"] as $matchInfo){#取得符合條件的行索引$index=$matchInfo["lineNo"];#取得用戶要求的method$method=$matchInfo["parsedVar"][0]["method"][0];#取得用戶要求的protocal$protocol=$matchInfo["parsedVar"][0]["protocol"][0];#取得回應的code$responseCode=$matchInfo["parsedVar"][0]["responseCode"][0];#如果 method 為 "CONNECT"if($method==="CONNECT"){#這裡不做事情,但後面繼續執行}#if end#如果 protocol 為 "HTTP/1.0"else if($protocol==="HTTP/1.0"){#這裡不做事情,但後面繼續執行}#if end#如果回應的 code 不為 4 開頭else if($responseCode[0]!=="4"){#略過,看下一行continue;}#if end#取得用戶要求的路徑$path=$matchInfo["parsedVar"][0]["path"][0];#剔除要求的資源名稱結尾為 ".css" ".js" "favicon.ico" ".jpg" ".png" 者. - start#函式說明:#尋找字串中是否含有符合多個格式之一的內容,且回傳解析好的變數數值.#回傳結果:#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.#$reuslt["error"],執行不正常結束的錯訊息陣列.#$result["function"],當前執行的函式名稱.#$result["argu"],所使用的參數.#$result["found"],是否有找到符合格式的字串內容,"true"代表有找到,"false"代表沒有找到.#$result["content"],陣列,若為n個${*},則當found為"true"時,就會回傳n個元素.#必填參數:#$conf["input"],字串,要檢查的字串.$conf["search::findSpecifyStrFormats"]["input"]=$getFileContent["fileContent"][$index];#$conf["format"],格式字串陣列,要尋找的可能格式字串集合.格式為固定的字串("fixedStr format")與變數("${keyWordVarName}")組成.$conf["search::findSpecifyStrFormats"]["formats"]=array("\${str}.css","\${str}.js","\${str}.favicon.ico","\${str}.jpg","\${str}.jpeg","\${str}.png","\${str}.webp");#可省略參數:#無.#參考資料:#無.#備註:#無.$findSpecifyStrFormats=search::findSpecifyStrFormats($conf["search::findSpecifyStrFormats"]);unset($conf["search::findSpecifyStrFormats"]);#如果執行異常if($findSpecifyStrFormats["status"]==="false"){#設置執行失敗$result["status"]="false";#設置錯誤訊息$result["error"]=$findSpecifyStrFormats;#回傳結果return $result;}#if end#如果有符合的項目if($findSpecifyStrFormats["found"]==="true"){#略過,看下一行continue;}#if end#剔除要求的資源名稱結尾為 ".css" ".js" "favicon.ico" ".jpg" ".jpeg" ".png" ".webp" 者. - end#時間格式的參考# [\${day}/\${month}/\${year}:\${hour}:\${min}:\${sec} \${timezone}]#取得 log 的時間點$time=$matchInfo["parsedVar"][0]["day"][0]."/".$matchInfo["parsedVar"][0]["month"][0]."/".$matchInfo["parsedVar"][0]["year"][0].":".$matchInfo["parsedVar"][0]["hour"][0].":".$matchInfo["parsedVar"][0]["min"][0].":".$matchInfo["parsedVar"][0]["sec"][0]." ".$matchInfo["parsedVar"][0]["timezone"][0];#以 ip 為索引來儲存資料行$ips_byIp[$matchInfo["parsedVar"][0]["ip"][0]][]=array("log"=>$getFileContent["fileContent"][$index],"time"=>$time,"ip"=>$matchInfo["parsedVar"][0]["ip"][0]);}#foreach end#針對每個可能有問題的IPforeach($ips_byIp as $ip => $infos){#計數 ip 於同時間前來的計數$ipSameTimeCount=0;#用來存放來存取的同一時間$ipSameTime="";#看來拜訪的時間點foreach($infos as $info){#如果是初次if($ipSameTime===""){#記錄時間點$ipSameTime=$info["time"];#同時間點計數加1$ipSameTimeCount++;}#if end#反之如果時間點相同else if($ipSameTime===$info["time"]){#同時間點計數加1$ipSameTimeCount++;}#if end#反之時間點不相同else{#記錄時間點$ipSameTime=$info["time"];#同時間點計數重設為1$ipSameTimeCount=1;}#else end#如果同時間的計數達到3if($ipSameTimeCount===3){#初始化暫存的陣列$tmp=array();#儲存資訊$tmp["info"]=$infos;#儲存ip$tmp["ip"]=$info["ip"];#取得有問題的IP$ips[]=$tmp;#換檢查下一個IPcontinue 2;}#if end}#foreach end}#foreach end#設置結果$result["content"]=$ips;#設置執行正常$result["status"]="true";#回傳結果return $result;}#funcion checkHttpAttackLog end/*#函式說明:#檢查 postfixv log 中疑似攻擊的記錄.#回傳結果:#$result["status"],字串,執行是否正常,"true"代表正常,"false"代表不正常.#$result["error"],錯誤訊息陣列.#$result["function"],字串,當前執行的函式名稱.#$result["content"],陣列,攻擊記錄資訊,每個元素為陣列key為"ip"者為攻擊者的ip;key為info者為其資訊陣列,其key為"log"者代表log的行內容;key為"time"者代表時間點;key為ip者代表ip.#必填參數:#無.#可省略參數:#無#參考資料:#無.#備註:#無.*/public static function checkPostfixAttackLog(){#初始化要回傳的結果$result=array();#取得當前執行的函數名稱$result["function"]=__FUNCTION__;#透過 journalctl -a -e -f --unit=postfix.service | grep "authentication failed" 來取得認證失敗的 ip#函式說明:#呼叫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","--unit=postfix.service","|","grep","authentication failed","|","cat");#$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"){#如果有 statusCodeif(isset($callShell["statusCode"])){#如果shell回傳不為0也不為1if($callShell["statusCode"]!==0 && $callShell["statusCode"]!==1){#設置執行失敗$result["status"]="false";#設置錯誤訊息$result["error"]=$callShell;#回傳結果return $result;}#if end}#if end#設置執行失敗$result["status"]="false";#設置錯誤訊息$result["error"]=$callShell;#回傳結果return $result;}#if end#儲存有問題的smtp IP$ips_smtp=array();#狀態碼不為1才執行if($callShell["statusCode"]!==1){#初始化記錄每行log的時間點$occurTime=array();#初始化儲存log行資訊的變數$oriLog=array();#根據每筆記錄foreach($callShell["output"] as $index => $line){#截取出的格式#Sep 28 07:54:16 qbpwcf.org postfix/smtpd[2766456]: warning: unknown[158.94.208.72]: SASL LOGIN authentication failed: (reason unavailable), sasl_username=1q2w#Sep 28 07:57:15 qbpwcf.org postfix/smtpd[2768441]: warning: unknown[213.209.157.249]: SASL LOGIN authentication failed: (reason unavailable), sasl_username=sybase#Sep 28 08:01:09 qbpwcf.org postfix/smtpd[2771112]: warning: unknown[213.209.157.165]: SASL LOGIN authentication failed: (reason unavailable), sasl_username=spam#Sep 28 08:01:51 qbpwcf.org postfix/smtpd[2771112]: warning: unknown[103.109.20.174]: SASL LOGIN authentication failed: (reason unavailable), sasl_username=print@qbpwcf.org#Sep 28 08:03:14 qbpwcf.org postfix/smtpd[2771112]: warning: unknown[62.60.130.148]: SASL LOGIN authentication failed: (reason unavailable), sasl_username=admin2#Sep 28 08:16:06 qbpwcf.org postfix/smtpd[2781279]: warning: unknown[103.109.20.174]: SASL LOGIN authentication failed: (reason unavailable), sasl_username=user@qbpwcf.org#Sep 28 08:16:44 qbpwcf.org postfix/smtpd[2781279]: warning: unknown[178.16.53.142]: SASL LOGIN authentication failed: (reason unavailable), sasl_username=hualing@qbpwcf.org#Sep 28 08:16:53 qbpwcf.org postfix/smtpd[2781279]: warning: unknown[178.16.53.142]: SASL LOGIN authentication failed: (reason unavailable), sasl_username=hualing@qbpwcf.org#Sep 28 08:17:06 qbpwcf.org postfix/smtpd[2781279]: warning: unknown[178.16.53.142]: SASL LOGIN authentication failed: (reason unavailable), sasl_username=hualing@qbpwcf.org#Sep 28 08:17:16 qbpwcf.org postfix/smtpd[2781279]: warning: unknown[178.16.53.142]: SASL LOGIN authentication failed: Connection lost to authentication server, sasl_username=hualing@qbpwcf.org#Sep 28 08:20:28 qbpwcf.org postfix/smtpd[2784204]: warning: unknown[158.94.208.72]: SASL LOGIN authentication failed: (reason unavailable), sasl_username=1q2w1q2w#Sep 28 08:23:09 qbpwcf.org postfix/smtpd[2785986]: warning: unknown[213.209.157.249]: SASL LOGIN authentication failed: (reason unavailable), sasl_username=informix#Sep 28 08:23:39 qbpwcf.org postfix/smtpd[2785986]: warning: unknown[62.60.130.148]: SASL LOGIN authentication failed: (reason unavailable), sasl_username=admin3#May 22 12:58:54 qbpwcf.org postfix/smtpd[2059124]: warning: unknown[80.94.95.242]: SASL LOGIN authentication failed: Invalid authentication mechanism: 'LOGIN', sasl_username=(unavailable)#May 22 12:58:59 qbpwcf.org postfix/smtpd[2059124]: warning: unknown[80.94.95.242]: SASL PLAIN authentication failed: (reason unavailable), sasl_username=nonexistent_user_26@qbpwcf.org#May 22 12:59:07 qbpwcf.org postfix/smtpd[2059124]: warning: unknown[80.94.95.242]: SASL PLAIN authentication failed: (reason unavailable), sasl_username=finance@qbpwcf.org#"${doNotNeed} postfix/smtpd[${pid}]${doNotNeed}[${ip}]"#用 " " 分割 以取得 月日時分秒#函式說明:#將固定格式的字串分開,並回傳分開的結果.#回傳結果:#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.#$result["error"],錯誤訊息陣列#$result["function"],當前執行的函數名稱.#$result["argu"],使用的參數.#$result["oriStr"],要分割的原始字串內容#$result["dataArray"],爲分割好字串的陣列內容,$result["dataArray"][$i]爲第($i+1)段的內容。#$result["dataCounts"],爲總共分成幾段#$result["found"],是否有在$conf["stringIn"]找到$conf["spiltSymbol"],"true"代表有找到,"false"代表沒有找到.#必填參數:#$conf["stringIn"],字串,要處理的字串.$conf["stringProcess::spiltString"]["stringIn"]=$line;#$conf["spiltSymbol"],字串,爲以哪個符號作爲分割.$conf["stringProcess::spiltString"]["spiltSymbol"]=" ";#可省略參數:#$conf["allowEmptyStr"],是否允許分割出來空字串,預設為"false"不允許;"true"代表允許.#$conf["allowEmptyStr"]="false";#參考資料:#無.#備註:#無.$spiltString=stringProcess::spiltString($conf["stringProcess::spiltString"]);unset($conf["stringProcess::spiltString"]);#如果分割失敗if($spiltString["status"]==="false"){#設置執行失敗$result["status"]="false";#設置錯誤訊息$result["error"]=$spiltString;#回傳結果return $result;}#if end#如果分割失敗if($spiltString["dataCounts"]<3){#設置執行失敗$result["status"]="false";#設置錯誤訊息$result["error"]=$spiltString;#回傳結果return $result;}#if end#儲存時間$occurTime[$index]=strtotime($spiltString["dataArray"][0]." ".$spiltString["dataArray"][1]." ".$spiltString["dataArray"][2]);#取得 ip#函式說明:#尋找字串中是否含有符合格式的內容,且回傳解析好的變數數值.#回傳結果:#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.#$reuslt["error"],執行不正常結束的錯訊息陣列.#$result["function"],當前執行的函式名稱.#$result["argu"],所使用的參數.#$result["found"],是否有找到符合格式的字串內容,"true"代表有找到,"false"代表沒有找到.#$result["content"],陣列,若為n個${*},則當found為"true"時,就會回傳n個元素.#$result["parsedVar"][varName],陣列,解析好的變數陣列,varName為${}中的內容.#必填參數:#$conf["input"],字串,要檢查的字串.$conf["search::findSpecifyStrFormat"]["input"]=$line;#$conf["format"],格式字串,要尋找的格式字串.格式為固定的字串("fixedStr format")與變數("${keyWordVarName}")組成.$conf["search::findSpecifyStrFormat"]["format"]="\${doNotNeed} postfix/smtpd[\${pid}]\${doNotNeed}[\${ip}]:[\${reason}]";#可省略參數:#$conf["varEqual"],陣列,變數對應的數值,null代表不指定,其他內容代表該變數解析出來必須要為該內容.#$conf["search::findSpecifyStrFormat"]["varEqual"]=array(null,"found");#$conf["varCon"],陣列,每個varEqual為null者,其是否有其他條件,預設為null代表無其他條件,條件的表示是用陣列的key與value來表達,例如:array("no_tail"=>" not"),就代表變數的結尾不能為" not",可以用的key有"head",代表開頭要有什麼;"no_head",代表不能為什麼開頭;"tail",代表要什麼結尾;"no_tail",代表不能什麼結尾.#$conf["varCon"]=array("no_tail"=>" not");#參考資料:#無.#備註:#無.$findSpecifyStrFormat=search::findSpecifyStrFormat($conf["search::findSpecifyStrFormat"]);unset($conf["search::findSpecifyStrFormat"]);#如果分割失敗if($findSpecifyStrFormat["status"]==="false"){#設置執行失敗$result["status"]="false";#設置錯誤訊息$result["error"]=$findSpecifyStrFormat;#回傳結果return $result;}#if end#如果沒有符合格式if($findSpecifyStrFormat["found"]==="false"){#剔除時間點 記錄array_pop($occurTime);#跳過該行continue;}#if end#取得解析好的ip$ip=$findSpecifyStrFormat["parsedVar"]["ip"];#儲存原始的log行內容$oriLog[$index]=$spiltMutiString["spiltString"][$index ]["oriStr"];#初始化暫存的陣列$tmp=array();#設置log、time$tmp["info"][]=array("log"=>$oriLog[$index],"time"=>$occurTime[$index]);#設置問題ip$tmp["ip"]=$ip;#取得所需的有問題的IP$ips_smtp[]=$tmp;}#foreach end}#if end#設置結果$result["content"]=$ips_smtp;#設置執行正常$result["status"]="true";#回傳結果return $result;}#function checkPostfixAttackLog end/*#函式說明:#檢查 named log 中疑似攻擊的記錄.#回傳結果:#$result["status"],字串,執行是否正常,"true"代表正常,"false"代表不正常.#$result["error"],錯誤訊息陣列.#$result["function"],字串,當前執行的函式名稱.#$result["content"],陣列,攻擊記錄資訊,每個元素為陣列key為"ip"者為攻擊者的ip;key為info者為其資訊陣列,其key為"log"者代表log的行內容;key為"time"者代表時間點;key為ip者代表ip.#必填參數:#無.#可省略參數:#無#參考資料:#無.#備註:#無.*/public static function checkNamedAttackLog(){#初始化要回傳的結果$result=array();#取得當前執行的函數名稱$result["function"]=__FUNCTION__;#透過 journalctl -a -e -f --unit=named.service | grep ' query ' 來取得 IP#函式說明:#呼叫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","--unit=named.service","|","grep"," query ","|","cat");#$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"){#如果有 statusCodeif(isset($callShell["statusCode"])){#如果shell回傳不為0也不為1if($callShell["statusCode"]!==0 && $callShell["statusCode"]!==1){#設置執行失敗$result["status"]="false";#設置錯誤訊息$result["error"]=$callShell;#回傳結果return $result;}#if end}#if end#設置執行失敗$result["status"]="false";#設置錯誤訊息$result["error"]=$callShell;#回傳結果return $result;}#if end#記錄攻擊者的IP$attacker_ips_namd=array();#狀態碼不為1才執行if($callShell["statusCode"]!==1){#截取出的格式#Nov 24 20:55:15 localhost.localdomain named[99512]: client @0x7f7714041d10 191.7.219.100#6238 (PEACECORPS.GOV): query (cache) 'PEACECORPS.GOV/ANY/IN' denied#Nov 24 20:55:15 localhost.localdomain named[99512]: client @0x7f77180297c0 191.7.219.100#6238 (PEACECORPS.GOV): query (cache) 'PEACECORPS.GOV/ANY/IN' denied#Nov 24 20:55:15 localhost.localdomain named[99512]: client @0x7f7714041d10 191.7.219.100#6238 (PEACECORPS.GOV): query (cache) 'PEACECORPS.GOV/ANY/IN' denied#Nov 24 20:55:15 localhost.localdomain named[99512]: client @0x7f77180297c0 191.7.219.100#6238 (PEACECORPS.GOV): query (cache) 'PEACECORPS.GOV/ANY/IN' denied#Nov 24 20:55:15 localhost.localdomain named[99512]: client @0x7f7714041d10 191.7.219.100#6238 (PEACECORPS.GOV): query (cache) 'PEACECORPS.GOV/ANY/IN' denied#Nov 24 20:55:17 localhost.localdomain named[99512]: client @0x7f7714041d10 34.80.86.198#31220 (PEACECORPS.GOV): query (cache) 'PEACECORPS.GOV/ANY/IN' denied#Nov 24 20:55:17 localhost.localdomain named[99512]: client @0x7f7714041d10 34.80.86.198#31220 (PEACECORPS.GOV): query (cache) 'PEACECORPS.GOV/ANY/IN' denied#Nov 24 20:55:17 localhost.localdomain named[99512]: client @0x7f7714041d10 34.80.86.198#31220 (PEACECORPS.GOV): query (cache) 'PEACECORPS.GOV/ANY/IN' denied#Nov 24 20:55:17 localhost.localdomain named[99512]: client @0x7f77180297c0 34.80.86.198#31220 (PEACECORPS.GOV): query (cache) 'PEACECORPS.GOV/ANY/IN' denied#Nov 24 20:55:17 localhost.localdomain named[99512]: client @0x7f770c077bf0 34.80.86.198#31220 (PEACECORPS.GOV): query (cache) 'PEACECORPS.GOV/ANY/IN' denied#Nov 24 20:55:17 localhost.localdomain named[99512]: client @0x7f770c077bf0 191.7.219.100#8794 (PEACECORPS.GOV): query (cache) 'PEACECORPS.GOV/ANY/IN' denied#Nov 24 20:55:17 localhost.localdomain named[99512]: client @0x7f77180297c0 191.7.219.100#8794 (PEACECORPS.GOV): query (cache) 'PEACECORPS.GOV/ANY/IN' denied#Nov 24 20:55:17 localhost.localdomain named[99512]: client @0x7f770c077bf0 191.7.219.100#8794 (PEACECORPS.GOV): query (cache) 'PEACECORPS.GOV/ANY/IN' denied#Nov 24 20:55:17 localhost.localdomain named[99512]: client @0x7f7714041d10 191.7.219.100#8794 (PEACECORPS.GOV): query (cache) 'PEACECORPS.GOV/ANY/IN' denied#Nov 24 20:55:18 localhost.localdomain named[99512]: client @0x7f770c077bf0 5.29.224.190#10027 (PEACECORPS.GOV): query (cache) 'PEACECORPS.GOV/ANY/IN' denied#Nov 24 20:55:18 localhost.localdomain named[99512]: client @0x7f770c077bf0 5.29.224.190#10027 (PEACECORPS.GOV): query (cache) 'PEACECORPS.GOV/ANY/IN' denied#Nov 24 20:55:18 localhost.localdomain named[99512]: client @0x7f7714041d10 5.29.224.190#10027 (PEACECORPS.GOV): query (cache) 'PEACECORPS.GOV/ANY/IN' denied#Nov 24 20:55:18 localhost.localdomain named[99512]: client @0x7f77180297c0 5.29.224.190#10027 (PEACECORPS.GOV): query (cache) 'PEACECORPS.GOV/ANY/IN' denied#Nov 24 20:55:18 localhost.localdomain named[99512]: client @0x7f7714041d10 5.29.224.190#10027 (PEACECORPS.GOV): query (cache) 'PEACECORPS.GOV/ANY/IN' denied#Nov 24 20:55:18 localhost.localdomain named[99512]: client @0x7f77180297c0 5.29.224.190#10027 (PEACECORPS.GOV): query (cache) 'PEACECORPS.GOV/ANY/IN' denied#Nov 24 20:55:18 localhost.localdomain named[99512]: client @0x7f7714041d10 5.29.224.190#10027 (PEACECORPS.GOV): query (cache) 'PEACECORPS.GOV/ANY/IN' denied#Nov 24 20:55:22 localhost.localdomain named[99512]: client @0x7f7714041d10 123.253.64.16#54404 (PEACECORPS.GOV): query (cache) 'PEACECORPS.GOV/ANY/IN' denied#Nov 24 20:55:22 localhost.localdomain named[99512]: client @0x7f7714041d10 123.253.64.16#54404 (PEACECORPS.GOV): query (cache) 'PEACECORPS.GOV/ANY/IN' denied#Nov 24 20:55:22 localhost.localdomain named[99512]: client @0x7f7714041d10 123.253.64.16#54404 (PEACECORPS.GOV): query (cache) 'PEACECORPS.GOV/ANY/IN' denied#Dec 14 18:51:45 localhost.localdomain named[1159]: client @0x7f3dc801bc80 61.220.11.198#40052 (dns.qbpwcf.org): query 'dns.qbpwcf.org/AAAA/IN' denied#Dec 14 18:51:45 localhost.localdomain named[1159]: client @0x7f3dc8003700 61.220.11.198#48628 (aesopower-cms-sock-latest.qbpwcf.org): query 'aesopower-cms-sock-latest.qbpwcf.org/A/IN' denied#Dec 14 18:51:45 localhost.localdomain named[1159]: client @0x7f3dc8003700 61.220.11.198#52460 (dns.qbpwcf.org): query 'dns.qbpwcf.org/AAAA/IN' denied#Dec 14 18:51:45 localhost.localdomain named[1159]: client @0x7f3dc801bc80 61.220.11.198#60457 (aesopower-cms-sock-latest.qbpwcf.org): query 'aesopower-cms-sock-latest.qbpwcf.org/A/IN' denied#Dec 14 18:51:45 localhost.localdomain named[1159]: client @0x7f3dc801bc80 61.220.11.198#10213 (dns.qbpwcf.org): query 'dns.qbpwcf.org/AAAA/IN' denied#Dec 14 18:51:45 localhost.localdomain named[1159]: client @0x7f3dc801bc80 61.220.11.198#44377 (aesopower-cms-sock-latest.qbpwcf.org): query 'aesopower-cms-sock-latest.qbpwcf.org/A/IN' denied#Dec 14 18:51:45 localhost.localdomain named[1159]: client @0x7f3dc8003700 61.220.11.198#4481 (dns.qbpwcf.org): query 'dns.qbpwcf.org/AAAA/IN' denied#Dec 14 18:51:45 localhost.localdomain named[1159]: client @0x7f3dc8003700 61.220.11.198#53061 (aesopower-cms-sock-latest.qbpwcf.org): query 'aesopower-cms-sock-latest.qbpwcf.org/A/IN' denied#Dec 14 18:51:45 localhost.localdomain named[1159]: client @0x7f3dc8003700 61.220.11.198#31654 (dns.qbpwcf.org): query 'dns.qbpwcf.org/AAAA/IN' denied#Dec 14 18:51:45 localhost.localdomain named[1159]: client @0x7f3dc802a410 61.220.11.198#57701 (aesopower-cms-sock-latest.qbpwcf.org): query 'aesopower-cms-sock-latest.qbpwcf.org/A/IN' denied#Sep 29 03:37:20 dns.qbpwcf.org named[94]: client @0x7f60e00734e8 61.166.210.84#49954 (twitter.com): query failed (REFUSED) for twitter.com/IN/AAAA at ../../../lib/ns/query.c:5691#Sep 29 03:37:20 dns.qbpwcf.org named[94]: client @0x7f60e006f428 61.166.210.84#49954 (twitter.com): query failed (REFUSED) for twitter.com/IN/A at ../../../lib/ns/query.c:5691#Sep 29 03:37:21 dns.qbpwcf.org named[94]: client @0x7f60e80889a8 61.166.210.84#50057 (astrill4u.com): query failed (REFUSED) for astrill4u.com/IN/AAAA at ../../../lib/ns/query.c:5691#Sep 29 03:37:21 dns.qbpwcf.org named[94]: client @0x7f60e805ed08 61.166.210.84#50057 (astrill4u.com): query failed (REFUSED) for astrill4u.com/IN/A at ../../../lib/ns/query.c:5691#Sep 29 03:46:33 dns.qbpwcf.org named[94]: client @0x7f60d402b618 165.22.223.147#16200 (tool.lu): query failed (REFUSED) for tool.lu/IN/A at ../../../lib/ns/query.c:5691#Sep 29 03:49:16 dns.qbpwcf.org named[94]: client @0x7f60e0060a28 76.20.229.207#80 (sl): query failed (REFUSED) for sl/IN/ANY at ../../../lib/ns/query.c:5691#Sep 29 04:19:10 dns.qbpwcf.org named[94]: client @0x7f60e0060a28 76.20.229.207#80 (sl): query failed (REFUSED) for sl/IN/ANY at ../../../lib/ns/query.c:5691#Sep 29 04:20:28 dns.qbpwcf.org named[94]: client @0x7f60e0060a28 76.20.229.207#80 (sl): query failed (REFUSED) for sl/IN/ANY at ../../../lib/ns/query.c:5691#Sep 29 04:24:20 dns.qbpwcf.org named[94]: client @0x7f60e0060a28 76.20.229.207#80 (sl): query failed (REFUSED) for sl/IN/ANY at ../../../lib/ns/query.c:5691#Sep 29 04:24:59 dns.qbpwcf.org named[94]: client @0x7f60e0060a28 76.20.229.207#80 (sl): query failed (REFUSED) for sl/IN/ANY at ../../../lib/ns/query.c:5691#Sep 29 04:40:48 dns.qbpwcf.org named[94]: client @0x7f60f9377888 174.96.56.126#80 (sl): query failed (REFUSED) for sl/IN/ANY at ../../../lib/ns/query.c:5691#${month} ${day} ${hour}:${min}:${sec} ${doNotNeed} client ${doNotNeed} ${ip}#${remoteRevPort} (${$queryTarget}): ${doNotNeed}#函式說明:#檢查多個字串中的每個字串是否有多個關鍵字#回傳結果:#$result["status"],整體來說,執行是否成功,"true"代表執行成功,"false"代表執行失敗。#$result["function"],當前執行的函數名稱.#$result["error"],錯誤訊息.#$result["argu"],使用的參數.#$result["foundedTrueKey"],結果為"true"的被搜尋元素key陣列,與其數值內容.#$result["foundedKeyWords"],找到的關鍵字陣列.#$result["foundedFalseKey"],結果為"false"的被搜尋元素key陣列,與其數值內容.#$result["foundedTrueKeyWords"],二維陣列,各個字串有找到的關鍵字陣列.#$result["foundedAll"],是否每個關鍵字都有找到,"true"代表每個都有找到,"false"代表沒有每個都找到.#$result["keyWordsIncludeStr"],陣列,儲存有找到關鍵字的來源的索引(sourceIndex)與其內容(sourceVal)跟找到的關鍵字項目陣列(KeyWords).#必填參數:#$conf["keyWords"],字串陣列,想要搜尋的關鍵字.$conf["search::findManyKeyWordsFromManyString"]["keyWords"]=array("(REFUSED)"," denied");#$conf["stringArray"],字串陣列,要被搜尋的字串內容陣列.$conf["search::findManyKeyWordsFromManyString"]["stringArray"]=$callShell["output"];#可省略參數:#$conf["completeEqual"],字串,是否內容要完全符合,不能多出任何不符合的內容,預設為"false"不需要完全符合.#$conf["completeEqual"]="true";#參考資料:#無.#備註:#無.$findManyKeyWordsFromManyString=search::findManyKeyWordsFromManyString($conf["search::findManyKeyWordsFromManyString"]);unset($conf["search::findManyKeyWordsFromManyString"]);#如果執行失敗if($findManyKeyWordsFromManyString["status"]==="false"){#設置執行失敗$result["status"]="false";#設置錯誤訊息$result["error"]=$findManyKeyWordsFromManyString;#回傳結果return $result;}#if end#初始化儲存原始log行內容#$oriLog=array();#儲存疑似有問題的IP$ips_named=array();#初始化儲存確定有問題的ip$attacker_ips_namd=array();#針對每個符合的行foreach($findManyKeyWordsFromManyString["foundedTrueKey"] as $oriLog){#初始化儲存資訊的暫存陣列$info=array();#解析時間與來源ip#函式說明:#尋找字串中是否含有符合格式的內容,且回傳解析好的變數數值.#回傳結果:#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.#$reuslt["error"],執行不正常結束的錯訊息陣列.#$result["function"],當前執行的函式名稱.#$result["argu"],所使用的參數.#$result["found"],是否有找到符合格式的字串內容,"true"代表有找到,"false"代表沒有找到.#$result["content"],陣列,若為n個${*},則當found為"true"時,就會回傳n個元素.#$result["parsedVar"][varName],陣列,解析好的變數陣列,varName為${}中的內容.#必填參數:#$conf["input"],字串,要檢查的字串.$conf["search::findSpecifyStrFormat"]["input"]=$oriLog;#$conf["format"],格式字串,要尋找的格式字串.格式為固定的字串("fixedStr format")與變數("${keyWordVarName}")組成.$conf["search::findSpecifyStrFormat"]["format"]="\${month} \${day} \${hour}:\${min}:\${sec} \${doNotNeed} client \${doNotNeed} \${ip}#\${remoteRevPort} (\${queryTarget}): \${doNotNeed}";#可省略參數:#$conf["varEqual"],陣列,變數對應的數值,null代表不指定,其他內容代表該變數解析出來必須要為該內容.#$conf["search::findSpecifyStrFormat"]["varEqual"]=array(null,"found");#$conf["varCon"],陣列,每個varEqual為null者,其是否有其他條件,預設為null代表無其他條件,條件的表示是用陣列的key與value來表達,例如:array("no_tail"=>" not"),就代表變數的結尾不能為" not",可以用的key有"head",代表開頭要有什麼;"no_head",代表不能為什麼開頭;"tail",代表要什麼結尾;"no_tail",代表不能什麼結尾.#$conf["varCon"]=array("no_tail"=>" not");#參考資料:#無.#備註:#無.$findSpecifyStrFormat=search::findSpecifyStrFormat($conf["search::findSpecifyStrFormat"]);unset($conf["search::findSpecifyStrFormat"]);#如果分割失敗if($findSpecifyStrFormat["status"]==="false"){#設置執行失敗$result["status"]="false";#設置錯誤訊息$result["error"]=$findSpecifyStrFormat;#回傳結果return $result;}#if end#如果沒有符合格式if($findSpecifyStrFormat["found"]==="false"){#跳過該行continue;}#if end#儲存時間點$info["time"]=$findSpecifyStrFormat["parsedVar"]["month"][0]." ".$findSpecifyStrFormat["parsedVar"]["day"][0]." ".$findSpecifyStrFormat["parsedVar"]["hour"][0].":".$findSpecifyStrFormat["parsedVar"]["min"][0].":".$findSpecifyStrFormat["parsedVar"]["sec"][0];#儲存ip$info["ip"]=$findSpecifyStrFormat["parsedVar"]["ip"][0];#儲存log$info["log"]=$oriLog;#儲存查詢的目標$info["queryTarget"]=$findSpecifyStrFormat["parsedVar"]["queryTarget"][0];#儲存疑似有問題的ip$ips_named[$info["ip"]][]=$info;}#foreach end#針對每個可能有問題ip的每個log行foreach($ips_named as $ip => $infos){#初始化記錄ip來訪不大於1分鐘的計數$count=0;#初始化記錄歷史log跟time$history=array();#針對每個log行資訊foreach($infos as $index => $info){#unixtime$time=strtotime($info["time"]);#如果沒有下筆記錄if(!isset($infos[$index+1])){#結束 foreachbreak;}#if end#取得unixtime$next_time=strtotime($infos[$index+1]["time"]);#如果時間間隔大於60秒if($next_time-$time>60){#跳過,看下筆記錄continue;}#if end#計數+1$count++;#記錄歷史資訊$history[]=array("time"=>$time,"log"=>$info["log"]);}#foreach end#如果有達到3次if($count>=3){#初始化暫存的陣列$tmp=array();#設置ip$tmp["ip"]=$ip;#設置info$tmp["info"]=$history;#記錄攻擊者的IP$attacker_ips_namd[]=$tmp;}#if end}#foreach end}#if end#設置結果$result["content"]=$attacker_ips_namd;#設置執行正常$result["status"]="true";#回傳結果return $result;}#function checkNamedAttackLog end/*#函式說明:#檢查 dovecot log 中疑似攻擊的記錄.#回傳結果:#$result["status"],字串,執行是否正常,"true"代表正常,"false"代表不正常.#$result["error"],錯誤訊息陣列.#$result["function"],字串,當前執行的函式名稱.#$result["content"],陣列,攻擊記錄資訊,每個元素為陣列key為"ip"者為攻擊者的ip;key為info者為其資訊陣列,其key為"log"者代表log的行內容;key為"time"者代表時間點;key為ip者代表ip.#必填參數:#無.#可省略參數:#無#參考資料:#無.#備註:#無.*/public static function checkDovecotAttackLog(){#初始化要回傳的結果$result=array();#取得當前執行的函數名稱$result["function"]=__FUNCTION__;#透過 journalctl -a -e --unit=dovecot.service 來取得 IP#函式說明:#呼叫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","--unit=dovecot.service");#$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"){#如果有 statusCodeif(isset($callShell["statusCode"])){#如果shell回傳不為0也不為1if($callShell["statusCode"]!==0 && $callShell["statusCode"]!==1){#設置執行失敗$result["status"]="false";#設置錯誤訊息$result["error"]=$callShell;#回傳結果return $result;}#if end}#if end#設置執行失敗$result["status"]="false";#設置錯誤訊息$result["error"]=$callShell;#回傳結果return $result;}#if end#記錄攻擊者的IP$attacker_ips_imap=array();/* $callShell["output"] 範例截取結果Feb 23 00:24:58 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=<MxQuPu+73xpliNc9>Feb 23 00:24:58 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=<hH8xPu+7dBtliNc9>Feb 23 00:24:58 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=<nmI0Pu+7zhtliNc9>Feb 23 00:24:58 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=<1GU2Pu+7NBhliNc9>Feb 23 00:24:59 localhost.localdomain dovecot[1427]: imap-login: Disconnected (no auth attempts in 1 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=<0Io5Pu+7sRhliNc9>Feb 23 00:24:59 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=<zbQ+Pu+7rhlliNc9>Feb 23 00:24:59 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=<0P5APu+7/BlliNc9>Feb 23 00:24:59 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=<gKRDPu+7XhpliNc9>Feb 23 00:24:59 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=<4hNHPu+77hpliNc9>Feb 23 00:25:00 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=<belIPu+7bBtliNc9>Feb 23 00:25:00 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=<VhRLPu+7xBtliNc9>Feb 23 00:46:19 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=<loiMiu+7cxhliNc9>Feb 23 00:46:19 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=<RNCQiu+7/xhliNc9>Feb 23 00:46:20 localhost.localdomain dovecot[1427]: imap-login: Disconnected (no auth attempts in 1 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=<NWCTiu+7PBlliNc9>Feb 23 00:46:20 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=<2tiViu+7hBlliNc9>Feb 23 00:46:20 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=<w6Sbiu+7/xlliNc9>Feb 23 00:46:21 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=<SkWkiu+7gBtliNc9>Feb 23 00:46:21 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=<bGCmiu+7qBtliNc9>Feb 23 00:46:21 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=<0E+oiu+76RtliNc9>Feb 23 00:46:21 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=<FBGriu+7UhhliNc9>Feb 23 00:46:21 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=<AeSsiu+7iBhliNc9>Feb 23 00:46:21 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=<gpSuiu+70hhliNc9>Feb 23 01:40:38 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=<zYfITPC7RBlliNc9>Feb 23 01:40:38 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=<GULMTPC7zhlliNc9>Feb 23 01:40:38 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=<3jjOTPC7CBpliNc9>Feb 23 01:40:38 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=<vhHQTPC7UBpliNc9>Feb 23 01:40:38 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=<vArTTPC7rxpliNc9>Feb 23 01:40:39 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=<hDTXTPC7GhtliNc9>Feb 23 01:40:39 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=<c6vZTPC7SRtliNc9>Feb 23 01:40:39 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=<rQzcTPC7jBtliNc9>Feb 23 01:40:39 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=<LSffTPC78htliNc9>Feb 23 01:40:39 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=<XLThTPC7KBhliNc9>Feb 23 01:40:40 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=<tZfjTPC7dxhliNc9>Feb 23 03:27:10 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=<i3bIyfG7AxtliNc9>Feb 23 03:27:11 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=<0sLVyfG7uxtliNc9>Feb 23 03:27:11 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=<BJXZyfG7BhhliNc9>Feb 23 03:27:11 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=<xK3cyfG7SxhliNc9>Feb 23 03:27:12 localhost.localdomain dovecot[1427]: imap-login: Disconnected (no auth attempts in 1 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=<q43gyfG7aRhliNc9>Feb 23 03:27:12 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=<Oj3syfG7FBlliNc9>Feb 23 03:27:12 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=<SF7uyfG7RhlliNc9>Feb 23 03:27:13 localhost.localdomain dovecot[1427]: imap-login: Disconnected (no auth attempts in 1 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=<IM/wyfG7ZRlliNc9>Feb 23 03:27:13 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=<pXv1yfG7vBlliNc9>Feb 23 03:27:13 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=<8ub4yfG7/xlliNc9>Feb 23 03:27:13 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=<H0j7yfG7NRpliNc9>Feb 23 06:10:07 localhost.localdomain dovecot[1427]: imap-login: Disconnected (no auth attempts in 1 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=<Zw6FEPS7WxhliNc9>Feb 23 06:10:08 localhost.localdomain dovecot[1427]: imap-login: Disconnected (no auth attempts in 1 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=<vmKTEPS7cRpliNc9>Feb 23 06:10:08 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=<SkOXEPS7BxtliNc9>Feb 23 06:10:08 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=<H42bEPS7WRtliNc9>Feb 23 06:10:09 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=<jFqoEPS7SRhliNc9>Feb 23 06:10:10 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=<TNy4EPS7DhpliNc9>Feb 23 06:10:10 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=<JYW7EPS7mBpliNc9>Feb 23 06:10:10 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=</Ve+EPS76hpliNc9>Feb 23 06:10:11 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=<StLGEPS7qhtliNc9>Feb 23 06:10:11 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=<7RnLEPS7DBhliNc9>Feb 23 06:10:11 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=<6xTOEPS7eBhliNc9>Feb 23 06:29:27 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=<YHy0VfS7uBhliNc9>Feb 23 06:29:28 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=<WLW4VfS7fxlliNc9>Feb 23 06:29:28 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=<lM66VfS73BlliNc9>Feb 23 06:29:28 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=<Q4K9VfS7NxpliNc9>Feb 23 06:29:28 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=<JiLBVfS7rRpliNc9>Feb 23 06:29: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=<DETIVfS7qxtliNc9>Feb 23 06:29: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=<UlLLVfS7GhhliNc9>Feb 23 06:29: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=<safNVfS7txhliNc9>Feb 23 06:29: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=<M/DQVfS7LxlliNc9>Feb 23 06:29: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=<+zPTVfS7eRlliNc9>Feb 23 06:29:30 localhost.localdomain dovecot[1427]: imap-login: Disconnected (no auth attempts in 1 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=<dxXWVfS72hlliNc9>Feb 23 06:44:28 localhost.localdomain dovecot[1427]: imap-login: Disconnected (no auth attempts in 1 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=<S0pci/S7SxhliNc9>Feb 23 06:44:28 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=<zThji/S78RhliNc9>Feb 23 06:44:28 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=<8PJoi/S7ixlliNc9>Feb 23 06: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=<Qkhui/S7PBpliNc9>Feb 23 06: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=<SXVzi/S7hhtliNc9>Feb 23 06: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=</X55i/S7uhhliNc9>Feb 23 06:44:30 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=<MHJ9i/S74hlliNc9>Feb 23 06:44:30 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=<RBWBi/S7pRpliNc9>Feb 23 06:44:30 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=<NJeGi/S7yhtliNc9>Feb 23 06:44:31 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=<QsaMi/S7rxhliNc9>Feb 23 06:44:31 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=<8fiPi/S7uBlliNc9>Feb 23 07:01:29 localhost.localdomain dovecot[1427]: imap-login: Disconnected (no auth attempts in 1 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=<dt04yPS7KBlliNc9>Feb 23 07:01: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=<ZMI9yPS7WxpliNc9>Feb 23 07:01: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=<nTVAyPS7ARtliNc9>Feb 23 07:01: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=<wj1CyPS7lxtliNc9>Feb 23 07:01: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=<u7RFyPS7YRhliNc9>Feb 23 07:01:30 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=<tpBLyPS7ZhlliNc9>Feb 23 07:01:30 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=<CRdOyPS7wxlliNc9>Feb 23 07:01:30 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=<v9NQyPS7JxpliNc9>Feb 23 07:01:30 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=<81lUyPS73hpliNc9>Feb 23 07:01:31 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=<PCZXyPS7TRtliNc9>Feb 23 07:01:31 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=<VnNZyPS7qxtliNc9>Feb 23 07:14:28 localhost.localdomain dovecot[1427]: imap-login: Disconnected (no auth attempts in 1 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=<op+l9vS7ZxhliNc9>Feb 23 07:14:28 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=<aBCr9vS7CBlliNc9>Feb 23 07:14:28 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=<0sOt9vS7dRlliNc9>Feb 23 07:14:28 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=<NFaw9vS7xhlliNc9>Feb 23 07:14:28 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=<QS609vS7SRpliNc9>Feb 23 07:14: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=<4FW79vS76htliNc9>Feb 23 07:14: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=<Fxu+9vS7gBhliNc9>Feb 23 07:14: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=<3djA9vS75RhliNc9>Feb 23 07:14:30 localhost.localdomain dovecot[1427]: imap-login: Disconnected (no auth attempts in 1 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=<hgzE9vS7mxlliNc9>Feb 23 07:14:30 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=<J8TG9vS7GBpliNc9>Feb 23 07:14:30 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=<t87I9vS7mBpliNc9>Feb 23 07:29:27 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=<1xBILPW7MRtliNc9>Feb 23 07:29:28 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=<IXZNLPW79htliNc9>Feb 23 07:29:28 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=<6OdPLPW7chhliNc9>Feb 23 07:29:28 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=<M5BSLPW78hhliNc9>Feb 23 07:29:28 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=<Nv9VLPW7UxlliNc9>Feb 23 07:29: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=<foJbLPW7KRpliNc9>Feb 23 07:29: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=<EoVeLPW7nxpliNc9>Feb 23 07:29: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=<DwNhLPW7JRtliNc9>Feb 23 07:29: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=<mKhkLPW7ohtliNc9>Feb 23 07:29: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=<3nhnLPW7/htliNc9>Feb 23 07:29:30 localhost.localdomain dovecot[1427]: imap-login: Disconnected (no auth attempts in 1 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=<e+lpLPW7XRhliNc9>Feb 23 07:44:27 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=<KtTtYfW7dBhliNc9>Feb 23 07:44:28 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=<MLTxYfW77BhliNc9>Feb 23 07:44:28 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=<9GL0YfW7KBlliNc9>Feb 23 07:44:28 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=<JNT2YfW7fRlliNc9>Feb 23 07:44:28 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=<8Zv5YfW72RlliNc9>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=<lbv/YfW73BpliNc9>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=<5zsCYvW7EBtliNc9>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=<aE8EYvW7bRtliNc9>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=<LEIHYvW75RtliNc9>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=<rLsJYvW7MRhliNc9>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>Feb 23 07:59:28 localhost.localdomain dovecot[1427]: imap-login: Disconnected (no auth attempts in 1 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=<x7SUl/W7mBpliNc9>Feb 23 07:59:28 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=<k1KZl/W73xtliNc9>Feb 23 07:59:28 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=<Veabl/W7PxhliNc9>Feb 23 07:59:28 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=<Yamel/W7sxhliNc9>Feb 23 07:59:28 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=<wpGil/W7OBlliNc9>Feb 23 07:59: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=<+VCol/W7aBpliNc9>Feb 23 07:59: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=<TMaql/W7zhpliNc9>Feb 23 07:59: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=<KnKtl/W7GBtliNc9>Feb 23 07:59: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=<Lkixl/W7ixtliNc9>Feb 23 07:59:30 localhost.localdomain dovecot[1427]: imap-login: Disconnected (no auth attempts in 1 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=<8bWzl/W7ARhliNc9>Feb 23 07:59:30 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=<70q2l/W7PBhliNc9>Sep 29 06:53:42 qbpwcf.org dovecot[98]: imap-login: Disconnected: Connection closed (no auth attempts in 0 secs): user=<>, rip=3.231.151.171, lip=169.254.2.1, TLS, session=<MaKQGOs/wIMD55er>Sep 29 07:42:58 qbpwcf.org auth[3737748]: pam_unix(dovecot:auth): check pass; user unknownSep 29 07:42:58 qbpwcf.org auth[3737748]: pam_unix(dovecot:auth): authentication failure; logname=liveuser uid=0 euid=0 tty=dovecot ruser=account@qbpwcf.org rhost=62.60.131.29Sep 29 08:10:02 qbpwcf.org dovecot[98]: imap(liveuser)<3755807><SvyIKew/xLpyIuFn>: Disconnected: Connection closed (UID SEARCH finished 0.039 secs ago) in=119 out=1504 deleted=0 expunged=0 trashed=0 hdr_count=0 hdr_bytes=0 body_count=0 body_bytes=0Sep 29 08:12:02 qbpwcf.org dovecot[98]: imap-login: Login: user=<liveuser>, method=PLAIN, rip=149.102.158.38, lip=169.254.2.1, mpid=3757116, TLS, session=<B2O9MOw/TrmVZp4m>Sep 29 08:12:04 qbpwcf.org dovecot[98]: imap(liveuser)<3757116><B2O9MOw/TrmVZp4m>: Disconnected: Logged out in=240 out=21891 deleted=0 expunged=0 trashed=0 hdr_count=0 hdr_bytes=0 body_count=0 body_bytes=0Sep 29 08:12:06 qbpwcf.org dovecot[98]: imap-login: Login: user=<liveuser>, method=PLAIN, rip=149.102.158.38, lip=169.254.2.1, mpid=3757144, TLS, session=<S0rwMOw/XLmVZp4m>Sep 29 08:12:09 qbpwcf.org dovecot[98]: imap(liveuser)<3757144><S0rwMOw/XLmVZp4m>: Disconnected: Logged out in=885 out=25454 deleted=0 expunged=0 trashed=0 hdr_count=2 hdr_bytes=21658 body_count=0 body_bytes=0Sep 29 08:28:48 qbpwcf.org dovecot[98]: imap-login: Login: user=<liveuser>, method=PLAIN, rip=114.34.225.103, lip=169.254.2.1, mpid=3768144, TLS, session=<Gk6ybOw/nNpyIuFn>Sep 29 08:28:51 qbpwcf.org dovecot[98]: imap(liveuser)<3768144><Gk6ybOw/nNpyIuFn>: Disconnected: Connection closed (LIST finished 1.939 secs ago) in=50 out=17609 deleted=0 expunged=0 trashed=0 hdr_count=0 hdr_bytes=0 body_count=0 body_bytes=0Sep 29 08:28:51 qbpwcf.org dovecot[98]: imap-login: Login: user=<liveuser>, method=PLAIN, rip=114.34.225.103, lip=169.254.2.1, mpid=3768149, TLS, session=<ct7bbOw/qtpyIuFn>Sep 29 08:28:52 qbpwcf.org dovecot[98]: imap(liveuser)<3768149><ct7bbOw/qtpyIuFn>: Disconnected: Connection closed (UID FETCH finished 0.045 secs ago) in=196 out=2381 deleted=0 expunged=0 trashed=0 hdr_count=0 hdr_bytes=0 body_count=0 body_bytes=0Sep 29 08:28:53 qbpwcf.org dovecot[98]: imap-login: Login: user=<liveuser>, method=PLAIN, rip=114.34.225.103, lip=169.254.2.1, mpid=3768155, TLS, session=<DvP1bOw/tNpyIuFn>Sep 29 08:28:55 qbpwcf.org dovecot[98]: imap(liveuser)<3768155><DvP1bOw/tNpyIuFn>: Disconnected: Connection closed (UID SEARCH finished 0.180 secs ago) in=119 out=1504 deleted=0 expunged=0 trashed=0 hdr_count=0 hdr_bytes=0 body_count=0 body_bytes=0Sep 29 08:39:24 qbpwcf.org auth[3775219]: pam_unix(dovecot:auth): check pass; user unknownSep 29 08:39:24 qbpwcf.org auth[3775219]: pam_unix(dovecot:auth): authentication failure; logname=liveuser uid=0 euid=0 tty=dovecot ruser=test rhost=196.251.92.78Sep 29 08:40:44 qbpwcf.org auth[3776113]: pam_unix(dovecot:auth): check pass; user unknownSep 29 08:40:44 qbpwcf.org auth[3776113]: pam_unix(dovecot:auth): authentication failure; logname=liveuser uid=0 euid=0 tty=dovecot ruser=1q2w3e4r5t4567 rhost=158.94.208.72Sep 29 08:41:18 qbpwcf.org auth[3776113]: pam_unix(dovecot:auth): check pass; user unknownSep 29 08:41:18 qbpwcf.org auth[3776113]: pam_unix(dovecot:auth): authentication failure; logname=liveuser uid=0 euid=0 tty=dovecot ruser=spam rhost=62.60.130.148*/#認證失敗的關鍵字$keyWordAF="authentication failure";#未認證或SSL錯誤$keyWordNAA="no auth attempts";#搜尋符合關鍵字的log行#函式說明:#檢查多個字串中的每個字串是否有多個關鍵字#回傳結果:#$result["status"],整體來說,執行是否成功,"true"代表執行成功,"false"代表執行失敗。#$result["function"],當前執行的函數名稱.#$result["error"],錯誤訊息.#$result["argu"],使用的參數.#$result["foundedTrueKey"],結果為"true"的被搜尋元素key陣列,與其數值內容.#$result["foundedKeyWords"],找到的關鍵字陣列.#$result["foundedFalseKey"],結果為"false"的被搜尋元素key陣列,與其數值內容.#$result["foundedTrueKeyWords"],二維陣列,各個字串有找到的關鍵字陣列.#$result["foundedAll"],是否每個關鍵字都有找到,"true"代表每個都有找到,"false"代表沒有每個都找到.#$result["keyWordsIncludeStr"],陣列,儲存有找到關鍵字的來源的索引(sourceIndex)與其內容(sourceVal)跟找到的關鍵字項目陣列(KeyWords).#必填參數:#$conf["keyWords"],字串陣列,想要搜尋的關鍵字.$conf["search::findManyKeyWordsFromManyString"]["keyWords"]=array($keyWordAF,$keyWordNAA);#$conf["stringArray"],字串陣列,要被搜尋的字串內容陣列.$conf["search::findManyKeyWordsFromManyString"]["stringArray"]=$callShell["output"];#可省略參數:#$conf["completeEqual"],字串,是否內容要完全符合,不能多出任何不符合的內容,預設為"false"不需要完全符合.#$conf["completeEqual"]="true";#參考資料:#無.#備註:#無.$findManyKeyWordsFromManyString=search::findManyKeyWordsFromManyString($conf["search::findManyKeyWordsFromManyString"]);unset($conf["search::findManyKeyWordsFromManyString"]);#如果執行失敗if($findManyKeyWordsFromManyString["status"]==="false"){#設置執行失敗$result["status"]="false";#設置錯誤訊息$result["error"]=$findManyKeyWordsFromManyString;#回傳結果return $result;}#if end#初始化儲存可能有問題的存取Dovecot服務遠端ip$rickyIpsOfDocecot=array();#針對每個符合的log行foreach($findManyKeyWordsFromManyString["foundedTrueKey"] as $index => $oriLog){#找到的關鍵字$foundKeyWord=$findManyKeyWordsFromManyString["foundedTrueKeyWords"][$index][0];#依照符合的關鍵字switch($foundKeyWord){#如果是認證失敗case $keyWordAF:#範例#Sep 29 08:41:18 qbpwcf.org auth[3776113]: pam_unix(dovecot:auth): authentication failure; logname=liveuser uid=0 euid=0 tty=dovecot ruser=spam rhost=62.60.130.148#${month} ${day} ${hour}:${min}:${sec} ${doNotNeed} : authentication failure; logname=${account} ${doNotNeed} rhost=${ip}#取得時間點跟遠端IP#函式說明:#尋找字串中是否含有符合格式的內容,且回傳解析好的變數數值.#回傳結果:#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.#$reuslt["error"],執行不正常結束的錯訊息陣列.#$result["function"],當前執行的函式名稱.#$result["argu"],所使用的參數.#$result["found"],是否有找到符合格式的字串內容,"true"代表有找到,"false"代表沒有找到.#$result["content"],陣列,若為n個${*},則當found為"true"時,就會回傳n個元素.#$result["parsedVar"][varName],陣列,解析好的變數陣列,varName為${}中的內容.#必填參數:#$conf["input"],字串,要檢查的字串.$conf["search::findSpecifyStrFormat"]["input"]=$oriLog;#$conf["format"],格式字串,要尋找的格式字串.格式為固定的字串("fixedStr format")與變數("${keyWordVarName}")組成.$conf["search::findSpecifyStrFormat"]["format"]="\${month} \${day} \${hour}:\${min}:\${sec} \${doNotNeed} : authentication failure; logname=\${account} \${doNotNeed} rhost=\${ip}";#可省略參數:#$conf["varEqual"],陣列,變數對應的數值,null代表不指定,其他內容代表該變數解析出來必須要為該內容.#$conf["search::findSpecifyStrFormat"]["varEqual"]=array(null,"found");#$conf["varCon"],陣列,每個varEqual為null者,其是否有其他條件,預設為null代表無其他條件,條件的表示是用陣列的key與value來表達,例如:array("no_tail"=>" not"),就代表變數的結尾不能為" not",可以用的key有"head",代表開頭要有什麼;"no_head",代表不能為什麼開頭;"tail",代表要什麼結尾;"no_tail",代表不能什麼結尾.#$conf["varCon"]=array("no_tail"=>" not");#參考資料:#無.#備註:#無.$findSpecifyStrFormat=search::findSpecifyStrFormat($conf["search::findSpecifyStrFormat"]);unset($conf["search::findSpecifyStrFormat"]);#如果分割失敗if($findSpecifyStrFormat["status"]==="false"){#設置執行失敗$result["status"]="false";#設置錯誤訊息$result["error"]=$findSpecifyStrFormat;#回傳結果return $result;}#if end#如果沒有符合格式if($findSpecifyStrFormat["found"]==="false"){#跳過該行continue 2;}#if end#取得時間點$time=$findSpecifyStrFormat["parsedVar"]["month"][0]." ".$findSpecifyStrFormat["parsedVar"]["day"][0]." ".$findSpecifyStrFormat["parsedVar"]["hour"][0].":".$findSpecifyStrFormat["parsedVar"]["min"][0].":".$findSpecifyStrFormat["parsedVar"]["sec"][0];#取得ip$ip=$findSpecifyStrFormat["parsedVar"]["ip"][0];#儲存其資訊$rickyIpsOfDocecot[$ip][]=array("time"=>$time,"ip"=>$ip,"log"=>$oriLog);#跳出 switchbreak;#如果是未認證或SSL錯誤case $keyWordNAA:#範例#Feb 23 07:59:30 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=<70q2l/W7PBhliNc9>#Sep 29 06:53:42 qbpwcf.org dovecot[98]: imap-login: Disconnected: Connection closed (no auth attempts in 0 secs): user=<>, rip=3.231.151.171, lip=169.254.2.1, TLS, session=<MaKQGOs/wIMD55er>#${month} ${day} ${hour}:${min}:${sec} ${doNotNeed} ( no auth attempts in ${doNotNeed} user=<${account}>, rip=${ip}, ${doNotNeed}#取得時間點跟遠端IP#函式說明:#尋找字串中是否含有符合格式的內容,且回傳解析好的變數數值.#回傳結果:#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.#$reuslt["error"],執行不正常結束的錯訊息陣列.#$result["function"],當前執行的函式名稱.#$result["argu"],所使用的參數.#$result["found"],是否有找到符合格式的字串內容,"true"代表有找到,"false"代表沒有找到.#$result["content"],陣列,若為n個${*},則當found為"true"時,就會回傳n個元素.#$result["parsedVar"][varName],陣列,解析好的變數陣列,varName為${}中的內容.#必填參數:#$conf["input"],字串,要檢查的字串.$conf["search::findSpecifyStrFormat"]["input"]=$oriLog;#$conf["format"],格式字串,要尋找的格式字串.格式為固定的字串("fixedStr format")與變數("${keyWordVarName}")組成.$conf["search::findSpecifyStrFormat"]["format"]="\${month} \${day} \${hour}:\${min}:\${sec} \${doNotNeed} ( no auth attempts in \${doNotNeed} user=<\${account}>, rip=\${ip}, \${doNotNeed}";#可省略參數:#$conf["varEqual"],陣列,變數對應的數值,null代表不指定,其他內容代表該變數解析出來必須要為該內容.#$conf["search::findSpecifyStrFormat"]["varEqual"]=array(null,"found");#$conf["varCon"],陣列,每個varEqual為null者,其是否有其他條件,預設為null代表無其他條件,條件的表示是用陣列的key與value來表達,例如:array("no_tail"=>" not"),就代表變數的結尾不能為" not",可以用的key有"head",代表開頭要有什麼;"no_head",代表不能為什麼開頭;"tail",代表要什麼結尾;"no_tail",代表不能什麼結尾.#$conf["varCon"]=array("no_tail"=>" not");#參考資料:#無.#備註:#無.$findSpecifyStrFormat=search::findSpecifyStrFormat($conf["search::findSpecifyStrFormat"]);unset($conf["search::findSpecifyStrFormat"]);#如果分割失敗if($findSpecifyStrFormat["status"]==="false"){#設置執行失敗$result["status"]="false";#設置錯誤訊息$result["error"]=$findSpecifyStrFormat;#回傳結果return $result;}#if end#如果沒有符合格式if($findSpecifyStrFormat["found"]==="false"){#跳過該行continue 2;}#if end#取得時間點$time=$findSpecifyStrFormat["parsedVar"]["month"][0]." ".$findSpecifyStrFormat["parsedVar"]["day"][0]." ".$findSpecifyStrFormat["parsedVar"]["hour"][0].":".$findSpecifyStrFormat["parsedVar"]["min"][0].":".$findSpecifyStrFormat["parsedVar"]["sec"][0];#取得ip$ip=$findSpecifyStrFormat["parsedVar"]["ip"][0];#儲存其資訊$rickyIpsOfDocecot[$ip][]=array("time"=>$time,"ip"=>$ip,"log"=>$oriLog);#跳出 switchbreak;#不應該執行到這邊default:#設置執行失敗$result["status"]="false";#設置錯誤訊息$result["error"][]="unexpected error";#設置錯誤訊息$result["error"][]=$findManyKeyWordsFromManyString;#回傳結果return $result;}#switch end}#foreach end#初始化儲存可能有問題的ip資訊$risky_ips=array();#針對每個ipforeach($rickyIpsOfDocecot as $ip => $info){#如果同樣ip不到3次if(count($rickyIpsOfDocecot[$ip])<3){#換看下個ipcontinue;}#if end#儲存可能有問題的ip資訊$risky_ips[]=$rickyIpsOfDocecot[$ip];}#foreach end#針對每個可能有問題ip的每個log行foreach($risky_ips as $ip => $infos){#初始化暫存歷史資訊的陣列$history=array();#初始化記錄ip來訪不大於1分鐘的計數$count=0;#針對每個log行資訊foreach($infos as $index => $info){#unixtime$time=strtotime($info["time"]);#如果沒有下筆記錄if(!isset($infos[$index+1])){#結束 foreachbreak;}#if end#取得unixtime$next_time=strtotime($infos[$index+1]["time"]);#如果時間間隔大於60秒if($next_time-$time>60){#跳過,看下筆記錄continue;}#if end#計數+1$count++;#記錄該次事件資訊$history[]=array("time"=>$time,"log"=>$info["log"]);}#foreach end#如果有達到3次if($count>=3){#初始化陣列$tmp=array();#記錄ip$tmp["ip"]=$ip;#記錄歷史資訊$tmp["info"]=$history;#記錄攻擊者的IP$attacker_ips_imap[]=$ip;}#if end}#foreach end#設置結果$result["content"]=$attacker_ips_imap;#設置執行正常$result["status"]="true";#回傳結果return $result;}#function checkDovecotAttackLog end/*#函式說明:#檢查 ssh log 中疑似攻擊的記錄.#回傳結果:#$result["status"],字串,執行是否正常,"true"代表正常,"false"代表不正常.#$result["error"],錯誤訊息陣列.#$result["function"],字串,當前執行的函式名稱.#$result["content"],陣列,攻擊記錄資訊,每個元素為陣列key為"ip"者為攻擊者的ip;key為info者為其資訊陣列,其key為"log"者代表log的行內容;key為"time"者代表時間點;key為ip者代表ip.#必填參數:#無.#可省略參數:#無#參考資料:#無.#備註:#無.*/public static function checkSshAttackLog(){#初始化要回傳的結果$result=array();#取得當前執行的函數名稱$result["function"]=__FUNCTION__;#記錄ssh攻擊者的IP$attacker_ips_ssh=array();#透過 journalctl -a -e --unit=sshd.service來取得 ssh 攻擊者的 IP#函式說明:#呼叫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","--unit=sshd.service");#$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"){#如果有 statusCodeif(isset($callShell["statusCode"])){#如果shell回傳不為0也不為1if($callShell["statusCode"]!==0 && $callShell["statusCode"]!==1){#設置執行失敗$result["status"]="false";#設置錯誤訊息$result["error"]=$callShell;#回傳結果return $result;}#if end}#if end#設置執行失敗$result["status"]="false";#設置錯誤訊息$result["error"]=$callShell;#回傳結果return $result;}#if end/*得到的範例輸出Sep 30 00:36:36 silverblue-guest.qbpwcf.org sshd-session[1607010]: Invalid user lizepeng from 60.213.10.69 port 39156Sep 30 00:36:36 silverblue-guest.qbpwcf.org sshd-session[1607010]: pam_unix(sshd:auth): check pass; user unknownSep 30 00:36:36 silverblue-guest.qbpwcf.org sshd-session[1607010]: pam_unix(sshd:auth): authentication failure; logname= uid=0 euid=0 tty=ssh ruser= rhost=60.213.10.69Sep 30 00:36:38 silverblue-guest.qbpwcf.org sshd-session[1607010]: Failed password for invalid user lizepeng from 60.213.10.69 port 39156 ssh2Sep 30 00:36:40 silverblue-guest.qbpwcf.org sshd-session[1607010]: Connection closed by invalid user lizepeng 60.213.10.69 port 39156 [preauth]Sep 30 05:54:01 silverblue-guest.qbpwcf.org sshd-session[2346022]: pam_unix(sshd:auth): authentication failure; logname= uid=0 euid=0 tty=ssh ruser= rhost=60.213.10.81 user=rootSep 30 05:54:03 silverblue-guest.qbpwcf.org sshd-session[2346022]: Failed password for root from 60.213.10.81 port 41644 ssh2Sep 30 05:54:04 silverblue-guest.qbpwcf.org sshd-session[2346022]: Connection closed by authenticating user root 60.213.10.81 port 41644 [preauth]Sep 30 05:54:20 silverblue-guest.qbpwcf.org sshd-session[2346860]: Invalid user qy from 60.213.10.81 port 42960Sep 30 05:54:21 silverblue-guest.qbpwcf.org sshd-session[2346860]: pam_unix(sshd:auth): check pass; user unknownSep 30 05:54:21 silverblue-guest.qbpwcf.org sshd-session[2346860]: pam_unix(sshd:auth): authentication failure; logname= uid=0 euid=0 tty=ssh ruser= rhost=60.213.10.81Sep 30 05:54:22 silverblue-guest.qbpwcf.org sshd-session[2346860]: Failed password for invalid user qy from 60.213.10.81 port 42960 ssh2Sep 30 05:54:23 silverblue-guest.qbpwcf.org sshd-session[2346860]: Connection closed by invalid user qy 60.213.10.81 port 42960 [preauth]Sep 30 06:08:06 silverblue-guest.qbpwcf.org sshd-session[2378295]: Connection closed by 167.94.145.105 port 55712 [preauth]Sep 30 08:09:51 silverblue-guest.qbpwcf.org sshd-session[2662907]: pam_unix(sshd:auth): authentication failure; logname= uid=0 euid=0 tty=ssh ruser= rhost=183.13.207.69 user=rootSep 30 08:09:54 silverblue-guest.qbpwcf.org sshd-session[2662907]: Failed password for root from 183.13.207.69 port 18258 ssh2Sep 30 08:09:54 silverblue-guest.qbpwcf.org sshd-session[2662907]: Connection closed by authenticating user root 183.13.207.69 port 18258 [preauth]Sep 30 08:10:11 silverblue-guest.qbpwcf.org sshd-session[2663658]: pam_unix(sshd:auth): authentication failure; logname= uid=0 euid=0 tty=ssh ruser= rhost=183.13.207.69 user=rootSep 30 08:10:13 silverblue-guest.qbpwcf.org sshd-session[2663658]: Failed password for root from 183.13.207.69 port 17293 ssh2Sep 30 08:10:13 silverblue-guest.qbpwcf.org sshd-session[2663658]: Connection closed by authenticating user root 183.13.207.69 port 17293 [preauth]*/#認證失敗的關鍵字$keyWordFP=" Failed password ";#不存在使用者的關鍵字$keyWordIU=" Invalid user ";#搜尋符合關鍵字的log行#函式說明:#檢查多個字串中的每個字串是否有多個關鍵字#回傳結果:#$result["status"],整體來說,執行是否成功,"true"代表執行成功,"false"代表執行失敗。#$result["function"],當前執行的函數名稱.#$result["error"],錯誤訊息.#$result["argu"],使用的參數.#$result["foundedTrueKey"],結果為"true"的被搜尋元素key陣列,與其數值內容.#$result["foundedKeyWords"],找到的關鍵字陣列.#$result["foundedFalseKey"],結果為"false"的被搜尋元素key陣列,與其數值內容.#$result["foundedTrueKeyWords"],二維陣列,各個字串有找到的關鍵字陣列.#$result["foundedAll"],是否每個關鍵字都有找到,"true"代表每個都有找到,"false"代表沒有每個都找到.#$result["keyWordsIncludeStr"],陣列,儲存有找到關鍵字的來源的索引(sourceIndex)與其內容(sourceVal)跟找到的關鍵字項目陣列(KeyWords).#必填參數:#$conf["keyWords"],字串陣列,想要搜尋的關鍵字.$conf["search::findManyKeyWordsFromManyString"]["keyWords"]=array($keyWordFP,$keyWordIU);#$conf["stringArray"],字串陣列,要被搜尋的字串內容陣列.$conf["search::findManyKeyWordsFromManyString"]["stringArray"]=$callShell["output"];#可省略參數:#$conf["completeEqual"],字串,是否內容要完全符合,不能多出任何不符合的內容,預設為"false"不需要完全符合.#$conf["completeEqual"]="true";#參考資料:#無.#備註:#無.$findManyKeyWordsFromManyString=search::findManyKeyWordsFromManyString($conf["search::findManyKeyWordsFromManyString"]);unset($conf["search::findManyKeyWordsFromManyString"]);#如果執行失敗if($findManyKeyWordsFromManyString["status"]==="false"){#設置執行失敗$result["status"]="false";#設置錯誤訊息$result["error"]=$findManyKeyWordsFromManyString;#回傳結果return $result;}#if end#初始化儲存可能有問題的存取ssh服務遠端ip$risky_ips=array();#針對每個符合的log行foreach($findManyKeyWordsFromManyString["foundedTrueKey"] as $index => $oriLog){#找到的關鍵字$foundKeyWord=$findManyKeyWordsFromManyString["foundedTrueKeyWords"][$index][0];#依照符合的關鍵字switch($foundKeyWord){#如果是秘密碼錯誤case $keyWordFP:#範例#Sep 30 08:10:13 silverblue-guest.qbpwcf.org sshd-session[2663658]: Failed password for root from 183.13.207.69 port 17293 ssh2#${month} ${day} ${hour}:${min}:${sec} ${doNotNeed} Failed password for ${account} from ${ip} ${doNotNeed}#取得時間點跟遠端IP#函式說明:#尋找字串中是否含有符合格式的內容,且回傳解析好的變數數值.#回傳結果:#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.#$reuslt["error"],執行不正常結束的錯訊息陣列.#$result["function"],當前執行的函式名稱.#$result["argu"],所使用的參數.#$result["found"],是否有找到符合格式的字串內容,"true"代表有找到,"false"代表沒有找到.#$result["content"],陣列,若為n個${*},則當found為"true"時,就會回傳n個元素.#$result["parsedVar"][varName],陣列,解析好的變數陣列,varName為${}中的內容.#必填參數:#$conf["input"],字串,要檢查的字串.$conf["search::findSpecifyStrFormat"]["input"]=$oriLog;#$conf["format"],格式字串,要尋找的格式字串.格式為固定的字串("fixedStr format")與變數("${keyWordVarName}")組成.$conf["search::findSpecifyStrFormat"]["format"]="\${month} \${day} \${hour}:\${min}:\${sec} \${doNotNeed} Failed password for \${account} from \${ip} \${doNotNeed}";#可省略參數:#$conf["varEqual"],陣列,變數對應的數值,null代表不指定,其他內容代表該變數解析出來必須要為該內容.#$conf["search::findSpecifyStrFormat"]["varEqual"]=array(null,"found");#$conf["varCon"],陣列,每個varEqual為null者,其是否有其他條件,預設為null代表無其他條件,條件的表示是用陣列的key與value來表達,例如:array("no_tail"=>" not"),就代表變數的結尾不能為" not",可以用的key有"head",代表開頭要有什麼;"no_head",代表不能為什麼開頭;"tail",代表要什麼結尾;"no_tail",代表不能什麼結尾.#$conf["varCon"]=array("no_tail"=>" not");#參考資料:#無.#備註:#無.$findSpecifyStrFormat=search::findSpecifyStrFormat($conf["search::findSpecifyStrFormat"]);unset($conf["search::findSpecifyStrFormat"]);#如果分割失敗if($findSpecifyStrFormat["status"]==="false"){#設置執行失敗$result["status"]="false";#設置錯誤訊息$result["error"]=$findSpecifyStrFormat;#回傳結果return $result;}#if end#如果沒有符合格式if($findSpecifyStrFormat["found"]==="false"){#跳過該行continue 2;}#if end#取得時間點$time=$findSpecifyStrFormat["parsedVar"]["month"][0]." ".$findSpecifyStrFormat["parsedVar"]["day"][0]." ".$findSpecifyStrFormat["parsedVar"]["hour"][0].":".$findSpecifyStrFormat["parsedVar"]["min"][0].":".$findSpecifyStrFormat["parsedVar"]["sec"][0];#取得ip$ip=$findSpecifyStrFormat["parsedVar"]["ip"][0];#儲存其資訊$risky_ips[$ip][]=array("time"=>$time,"ip"=>$ip,"log"=>$oriLog);#跳出 switchbreak;#如果是不存在的使用者case $keyWordIU:#範例#Sep 30 00:36:36 silverblue-guest.qbpwcf.org sshd-session[1607010]: Invalid user lizepeng from 60.213.10.69 port 39156#${month} ${day} ${hour}:${min}:${sec} ${doNotNeed} Invalid user ${account} from ${ip} port ${doNotNeed}#取得時間點跟遠端IP#函式說明:#尋找字串中是否含有符合格式的內容,且回傳解析好的變數數值.#回傳結果:#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.#$reuslt["error"],執行不正常結束的錯訊息陣列.#$result["function"],當前執行的函式名稱.#$result["argu"],所使用的參數.#$result["found"],是否有找到符合格式的字串內容,"true"代表有找到,"false"代表沒有找到.#$result["content"],陣列,若為n個${*},則當found為"true"時,就會回傳n個元素.#$result["parsedVar"][varName],陣列,解析好的變數陣列,varName為${}中的內容.#必填參數:#$conf["input"],字串,要檢查的字串.$conf["search::findSpecifyStrFormat"]["input"]=$oriLog;#$conf["format"],格式字串,要尋找的格式字串.格式為固定的字串("fixedStr format")與變數("${keyWordVarName}")組成.$conf["search::findSpecifyStrFormat"]["format"]="\${month} \${day} \${hour}:\${min}:\${sec} \${doNotNeed} Invalid user \${account} from \${ip} port \${doNotNeed}";#可省略參數:#$conf["varEqual"],陣列,變數對應的數值,null代表不指定,其他內容代表該變數解析出來必須要為該內容.#$conf["search::findSpecifyStrFormat"]["varEqual"]=array(null,"found");#$conf["varCon"],陣列,每個varEqual為null者,其是否有其他條件,預設為null代表無其他條件,條件的表示是用陣列的key與value來表達,例如:array("no_tail"=>" not"),就代表變數的結尾不能為" not",可以用的key有"head",代表開頭要有什麼;"no_head",代表不能為什麼開頭;"tail",代表要什麼結尾;"no_tail",代表不能什麼結尾.#$conf["varCon"]=array("no_tail"=>" not");#參考資料:#無.#備註:#無.$findSpecifyStrFormat=search::findSpecifyStrFormat($conf["search::findSpecifyStrFormat"]);unset($conf["search::findSpecifyStrFormat"]);#如果分割失敗if($findSpecifyStrFormat["status"]==="false"){#設置執行失敗$result["status"]="false";#設置錯誤訊息$result["error"]=$findSpecifyStrFormat;#回傳結果return $result;}#if end#如果沒有符合格式if($findSpecifyStrFormat["found"]==="false"){#跳過該行continue 2;}#if end#取得時間點$time=$findSpecifyStrFormat["parsedVar"]["month"][0]." ".$findSpecifyStrFormat["parsedVar"]["day"][0]." ".$findSpecifyStrFormat["parsedVar"]["hour"][0].":".$findSpecifyStrFormat["parsedVar"]["min"][0].":".$findSpecifyStrFormat["parsedVar"]["sec"][0];#取得ip$ip=$findSpecifyStrFormat["parsedVar"]["ip"][0];#儲存其資訊$risky_ips[$ip][]=array("time"=>$time,"ip"=>$ip,"log"=>$oriLog);#跳出 switchbreak;#不應該執行到這邊default:#設置執行失敗$result["status"]="false";#設置錯誤訊息$result["error"][]="unexpected error";#設置錯誤訊息$result["error"][]=$findManyKeyWordsFromManyString;#回傳結果return $result;}#switch end}#foreach end#針對每個可能有問題ip的每個log行foreach($risky_ips as $ip => $infos){#初始化暫存歷史記錄的陣列$history=array();#初始化記錄ip來訪不大於1分鐘的計數$count=0;#針對每個log行資訊foreach($infos as $index => $info){#unixtime$time=strtotime($info["time"]);#如果沒有下筆記錄if(!isset($infos[$index+1])){#結束 foreachbreak;}#if end#取得unixtime$next_time=strtotime($infos[$index+1]["time"]);#如果下筆時間記錄與當前這筆間隔大於60秒if($next_time-$time>60){#跳過,看下筆記錄continue;}#if end#計數+1$count++;#記錄該次記錄$history[]=array("time"=>$time,"log"=>$info["log"]);}#foreach end#如果有達到3次if($count>=3){#初始化暫存的陣列$tmp=array();#取得資訊$tmp["info"]=$history;#取得問題ip$tmp["ip"]=$ip;#記錄攻擊者的IP$attacker_ips_ssh[]=$tmp;}#if end}#foreach end#設置結果$result["content"]=$attacker_ips_ssh;#設置執行正常$result["status"]="true";#回傳結果return $result;}#function checkSshAttackLog end}#class security end?>