syslog-ng (日本語) - ArchWiki

# syslog-ng (日本語)

関連記事

- rsyslog
- Netconsole

Note: systemd にアップグレードした後は、systemd の journal でログを見ることができるので、ほとんどの場合、syslog-ng は必要なくなりアンインストールすることができます。

## 概要

syslog-ng は定義済みの 'source' からのメッセージを受け取って、強力な filter ディレクティブに基づいて、適当な destination に転送します。標準的なシンプルな設定だと、syslog-ng は3つの source からメッセージを読み取ります:

1. デフォルトの `/dev/log` デバイス (ほとんどのログはここに送られます)
2. syslog-ng の"内部的な"ログメッセージ
3. `/proc/kmsg` カーネルメッセージ

受信元は "source" ディレクティブを使って定義します。受信されたメッセージは次に定義済みのフィルター ("filter" キーワード) によってフィルタリングされ、送信元のプログラムやログレベルにあわせて、適当な "destination" に送信されます。送信先としてはログファイル (例: `/var/log/messages.log`) や、コンソールやリモートサーバーにメッセージを表示するなどが考えられます。中心的な関数は log です。この関数は特定の source に対してどのフィルターを適用し、作成されたメッセージをどこに送信すればいいのか定義します。

`syslog-ng.service` サービスファイルを使って syslog-ng を有効化します。systemd 216 から、メッセージはデフォルトでは syslog に転送されなくなりました。転送を有効にするには、root で `/etc/systemd/journald.conf` を編集して、`#ForwardToSyslog=no` を `ForwardToSyslog=yes` に変更してください。

## Source

syslog-ng は source からログメッセージを受信します。source を定義するときは以下の構文に従う必要があります:

    source <identifier> { source-driver(params); source-driver(params); ... };

identifier と source-driver については 公式マニュアル で読むことができます。マニュアルにしたがって上記の設定ファイルを説明します。unix-stream() source-driver は指定された AF_UNIX ソケットを開いてメッセージが来るのを待ちます。internal() source-driver は syslog-ng によって生成されたメッセージを取得します。

したがって、以下の設定の意味は: `src` は `/dev/log` ソケットと syslog-ng からのメッセージを取得する、となります。

    source src { unix-stream("/dev/log"); internal(); };

カーネルはログメッセージを `/proc/kmsg` に送信して file() ドライバーはファイルからログメッセージを読み取ります。したがって、以下の設定の意味は: kernsrc は `/proc/kmsg` ファイルからメッセージを取得する、となります。

    source kernsrc { file("/proc/kmsg"); };

デフォルト設定では syslog-ng の後に、以下のように source が定義されています:

    source src { unix-stream("/dev/log"); internal(); pipe("/proc/kmsg"); };

`pipe("/proc/kmsg")` によってメッセージを読み込むことでパフォーマンスには良い影響がありますが、読み書きモードで開くのでセキュリティ上問題になります。このことは syslog-ng admin guide のセクション 3.3.3 で触れられています:

"パイプは file() ドライバーとよく似ていますが、多少の違いがあり、例えば pipe() は読み書きモードで開くので、`/proc/kmsg` などの特殊なファイルで使用するのは推奨されません" (この議論については ここの投稿 で読むことができます)。

リモートサーバーからデータを読み取るためにポートを開けるには、以下の構文の source を定義します。UDP の場合:

    source s_net { udp(); };

もしくは TCP によってログメッセージを受信するには:

    source s_net { tcp(); };

どちらも514番ポートを listen します。

## Destination

syslog-ng では、ログメッセージはファイルに送信されます。構文は source とよく似ています:

    destination <identifier> {destination-driver(params); destination-driver(params); ... };

通常はファイルにログを出力することになりますが、他にも様々な destination-driver にログを書き出すことが可能です: パイプ, Unix ソケット, TCP-UDP ポート, ターミナルまたは特定のプログラムなど。したがって、以下の設定は authlog メッセージを `/var/log/auth.log` に送信します:

    destination authlog { file("/var/log/auth.log"); };

(ユーザーがログインしているとき) `usertty()` は指定されたユーザーのターミナルにメッセージを送信します。root のターミナルにコンソールメッセージを送りたい場合:

    destination console { usertty("root"); };

`pipe()` を使えばメッセージをパイプに送信することができます。以下の設定は xconsole メッセージを `/dev/xconsole` パイプに送信します。

    destination xconsole { pipe("/dev/xconsole"); };

ネットワーク上にメッセージを送信するには、`udp()` を使います。以下の destination はログデータを別のサーバーに送信します。

    destination remote_server { udp("10.0.0.2" port(514)); };

