將系統Log存入MySQL 以Trigger機制觸發郵件通知
自建登入事件回報系統 即時監看Log免寫程式碼
這裡將把Log資料儲存至遠端資料庫上並利用MySQL中Trigger的機制,在無須撰寫任何程式碼的前提下,完成一項可直接從資料庫層面自動回報Log紀錄中異常情況的功能。
魔鬼都藏在細節中,對系統而言,細節都藏在Log紀錄中,但由於Log紀錄十分繁雜,常使人退避三舍,因而浪費了可從Log紀錄中挖寶的機會。若能做一些設定,在無須撰寫任何程式碼的情況下,就能夠從資料庫自動回報Log紀錄中的異常情況,那將大幅提高網管人員的工作效率。
為了簡化說明,本文僅以「登入」事件為例,一旦發現有登入的事件(即有人登入)發生,就發送電子郵件通知管理者,相關架構如圖1所示,而架構流程如下所述:
1.主機產生Log事件,並將該Log事件儲存至遠端的MySQL資料庫。
2.MySQL資料庫發生資料庫新增(INSERT)事件,即觸發MySQL的觸發(Trigger)程式,而後利用正規表示法來解析(利用mysqludf_preg的正規表示法功能來取得登入事件的樣式)該新增的紀錄是否符合樣式。
3.如果符合樣式,就從資料庫中直接呼叫外部程式(以mysqludf_sys的呼叫外部程式功能),以電子郵件的方式通知管理者。
▲圖1 實作架構圖。
本次實作將會使用到的套件,則如表1所示。
表1 實作所需的套件
什麼是syslog
在實作之前,首先來了解Log紀錄所使用的格式(稱為syslog),syslog又被稱為系統日誌,這是一種用來在網際網路協定(TCP/IP)的網路中傳遞紀錄檔訊息的標準。syslog協定是一種主從式的架構(Client-Server),syslog Client端利用傳送出一個小的文字訊息(小於1024位元組)到syslog Server端(通常為syslogd程式)。syslog系統日誌訊息可以利用UDP協定或TCP協定來傳送。基本上,相關系統日誌資料是以明碼型態傳送。syslog的格式如下所示:
syslog格式定義共分為四個欄位:
· 記錄欄位事件發生的日期與時間
· 記錄發生此事件的主機名稱(如上述的Spampc)
· 記錄啟動此事件的服務名稱(如上述的sshd)
· 記錄訊息的實際資料內容
syslog是以Facility(種類)與Level(嚴重等級)來定義事件的種類及嚴重等級,其中Facility指的是那些種類的事件(如ftp mail等類型事件),Linux系統將事件類型區分如表2所示。
表2 事件類型說明
Level則是用來描述事件嚴重的程度,如表3所示可區分成下列的嚴重級別(由低至高)。
表3 嚴重級別說明

