3.4. Destinations and destination drivers

A destination is where a log message is sent if the filtering rules match. Similarly to sources, destinations consist of one or more drivers, each defining where and how messages are sent.

[Tip] Tip

If no drivers are defined for a destination, all messages sent to the destination are discarded. This is equivalent to omitting the destination from the log statement.

To define a destination, add a destination statement to the syslog-ng configuration file using the following syntax:

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

[Example] Example 3.16. A simple destination statement

The following destination statement sends messages to the TCP port 1999 of the 10.1.2.3 host.

destination d_demo_tcp { tcp("10.1.2.3" port(1999)); };

If name resolution is configured, the hostname of the target server can be used as well.

destination d_tcp { tcp("target_host" port(1999); localport(999)); };

The following table lists the destination drivers available in syslog-ng.

Name Description
file() Writes messages to the specified file.
logstore()* Writes messages to the specified binary logstore file. *Available only in syslog-ng Premium Edition.
fifo(), pipe() Writes messages to the specified named pipe.
program() Forks and launches the specified program, and sends messages to its standard input.
sql() Sends messages into an SQL database. In addition to the standard syslog-ng packages, the sql() destination requires database-specific packages to be installed. Refer to the section appropriate for your platform in Chapter 4, Installing syslog-ng.
syslog() Sends messages to the specified remote host using the IETF-syslog protocol. The IETF standard supports message transport using the UDP, TCP, and TLS networking protocols.
tcp() and tcp6() Sends messages to the specified TCP port of a remote host using the BSD-syslog protocol over IPv4 and IPv6, respectively.
udp() and udp6() Sends messages to the specified UDP port of a remote host using the BSD-syslog protocol over IPv4 and IPv6, respectively.
unix-dgram() Sends messages to the specified unix socket in SOCK_DGRAM style (BSD).
unix-stream() Sends messages to the specified unix socket in SOCK_STREAM style (Linux).
usertty() Sends messages to the terminal of the specified user, if the user is logged in.

Table 3.3. Destination drivers available in syslog-ng


For detailed list of driver parameters, see Section 8.2, “Destination drivers”.

3.4.1. Storing messages in plain-text files

The file driver is one of the most important destination drivers in syslog-ng. It allows to output messages to the specified text file, or to a set of files.

The destination filename may include macros which get expanded when the message is written, thus a simple file() driver may create several files. For more information on available macros see Section 8.5, “Macros”.

If the expanded filename refers to a directory which does not exist, it will be created depending on the create_dirs() setting (both global and a per destination option).

The file() has a single required parameter that specifies the filename that stores the log messages. For the list of available optional parameters, see Section 8.2.1, “file()”.

Declaration:
                file(filename options());
[Example] Example 3.17. Using the file() driver
destination d_file { file("/var/log/messages" ); };
[Example] Example 3.18. Using the file() driver with macros in the file name and a template for the message
destination d_file {
        file("/var/log/$YEAR.$MONTH.$DAY/messages"
             template("$HOUR:$MIN:$SEC $TZ $HOST [$LEVEL] $MSG $MSG\n")
             template_escape(no));
};
[Note] Note

When using the file() destination, update the configuration of your log rotation program to rotate these files. Otherwise, the log files can become very large.

[Warning] Warning

Since the state of each created file must be tracked by syslog-ng, it consumes some memory for each file. If no new messages are written to a file within 60 seconds (controlled by the time_reap() global option), it is closed, and its state is freed.

Exploiting this, a DoS attack can be mounted against the system. If the number of possible destination files and its needed memory is more than the amount available on the syslog-ng server.

The most suspicious macro is $PROGRAM, where the number of possible variations is rather high. Do not use the $PROGRAM macro in insecure environments.

3.4.2. Storing messages in encrypted files

The logstore() driver stores log messages in binary files that can be encrypted, compressed, checked for integrity, and timestamped by an external Timestamping Authority (TSA). Otherwise, it is very similar to the file() destination.

Logstore files consist of individual chunks, every chunk can be encrypted, compressed, and timestamped separately. Chunks contain log message data, chunk size defaults to 128k (about 1MB worth of compressed logs).

