連載
» 2004年04月07日 00時00分 UPDATE

止められないUNIXサーバのセキュリティ対策(10):安全性の高いログ・サーバへの乗り換えのススメ(2)〜 ログ管理のセキュリティ強化を実現する方法を知ろう 〜

[木村靖,三井物産GTI]
※ご注意
本稿の内容を検証する場合は、必ず影響を及ぼさない限られた環境下で行って下さい。また、本稿を利用した行為による問題に関しましては、筆者および株式会社アットマーク・アイティは一切責任を負いかねます。ご了承ください。

 前回に引き続き今回も、安全性がより考慮されたsyslogサーバのsyslog-ng(syslog-next generation)への切り替えについて述べる。

syslog-ngへの切り替え

syslogdの設定を引き継ぐ

 現行のsyslogdから切替える場合は、syslogdの設定内容をそのまま引き継ぐようにする。もちろん、一からsyslog-ngの設定を書き上げてもよいが、後々の運用管理において混乱が生じないようにするためには、現行syslogdの設定内容を引き継いだ方がよい。syslogdからsyslog-ngへの移行例(設定例)を以下に示す。

移行前:syslogdの設定(syslog.conf)

*.err;kern.*;auth.notice;authpriv.none;mail.crit        /dev/console
*.info;auth,authpriv,cron,ftp,kern,lpr,mail.none        /var/log/messages
kern.debug                                              /var/log/messages
auth,authpriv.info                                      /var/log/authlog
cron.info                                               /var/cron/log
ftp.info                                                /var/log/xferlog
lpr.info                                                /var/log/lpd-errs
mail.info                                               /var/log/maillog
*.emerg                                                 *
*.notice                                                root

 上記syslog.confをsyslog-ngに移行した場合、以下のとおりとなる。

移行後:syslog-ngの設定(syslog-ng.conf)

source s_local { unix-dgram("/var/run/log"); internal(); };
destination d_console  { pipe("/dev/console"); };
destination d_messages { file("/var/log/messages"); };
destination d_authlog  { file("/var/log/authlog"); };
destination d_cron     { file("/var/cron/log"); };
destination d_ftp      { file("/var/log/xferlog"); };
destination d_lpr      { file("/var/log/lpd-errs"); };
destination d_maillog  { file("/var/log/maillog");
 }; destination d_alluser  { usertty("*"); };
destination d_root     { usertty("root"); };
filter f_console  { level(err..emerg)
                    or facility(kern) and level(debug)
                    or facility(auth) and level(notice..emerg)
                    or facility(mail) and level(crit..emerg)
                    and not facility(authpriv); };
filter f_messages { level(info..emerg)                     and not facility(auth,authpriv,cron,ftp,kern,lpr,mail)
                    or facility(kern) and level(debug); };
filter f_authlog  { facility(auth,authpriv)  and level(info); };
filter f_cron     { facility(cron) and level(info); };
filter f_ftp      { facility(ftp) and level(info); };
filter f_lpr      { facility(lpr) and level(info); };
filter f_maillog  { facility(mail) and level(info); };
filter f_alluser  { level(emerg); };
filter f_root     { level(notice); };
log { source(s_local); filter(f_console);  destination(d_console); };
log { source(s_local); filter(f_messages); destination(d_messages); };
log { source(s_local); filter(f_authlog);  destination(d_authlog); };
log { source(s_local); filter(f_cron);     destination(d_cron); };
log { source(s_local); filter(f_ftp);      destination(d_ftp); };
log { source(s_local); filter(f_lpr);      destination(d_lpr); };
log { source(s_local); filter(f_mail);     destination(d_maillog); };
log { source(s_local); filter(f_alluser);  destination(d_alluser); };
log { source(s_local); filter(f_root);     destination(d_root); };

syslog-ngの起動オプションを知る

 syslog-ngの設定が完了したら、後は現行のsyslogdを停止してからsyslog-ngを起動するだけだが、その前にsyslog-ngの起動オプションを知っておく必要がある。

 syslog-ng 1.6.2には、以下のようなオプションが用意されている。