rsyslog伺服器介紹
rsyslog早從2004年即開始進行開發,目的在於開發一個更強大的syslog伺服器來取代掉傳統的syslog伺服器,時至今日,大部分的Linux系統均已內建rsyslog來取代傳統的syslog伺服器。rsyslog伺服器是一個模組化的架構,它區分為三個模組(Module),如圖2所示。
▲圖2 rsyslog伺服器的三大模組。
其中,INPUT模組是指定資料來源,例如可指定syslog的資料來源為檔案或從Socket而來,而PARSE(解析)模組提供針對所接收到的syslog資訊再設定過濾條件以取得更精確的資訊,最後的OUTPUT模組則是指定要將最後的syslog資訊儲存到那裡(如資料庫或檔案或其他)。
在本文中將不管PARSE模組,而僅將所收到的主機紀錄(Log)傳遞至資料庫中,常用的模組說明如表4所示。
表4 常用模組功能介紹
在說明rsyslog的基本組態後,接下來說明如何編譯rsyslog。由於預設的rsyslog伺服器並未安裝支援MySQL資料庫的選項,所以這裡要重新以原始碼編譯。
在下載原始碼並解壓縮後,執行如下的指令(如下#為註解):
安裝成功後,在「<原始碼目錄>/plugins/ommysql」下的createDB.sql檔案內有記錄需建立的資料庫表格名稱。利用檔案內容來建立相關的資料庫表格。建立完成後,接著說明rsyslog伺服器組態檔(/etc/rsyslog.conf)的設定說明,如表5所示。
表5 rsyslog伺服器組態檔設定說明
接下來,設定rsyslog.conf來為rsyslog伺服器加上MySQL功能,基本上,只要在rsyslog所提供的預設組態檔內加入下列設定即可,如圖3所示:
▲圖3 在預設組態檔內加入新設定。
本例是將所有產生的Log紀錄置入本機內MySQL資料庫上名稱為syslog的資料庫,在設定完成後,利用「/usr/local/rsyslog/sbin/rsyslogd -f /etc/rsyslog.conf」來啟動rsyslog伺服器,如果一切正常,此時syslog的紀錄資訊應該會即時地匯入資料庫中。
Trigger簡介
觸發(Trigger)是MySQL提供的一種事件驅動的機制,它可在資料庫事件(例如新增或修改等動作)執行某些動作(最常見的是檢查資料庫資訊的正確性)。
在實務上,經常會有資料庫檢查的要求(如本文所要求的,當有登入事件發生時,就發出電子郵件通知管理者)。為解決此類問題,一般都會使用自行撰寫的程式,以輪詢(Pooling)的方式定時地對資料庫做檢查的動作,但如此的做法常會造成一些時間的落差(依輪詢所設定的檢查密度而定,如5分鐘檢查一次)。
另一種做法是可考慮在資料庫層面上解決,一旦資料庫發生相關的異動,就利用MySQL觸發機制來觸發,執行相關的指令或程式,本文就是採用此種解決方案。
利用觸發的方式,當資料庫接收到主機傳來的Log資訊時即觸發外部程式來執行相關動作。在本文中,希望達到的功能是,當資料庫接收到有登入事件時,就以電子郵件(E-mail)的方式通知管理者。接著,就來說明MySQL的觸發機制。
在MySQL 5.0.2版本之後,就支援觸發器的功能。觸發器是一種註冊在資料庫表格上的程式。當新增(Insert)資料、修改(Update)資料或刪除(Delete)資料等資料庫事件發生時,就可依相對應的觸發條件來處理,例如在新增資料後或新增資料前發生時觸發相關程式。所以,通常被應用在當資料新增或修改時來驗證資料的正確性,或者做相關的資料計算,以下說明觸發器的用法。
觸發器將觸發的時機點定義為之前(Before,在資料庫動作之前觸發)與之後(After,在資料庫動作之後觸發),並定義New(資料庫更新後的資料)及Old(資料庫更新前的資料)來表示新舊的資料庫。以下為建立觸發的語法:
在說明MySQL的觸發器機制後,繼續說明本文會使用到的MySQL外掛程式(UDF)。
什麼是UDF
為了讓更多人能參與增進MySQL功能的工作,MySQL提出了UDF(使用者自定函數,User Define Function)的架構,只要撰寫程式的內容符合此架構的規範,即可撰寫MySQL定義的函數來提升MySQL的功能。在「http://www.mysqludf.org/」網站中有相當多的UDF函數,值得一看。表6為常用的UDF函數說明。
表6 常用的UDF函數
接下來,說明本文所使用的UDF函數。
lib_mysqludf_sys簡介
或許是因為考量資訊安全的關係,MySQL並不像其他的商業化資料庫軟體如微軟的MSSQL,有提供直接呼叫系統指令的功能。不過,從使用者的便利性來看,提供可直接從MySQL執行系統指令的功能,在某些情況下是相當便利的,而lib_mysqludf_sys就是用來直接從資料庫呼叫外部程式的功能。本文將利用此程式庫所提供的功能呼叫外部程式來寄發電子郵件。
要特別注意的是,在lib_mysqludf_sys的說明文件中,有特別說明此程式庫尚在實驗的階段,亦即尚未完全穩定,在使用上可能會有一些不可預期的結果出現。依照筆者的測試,簡單的系統指令(如ls cat等指令)可以正常的運作,但若執行自定義的程式(例如自行撰寫的程式),有時候會造成資料庫重新啟動的現象。以下就來說明如何安裝lib_mysqludf_sys程式庫,安裝步驟如下:
先下載lib_mysqludf_sys,並解壓縮原始碼:
然後,將lib_mysqludf_sys.so複製至MySQL的Plugin目錄(通常為MySQL的「lib」目錄下的「plugin」目錄),在此為「/usr/local/mysql5/lib/plugin/」。
登入MySQL後,以「mysql -u root -p[資料庫密碼]」登入,接著以下列指令新建函數(其中mysql>為提示字元):
lib_mysqludf_sys的相關函數功能,以下分別加以說明:
·sys_get:取得系統變數例如PATH(系統路徑)的變數內容,如圖4所示。
▲圖4 取得PATH(系統路徑)的變數內容。
·sys_set:設定系統變數的內容,如圖5所示為設定系統變數(MYPATH)的內容。
▲圖5 設定系統變數(MYPATH)的內容。
·sys_eval:執行指令並取得回覆的資訊,如圖6所示為顯示passwd的檔案名稱,與sys_exec不同的是,此指令回覆的資訊為執行的結果,而sys_exec指令回覆的是此指令是否成功的執行,也就是回傳代碼(如1或255)。
▲圖6 顯示passwd的檔案名稱。
·sys_exec:執行指令並取得執行後的回傳代碼(僅傳回零值與非零值來代表指令是否有正常的執行)。
lib_mysqludf_preg簡介
lib_mysqludf_preg程式庫主要是提供MySQL更進階的正規化表示法的功能,本文利用此程式庫所提供的正規化表示功能來取得相關Log的樣式,安裝步驟如下:

登入後,以「mysql -u root -p[資料庫密碼]」登入,然後使用下列指令新建函數(mysql>為提示字元):
相關的函數說明如下,這裡僅說明有用到的函數:
·PREG_RLIKE:以正規表示法來表示符合的紀錄,語法如下:
·pattern:為正規表示法
·subject:為要驗證的欄位
執行範例如如圖7所示,該例為查詢Message欄位是否有Accepted password的樣式,亦即登入的資訊。
▲圖7 查詢Message欄位是否內含Accepted password的樣式。
·preg_capture:取得樣式中的字串,語法如下:
·pattern:為正規表示法
·subject:為要驗證的欄位
·capture:取得符合樣式的字串
執行範例如圖8所示(在登入事件的記錄中,取得登入使用的來源IP)。
▲圖8 在登入事件的記錄中取得登入使用的來源IP。
最後,使用以下的Trigger(觸發)直接從資料庫收到登入事件,即可呼叫外部程式(名稱為email)發出電子郵件通知管理者:
至此,即可在不撰寫任何程式的情況下完成登入事件自動回報的系統。
<本文作者:吳惠麟,多年資安經驗,喜好利用開源碼建構相關解決方案,著有「資訊安全原理與實驗」等書。>