## メッセージのフィルターを作成

filter ステートメントの構文は:

    filter <identifier> { expression; };

expression には関数を使うことができます。例えばファシリティコードによってメッセージを選り分ける `facility()` 関数などです。Linux カーネルには少数ながらログに使うことが出来る facility がいくつかあります。それぞれの facility にはログレベルが存在します。debug は最も情報量が多く、panic は深刻なエラーのみを表示します。facility, ログレベル, プライオリティの名前は `/usr/include/sys/syslog.h` で確かめることができます。May 11 23:42:31 mimosinnet su(pam_unix)[18569]: session opened for user root by (uid=1000) のような authorization からのメッセージを取り出すには、以下を使います:

    filter f_auth { facility(auth); };

facility には論理演算子 `and`, `or`, `not` を使うことが可能です。例えば以下のフィルターは authorization, network news, mail からではないメッセージを選択します:

    filter f_debug { not facility(auth, authpriv, news, mail); };

`level()` 関数はプライオリティレベルによってメッセージを選択します。informational レベルを選択したい場合は:

    filter f_info { level(info); };

関数と論理演算子は組み合わせて複雑な条件を作成することができます。以下のフィルターはプライオリティレベルが informational から warning の間で facility が auth, authpriv, mail, news ではないメッセージを抜き出します:

    filter f_messages { level(info..warn) and not facility(auth, authpriv, mail, news); };

`match("regex" value("TEMPLATE"))` 関数を使って正規表現にメッセージをマッチさせて選択することも可能です。例えば:

    filter f_failed { match("failed" value("MESSAGE")); };

以下はテンプレートのリストです:

     "AMPM", "BSDTAG", "DATE, C_DATE, R_DATE, S_DATE", "DAY, C_DAY, R_DAY, S_DAY", "FACILITY", "FACILITY_NUM", "FULLDATE, C_FULLDATE, R_FULLDATE, S_FULLDATE", "FULLHOST", "FULLHOST_FROM", "HOUR, C_HOUR, R_HOUR, S_HOUR", "HOUR12, C_HOUR12, R_HOUR12, S_HOUR12", "HOST", "HOST_FROM", "ISODATE, C_ISODATE, R_ISODATE, S_ISODATE", "LEVEL_NUM", "LOGHOST", "MIN, C_MIN, R_MIN, S_MIN", "MONTH, C_MONTH, R_MONTH, S_MONTH", "MONTH_ABBREV, C_MONTH_ABBREV, R_MONTH_ABBREV, S_MONTH_ABBREV", "MONTH_NAME, C_MONTH_NAME, R_MONTH_NAME, S_MONTH_NAME", "MONTH_WEEK, C_MONTH_WEEK, R_MONTH_WEEK, S_MONTH_WEEK", "MSEC, C_MSEC, R_MSEC, S_MSEC", "MSG or MESSAGE", "MSGHDR", "MSGID", "MSGONLY", "PID", "PRI", "PRIORITY or LEVEL", "PROGRAM", "SDATA, .SDATA.SDID.SDNAME", "SEC, C_SEC, R_SEC, S_SEC", "SOURCEIP", "SEQNUM", "STAMP, R_STAMP, S_STAMP", "SYSUPTIME", "TAG", "TAGS", "TZ, C_TZ, R_TZ, S_TZ", "TZOFFSET, C_TZOFFSET, R_TZOFFSET, S_TZOFFSET", "UNIXTIME, C_UNIXTIME, R_UNIXTIME, S_UNIXTIME", "USEC, C_USEC, R_USEC, S_USEC", "YEAR, C_YEAR, R_YEAR, S_YEAR", "WEEK, C_WEEK, R_WEEK, S_WEEK", "WEEK_ABBREV, C_WEEK_ABBREV, R_WEEK_ABBREV, S_WEEK_ABBREV", "WEEK_DAY, C_WEEK_DAY, R_WEEK_DAY, S_WEEK_DAY", "WEEKDAY, C_WEEKDAY, R_WEEKDAY, S_WEEKDAY", "WEEK_DAY_NAME, C_WEEK_DAY_NAME, R_WEEK_DAY_NAME, S_WEEK_DAY_NAME".

特定のリモートホストから受信したメッセージをフィルタリングする場合は、`host()` 関数を使って下さい:

    filter f_host { host( "192.168.1.1" ); };

## ログのパス