% syslog-ng -h
Usage: syslog-ng [options]
Accept and manage system log messages
Options:
  -s, --syntax-only                Only read and parse config file
  -d, --debug                      Turn on debugging messages   
-v, --verbose                    Be a bit more verbose
  -F, --foreground                 Don't fork into background
  -f '<'fname'>', --cfgfile='<'fname'>'    Set config file name, 
default=/usr/local/etc/syslog-ng/syslog-ng.conf
  -V, --version                    Display version number (syslog-ng 1.6.2)
  -p '<'fname'>', --pidfile='<'fname'>'    Set pid file name, default=/var/run/syslog-ng.pid
  -C '<'dir'>', --chroot='<'dir'>'         Chroot to directory
  -u '<'user'>', --user='<'user'>'         Switch to user
  -g '<'group'>', --group='<'group'>'      Switch to group
  -y, --yydebug                    Turn on yacc debug messages

 このうち重要となるのが、構文チェックの-s(--syntax-only)、実行ユーザー/グループを変更する-u(--user)、-g(--group)である。これらについては後述する。

syslog-ng起動前に行うべきこと(構文チェック)

 syslog-ngを実際に起動する前に、syslog-ng.confの構文チェックを必ず行うこと。syslog-ngには、構文チェックを行うための便利なオプション(-s)が提供されているので、syslog-ngの設定変更時は、必ず-sオプションで事前確認するとよい。

% syslog-ng -s
※注 必要に応じてフルパス(/usr/local/sbin/syslog-ng)を指定する。

 例えば、syslog-ng.confの26行目の構文が間違えていた場合は、以下のように表示される。

% syslog-ng -s
parse error at 26
Parse error reading configuration file, exiting. (line 26)
%

 syslog-ng.confが正しく設定されていれば、何も表示されない。

% syslog-ng -s
%

syslog-ngの起動

 前述の構文チェックをクリアできたら、後は現在稼働中のsyslogdを停止し、syslog-ngを起動するだけだ。以下に各OS別の切り替え手順をまとめる。

●FreeBSD 4.6-RELEASEの場合

 起動スクリプトは、portsのものを利用する。

    # cd /usr/ports/sysutils/syslog-ng/files
    # cp syslog-ng.sh.sample /usr/local/etc/rc.d/syslog-ng.sh

 実行ユーザーを変更する場合は、起動スクリプトに「-u 実行ユーザー名」を追加する。以下の例では、実行ユーザー名をnobodyとしている。

 変更前:

    start)
    [ -x ${PREFIX}/sbin/syslog-ng ] && ${PREFIX}/sbin/syslog-ng && echo -n ' syslog-ng'

 変更後:

    start)
    [ -x ${PREFIX}/sbin/syslog-ng ] && ${PREFIX}/sbin/syslog-ng -u nobody && echo -n ' syslog-ng'

 syslog-ngの準備完了。syslogdを停止する。

    # ps -ax | grep syslogd
    20258 ?? Is 0:20.21 /usr/sbin/syslogd
    # kill -TERM 20258

 syslog-ngを即座に起動する。

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

 次回OS起動時に、syslogdではなくsyslog-ngを起動する場合は、/etc/rc.confに次の一行を追加する。

    syslogd_enable="NO"

●NetBSD 1.6の場合

    # cp /etc/rc.d/syslogd /etc/rc.d/syslogng
    # vi /etc/rc.d/syslogng

 以下のとおりsyslogdをsyslogngに変更する。一部のパスはsyslog-ngにする。

    # PROVIDE: syslogng
    name="syslogng"
    command="/usr/local/sbin/syslog-ng"
    required_files="/etc/syslog-ng/syslog-ng.conf"
    _sockfile="/var/run/syslog-ng.sockets"
    # vi /etc/rc.conf

 /etc/rc.confに以下を追加する。

    syslogng=YES
    syslogng_flags="-f /etc/syslog-ng/syslog-ng.conf"

 実行ユーザーを変更する場合は、syslogng_flagsに「-u 実行ユーザー名」を追加する。以下の例では、実行ユーザー名をnobodyとしている。

    syslogng_flags="-u nobody -f /etc/syslog-ng/syslog-ng.conf"

 これでsyslog-ngの準備は完了。syslogdを停止する。

    # /etc/rc.d/syslogd stop

 syslog-ngを即座に起動する。

    # /etc/rc.d/syslogng start
    Starting syslogng.

 次回OS起動時に、syslogdを起動しないようにするため、/etc/rc.confに次の一行を追加する。

    syslogd=NO