To display the contents of a logstore file, use the logcat command supplied with syslog-ng, e.g., logcat /var/log/messages.lgs. To display the contents of encrypted log files, specify the private key of the certificate used to encrypt the file, e.g., logcat -k private.key /var/log/messages.lgs. The contents of the file are sent to the standard output, so it is possible to use grep and other tools to find particular log messages, e.g., logcat /var/log/messages.lgs |grep 192.168.1.1.

Every record that is stored in the logstore has a unique record ID. The logcat application can quickly jump to a specified record using the -- seek option.

For files that are in use by syslog-ng, the last chunk that is open cannot be read. Chunks are closed when their size reaches the limit set in the chunk_size parameter, or when the time limit set in the chunk_time parameter expires and no new message arrives.

The syslog-ng PE application generates an SHA-1 hash for every chunk to verify the integrity of the chunk. The hashes of the chunks are chained together to prevent injecting chunks into the logstore file. The syslog-ng application can encrypt the logstore using the aes128 algorithm in CBC mode; the hashing (HMAC) algorithm is hmac-sha1. Currently it is not possible to use other algorithms.

[Warning] Warning

If the syslog-ng Premium Edition application or the computer crashes, an unclosed chunk remains at the end of the file. This chunk is marked as broken, its data stays there but is not shown by logcat.

The destination filename may include macros which get expanded when the message is written, thus a simple logstore() driver may create several files. For more information on available macros see Section 8.5, “Macros”.

If the expanded filename refers to a directory which does not exist, it will be created depending on the create_dirs() setting (both global and a per destination option).

The logstore() has a single required parameter that specifies the filename that stores the log messages. For the list of available optional parameters, see Section 8.2.2, “logstore()”.

Declaration:
                logstore(filename options());
[Example] Example 3.19. Using the logstore() driver

A simple example saving and compressing log messages.

destination d_logstore { file("/var/log/messages.lgs" compress(5) ); };

A more detailed example that encrypts messages, modifies the parameters for closing chunks, and sets file privileges.

destination d_logstore { logstore("/var/log/messages-logstore.lgs"
    encrypt_certificate("/opt/syslog-ng/etc/syslog-ng/keys/10-100-20-40/public-certificate-of-the-server.pem")			
    chunk_size(100) 
    chunk_time(5)
    owner("balabit")
    group("balabit")
    perm(0777)
); };
[Note] Note

When using the logstore() destination, update the configuration of your log rotation program to rotate these files. Otherwise, the log files can become very large.

[Warning] Warning

Since the state of each created file must be tracked by syslog-ng, it consumes some memory for each file. If no new messages are written to a file within 60 seconds (controlled by the time_reap() global option), it is closed, and its state is freed.

Exploiting this, a DoS attack can be mounted against the system. If the number of possible destination files and its needed memory is more than the amount available on the syslog-ng server.

The most suspicious macro is $PROGRAM, where the number of possible variations is rather high. Do not use the $PROGRAM macro in insecure environments.

3.4.3. Sending messages to named pipes

The pipe() driver sends messages to a named pipe like /dev/xconsole.

The pipe driver has a single required parameter, specifying the filename of the pipe to open. The filename can include macros. For the list of available optional parameters, see Section 8.2.3, “pipe()”.

Declaration:
                pipe(filename);
[Warning] Warning

As of syslog-ng Open Source Edition 3.0.2, pipes are created automatically. In earlier versions, you had to create the pipe using the mkfifo(1) command.

[Example] Example 3.20. Using the pipe() driver
destination d_pipe { pipe("/dev/xconsole"); };

3.4.4. Sending messages to external applications

The program() driver starts an external application or script and sends the log messages to its standard input (stdin).

The program() driver has a single required parameter, specifying a program name to start. The program is executed with the help of the current shell, so the command may include both file patterns and I/O redirections. For the list of available optional parameters, see Section 8.2.4, “program()”.

Declaration: 
                program(command_to_run);
[Note] Note

The syslog-ng application automatically restarts the external program if it exits for reliability reasons. However it is not recommended to launch programs for single messages, because if the message rate is high, launching several instances of an application might overload the system, resulting in Denial of Service.

Note that the message format does not include the priority and facility values by default. To add these values, specify a template for the program destination, as shown in the following example.