syslog-ng は source, filter, destination を log ステートメントで接続します。構文は:

    log {source(s1); source(s2); ...
    filter(f1); filter(f2); ...
    destination(d1); destination(d2); ...
    flags(flag1[, flag2...]); };

以下は `src` source からのメッセージを `f_info` filter でフィルターにかけて `mailinfo` destination に送信する例です:

    log { source(src); filter(f_mail); filter(f_info); destination(mailinfo); };

## Tips and Tricks

syslog-ng の背後にあるロジックを理解したら、様々な設定、複雑な設定をすることが可能になります。以下はほんの一例です。

### syslog-ng に設定ファイルをリロードさせる

You can make syslog-ng re-evaluate the configuration file. You can do so manually by sending a `SIGHUP` to the process, or call the reload function with systemctl:

    # systemctl reload syslog-ng

### Failover Logging to Remote Host

This setup shows how to send the default unencrypted syslog packets across both TCP and UDP protocols, using the standard port (514) and an alternate port. This is sending the same output to the same machine 4 different ways to try and make sure packets make it. Mostly useful if you are debugging a remote server that fails to reboot. The different ports and protocols are to make it past any firewall filters or other network problems. Also useful for port-forwarding and using tunnels. Something like this setup is ideal to tunnel across an ssh connection that the prone-to-failover host initiates through a reverse connection.

    #sending to a remote syslog server on TCP and UDP ports (not encrypted)
    destination askapache_failover_loghost {
        tcp("208.86.158.195" port(25214));
        udp("208.86.158.195" port(25214));
        udp("mysyslog1.dyndns.org" port(514));
    };
    log {
        source(src);
        destination(askapache_failover_loghost);
    };

And then on the loghost receiving these logs:

    #a USB redirected console for flexible viewing
    destination debugging_console {
        file("/dev/ttyU1");
    };

    # listens on IP addresses and ports, sets the incoming settings
    source prone_to_failover_host {
        tcp(ip(208.86.158.195),port(25214));
        udp(ip(208.86.158.195) port(25214));

        udp(default-facility(syslog) default-priority(emerg));
        tcp(default-facility(syslog) default-priority(emerg));
    }

    # log it
    log {
        source(prone_to_failover_host);
        destination(debugging_console);
    };

### ログを別のファイルに移動

ログを `/var/log/messages` から他のファイルに移動するには:

    #sshd configuration
    destination ssh { file("/var/log/ssh.log"); };
    filter f_ssh { program("sshd"); };
    log { source(src); filter(f_ssh); destination(ssh); };

### Configuring as a loghost

Configuring your system to be a loghost is quite simple. Drop the following into your configuration, and create the needed directory. With this simple configuration, log filenames will be based on the FQDN of the remote host, and located in `/var/log/remote/`. After creating the remote directory, reload your syslog-ng configuration.

    source net { udp(); };
    destination remote { file("/var/log/remote/${FULLHOST}-log"); };
    log { source(net); destination(remote); };

### パフォーマンスの向上

いくつかの方法を使って syslog-ng のパフォーマンスを上げることができます:

#### Write every so often

It seems that the old `sync(X)` option is called `flush_lines(X)` now, where the writing to the file is buffered for `X` lines. Default is 0 (no buffering).

#### Avoid redundant processing and disk space

A single log message can be sent to different log files several times. For example, in the initial configuration file, we have the following definitions:

    destination cron { file("/var/log/cron.log"); };
    destination messages { file("/var/log/messages"); };
    filter f_cron { facility(cron); };
    filter f_messages { level(info..warn)
           and not facility(auth, authpriv, mail, news); };
    log { source(src); filter(f_cron); destination(cron); };
    log { source(src); filter(f_messages); destination(messages); };

The same message from the `cron` facility will end up in both the `cron.log` and `messages` files. To change this behavior we can use the `final` flag, ending up further processing with the message. Therefore, in this example, if we want messages from the `cron` facility not ending up in the messages file, we should change the cron's log sentence by:

     log { source(src); filter(f_cron); destination(cron); flags(final); };

another way is to exclude the `cron` facility from `f_messages` filter:

     filter f_messages { level(info..warn) and not facility(cron, auth, authpriv, mail, news); };

### PostgreSQL Destination

This section will use two roles: `syslog` and `logwriter`. `syslog` will be the administrator of the database `syslog` and `logwriter` will only be able to add records to the `logs` table.

No longer needed to create table for logs. syslog-ng will create automatically.

    psql -U postgres

    postgres=# CREATE ROLE syslog WITH LOGIN;
    postgres=# \password syslog    # Using the \password function is secure because
    postgres=# \password logwriter # the password is not saved in history.
    postgres=# CREATE DATABASE syslog OWNER syslog;
    postgres=# \q # You are done here for the moment

