Rsyslog日誌系統

安全劍客發表於2018-12-25
在資料為王的時代,日誌管理是一個繞不開的話題,相應的開源軟體有不少,比如熱門的三件套:Logstash、ElasticSearch、Kibana,但這套開源日誌系統有點重量級。

一臺伺服器的日誌對系統工程師來說是至關重要的,一旦伺服器出現故障或被入侵,我們需要檢視日誌來定位問題的關鍵所在,所以說對於線上跑的伺服器而言日誌應該合理的處理及管理。

Syslog協議

系統日誌(Syslog)協議是在一個IP網路中轉發系統日誌資訊的標準,它是在美國加州大學伯克利軟體分佈研究中心(BSD)的TCP/IP系統實施中開發的,目前已成為工業標準協議,可用它記錄裝置的日誌。Syslog記錄著系統中的任何事件,管理者可以透過檢視系統記錄隨時掌握系統狀況。系統日誌透過Syslog程式記錄系統的有關事件,也可以記錄應用程式運作事件。透過適當配置,還可以實現執行Syslog協議的機器之間的通訊。透過分析這些網路行為日誌,可追蹤和掌握與裝置和網路有關的情況。

在Unix類作業系統上,syslog廣泛應用於系統日誌。syslog日誌訊息既可以記錄在本地檔案中,也可以透過網路傳送到接收syslog的伺服器。接收syslog的伺服器可以對多個裝置的syslog訊息進行統一的儲存,或者解析其中的內容做相應的處理。常見的應用場景是網路管理工具、安全管理系統、日誌審計系統。

完整的syslog日誌中包含產生日誌的程式模組(Facility)、嚴重性(Severity或 Level)、時間、主機名或IP、程式名、程式ID和正文。在Unix類作業系統上,能夠按Facility和Severity的組合來決定什麼樣的日誌訊息是否需要記錄,記錄到什麼地方,是否需要傳送到一個接收syslog的伺服器等。由於syslog簡單而靈活的特性,syslog不再僅限於Unix類主機的日誌記錄,任何需要記錄和傳送日誌的場景,都可能會使用syslog。

rsyslog日誌系統

對於日誌管理,老版本的 (  6以前)預設使用Syslog,在老版本的 系統上syslog不僅表示一個系統日誌協議,同時程式名稱也叫syslog,其配置檔案為”/etc/syslog.conf“,資訊如下介紹:

# 表示將所有facility的info級別,但不包括mail,authpriv,cron相關的資訊,記錄到 /var/log/messages檔案
*.info;mail.none;authpriv.none;cron.none       /var/log/messages
 
# 表示將許可權,授權相關的所有基本的資訊,記錄到/var/log/secure檔案中.這個檔案的許可權是600 
authpriv.*    /var/log/secure
 
# 表示將mail相關的所有基本的資訊記錄到/var/log/maillog檔案中,可以看到路徑前面有一個"-"而"-" 表示非同步寫入磁碟
mail.*        -/var/log/maillog 
 
# 表示將任務計劃相關的所有級別的資訊記錄到/var/log/cron檔案中
cron.*        /var/log/cron
 
# 表示將所有facility的emerg級別的資訊,傳送給登入到系統上的所有使用者
*.emerg       *
 
# 表示將uucp及news的crit級別的資訊記錄到/var/log/spooler檔案中
uucp,news.crit   /var/log/spooler
 
# 表示將local7的所有級別的資訊記錄到/var/log/boot.log檔案中上面說過local0 到local7這8個是使用者自定義使用的,這裡的local7記錄的是系統啟動相關的資訊
local7.*         /var/log/boot.log

關於Syslog的內容我並不想多說,大家如果有不清楚的地方,可以參考 的Linux私房菜。雖然Syslog中規中矩,但是隨著時間的推移,無論是功能還是效能,它都顯得捉襟見肘,於是出現了:Rsyslog和Syslog-ng,它們都涵蓋SysLog的常用功能,不過在功能和效能上更為出色,至於孰優孰劣是個仁者見仁智者見智的問題,鑑於多數Linux發行版均選擇了Rsyslog,下面就說說Rsyslog。