[Example] Example 3.21. Using the program() destination driver
destination d_prog { program("/bin/script" template("<$PRI>$DATE $HOST $MSG\n"); };

3.4.5. Storing messages in an SQL database

The sql() driver sends messages into an SQL database. Currently the Microsoft SQL (MSSQL), MySQL, Oracle, PostgreSQL, and SQLite databases are supported.

[Note] Note

In order to use the sql() destination, syslog-ng Premium Edition must run in server mode. Typically, only the central syslog-ng Premium Edition server uses the sql() destination.

The sql() driver has the following required parameters:

Name Type Default Description
type mssql, mysql, oracle, pgsql, or sqlite3 n/a Specifies the type of the database, i.e., the DBI database driver to use. Use the mssql option to send logs to an MSSQL database. See the examples of the databases on the following sections for details.
database string n/a Name of the database that stores the logs.
table string n/a Name of the database table to use (can include macros). When using macros, note that some databases limit the length of table names.
columns string list "date", "facility", "level", "host", "program", "pid", "message" Name of the columns storing the data in fieldname [dbtype] format. The [dbtype] parameter is optional, and specifies the type of the field. By default, syslog-ng creates text columns. Note that not every database engine can index text fields.
values string list "${R_YEAR}-${R_MONTH}-${R_DAY} ${R_HOUR}:${R_MIN}:${R_SEC}", "$FACILITY", "$LEVEL", "$HOST", "$PROGRAM", "$PID", "$MSGONLY" The parts of the message to store in the fields specified in the columns parameter.

Table 3.4. Required parameters of the sql() driver


For the list of available optional parameters, see Section 8.2.5, “sql()”.

Declaration: 
    sql(database_type host_parameters database_parameters [options]);
[Warning] Warning

The syslog-ng application requires read and write access to the SQL table, otherwise it cannot verify that the destination table exists.

Currently the syslog-ng application has default schemas for the different databases and uses these defaults if the database schema (e.g., columns and column types) is not defined in the configuration file. However, these schemas will be deprecated and specifying the exact database schema will be required in later versions of syslog-ng.

[Note] Note

In addition to the standard syslog-ng packages, the sql() destination requires database-specific packages to be installed. These packages are automatically installed by the binary syslog-ng installer.

The sql() driver is currently not available for every platform that is supported by syslog-ng. For a list of platforms that support the sql() driver, visit http://www.balabit.com/network-security/syslog-ng/central-syslog-server/.

The table and value parameters can include macros to create tables and columns dynamically (see Section 8.5, “Macros” for details).

[Warning] Warning

When using macros in table names, note that some databases limit the maximum allowed length of table names. Consult the documentation of the database for details.

Inserting the records into the database is performed by a separate thread. The syslog-ng application automatically performs the escaping required to insert the messages into the database.

[Example] Example 3.22. Using the sql() driver

The following example sends the log messages into a PostgreSQL database running on the logserver host. The messages are inserted into the logs database, the name of the table includes the exact date and the name of the host sending the messages. The syslog-ng application automatically creates the required tables and columns, if the user account used to connect to the database has the required privileges.

destination d_sql { 
  sql(type(pgsql)
  host("logserver") username("syslog-ng") password("password")
  database("logs")
  table("messages_${HOST}_${R_YEAR}${R_MONTH}${R_DAY}")
  columns("datetime", "host", "program", "pid", "message")
  values("$R_DATE", "$HOST", "$PROGRAM", "$PID", "$MSGONLY")
  indexes("datetime", "host", "program", "pid", "message"));
  };

The following example specifies the type of the database columns as well:

destination d_sql { 
  sql(type(pgsql)
  host("logserver") username("syslog-ng") password("password")
  database("logs")
  table("messages_${HOST}_${R_YEAR}${R_MONTH}${R_DAY}")
  columns("datetime varchar(16)", "host varchar(32)", "program  varchar(20)", "pid varchar(8)", "message  varchar(200)")
  values("$R_DATE", "$HOST", "$PROGRAM", "$PID", "$MSGONLY")
  indexes("datetime", "host", "program", "pid", "message"));
};

3.4.5.1. Using the sql() driver with an Oracle database

The Oracle sql destination has some special aspects that are important to note.

  • The hostname of the database server is set in the tnsnames.ora file, not in the host parameter of the sql() destination.

    Make sure to set the Oracle-related environment variables properly, so syslog-ng and the Oracle client will find the file. The following variables must be set: ORACLE_BASE, ORACLE_HOME, and ORACLE_SID. See the documentation of the Oracle Instant Client for details.

  • As certain database versions limit the maximum length of table names, macros in the table names should be used with care.

  • In the current version of syslog-ng PE, the types of database columns must be explicitly set for the Oracle destination. The column used to store the text part of the syslog messages should be able to store messages as long as the longest message permitted by syslog-ng, therefore it is usually recommended to use the varchar2 or clob column type. (The maximum length of the messages can be set using the log_msg_size() option.) See the following example for details.

[Example] Example 3.23. Using the sql() driver with an Oracle database

The following example sends the log messages into an Oracle database running on the logserver host, which must be set in the /etc/tnsnames.ora file. The messages are inserted into the LOGS database, the name of the table includes the exact date when the messages were sent. The syslog-ng application automatically creates the required tables and columns, if the user account used to connect to the database has the required privileges.

destination d_sql { 
  sql(type(oracle)
  username("syslog-ng") password("password")
  database("LOGS")
  table("msgs_${R_YEAR}${R_MONTH}${R_DAY}")
  columns("datetime varchar(16)", "host varchar(32)", "program varchar(32)", "pid varchar(8)", "message varchar2")                        
  values("$R_DATE", "$HOST", "$PROGRAM", "$PID", "$MSGONLY")
  indexes("datetime", "host", "program", "pid", "message"));
  };

The Oracle Instant Client retrieves the address of the database server from the /etc/tnsnames.ora file. Edit or create this file as needed for your configuration. A sample is provided below.

LOGS =
(DESCRIPTION =
(ADDRESS_LIST =
(ADDRESS = (PROTOCOL = TCP)
(HOST = logserver)
(PORT = 1521))
)
(CONNECT_DATA =
(SERVICE_NAME = EXAMPLE.SERVICE)
)
)

3.4.5.2. Using the sql() driver with a Microsoft SQL database

The mssql database driver can access Microsoft SQL (MSSQL) destinations. This driver has some special aspects that are important to note.

  • The date format used by the MSSQL database must be explicitly set in the /etc/locales.conf file of the syslog-ng server. See the following example for details.

  • As certain database versions limit the maximum length of table names, macros in the table names should be used with care.

  • In the current version of syslog-ng PE, the types of database columns must be explicitly set for the MSSQL destination. The column used to store the text part of the syslog messages should be able to store messages as long as the longest message permitted by syslog-ng. The varchar column type can store maximum 4096 bytes-long messages. The maximum length of the messages can be set using the log_msg_size() option. See the following example for details.

  • Remote access for SQL users must be explicitly enabled on the Microsoft Windows host running the Microsoft SQL Server. See Section 4.6, “Configuring Microsoft SQL Server to accept logs from syslog-ng” for details.

[Example] Example 3.24. Using the sql() driver with an MSSQL database

The following example sends the log messages into an MSSQL database running on the logserver host. The messages are inserted into the syslogng database, the name of the table includes the exact date when the messages were sent. The syslog-ng application automatically creates the required tables and columns, if the user account used to connect to the database has the required privileges.

destination d_mssql { 
sql(type(mssql) host("logserver") port("1433") 
  username("syslogng") password("syslogng") database("syslogng") 
  table("msgs_${R_YEAR}${R_MONTH}${R_DAY}")columns("datetime varchar(16)", "host varchar(32)",
  "program varchar(32)", "pid varchar(8)", "message varchar(4096)")
  values("$R_DATE", "$HOST", "$PROGRAM", "$PID", "$MSGONLY")
  indexes("datetime", "host", "program", "pid", "message"));
  };

The date format used by the MSSQL database must be explicitly set in the /etc/locales.conf file of the syslog-ng server. Edit or create this file as needed for your configuration. A sample is provided below.

[default]
date = "%Y-%m-%d %H:%M:%S"

3.4.6. Sending messages to a remote logserver using the IETF-syslog protocol

The syslog() driver sends messages to a remote host (e.g., a syslog-ng server or relay) on the local intranet or internet using the new standard syslog protocol developed by IETF (see Section 2.18.2, “IETF-syslog messages” for details about the new protocol). The protocol supports sending messages using the UDP, TCP, or the encrypted TLS networking protocols.

The required arguments of the driver are the address of the destination host (where messages should be sent). The transport method (networking protocol) is optional, syslog-ng uses the TCP protocol by default. For the list of available optional parameters, see Section 8.2.6, “syslog()”.

Declaration:
                syslog(host transport [options]);
[Note] Note

Note that the syslog destination driver has required parameters, while the source driver defaults to the local bind address, and every parameter is optional.

The udp transport method automatically sends multicast packets if a multicast destination address is specified. The tcp and tls methods do not support multicasting.

[Note] Note

The default ports for the different transport protocols are as follows: UDP — 514; TLS — 6514.

[Example] Example 3.25. Using the syslog() driver
destination d_tcp { syslog(ip"10.1.2.3" transport("tcp") port(1999); localport(999)); };

If name resolution is configured, the hostname of the target server can be used as well.

destination d_tcp { syslog(ip"target_host" transport("tcp") port(1999); localport(999)); };

Send the log messages using TLS encryption and use mutual authentication. See Section 8.10, “TLS options” for details on the encryption and authentication options.

destination d_syslog_tls{ 
                syslog("10.100.20.40"
                transport("tls")
                port(6514)
                tls(peer-verify(required-trusted)
                ca_dir('/opt/syslog-ng/etc/syslog-ng/keys/ca.d/')
                key_file('/opt/syslog-ng/etc/syslog-ng/keys/client_key.pem')
                cert_file('/opt/syslog-ng/etc/syslog-ng/keys/client_certificate.pem'))
                );};

3.4.7. Sending messages to a remote logserver using the legacy BSD-syslog protocol

The tcp(), tcp6(), udp(), and udp6() drivers send messages to another host (e.g., a syslog-ng server or relay) on the local intranet or internet using the UDP or TCP protocol. The tcp6() and udp6() drivers use the IPv6 network protocol.

All four drivers have a single required parameter specifying the destination host address, where messages should be sent. For the list of available optional parameters, see Section 8.2.7, “tcp(), tcp6(), udp(), and udp6(),”.

The udp() and udp6() drivers automatically send multicast packets if a multicast destination address is specified. The tcp() and tcp6() drivers do not support multicasting.

Declaration:
                tcp(host [options]);
                udp(host [options]);
                tcp6(host [options]);
                udp6(host [options]);
[Example] Example 3.26. Using the tcp() driver
destination d_tcp { tcp("10.1.2.3" port(1999); localport(999)); };

If name resolution is configured, the hostname of the target server can be used as well.

destination d_tcp { tcp("target_host" port(1999); localport(999)); };

To send messages using the IETF-syslog message format, enable the syslog-protocol flag:

destination d_tcp { tcp("10.1.2.3" port(1999); flags(syslog-protocol) };

3.4.8. Sending messages to UNIX domain sockets

The unix-stream() and unix-dgram() drivers send messages to a UNIX domain socket in either SOCK_STREAM or SOCK_DGRAM mode.

Both drivers have a single required argument specifying the name of the socket to connect to. For the list of available optional parameters, see Section 8.2.8, “unix-stream() & unix-dgram()”.

Declaration: 
                unix-stream(filename [options]);
                unix-dgram(filename [options]);
[Example] Example 3.27. Using the unix-stream() driver
destination d_unix_stream { unix-stream("/var/run/logs"); };

3.4.9. usertty()

This driver writes messages to the terminal of a logged-in user.

The usertty() driver has a single required argument, specifying a username who should receive a copy of matching messages.

Declaration: 
    usertty(username);

The usertty() does not have any further options nor does it support templates.

[Example] Example 3.28. Using the usertty() driver
destination d_usertty { usertty("root"); };

© 2007-2008 BalaBit IT Security
Please send your comments or documentation bugs to: documentation@balabit.com