搜尋此網誌

2012年6月8日 星期五

[迷你好兔] 利用 syslog/rsyslog + 腳本即時監測 Linux 帳號的登入

login_large之前我提過如何利用 Fail2Ban 來避免系統遭受暴力破解的危害,而 Fail2Ban 與其他類似的機制大多著眼於錯誤的行為 (如輸入密碼錯誤)。但是在系統運作的過程中,不但這些錯誤的行為必須加以注意,很多看似"正常"的行為,更是輕忽不得。其中一種絕對不可忽視的行為,就是帳號的登入,尤其是所謂特權帳號 (root 或是 administrator) 的登入。特權帳號的登入,是一個很重要的行為,而成功的登入甚至比錯誤登入更必須加以注意。如果沒有做好相關的監測,哪天忽然發現系統多了一些莫名其妙的檔案,也沒什麼好大驚小怪的了。

有一些事後日誌的分析工具,可以針對這些成功登入的事件加以設定並提出報告。但是事後分析再好,終究無法挽回已經發生的遺憾。如果能夠在第一時間就知道登入的行為,就可以減少遺憾發生的機會。據我所知,目前並沒有很方便的小工具可以達到這個需求,所以我們只好自己動手。有不少方式可以完成這個目標,今天我要跟各位分享一個相當簡單的方式,那就是利用 syslog/rsyslog 將訊息送到 named pipe 的功能,然後撰寫一個簡單的腳本將相關訊息從 named pipe 中讀出並透過電子郵件即時通知管理者

我今天選擇的環境是 CentOS 6.2,至於其他的環境,只要依據實際的狀況做調整就可以了。好了,馬上就開始我們今天的目標吧:
  1. 建立 named pipe
    指令是
    mkfifo /var/run/secure.pipe

  2. 限制 named pipe 的權限
    將群組與全域的權限予以關閉,指令是
    chmod og-rwx /var/run/secure.pipe

  3. 修改 syslog/rsyslog 的設定檔
    CentOS 6.2 內建的套件是 rsyslog,其設定檔是 /etc/rsyslog.conf 。打開檔案後找到相關位置並加上最後一行
    # The authpriv file has restricted access.
    authpriv.*                                              /var/log/secure
    authpriv.*                                              |/var/run/secure.pipe

    如果你的環境使用 syslog 套件,設定上也沒有多大的差別,只要找到相關的設定檔即可。

  4. 重新啟動 syslog/rsyslog 服務
    指令是
    service rsyslog restart 

  5. 撰寫腳本
    建立一個名稱為 monitor.pl 的腳本,內容如下
    #!/usr/bin/perl
    
    my $named_pipe = '/var/run/secure.pipe';
    my $sender = 'SWatchDog<cyril.hcwang@gmail.com>';
    my $receiver = 'cyril.hcwang@gmail.com';
    my @ip_whitelist = ('127.0.0.1', '192.168.1.1');
    
    open (SYSLOG, "+<$named_pipe")
        or die "Couldn't open $named_pipe: $!\n";
    
    while (<SYSLOG>) {
        if ($_ =~ m/(.*) (\S*) sshd\[(\d*)\]: Accepted (\S*) for (\S*) from (\S*)/) {
            if (!ip_in_whitelist($6)) {
                $message = <<END;
    $5 在 $1 從 $6 登入 $2;
    END
                $subject = "[SWatchDog] Session activation report for ".$2;
                print "sending email to ".$receiver." with message \"".$message."\"";
                &email($subject, $message);
            }
        }
    }
    
    close (SYSLOG);
    
    sub email
    {
        ($subject, $message) = @_;
        open(SENDMAIL, "|sendmail -t") or die "Cannot open $sendmail: $!";
        print SENDMAIL "From: ".$sender."\n";
        print SENDMAIL "Subject: ".$subject."\n";
        print SENDMAIL "To: ".$receiver."\n";
        print SENDMAIL "Content-type: text/plain\n\n";
        print SENDMAIL $message;
        close (SENDMAIL);
    }
    
    sub ip_in_whitelist
    {
       ($ip) = @_;
       for ($i=0; $i<=$#ip_whitelist; $i++) {
          if ($ip eq $ip_whitelist[$i]) {
              return 1;
          }
       }
       return 0;
    }
    這個腳本有三個必須注意的地方,第一個當然就是信件通知的對象 ($receiver),另外一個則是哪些 IP 的登入資訊不要通知 (@ip_whitelist) 。最後則是關於訊息的比對指令。 在 CentOS 6.2 上,成功登入的訊息類似如下:
    Jun  1 16:22:38 xxx sshd[28516]: Accepted publickey for root from 127.0.0.1 port 60873 ssh2 
    而比對指令 $_ =~ m/(.*) (\S*) sshd\[(\d*)\]: Accepted (\S*) for (\S*) from (\S*)/ 就是根據這些訊息而撰寫的。如果在你的環境下訊息格式有所不同,可能就必須調整比對的指令了。

  6. 增加執行的權限
    指令是
    chmod +x monitor.pl 

  7. 執行腳本
    指令是
    nohup ./monitor.pl >> /var/log/monitor.log 2>&1 &

    nohup 可以避免我們登出後程式的執行就被中斷。

  8. 嘗試登入系統
    當我們成功登入系統後應該就可以在設定的信箱收到通知訊息,以下是 gmail 信箱的畫面。

    swatchdog

  9. 加入開機自動執行

    我選擇放在 /etc/rc.local 這個檔案,加上下列設定
    /path_to_monitor.pl/monitor.pl >> /var/log/monitor.log 2>&1 
透過 syslog/rsyslog、named pipe 以及 mail,我們輕鬆完成即時監控成功登入系統的事件。這個腳本還有一些可以改進的地方,像是使用其他更即時的通知方式 (msn、簡訊)、提供登入 IP 位址更詳細的資訊(例如這個 IP 位址在哪個地方) 等。只是這種方式雖然簡單,卻有幾個問題必須加以面對,其中一個是每台主機都必須執行這個腳本,在管理上會增加不少負擔。另外一個問題則是腳本一旦停止執行 (或根本沒有執行) 就失去了監測的能力。此外,如果有其他的程式也在讀取這個 named pipe,那麼寫入這個 named pipe 的資料可就不保證會被我們的腳本讀到。所以,named pipe 的權限設定就很重要。

當然,這幾個問題也不是不能解決,只是每台主機自我管理終究還是不夠方便。解決方式之一就是利用 syslog/rsyslog 遠端遞送的功能,把所有相關事件集中到同一台主機,然後在那台主機執行監測的腳本,如此一來就可以減少許多管理的負擔。至於如何將 syslog/rsyslog 事件遞送到遠端,就請有需要的朋友自行參考之前的另外一篇文章了。

About