Edit `pg_hba.conf` to allow `syslog` and `logwriter` to establish a connection to PostgreSQL.

    /var/lib/postgresql/data/pg_hba.conf

    # TYPE  DATABASE    USER        CIDR-ADDRESS          METHOD

    host    syslog      logwriter   192.168.0.1/24        md5
    host    syslog      syslog      192.168.0.10/32       md5

Tell PostgreSQL to reload the configuration files:

    # systemctl reload postgresql

Edit `/etc/syslog-ng.conf` so that it knows where and how to write to PostgreSQL. syslog-ng will utilize the `logwriter` role.

    ...
    #
    # SQL logging support
    #

    destination d_pgsql {
      sql(type(pgsql)
      host("127.0.0.1") username("logwriter") password("password")
      database("syslog")
      table("logs_${HOST}_${R_YEAR}${R_MONTH}${R_DAY}") #or whatever you want, example ${HOST}" for hosts, ${LEVEL}" for levels.. etc
      columns("datetime timestamp with time zone", "host varchar(32)", "program varchar(16)", "pid varchar(16)", "message varchar(200)")
      values("$R_ISODATE", "$HOST", "$PROGRAM", "$PID", "$MSG")
      indexes("datetime", "host", "program", "pid", "message"));
    };

    log { source(src); destination(d_pgsql); };

Finally, restart syslog-ng.

    # systemctl restart syslog-ng

And check to see if things are being logged.

    psql -U logwriter -d syslog
    syslog=> SELECT * FROM <your table name> ORDER BY datetime DESC LIMIT 10;

### ISO 8601 タイムスタンプ

ビフォー:

    #logger These timestamps are not optimal.
    #tail -n 1 /var/log/messages.log
    Feb 18 14:25:01 hostname logger: These timestamps are not optimal.
    #

`ts_format(iso);` を `/etc/syslog-ng/syslog-ng.conf` の options セクションに追加。例:

    options {
      stats_freq (0);
      flush_lines (0);
      time_reopen (10);
      log_fifo_size (1000);
      long_hostnames(off);
      use_dns (no);
      use_fqdn (no);
      create_dirs (no);
      keep_hostname (yes);
      perm(0640);
      group("log");
      ts_format(iso);      #make ISO-8601 timestamps
    };

そして:

    # systemctl reload syslog-ng

アフター:

    #logger Now THAT is a timestamp!
    #tail -n 2 /var/log/messages.log
    Feb 18 14:25:01 hostname logger: These timestamps are not optimal.
    2010-02-18T20:23:58-05:00 electron logger: Now THAT is a timestamp!
    #

### RFC 3339 タイムスタンプ

上記と同じように編集。ただし `ts_format` には `iso` の代わりに `rfc3339` を使用。

### ログレベル

Log levels are defined separately for each logged facility in syslog-ng config. Available log levels are listed in /usr/include/sys/syslog.h :

    define LOG_EMERG       0       /* system is unusable */
    define LOG_ALERT       1       /* action must be taken immediately */
    define LOG_CRIT        2       /* critical conditions */
    define LOG_ERR         3       /* error conditions */
    define LOG_WARNING     4       /* warning conditions */
    define LOG_NOTICE      5       /* normal but significant condition */
    define LOG_INFO        6       /* informational */
    define LOG_DEBUG       7       /* debug-level messages */

### マクロと変数

Macros can be used in both templates, and in destination file names. Macros of syslog-ng OSE.