●Red Hat Linux 7.3の場合

 ソースコードからインストールした場合は、syslog-ngのソースコードのcontrib以下にある起動スクリプト(init.d.RedHat-7.3)を利用する。

    % cd /usr/local/src/syslog-ng-1.6.2
    # cp contrib/init.d.RedHat-7.3 /etc/init.d/syslog-ng
    # chkconfig --add syslog-ng

起動スクリプトが有効(ランレベル2、3がon)になったことを確認する。

    # chkconfig --list syslog-ng
    syslog-ng 0:off 1:off 2:on 3:on 4:on 5:on 6:off

 実行ユーザーを変更する場合は、/etc/sysconfig/syslog-ngファイルのSYSLOGNG_OPTIONSに「-u 実行ユーザー名」を追加する。以下の例では、実行ユーザー名をnobodyとしている。

    SYSLOGNG_OPTIONS="-u nobody"

 syslog-ngの準備完了。syslogdを停止する。

    # service syslog stop

 即座にsyslog-ngを起動する。

    # service syslog-ng start

 次回OS起動時に、syslogdを起動しないようにする。

    # chkconfig syslog off
    # chkconfig --level 2 syslog off
    # chkconfig --list syslog
    syslog    0:off  1:off  2:off  3:off  4:off  5:off  6:off

●Solaris 8の場合

 ソースコードからインストールした場合は、syslog-ngのソースコードのcontrib以下にある起動スクリプト(init.d.solaris)を利用する。

    % cd /usr/local/src/syslog-ng-1.6.2
    # cp contrib/init.d.solaris /etc/init.d/syslog-ng
    # ln /etc/init.d/syslog-ng /etc/rc0.d/K40syslog-ng
    # ln /etc/init.d/syslog-ng /etc/rc1.d/K40syslog-ng
    # ln /etc/init.d/syslog-ng /etc/rc2.d/S74syslog-ng
    # ln /etc/init.d/syslog-ng /etc/rcS.d/K40syslog-ng

 実行ユーザーを変更する場合は、/etc/init.d/syslog-ngファイルのOPTIONSに「- u 実行ユーザー名」を追加する。以下の例では、実行ユーザー名をnobodyとしている。

 変更前:

    OPTIONS="-f /etc/syslog-ng/syslog-ng.conf"

 変更後:

    OPTIONS="-u nobody -f /etc/syslog-ng/syslog-ng.conf"

 syslog-ngの準備完了。syslogdを停止する。

    # /etc/init.d/syslog stop

 即座にsyslog-ngを起動する。

    # /etc/init.d/syslog-ng start

 次回OS起動時に、syslogdを起動しないようにする。

    # mv /etc/rc2.d/S74syslog /etc/rc2.d/disable.S74syslog

起動後の確認

 syslog-ngの起動が正常に行われると、以下のようなログが出力される(通常は /var/log/messages)。

Mar 14 04:30:30 s_local@server1 syslog-ng[1395]: syslog-ng version 1.6.2 starting

 もちろん、syslogdの場合と同じく、loggerコマンド*1を使った確認も忘れずに行うこと。

ログ・ローテーションの設定変更

 最近のUNIXでは、標準でnewsyslogやlogrotateなどを使用して、ログファイルのローテーションが行われている。syslogdからsyslog-ngへの切り替えを行った場合、それらログ・ローテーションに関する設定も変更する必要がある。

 なぜなら、ログファイルのローテーションを実施する際に、稼働中のsyslogサーバのプロセスに対して、HUPシグナルを送る必要があるからだ。従来の場合は、syslogdが仮定されているため、それをsyslog-ng用に変更する。