它所做的事就是統一記錄系統的各個子系統產生的日誌。但是像FTP、HTTP它們都有自己日誌記錄格式不是系統的Rsyslog。在Rsyslog系統有兩個程式分別是klogd,syslogd。而為什麼需要兩個守護程式呢?是因為核心跟其他資訊需要記錄的詳細程度及格式的不同。

klogd:記錄核心資訊,系統啟動中在登入之前使用的都是物理終端/dev/console,這個時候虛擬終端還沒有啟動而核心啟動日誌都存放在/var/log/dmesg檔案中,使用dmesg命令可以檢視。

syslogd:記錄非核心系統產生的資訊,當系統啟動/sbin/init程式時產生的日誌都存放在以下各個日誌檔案中。

/var/log/message    #標準系統錯誤資訊;
/var/log/maillog    #郵件系統產生的日誌資訊;
/var/log/secure     #記錄系統的登入情況;
/var/log/dmesg      #記錄linux系統在引導過程中的各種記錄資訊;
/var/log/cron       #記錄crond計劃任務產生的時間資訊;
/var/log/lastlog    #記錄每個使用者最近的登入事件;
/var/log/wtmp       #記錄每個使用者登入、登出及系統啟動和停機事件;
/var/run/btmp       #記錄失敗的、錯誤的登入嘗試及驗證事件;

另外當日志檔案過大時會透過系統crontab定義日誌滾動的,也稱日誌切割,由logrotate控制其配置檔案/etc/logrotate.conf,然後再由系統任務計劃執行。logrotate負責備份和刪除舊日誌, 以及更新日誌檔案。後面詳說。

syslog協議格式定義如下
facility.priority action

facility(設施):標識系統需要記錄日誌的子系統,大概有以下子系統。

auth             #PAM認證相關日誌;
authpriv         #SSH、FTP登入相關日誌;
cron             #任務計劃相關日誌;
daemon           #守護程式相關日誌;
kern             #核心相關日誌;
lpr              #列印相關日誌;
mail             #郵件相關日誌;
mark             #標記相關日誌;
news             #新聞相關日誌;
security         #安全相關日誌與auth類似;
syslog           #Rsyslog自己的日誌;
user             #使用者相關日誌;
uucp             #UNIX to UNIX cp相關日誌;
local0 to local7 #使用者自定義使用設定日誌;
*                #表示所有的facility;

priority(級別):用來標識日誌級別,級別越低資訊越詳細,有以下日誌級別,從上到下,級別從低到高,記錄的資訊越來越少,詳細的可以檢視手冊: man 3 syslog。

debug            #程式或系統除錯資訊;
info             #一般資訊;
notice           #不影響正常功能需要注意的資訊;
warning          #可能影響系統功能提醒使用者的重要事件;
error            #錯誤資訊;
crit             #比較嚴重的資訊;
alert            #必須馬上處理的警告資訊;
emerg/panic      #會導致系統不可用的嚴重資訊;
*                #表示所有日誌級別;
none             #跟*相反表示什麼都沒有;

action(動作):設定日誌記錄的位置,有以下幾種。

1)記錄到普通檔案或裝置檔案
*.*     /var/log/file.log   #絕對路徑
*.*     /dev/pts/0          #裝置檔案
2)”|”,表示將日誌送給其他命令處理
3)”@HOST”,表示將日誌傳送到特定的主機
*.emerg                     @192.168.10.1
4)”使用者”,表示將日誌傳送到特定的使用者
5)”*”,表示將日誌傳送所有登入到系統上的使用者
連線符號
.                  #表示大於等於xxx級別的資訊;
.=                 #表示等於xxx級別的資訊;
.!                 #表示在xxx之外的等級的資訊;
格式定義案例(定義在/etc/rsyslog.conf配置檔案)
# 表示將mail相關的,info級別及以上級別都記錄到mail.log檔案中
mail.info  /var/log/mail.log
 