The following code will write the log lines to `/var/log/test.log` in the format of `macroname=value@`.

    template t_test { template("PROGRAM=$PROGRAM@PID=$PID@BSDTAG=$BSDTAG@TAG=$TAG@TAGS=$TAGS@FACILITY=$FACILITY@FACILITY_NUM=$FACILITY_NUM@LEVEL=$LEVEL@LEVEL_NUM=$LEVEL_NUM@PRI=$PRI@PRIORITY=$PRIORITY@FULLHOST=$FULLHOST@FULLHOST_FROM=$FULLHOST_FROM@HOST=$HOST@HOST_FROM=$HOST_FROM@LOGHOST=$LOGHOST@MSGHDR=$MSGHDR@MSGID=$MSGID@MSGONLY=$MSGONLY@MSG=$MSG@MESSAGE=$MESSAGE@SOURCE=$SOURCE@SOURCEIP=$SOURCEIP@SOURCE_IP=$SOURCE_IP@SEQNUM=$SEQNUM@UNIXTIME=$UNIXTIME@FULLDATE=$FULLDATE@ISODATE=$ISODATE@DATE=$DATE@STAMP=$STAMP@TZ=$TZ@TZOFFSET=$TZOFFSET@SEC=$SEC@MIN=$MIN@HOUR=$HOUR@HOUR12=$HOUR12@DAY=$DAY@WEEK=$WEEK@WEEK_DAY=$WEEK_DAY@WEEK_DAY_ABBREV=$WEEK_DAY_ABBREV@WEEK_DAY_NAME=$WEEK_DAY_NAME@MONTH=$MONTH@MONTH_ABBREV=$MONTH_ABBREV@MONTH_NAME=$MONTH_NAME@MONTH_WEEK=$MONTH_WEEK@YEAR=$YEAR@YEAR_DAY=$YEAR_DAY
    \n"); template_escape(no); };

    destination d_test { file("/var/log/test.log" template(t_test)); };

    log { source(s_local); destination(d_test); flags(final); };

You can create your own value list as below once syslog-ng is restarted with: `tail /var/log/test.log|tr "@" "\n"`

    PROGRAM=kernel
    PID=
    BSDTAG=4A
    TAG=04
    TAGS=.source.s_local
    FACILITY=kern
    FACILITY_NUM=0
    LEVEL=warning
    LEVEL_NUM=4
    PRI=4
    PRIORITY=warning
    FULLHOST=www.askapache.com
    FULLHOST_FROM=www.askapache.com
    HOST=www.askapache.com
    HOST_FROM=www.askapache.com
    LOGHOST=
    MSGHDR=kernel:
    MSGID=
    MSGONLY=Firewall: *INVALID* IN=eth0 OUT= MAC=00:00 SRC=x.x.x.x DST=198.101.159.98 LEN=40 TOS=0x00 PREC=0x00 TTL=113 ID=7730 DF PROTO=TCP SPT=52369 DPT=80 WINDOW=0 RES=0x00 ACK RST URGP=0
    MSG=Firewall: *INVALID* IN=eth0 OUT= MAC=00:00 SRC=x.x.x.x DST=198.101.159.98 LEN=40 TOS=0x00 PREC=0x00 TTL=113 ID=7730 DF PROTO=TCP SPT=52369 DPT=80 WINDOW=0 RES=0x00 ACK RST URGP=0
    MESSAGE=Firewall: *INVALID* IN=eth0 OUT= MAC=00:00 SRC=x.x.x.x DST=198.101.159.98 LEN=40 TOS=0x00 PREC=0x00 TTL=113 ID=7730 DF PROTO=TCP SPT=52369 DPT=80 WINDOW=0 RES=0x00 ACK RST URGP=0
    SOURCE=s_local
    SOURCEIP=127.0.0.1
    SOURCE_IP=
    UNIXTIME=1369742458
    FULLDATE=2013 May 28 08:00:58
    ISODATE=2013-05-28T08:00:58-04:00
    DATE=May 28 08:00:58
    STAMP=2013-05-28T08:00:58-04:00
    TZ=-04:00
    TZOFFSET=-04:00
    SEC=58
    MIN=00
    HOUR=08
    HOUR12=
    DAY=28
    WEEK=21
    WEEK_DAY=3
    WEEK_DAY_ABBREV=Tue
    WEEK_DAY_NAME=Tuesday
    MONTH=05
    MONTH_ABBREV=May
    MONTH_NAME=May
    MONTH_WEEK=4
    YEAR=2013
    YEAR_DAY=148

## 参照

- syslog-ng OSE Project Page
- Portal to syslog-ng Documentation
  - The syslog-ng 3.4 Administrator Guide
  - List of syslog-ng 3.4 Parameters
  - List of syslog-ng 3.4 Macros
- syslog-ng Project Page on Freshmeat
- Gentoo syslog-ng wiki
- Gentoo Security Handbook on Logging
- Syslog Logging with PostgreSQL HOWTO
- ISO_8601 Wikipedia page for ISO 8601
- RFC 3164 - The BSD syslog Protocol
- RFC 5424 - The Syslog Protocol
  - RFC 5425 - Transport Layer Security (TLS) Transport Mapping for Syslog
  - RFC 5426 - Transmission of Syslog Messages over UDP
  - RFC 5427 - Textual Conventions for Syslog Management
  - RFC 5428 - MIB for PacketCable and IPCablecom-Compliant Devices
- RFC 3339 - Date and Time on the Internet: Timestamps

Category:

- Daemons and system services (日本語)