●newsyslog(FreeBSD、NetBSDなどで標準)

 newsyslogの設定ファイル(/etc/newsyslog.conf)にて、syslog-ngのプロセスID(PID)ファイルへのパスを明示的に指定する。以下に例を示す。

 変更前:

    /var/cron/log           root:wheel      600  3    10   *    Z
    /var/log/aculog         uucp:dialer     640  7    *    24   Z
    /var/log/authlog                        600  5    30   *    Z
    …… 省略 ……

 変更後:

    /var/cron/log           root:wheel      600  3    10   *    Z
    /var/run/syslog-ng.pid
    /var/log/aculog         uucp:dialer     640  7    *    24   Z
    …… 省略 ……

●logrotate(Red Hat Linuxなどで標準)

 logrotateの設定ファイル(/etc/logrotate.conf)のpostrotate/endscriptにて、syslog-ngプロセスに対してHUPシグナルを送信する。以下に例を示す。

    postrotate         /sbin/kill -HUP 
    /var/run/syslog-ng.pid
    endscript

syslog-ngそのほかの設定

syslog-ngのチューニング

 通常は、optionsの値はデフォルト値で構わないが、必要に応じて変更するようにしよう。

●ホスト名の出力をsyslogdと同じにする

 syslog-ngのデフォルトでは、出力されるログのホスト名にsourceのが付加される。

    Mar 14 04:40:30 s_local@server1 syslog-ng[1545]: STATS: dropped 0

 上記では、server1というホスト名にs_localが付加されている。これを、syslogdと同じくserver1だけ出力したい場合は、long_hostnames(off)をセットする。

    options {
    long_hostnames(off);
    };

●ファイルのパーミッションを変更する

 syslog-ngのデフォルトでは、ログディレクトリ/ファイルの所有者やパーミッションは以下のとおりとなっている。

所有者(owner) root
グループ(group) root
パーミッション(ディレクトリ) 0700 (-rwx------)
パーミッション(ファイル) 0600 (-rw-------)

 この場合、後述のログのローテーション時にパーミッションをセットしていると不都合がおきる。なぜなら、syslog-ngの起動時に、こういった所有者やパーミッションを変更してしまうからだ。

 従来(ログローテーション)と同じにしたい場合は、optionsやdestinationにて、dir_perm()、perm()、owner()、group()を指定する。以下に一例を示す。

    options {
            dir_perm(0755);
            perm(0644);
            owner(root);
            group(wheel);
    };
    destination d_authlog {
            file("/var/log/authlog");
            perm(0600);
    };

上記では、それぞれ以下のとおり設定している。

  • dir_perm()で、ディレクトリのパーミッションを0755(-rwxr-xr-x)にセット
  • perm()で、ファイルのパーミッションを0644(-rw-r--r--)にセット
  • owner()で、所有者をrootにセット
  • group()で、グループをwheelにセット

 また、ログファイルごとにパーミッションを変更したい場合は、destination内で指定すればよい。例では、/var/log/authlogファイルのパーミッションを0600(-rw-------)にセットしている。

 上記のようにログファイルごとに変更したい場合は、destinationで指定する。そのほか、設定されていない場合は、optionsで設定した内容が適用される。

●syslog-ngの状態ログの出力間隔を変更する

 syslog-ng自身が出力するログを眺めていると、以下のようなログが定期的に出力される。

    Mar 14 04:40:30 s_local@server1 syslog-ng[1545]: STATS: dropped 0
    Mar 14 04:50:30 s_local@server1 syslog-ng[1545]: STATS: dropped 0
    Mar 14 05:00:30 s_local@server1 syslog-ng[1545]: STATS: dropped 0

 これは、syslog-ngの状態を定期的にレポートするもので、バッファ出力に失敗したログの数(STATS:dropped失敗した数)が出力される。デフォルト値は、10分(600秒)間隔となっているが、間隔をもっと延ばしたい場合は、optionsのstatsパラメータを調整する。なお、後述のsync(0)でログをバッファに保存しない場合は、stats(0)をセットするとよい。

 例:syslog-ngの状態監視を 24時間(86400秒)置きに実行する場合

    options {
    stats(86400);
    };