# 表示將auth相關的基本為info資訊記錄到遠端主機
auth.=info @192.168.10.1
 
# 表示記錄與user和error相反的
user.!error
 
# 表示記錄所有日誌資訊的info級別及以上級別
*.info
 
# 所有日誌及所有級別資訊都記錄下來
*.*

PS:多個日誌來源可以使用,號隔開,如cron.info;mail.info。

Rsyslog架構闡述

Rsyslog日誌系統Rsyslog日誌系統

Rsyslog架構,這是rsyslog官網上的一張圖,用來介紹rsyslog的架構,rsyslog的訊息流是從輸入模組->預處理模組->主佇列->過濾模組->執行佇列->輸出模組。

在這個流程圖中,輸入、輸出、過濾三個部分稱為module,輸入模組有imklg、imsock、imfile。輸出模組有omudp、omtcp、omfile、omprog、ommysql、omruleset(後兩者我沒有研究,本文不會涉及)。過濾模組研究不多,只會提到mmnormalize。

預處理模組主要解決各種syslog協議實現間的差異,舉例說明如果日誌系統client端使用rsyslog、server端使用syslog-ng,如果自己不做特殊處理syslog-ng是無法識別的。但是反過來,rsyslog的server端就可以識別syslog-ng發過來的訊息。

Input模組,包括imklg、imsock、imfile、imtcp等,是訊息來源。

Filetr模組,處理訊息的分析和過濾,rsyslog可以根據訊息的任何部分進行過濾,後面會介紹到具體的做法。

Output模組,包括omfile、omprog、omtcp、ommysql等。是訊息的目的地。

Queue模組,負責訊息的儲存,從Input傳入的未經過濾的訊息放在主佇列中,過濾後的訊息放入到不同action queue中,再由action queue送到各個輸出模組。

Rsyslog的概念

1)屬性替代
Rsyslog預定義了一些屬性,來代表訊息中的資訊,我們可以在定義輸出格式、動態檔名的時候使用到這些屬性。這裡面比較重要的屬性比如:msg(訊息體)、hostname、pri(訊息等級和類別)、time(時間有關),屬性的名稱中以$開頭的是從本地系統獲得的變數、不帶$是從訊息中獲得變數。

屬性替代的語法格式:

%propname:fromChar:toChar:options:fieldname%

屬性替換的功能很強大,你可以使用起始字元獲取自己所需的欄位,也可以使用正規表示式,也可以使用分隔符。舉幾個例子:為了相容一個rfc協議,rsyslog規定如果使用者輸入的msg不是以空格開頭,rsyslog會自動補充一個空格,因此如果你希望輸出的時候去掉這個空格,就可以使用

%msg:2:$%     #選取msg變數中,起始位置為2,終止位置為結尾

我們經常需要根據空格來分析字串,F表示使用字元分割,32是空格的ascii碼,例:

%msg:F,32:3%  #按照空格分隔,取第三個子串,

正則匹配可以匹配特定的文字和格式,我的正則比較差, 避免了使用這部分的內容,所以這部分沒有例子了。

屬性替代中還用到了一類特殊的以$!開頭的變數,這是使用mmnormalize模組時特有的,可以實現類似於syslog-ng中parser模組的功能。後面再講。

2)模板

模板的功能是定義輸出格式,或者定義omfile模組的動態路徑、動態檔案。需要使用上面提到的屬性替換。

模板定義的形式有四種,適用於不同的輸出模組,一般簡單的格式,可以使用string的形式,複雜的格式,建議使用list的形式,使用list的形式,可以使用一些額外的屬性欄位(property statement),例如:position.from、position.end。

如果不指定輸出模板,rsyslog會預設使用RSYSLOG_DEFAULT。

如果你只想輸出msg,可以定義模板:

$template  t_msg, "%msg\n%"

如果想按日期儲存輸出,需要使用動態路徑。可以定義模板

