FreeBSD/syslog-ng

syslog-ng(New Generation)

syslogdの機能面やセキュリティ面から見た課題

ログの出力先を細かく制御できない

アプリケーションごとにログの出力先を変更することが困難。

ログ監査の自動化が困難

swatchなど外部プログラムを使う必要がある。

ログ受信時のアクセス制御

ログ受信時の514/udpに対するアクセス制御が行えない。
行えたとしても、一部OSのsyslogd(FreeBSDNetBSDなど)に限られる。

root権限で動作する

syslogdは、root権限で動作する。
そのため、万が一syslogd経由による侵入を許した場合、即root権限の取得につながる。

syslog-ngの導入

syslog-ngは、GPL(General Public License)に基づいたフリーのsyslogソフトウェアで、
オリジナルのsyslogdの機能はもちろんのこと、さまざまな機能のサポートやセキュリティ面が考慮された作りになっている。
このsyslog-ngを導入することで、前述のsyslogdの課題をクリアすることができる。

syslogdの機能

従来のsyslogdで提供されている機能は、syslog-ngでも同様に利用できる。

ログの出力先を細かに制御できる

syslog-ngのfilter機能により、facilityやpriorityはもちろんのこと、
アプリケーション名や受信したログの内容に応じて、ログの出力先を指定できる。

ログ監査の自動化が行える

facility、priority、ホスト名、アプリケーション名などに合致したログをメールプログラムに渡すことで、
管理者に自動通知することができる。

ログ受信時のアクセス制御

ほかのsyslogサーバからログを受信する際に、アクセス制御を行える。
また、TCP Wrapper*2との連係によるアクセス制御も行える。

root以外のユーザー権限で動作可能

syslog-ngでは、実効ユーザー権限をroot以外にすることが可能だ。

TCPポートによるログ転送

従来のsyslogdは、ログ転送のために514/udpポート(固定)を使用していた。
syslog-ngでは、TCPポートかつ任意のポートを使用してログ転送可能だ。
TCPによるログ転送では、最大接続数の制限も行えるため、Flood系のDoS攻撃への対処が可能となる。

インストール

# cd /usr/ports/sysutils/syslog-ng2
# make install

pcreを入れておかないと下記のエラーでインストールできない

configure:44529: error: *** The system-supplied PCRE does not support Unicode properties or UTF-8.

■pcreをインストール

# cd /usr/ports/devel/pcre
# make install clean

/etc/rc.confの編集

# syslog-ng
syslogd_enable="NO"
syslog_ng_enable="YES"
syslog_ng_config="-u daemon"
syslog_ng_pid="/var/run/syslog.pid"