●sync()パラメータでバッファに保持するメッセージ数を調整

 sync()パラメータでは、ログをファイルへ出力前に、バッファに保持するメッセージ数(。行数)を指定する。デフォルトは2048。以下にsync()パラメータの設定例を示す。

    options {
    sync(0);
    };

 sync(0)を指定すると、ログをバッファに出力せず、そのままファイルなどに書き込むようにする。syslogdの挙動と同じにしたい場合に指定する。

●ガーベジコレクタの閾(しきい)値を調整

syslog-ngは、ガーベジコレクタ(garbage collector)の機能を持っているが、ガーベジコレクタの実行中は、ログメッセージを受け付けない。その場合、ログの受け渡しにunix-dgram()やudp()といった信頼性のないプロトコル(ソケット)を利用していると、ログを取りこぼす可能性が生じる。

syslog-ngでは、そういった取りこぼしを防ぐために、gc_idle_threshold()とgc_busy_threshold()のoptionsパラメータが提供されている。

gc_idle_threshold() syslog-ngがアイドル状態(100ミリ秒の間にメッセージが発生しない状態)の場合、かつ割り当てたオブジェクトの数がgc_idle_threshold()で指定した数に到達した場合、ガーベジコレクタを実行する。デフォルトは100。
gc_busy_threshold() syslog-ngがビジー状態(100ミリ秒の間に入出力イベントが発生した状態)、かつ割り当てたオブジェクト数がgc_busy_threshold()で指定した数に到達した場合、ガーベジコレクタを実行する。デフォルトは3000。この値が大きいほど、ガーベジコレクタによるメッセージ受信に帯する割り込みがなくなる。

 以下にgc_idle_threshold()とgc_busy_threshold()の設定例を示す。

    options {
    gc_idle_threshold(50);
    gc_busy_threshold(5000);
    };

 通常はデフォルト値で構わないが、ログが頻発するサーバの場合*2、gc_idle_threshold()を減らし、逆にgc_busy_threshold()の閾(しきい)値を増やす。

*2
前述のログに定期的に出力される、「STATS:dropped 破棄数」で確認。破棄数が0以外が頻発する場合は調整が必要。

ログ転送

 syslog-ngでは、「第8回 syslogによるログの一元管理」で説明したログ転送も同様に行える。

 syslogdから切り替える場合は、(1)ログ・サーバ、(2)ログ転送元サーバの順に1台ずつ切り替えるとよいだろう。

(1)ログ・サーバをsyslog-ngに切り替える

 まず、前述のsyslog-ngの基本的な設定までを行い、その後にログ受信に関する設定を以下のとおり行う。

●sourceの変更

 udp()により、ログを受信するポートを514/udpで待機させる。

 変更前:

    source s_local { unix-dgram("/var/run/log"); internal(); };

 変更後:

    source s_local { unix-dgram("/var/run/log"); internal(); udp(); };

 ネットワークインターフェイス(NIC)が複数あり、ログの受信を特定のIPアドレスを持つNICからのみに制限したい場合は、udp()内でip()を指定する。

 例えば、192.168.0.10と172.16.1.100のNICがあり、ログの受信を192.168.0.10のNICからのみに制限したい場合は、以下のように設定する。

    source s_local { unix-dgram("/var/run/log"); internal(); udp(ip("192.168.0.10") port(514)); };

 設定を有効にする場合は、稼働中のsyslog-ngプロセスにHUPシグナルを送信するだけだ(syslogdとは違い再起動の必要がない)。

●destinationの変更

 syslogdとは異なり、syslog-ngでは複数のsyslogサーバのログファイルを分けることができる。もし、ログを分けたい場合は、destinationを変更する必要がある。

 例:ログ転送元サーバserver1、server2の/var/log/authlogを分ける。destination、filter、logを以下のとおり設定する。

    destination d_authlog { file("/var/log/$HOST/authlog"); };
    filter f_authlog_server1 { host(server1) and facility(auth,authpriv) and level(info..emerg); };
    filter f_authlog_server2 { host(server2) and facility(auth,authpriv) and level(info..emerg); };
    log { source(s_local); filter(f_authlog_server1); destination(d_authlog); };
    log { source(s_local); filter(f_authlog_server2); destination(d_authlog); };

 $HOSTは、syslog-ngが保持する変数で、ログ送信元のホスト名が保持されている。

 なお、ディレクトリを自動作成しない設定(create_dirs(n))にしている場合は、あらかじめディレクトリを作成しておく必要がある。

    # mkdir /var/log/server1 /var/log/server2