$template  f_debug, "/data0/logs/%$year%-%$month%-%$day%/debug.log"

3)Ruleset

Ruleset實現的是多例項的功能,可以針對syslog的來源使用不同的過濾規則。需要注意的是,在配置檔案中需要先定義ruleset,才可以使用。比較典型的一個例子,針對不同的埠使用不同的過濾規則。

$Ruleset tcp1999
$RulesetCreateMainQueue on
Local3.*      @@10.0.0.44:1999
$Ruleset tcp2000
$RulesetCreateMainQueue on
Local4.*      @@10.0.0.44:2000

在定義好ruleset後,各個輸出模組就可以指定自己使用的ruleset了,具體如何指定,可以檢視輸出模組的手冊,一般會有一個ruleset的引數,用來實現這個功能。

4)Filter模組

Rsyslog可以使用syslog標準的過濾規則,同時自己新增了一些擴充套件。比如可以在輸出中指定rsyslog自己的處理方式,可以指定輸出template,方法是在規則後面新增template的名字,用分號隔開。

例如我們可以編寫一個規則:

Local3.*    -/data0/logs/local3.log;t_msg   #在這個輸出中使用t_msg的模板
Local4.*    -?f_local3_test;t_msg           #問號表示要使用模板定義的動態路徑

除了syslog標準的規則,rsyslog的作者還自己開發了一個叫做rainerscript的指令碼語言,來定義更復雜的過濾過則,rainerscript可以對屬性進行startwith、contains、%(取餘)等過濾規則,例如:

If $pri-txt == local3.* and $msg contains “abc” then{  #pri為local3,且在訊息中包含子串‘abc’
       *.*   -/data0/logs/local3.log;t_msg
}

還有第三種方式是使用屬性的表示方式,例如:

:msg, regex, "^ [g-z]"    /root/rsyslog_worker_dir/2000.log   #以字母g到z開頭的訊息,注意msg開頭有個空格

5)佇列

佇列是rsyslog中比較重要的一個部分,作為使用者,我們需要了解的是佇列的種類:主佇列和工作佇列。從輸入模組接收的訊息會進入主佇列,主佇列中的訊息,經過過濾模組,會進入到相應的工作佇列;佇列的四種工作模式:direct mode、disk mode、FixedArray mode和LinkedList mode,前兩種是磁碟佇列,更可靠,但是效能也較差,後兩種是記憶體佇列,區別是前者是預分配佇列長度,後者是動態分配,如果你的系統日誌流量比較平穩,可以使用預分配佇列,如果日誌屬於突發型,可以使用動態佇列。此外,記憶體佇列還可以透過指定一個queuename來新增DA模式,DA模式主要是為了防止意外情況(程式關閉、server端當機)下,記憶體佇列可以不丟失。

透過檢視rsyslog的系統命令,可以知道rsyslog對佇列進行大量的可配引數,來定義佇列的行為。可以根據需要來進行最佳化。

Rsyslog啟動引數

正常啟動:指定-f和-i就可以了,新版本不需要-c 5 這樣的引數。

rsyslogd -f /root/rsyslog_worker_dir/rsyslog.conf -i /root/rsyslog_worker_dir/rsyslog.pid

debug版本:debug訊息會輸出到標註輸出,如果出現未預期的結果,可以嘗試使用debug方式,檢視處理流程。

rsyslogd -f /root/rsyslog_worker_dir/rsyslog.conf -i /root/rsyslog_worker_dir/rsyslog.pid -dn >debuglog

測試配置檔案是否正確:

rsyslogd -N1 -f file
Rsyslog配置檔案

預設Rsyslog主配置檔案/etc/rsyslog.conf

#### 載入模組 ####
$ModLoad imuxsock   # provides support for local system logging (e.g. via logger command)
$ModLoad imklog     # provides kernel logging support (previously done by rklogd)
 
#### 定義日誌格式預設模板 ####
$ActionFileDefaultTemplate RSYSLOG_TraditionalFileFormat
 