※syslog-ng.pidとするとnewsyslogがpid fileを見つけられない。 (..;

syslogdを停止

# kill `cat /var/run/syslogd.pid`

syslog-ng.confファイル作成

# cp /usr/local/etc/syslog-ng/syslog-ng.conf.sample /usr/local/etc/syslog-ng.conf

syslog-ngをスタート

# /usr/local/etc/rc.d/syslog-ng start

sync()オプションについて

sync()オプションは、どのくらいのログをバッファとして溜め込んでおくか?である。

巷の設定例では sync(0) にしている例が見られるが、 これだとバッファせずに1行ずつ常にディスクに書き込みにいくので、当然ディスクI/O性能が悪化する。

例えばsync(100)にすると、ログが100行たまったらはじめてそれをディスクに書き込みに行くので、I/O頻度が減る=性能向上。

ただし、tailコマンドなどでログファイルを見ているとき、

「いつまでたってもログに出ないんですけど」「ある程度バッファしてるんだからそりゃそうだろ」という罠にご注意。

swatchも結局はtailコマンドないしはperlのFile::Tailでログファイルの末尾を直接監視しているのだから同じ罠が待っている。

syslog-ngで他ホストからログを受ける設定

# vi /usr/local/etc/syslog-ng.conf

# sources
#
source src { unix-dgram("/var/run/log");
             unix-dgram("/var/run/logpriv" perm(0600));
            udp( ); internal(); file("/dev/klog");
};
---------------------↓に変更--------------------------------
# sources
#
source src { unix-dgram("/var/run/log");
             unix-dgram("/var/run/logpriv" perm(0600));
            udp( ip(0.0.0.0) port(514) ); internal(); file("/dev/klog");
};

php-syslog-ng

http://code.google.com/p/php-syslog-ng/

proftpdのログをsyslogで取得

proftpd側の設定

proftpdは独自にログを吐いているので、通常だと取得できません。

# vi /usr/local/etc/proftpd.conf
# SystemLog        /var/log/proftpd.log
SyslogFacility LOCAL6
# /usr/local/etc/rc.d/proftpd.sh restart

※ちなみにxferlogは苦戦しましたが、無理でした。

syslog-ng側の設定

# vi /usr/local/etc/syslog-ng.conf
destination proftpd { file("/var/log/$HOST/$YEAR/proftpd.log.$MONTH$DAY"); };
log { source(src); filter(f_local6); destination(proftpd); };

Sambaのログをsyslogで取得

Samba側の設定

まずは--with-syslog付きで再コンパイル

# vi /usr/local/etc/smb.conf
syslog only = yes
syslog = 2
vfs objects = full_audit
 full_audit:failure = connect disconnect opendir closedir mkdir rmdir open close rename unlink
 full_audit:success = connect disconnect mkdir rmdir open close rename unlink

Sambaビルドオプション確認方法

# smbd -b
vfs_full_audit_init があればOK

syslog-ng側の設定

destination smbd { file("/var/log/$HOST/$YEAR/smbd.log.$MONTH$DAY"); };
destination nmbd { file("/var/log/$HOST/$YEAR/nmbd.log.$MONTH$DAY"); };
destination smbd_audit { file("/var/log/$HOST/$YEAR/smbd_audit.log.$MONTH$DAY"); };
filter f_smbd { program("smbd$"); };
filter f_nmbd { program("nmbd"); };
filter f_smbd_audit { program("smbd_audit"); };
#
# Samba
#
log { source(src); filter(f_smbd); destination(smbd); };
log { source(src); filter(f_nmbd); destination(nmbd); };
log { source(src); filter(f_smbd_audit); destination(smbd_audit); };

Apacheのログをsyslogで取得

Apache側の設定

#  vi /usr/local/etc/apache22/httpd.conf
ErrorLog syslog:local7
LogLevel warn
TransferLog "| /usr/bin/logger -t httpd -p local7.info"

syslog-ng側の設定

# vi /usr/local/etc/syslog-ng.conf
destination httpd_access { file("/var/log/$HOST/$YEAR/access.log.$MONTH$DAY"); };
destination httpd_error { file("/var/log/$HOST/$YEAR/error.log.$MONTH$DAY"); };
filter f_notice { level(notice..emerg); };
filter f_access { level(info); };
log { source(src); filter(f_local7); filter(f_access); destination(httpd_access); };
log { source(src); filter(f_local7); filter(f_notice); destination(httpd_error); };

ログローテート

「$YEAR$MONTH$DAY-messages」などのような形式でログを取得している場合。
syslog-ngデーモンを再起動する事でログローテートができます。

# vi /etc/crontab
0       0       *       *       *       root    /usr/local/etc/rc.d/syslog-ng restart

毎日0時にsyslog-ngを再起動するcronを登録しておく。

syslogクライアントサーバの設定

# vi /etc/syslog.conf
*.*                                                     @loghost
# vi /etc/hosts
172.16.8.114            syslog-server.itoh.co.jp loghost

メール送信スクリプト

# cat /root/sshd_mail.cgi 
#!/usr/bin/perl

# メールのタイトル
$subject = 'Syslog-ng sshd alert';

# 送信先メールアドレス
$mailto = 'matsui@syslog-server.itoh.co.jp';

# 送信元メールアドレス
$mailfrom = 'webmaster@syslog-server.itoh.co.jp';

# sendmailパス
$sendmail = '/usr/sbin/sendmail';

use Jcode;

### メール送信 ###
while ($message = <STDIN>) {

  $head = "不正アクセスがありませた。\n確認してください。\ni\n";
  # 頭の余分な部分を削除
  $message =~ s/^\<\w+\>//g;
  $message = $head.$message;

  Jcode::convert(\$subject,jis);
  Jcode::convert(\$message,jis);

  open(MAIL,"| $sendmail -t");
  print MAIL "To: $mailto\n";
  print MAIL "From: $mailfrom\n";
  print MAIL "Subject: $subject\n";
  print MAIL "MIME-Version: 1.0\n";
  print MAIL "Content-type: text/plain; charset=ISO-2022-JP\n";
  print MAIL "Content-Transfer-Encoding: 7bit\n";
  print MAIL "$message\n";
  close(MAIL);
}

メール送信スクリプトではJcodeを使用しています。

# cpan -i Jcode

/usr/local/etc/syslog-ng.conf

# This sample configuration file is essentially equilivent to the stock
# FreeBSD /etc/syslog.conf file.

#
# options
#
options {
        long_hostnames(off);
        sync(0);
        create_dirs (yes);
        perm(0640);
        dir_perm(0750);
        group(wheel);
        owner(root);
};

# sources
#
source src { unix-dgram("/var/run/log");
             unix-dgram("/var/run/logpriv" perm(0600));
            udp( ip(0.0.0.0) port(514) ); internal(); file("/dev/klog");
};
#
# destinations
#
destination messages { file("/var/log/$HOST/$YEAR/$MONTH$DAY-messages"); };
destination security { file("/var/log/$HOST/$YEAR/$MONTH$DAY-security"); };
destination authlog { file("/var/log/$HOST/$YEAR/$MONTH$DAY-auth.log"); };
destination maillog { file("/var/log/$HOST/$YEAR/$MONTH$DAY-maillog"); };
destination lpd-errs { file("/var/log/$HOST/$YEAR/$MONTH$DAY-lpd-errs"); };
destination xferlog { file("/var/log/$HOST/$YEAR/$MONTH$DAY-xferlog"); };
destination cron { file("/var/log/$HOST/$YEAR/$MONTH$DAY-cron"); };
destination debuglog { file("/var/log/$HOST/$YEAR/$MONTH$DAY-debug.log"); };
destination consolelog { file("/var/log/$HOST/$YEAR/$MONTH$DAY-console.log"); };
destination all { file("/var/log/$HOST/$YEAR/$MONTH$DAY-all.log"); };
destination proftpd { file("/var/log/$HOST/$YEAR/proftpd.log.$MONTH$DAY"); };
#destination newscrit { file("/var/log/$HOST/$YEAR/$MONTH$DAY/news/news.crit"); };
#destination newserr { file("/var/log/$HOST/$YEAR/$MONTH$DAY/news/news.err"); };
#destination newsnotice { file("/var/log/$HOST/$YEAR/$MONTH$DAY/news/news.notice"); };
destination slip { file("/var/log/$HOST/$YEAR/$MONTH$DAY-slip.log"); };
destination ppp { file("/var/log/$HOST/$YEAR/$MONTH$DAY-ppp.log"); };
destination httpd_access { file("/var/log/$HOST/$YEAR/access.log.$MONTH$DAY"); };
destination httpd_error { file("/var/log/$HOST/$YEAR/error.log.$MONTH$DAY"); };
destination boot { file("/var/log/$HOST/$YEAR/boot.log.$MONTH$DAY"); };
destination smbd { file("/var/log/$HOST/$YEAR/smbd.log.$MONTH$DAY"); };
destination nmbd { file("/var/log/$HOST/$YEAR/nmbd.log.$MONTH$DAY"); };
destination smbd_audit { file("/var/log/$HOST/$YEAR/smbd_audit.log.$MONTH$DAY"); };
destination console { file("/dev/console"); };
destination allusers { usertty("*"); };
#destination loghost { udp("loghost" port(514)); };
destination to_mail { program("/root/sshd_mail.cgi"); };

#
# log facility filters
#
filter f_auth { facility(auth); };
filter f_authpriv { facility(authpriv); };
filter f_not_authpriv { not facility(authpriv); };
filter f_console { facility(console); };
filter f_cron { facility(cron); };
filter f_daemon { facility(daemon); };
filter f_ftp { facility(ftp); };
filter f_kern { facility(kern); };
filter f_lpr { facility(lpr); };
filter f_mail { facility(mail); };
filter f_news { facility(news); };
filter f_security { facility(security); };
filter f_user { facility(user); };
filter f_uucp { facility(uucp); };
filter f_local0 { facility(local0); };
filter f_local1 { facility(local1); };
filter f_local2 { facility(local2); };
filter f_local3 { facility(local3); };
filter f_local4 { facility(local4); };
filter f_local5 { facility(local5); };
filter f_local6 { facility(local6); };
filter f_local7 { facility(local7); };

#
# log level filters
#
filter f_emerg { level(emerg); };
filter f_arplookup { not match("arplookup"); };
filter f_messages { level(info..emerg) and not facility(auth,authpriv,cron,ftp,kern,lpr,mail,local0,local6,local7) or facility(kern) and level(debug); };
filter f_messages_no { not program("smbd") and not program("nmbd") and not program("smbd_audit"); };
filter f_alert { level(alert..emerg); };
filter f_crit { level(crit..emerg); };
filter f_err { level(err..emerg); };
filter f_warning { level(warning..emerg); };
filter f_notice { level(notice..emerg); };
filter f_info { level(info..emerg); };
filter f_debug { level(debug..emerg); };
filter f_is_debug { level(debug); };
filter f_access { level(info); };
filter f_ssh_authfail { program("sshd") and match("Failed password for invalid user"); };


# Alert
log { source(src); filter(f_ssh_authfail); destination(to_mail); };


#
# program filters
#
filter f_ppp { program("ppp"); };
filter f_slip { program("startslip"); };
filter f_smbd { program("smbd$"); };
filter f_nmbd { program("nmbd"); };
filter f_smbd_audit { program("smbd_audit"); };

#
# *.err;kern.warning;auth.notice;mail.crit             /dev/console
#
log { source(src); filter(f_err); destination(console); };
log { source(src); filter(f_kern); filter(f_warning); destination(console); };
log { source(src); filter(f_auth); filter(f_notice); destination(console); };
log { source(src); filter(f_mail); filter(f_crit); destination(console); };

#
# *.notice;authpriv.none;kern.debug;lpr.info;mail.crit;news.err        /var/log/messages
#
log { source(src); filter(f_notice); filter(f_not_authpriv); filter(f_arplookup); filter(f_messages_no); destination(messages); };
log { source(src); filter(f_kern); filter(f_debug); filter(f_arplookup); destination(messages); };
log { source(src); filter(f_lpr); filter(f_info); filter(f_arplookup); destination(messages); };
log { source(src); filter(f_mail); filter(f_crit); filter(f_arplookup); destination(messages); };
log { source(src); filter(f_news); filter(f_err); filter(f_arplookup); destination(messages); };

#
# security.*                                           /var/log/security
#
log { source(src); filter(f_security); destination(security); };

#
# auth.info;authpriv.info                              /var/log/auth.log
log { source(src); filter(f_auth); filter(f_info); destination(authlog); };
log { source(src); filter(f_authpriv); filter(f_info); destination(authlog); };

#
# mail.info                                            /var/log/maillog
#
log { source(src); filter(f_mail); filter(f_info); destination(maillog); };

#
# lpr.info                                             /var/log/lpd-errs
#
log { source(src); filter(f_lpr); filter(f_info); destination(lpd-errs); };

#
# ftp.info                                             /var/log/xferlog
#
log { source(src); filter(f_ftp); filter(f_info); destination(xferlog); };

#
# cron.*                                               /var/log/cron
#
log { source(src); filter(f_cron); destination(cron); };

#
# *.=debug                                             /var/log/debug.log
#
log { source(src); filter(f_is_debug); destination(debuglog); };

#
# *.emerg                                              *
#
log { source(src); filter(f_emerg); destination(allusers); };

#
# uncomment this to log all writes to /dev/console to /var/log/console.log
# console.info                                         /var/log/console.log
#
#log { source(src); filter(f_console); filter(F_INFO); DESTINATION(consolelog); };

#
# uncomment this to enable logging of all log messages to /var/log/all.log
# touch /var/log/all.log and chmod it to mode 600 before it will work
# *.*                                                  /var/log/all.log
#
log { source(src); filter(f_arplookup); destination(all); };

#
# uncomment this to enable logging to a remote loghost named loghost
# *.*                                                  @loghost
#
#log { source(src); destination(loghost); };

#
# uncomment these if you're running inn
# news.crit                                            /var/log/news/news.crit
# news.err                                             /var/log/news/news.err
# news.notice                                          /var/log/news/news.notice
#
#log { source(src); filter(f_news); filter(f_crit); destination(newscrit); };
#log { source(src); filter(f_news); filter(f_err); destination(newserr); };
#log { source(src); filter(f_news); filter(f_notice); destination(newsnotice); };

#
# !startslip
# *.*                                                  /var/log/slip.log
#
log { source(src); filter(f_slip); destination(slip); };

#
# !ppp
# *.*                                                  /var/log/ppp.log
#
log { source(src); filter(f_ppp); destination(ppp); };

#
# !proftpd
# *.*                                                  /var/log/proftpd.log
#
log { source(src); filter(f_local6); destination(proftpd); };

#
# !httpd
# *.*                                                  /var/log/httpd/access.log
#
log { source(src); filter(f_local0); filter(f_access); destination(httpd_access); };
log { source(src); filter(f_local0); filter(f_notice); destination(httpd_error); };

#
# local7.*                                                /var/log/boot.log
#
log { source(src); filter(f_local7); destination(boot); };

#
# Samba
#
log { source(src); filter(f_smbd); destination(smbd); };
log { source(src); filter(f_nmbd); destination(nmbd); };
log { source(src); filter(f_smbd_audit); destination(smbd_audit); };

Windowsのログをsyslog-ngに送る

NTSyslogをWindowsに入れる
http://www.hi-ho.ne.jp/denkas/library/

解凍したフォルダ内のNTSyslog.exeとNTSyslogCtrl.exeをwindows\system32へコピー

コマンドプロンプトから ※vistaの場合、右クリックして管理者として実行

ntsyslog -install

アンインストール

ntsyslog -remove

実行

ntsyslogctrl.exe

syslogファシリティとプリオリティ

ファシリティ

FACILITYCODEDETAIL
kern0カーネルメッセージ
user1ユーザプログラムのメッセージ
mail2メールプログラム(sendmai,qmail,etc...)のメッセージ
daemon3デーモンプロセス(ftpd,named,etc...)のメッセージ
auth4認証サービス(login,su,getty,etc...)のメッセージ
syslog5SYSLOGのメッセージ
lpr6印刷サービスのメッセージ
news7ニュースサービスのメッセージ
uucp8UUCP転送を行うプログラムのメッセージ
cron9 
auth-priv10 
ftp11 
local016アプリケーション用の汎用ファシリティ
local117アプリケーション用の汎用ファシリティ
local218アプリケーション用の汎用ファシリティ
local319アプリケーション用の汎用ファシリティ
local420アプリケーション用の汎用ファシリティ
local521アプリケーション用の汎用ファシリティ
local622アプリケーション用の汎用ファシリティ
local723アプリケーション用の汎用ファシリティ

プライオリティ

PRIORITYLEVELDETAIL
emerg ( panic )( 8 )重大な状況時に送信されるメッセージ
alert( 7 )直ちに修復すべき状況を伝えるメッセージ
crit( 6 )致命的な状況を伝えるメッセージ
err ( error )( 5 )一般的なエラーメッセージ
warn ( warning )( 4 )警告メッセージ
notice( 3 )注意しておいたほうがいいメッセージ
info( 2 )いろいろな情報を伝えるメッセージ
debug( 1 )デバッグ用のメッセージ
none-メッセージを受け取らないことを示す、特別な PRIORITY 値