(2)ログ転送元をsyslog-ngに切り替える

 ログ・サーバと同じく、前述のsyslog-ngの基本的な設定までを行い、その後にログ送信に関する設定を以下のように行う。

●destinationの追加

 ログ転送用のdestinationを定義する。ログ・サーバが192.168.0.10の場合、以下のように設定する。

    destination d_loghost { udp("192.168.0.10"); };

 デフォルトでは、転送元ポート(localport)は任意のポートとなり、転送先ポート(port)は514となる。例えば、転送元ポートをsyslogdと同様に514にしたい場合は、以下のとおり設定する。

    destination d_loghost { udp("192.168.0.10" localport(514)); };

●logの変更

 追加したdestinationを各logに追加する。以下に例を示す。

    log { source(s_local); filter(f_authlog); destination(d_authlog); destination(d_loghost); };

 ログ転送の確認が完了し、ログの格納先を全てログ・サーバに切り替える場合は、以下のようにdestination(d_authlog)を取り除くだけだ。

    log { source(s_local); filter(f_authlog); destination(d_loghost); };

ログ監査の自動化

 syslog-ngでは、filter機能のprogram()、host()、match()を利用することで、ログ監査を自動化させることが可能だ。この機能は、従来のsyslogdにはなく、syslogdでそれを実現するには、swatch*3などの専用アプリケーションを別途導入する必要があった。

 以下にログ監査の例を示す。

 例:sshdに対するパスワードログイン失敗のログを捕捉した場合、管理者(root@example.com)にメール通知する。

 sshdのパスワードログインに失敗した場合、以下のようなログメッセージが出力される。

Mar 26 07:50:00 atmarkit sshd[27576]: Failed password for kimu from 192.168.0.1 port 1030 ssh2

 上記の場合、192.168.0.1からユーザーkimuによるパスワードログインに失敗した様子を示している。syslog-ngでこのログメッセージを捕捉し、管理者にメー ル送信をする場合は以下のように定義する。

destination d_mail-alert { program("/usr/local/bin/syslog-alert.sh"); }; filter f_sshd_failed_password { program("sshd") and match("Failed password "); }; log { source(s_local); filter(f_sshd-failed-password); destination(d_mail-alert); };

 出力先の/usr/local/bin/syslog-alert.shは、メール通知のためのシェルスクリプトだ。ここで使用するシェルスクリプトの内容を以下に示す。

#!/bin/sh
TO=root@example.com
while read line
do
        line=`echo $line | sed -e 's/^<[0-9]*>//'`;
        echo $line | /usr/bin/mail -s "alert mail" $TO
done

 上記のsedは、ログの行頭に付加される""の部分を取り除いている。つまり、オリジナルのログメッセージと同様にしている。

 以上の設定が完了したら、syslog-ngに対してHUPシグナルを送信する。なお、上記シェルスクリプトの内容を変更した場合も、HUPシグナルを送信しないと反映されないので注意が必要だ。

 正常に動作すると、以下のようなメールが管理者(root@example.com)に送られる。

From: nobody@example.com
To: root@example.com
Subject: alert mail
Mar 26 07:50:00 atmarkit sshd[27576]: Failed password for kimu from 192.168.0.1 port 1030 ssh2

 今回は、syslogサーバからセキュアなログ・サーバsyslog-ngへの切り替えに関して説明を行った。ログに関する設定は以上となる。次回は、ファイル改ざんの検出について説明する。

筆者紹介

三井物産GTI(現:三井物産セキュアディレクション株式会社

木村靖



Copyright© 2017 ITmedia, Inc. All Rights Reserved.

@IT Special

- PR -

TechTargetジャパン

この記事に関連するホワイトペーパー

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。