#### 包含其他配置檔案 ####
$IncludeConfig /etc/rsyslog.d/*.conf
 
#### 規則 ####
# 關於核心的所有日誌都放到/dev/console(控制檯)
#kern.*                                                 /dev/console
 
# 記錄所有日誌型別的info級別以及大於info級別的資訊到/var/log/messages,但是mail郵件資訊,authpriv驗證方面的資訊和cron時間任務相關的資訊除外
*.info;mail.none;authpriv.none;cron.none                /var/log/messages
 
# authpriv驗證相關的所有資訊存放在/var/log/secure
authpriv.*                                              /var/log/secure
 
# 郵件的所有資訊存放在/var/log/maillog; 這裡有一個-符號, 表示是使用非同步的方式記錄, 因為日誌一般會比較大
mail.*                                                  -/var/log/maillog
 
# 計劃任務有關的資訊存放在/var/log/cron
cron.*                                                  /var/log/cron
 
# 記錄所有的大於等於emerg級別資訊, 以wall方式傳送給每個登入到系統的人
*.emerg                                                 *
 
# 記錄uucp,news.crit等存放在/var/log/spooler
uucp,news.crit                                          /var/log/spooler
 
# 記錄啟動的相關資訊
local7.*                                                /var/log/boot.log
 
###日誌轉發規則###
#$WorkDirectory /var/spppl/rsyslog # where to place spool files
#$ActionQueueFileName fwdRule1   #unique name prefix for spool files
#$ActionQueueMaxDiskSpace 1g # 1gb space limit (use as much as possible)
#$ActionQueueSaveOnShutdown on   #save messages to disk on shutdown
#$ActionQueueType LinkedList     #run asynchronously
#$ActionResumeRetryCount -1      #infinite retries if host is down
# remote host is: name/ip:port, e.g. 192.168.0.1:514, port optional
#*.*    @@remote-host:514        #@@表示透過tcp協議傳送 @表示透過udp進行轉發
#local3.info @@localhost :514
#local7.*                        #@@192.168.56.7:514

下面提供一個把特定的Rsyslog日誌檔案傳送到遠端主機的配置。

# 定義從預設的裝置檔案中讀取日誌,/dev/log是預設的日誌讀取裝置檔案;
$AddUnixListenSocket  /dev/log
 
# 定義從指定的裝置檔案中讀取日誌,如PHP程式使用Rsyslog輸出日誌,同時PHP使用了chroot,那麼需要定義chroot後的路徑才可以讀取日誌;
#$AddUnixListenSocket /data/app/dev/log
 
# 定義一個模板,可選;
$template logstash,"%msg%\n" 
 
# Rsyslog預設日誌首都有空格,可以使用下面的模板刪除空格,可選;
$template logstash,"%msg:2:$%\n"
 
# 使用一個已定義的模板;
$ActionFileDefaultTemplate logstash
 
# 摘取$msg(訊息)變數內容,判斷如果有keyboard關鍵字就進行遠端傳送,沒有此關鍵字的就不傳送;
if $msg contains "keyboard"  then
action(type="omfwd" Target="172.18.20.60"\
       Port="8594"\
       Protocol="udp"\
       queue.type="LinkedList"\
       queue.spoolDirectory="/var/spool/rsyslog"\
       queue.filename="test2"\
       queue.size="100000"\
       queue.maxdiskspace="2g"\
       queue.highwatermark="60000"\
       queue.lowwatermark="2000"\
       queue.discardmark="80000"\
       queue.timeoutenqueue="3000"\
       queue.maxfilesize="200m"\
       queue.dequeuebatchsize="1000"\
       )
& stop

上面都是使用$msg為載體進行過濾,$msg就是取日誌內容。當然除了$msg外,常用的還有一個變數$programname,就是取程式名稱。兩種方式都可以使用。


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/31559985/viewspace-2286286/,如需轉載,請註明出處,否則將追究法律責任。

相關文章