summaryrefslogtreecommitdiffstats
path: root/source/tutorials
diff options
context:
space:
mode:
Diffstat (limited to 'source/tutorials')
-rw-r--r--source/tutorials/cert-script.tar.gzbin0 -> 3967 bytes
-rw-r--r--source/tutorials/database.rst280
-rw-r--r--source/tutorials/failover_syslog_server.rst72
-rw-r--r--source/tutorials/gelf_forwarding.rst70
-rw-r--r--source/tutorials/hash_sampling.rst82
-rw-r--r--source/tutorials/high_database_rate.rst161
-rw-r--r--source/tutorials/index.rst18
-rw-r--r--source/tutorials/log_rotation_fix_size.rst60
-rw-r--r--source/tutorials/log_sampling.rst13
-rw-r--r--source/tutorials/random_sampling.rst16
-rw-r--r--source/tutorials/recording_pri.rst141
-rw-r--r--source/tutorials/reliable_forwarding.rst171
-rw-r--r--source/tutorials/tls.rst335
-rw-r--r--source/tutorials/tls_cert.jpgbin0 -> 68335 bytes
-rw-r--r--source/tutorials/tls_cert_100.jpgbin0 -> 16607 bytes
-rw-r--r--source/tutorials/tls_cert_ca.jpgbin0 -> 9635 bytes
-rw-r--r--source/tutorials/tls_cert_ca.rst147
-rw-r--r--source/tutorials/tls_cert_client.rst74
-rw-r--r--source/tutorials/tls_cert_errmsgs.rst111
-rw-r--r--source/tutorials/tls_cert_machine.rst164
-rw-r--r--source/tutorials/tls_cert_scenario.rst26
-rw-r--r--source/tutorials/tls_cert_script.rst159
-rw-r--r--source/tutorials/tls_cert_server.rst115
-rw-r--r--source/tutorials/tls_cert_summary.rst143
-rw-r--r--source/tutorials/tls_cert_udp_relay.rst89
25 files changed, 2447 insertions, 0 deletions
diff --git a/source/tutorials/cert-script.tar.gz b/source/tutorials/cert-script.tar.gz
new file mode 100644
index 0000000..8600b5d
--- /dev/null
+++ b/source/tutorials/cert-script.tar.gz
Binary files differ
diff --git a/source/tutorials/database.rst b/source/tutorials/database.rst
new file mode 100644
index 0000000..7cc6f3c
--- /dev/null
+++ b/source/tutorials/database.rst
@@ -0,0 +1,280 @@
+Writing syslog messages to MySQL, PostgreSQL or any other supported Database
+============================================================================
+
+*Written by* \ `Rainer Gerhards <https://rainer.gerhards.net>`_\ *with
+some additions by Marc Schiffbauer (2008-02-28)*
+
+Abstract
+--------
+
+***In this paper, I describe how to
+write***\ `syslog <http://www.monitorware.com/en/topics/syslog/>`_\ ***messages
+to
+a***\ `MySQL <http://www.mysql.com/>`_\ ***or***\ `PostgreSQL <http://www.postgresql.org/>`_\ ***database.***\ *Having
+syslog messages in a database is often handy, especially when you intend
+to set up a front-end for viewing them. This paper describes an approach
+with*\ `rsyslogd <http://www.rsyslog.com/>`_\ *, an alternative enhanced
+syslog daemon natively supporting MySQL and PostgreSQL. I describe the
+components needed to be installed and how to configure them. Please note
+that as of this writing, rsyslog supports a variety of databases. While
+this guide is still MySQL- and PostgreSQL-focused, you can probably use
+it together with other ones too. You just need to modify a few
+settings.*
+
+Background
+----------
+
+In many cases, syslog data is simply written to text files. This
+approach has some advantages, most notably it is very fast and
+efficient. However, data stored in text files is not readily accessible
+for real-time viewing and analysis. To do that, the messages need to be
+in a database. There are various ways to store syslog messages in a
+database. For example, some have the syslogd write text files which are
+later feed via a separate script into the database. Others have written
+scripts taking the data (via a pipe) from a non-database-aware syslogd
+and store them as they appear. Some others use database-aware syslogds
+and make them write the data directly to the database. In this paper, I
+use that "direct write" approach. I think it is superior, because the
+syslogd itself knows the status of the database connection and thus can
+handle it intelligently (well ... hopefully ;)). I use rsyslogd to
+accomplish this, simply because I have initiated the rsyslog project with
+database-awareness as one goal.
+
+**One word of caution:** while message storage in the database provides
+an excellent foundation for interactive analysis, it comes at a cost.
+Database i/o is considerably slower than text file i/o. As such,
+directly writing to the database makes sense only if your message volume
+is low enough to allow a) the syslogd, b) the network, and c) the
+database server to catch up with it. Some time ago, I have written a
+paper on `optimizing syslog server
+performance <http://www.monitorware.com/Common/en/Articles/performance-optimizing-syslog-server.php>`_.
+While this paper talks about Window-based solutions, the ideas in it are
+generic enough to apply here, too. So it might be worth reading if you
+anticipate medium high to high traffic. If you anticipate really high
+traffic (or very large traffic spikes), you should seriously consider
+forgetting about direct database writes - in my opinion, such a
+situation needs either a very specialized system or a different approach
+(the text-file-to-database approach might work better for you in this
+case).
+
+Overall System Setup
+--------------------
+
+In this paper, I concentrate on the server side. If you are thinking
+about interactive syslog message review, you probably want to centralize
+syslog. In such a scenario, you have multiple machines (the so-called
+clients) send their data to a central machine (called server in this
+context). While I expect such a setup to be typical when you are
+interested in storing messages in the database, I do not describe how to
+set it up. This is beyond the scope of this paper. If you search a
+little, you will probably find many good descriptions on how to
+centralize syslog. If you do that, it might be a good idea to do it
+securely, so you might also be interested in my paper on `ssl-encrypting
+syslog message
+transfer <http://www.rsyslog.com/doc-rsyslog_stunnel.html>`_.
+
+No matter how the messages arrive at the server, their processing is
+always the same. So you can use this paper in combination with any
+description for centralized syslog reporting.
+
+As I already said, I use rsyslogd on the server. It has intrinsic
+support for talking to the supported databases. For obvious reasons, we
+also need an instance of MySQL or PostgreSQL running. To keep us
+focused, the setup of the database itself is also beyond the scope of
+this paper. I assume that you have successfully installed the database
+and also have a front-end at hand to work with it (for example,
+`phpMyAdmin <http://www.phpmyadmin.net/>`_ or
+`phpPgAdmin <http://phppgadmin.sourceforge.net/>`_. Please make sure
+that this is installed, actually working and you have a basic
+understanding of how to handle it.
+
+Setting up the system
+---------------------
+
+You need to download and install rsyslogd first. Obtain it from the
+`rsyslog site <http://www.rsyslog.com/>`_. Make sure that you disable
+stock syslogd, otherwise you will experience some difficulties. On some
+distributions  (Fedora 8 and above, for example), rsyslog may already by
+the default syslogd, in which case you obviously do not need to do
+anything specific. For many others, there are prebuild packages
+available. If you use either, please make sure that you have the
+required database plugins for your database available. It usually is a
+separate package and typically **not** installed by default.
+
+It is important to understand how rsyslogd talks to the database. In
+rsyslogd, there is the concept of "templates". Basically, a template is
+a string that includes some replacement characters, which are called
+"properties" in rsyslog. Properties are accessed via the "`Property
+Replacer <http://www.rsyslog.com/doc-property_replacer.html>`_\ ".
+Simply said, you access properties by including their name between
+percent signs inside the template. For example, if the syslog message is
+"Test", the template "%msg%" would be expanded to "Test". Rsyslogd
+supports sending template text as a SQL statement to the database. As
+such, the template must be a valid SQL statement. There is no limit in
+what the statement might be, but there are some obvious and not so
+obvious choices. For example, a template "drop table xxx" is possible,
+but does not make an awful lot of sense. In practice, you will always
+use an "insert" statement inside the template.
+
+An example: if you would just like to store the msg part of the full
+syslog message, you have probably created a table "syslog" with a single
+column "message". In such a case, a good template would be "insert into
+syslog(message) values ('%msg%')". With the example above, that would be
+expanded to "insert into syslog(message) values('Test')". This expanded
+string is then sent to the database. It's that easy, no special magic.
+The only thing you must ensure is that your template expands to a proper
+SQL statement and that this statement matches your database design.
+
+Does that mean you need to create database schema yourself and also must
+fully understand rsyslogd's properties? No, that's not needed. Because
+we anticipated that folks are probably more interested in getting things
+going instead of designing them from scratch. So we have provided a
+default schema as well as build-in support for it. This schema also
+offers an additional benefit: rsyslog is part of
+`Adiscon <http://www.adiscon.com/en/>`_'s `MonitorWare product
+line <http://www.monitorware.com/en/>`_ (which includes open source and
+closed source members). All of these tools share the same default schema
+and know how to operate on it. For this reason, the default schema is
+also called the "MonitorWare Schema". If you use it, you can simply add
+`phpLogCon, a GPLed syslog web interface <http://www.phplogcon.org/>`_,
+to your system and have instant interactive access to your database. So
+there are some benefits in using the provided schema.
+
+The schema definition is contained in the file "createDB.sql". It comes
+with the rsyslog package and one can be found for each supported
+database type (in the plugins directory). Review it to check that the
+database name is acceptable for you. Be sure to leave the table and
+field names unmodified, because otherwise you need to customize
+rsyslogd's default sql template, which we do not do in this paper. Then,
+run the script with your favorite SQL client. Double-check that the
+table was successfully created.
+
+It is important to note that the correct database encoding must be used
+so that the database will accept strings independent of the string
+encoding. This is an important part because it can not be guarantied
+that all syslog messages will have a defined character encoding. This is
+especially true if the rsyslog-Server will collect messages from
+different clients and different products.
+
+For example PostgreSQL may refuse to accept messages if you would set
+the database encoding to “UTF8” while a client is sending invalid byte
+sequences for that encoding.
+
+Database support in rsyslog is integrated via loadable plugin modules.
+To use the database functionality, the database plugin must be enabled
+in the config file BEFORE the first database table action is used. This
+is done by placing the
+
+ ``$ModLoad ommysql``
+
+directive at the beginning of /etc/rsyslog.conf for MySQL and
+
+ ``$ModLoad ompgsql``
+
+for PostgreSQL.
+
+For other databases, use their plugin name (e.g. omoracle).
+
+Next, we need to tell rsyslogd to write data to the database. As we use
+the default schema, we do NOT need to define a template for this. We can
+use the hardcoded one (rsyslogd handles the proper template linking). So
+all we need to do e.g. for MySQL is add a simple selector line to
+/etc/rsyslog.conf:
+
+ ``*.*       :ommysql:database-server,database-name,database-userid,database-password``
+
+Again, other databases have other selector names, e.g. ":ompgsql:"
+instead of ":ommysql:". See the output plugin's documentation for
+details.
+
+In many cases, the database will run on the local machine. In this case,
+you can simply use "127.0.0.1" for *database-server*. This can be
+especially advisable, if you do not need to expose the database to any
+process outside of the local machine. In this case, you can simply bind
+it to 127.0.0.1, which provides a quite secure setup. Of course, rsyslog
+also supports remote database instances. In that case, use the remote
+server name (e.g. mydb.example.com) or IP-address. The *database-name*
+by default is "Syslog". If you have modified the default, use your name
+here. *Database-userid* and *-password* are the credentials used to
+connect to the database. As they are stored in clear text in
+rsyslog.conf, that user should have only the least possible privileges.
+It is sufficient to grant it INSERT privileges to the systemevents
+table, only. As a side note, it is strongly advisable to make the
+rsyslog.conf file readable by root only - if you make it world-readable,
+everybody could obtain the password (and eventually other vital
+information from it). In our example, let's assume you have created a
+database user named "syslogwriter" with a password of "topsecret" (just
+to say it bluntly: such a password is NOT a good idea...). If your
+database is on the local machine, your rsyslog.conf line might look like
+in this sample:
+
+ ``*.*       :ommysql:127.0.0.1,Syslog,syslogwriter,topsecret``
+
+Save rsyslog.conf, restart rsyslogd - and you should see syslog messages
+being stored in the "systemevents" table!
+
+The example line stores every message to the database. Especially if you
+have a high traffic volume, you will probably limit the amount of
+messages being logged. This is easy to accomplish: the "write database"
+action is just a regular selector line. As such, you can apply normal
+selector-line filtering. If, for example, you are only interested in
+messages from the mail subsystem, you can use the following selector
+line:
+
+ ``mail.*       :ommysql:127.0.0.1,syslog,syslogwriter,topsecret``
+
+Review the
+`rsyslog.conf <http://www.rsyslog.com/doc-rsyslog_conf.html>`_
+documentation for details on selector lines and their filtering.
+
+**You have now completed everything necessary to store syslog messages
+to the a database.** If you would like to try out a front-end, you might
+want to look at `phpLogCon <http://www.phplogcon.org/>`_, which displays
+syslog data in a browser. As of this writing, phpLogCon is not yet a
+powerful tool, but it's open source, so it might be a starting point for
+your own solution.
+
+On Reliability...
+-----------------
+
+Rsyslogd writes syslog messages directly to the database. This implies
+that the database must be available at the time of message arrival. If
+the database is offline, no space is left or something else goes wrong -
+rsyslogd can not write the database record. If rsyslogd is unable to
+store a message, it performs one retry. This is helpful if the database
+server was restarted. In this case, the previous connection was broken
+but a reconnect immediately succeeds. However, if the database is down
+for an extended period of time, an immediate retry does not help.
+
+Message loss in this scenario can easily be prevented with rsyslog. All
+you need to do is run the database writer in queued mode. This is now
+described in a generic way and I do not intend to duplicate it here. So
+please be sure to read "`Handling a massive syslog database insert rate
+with
+Rsyslog <http://www.rsyslog.com/doc-rsyslog_high_database_rate.html>`_\ ",
+which describes the scenario and also includes configuration examples.
+
+Conclusion
+----------
+
+With minimal effort, you can use rsyslogd to write syslog messages to a
+database. You can even make it absolutely fail-safe and protect it
+against database server downtime. Once the messages are arrived there,
+you can interactively review and analyze them. In practice, the messages
+are also stored in text files for longer-term archival and the databases
+are cleared out after some time (to avoid becoming too slow). If you
+expect an extremely high syslog message volume, storing it in real-time
+to the database may outperform your database server. In such cases,
+either filter out some messages or used queued mode (which in general is
+recommended with databases).
+
+The method outlined in this paper provides an easy to setup and maintain
+solution for most use cases.
+
+References and Additional Material
+----------------------------------
+
+- `www.rsyslog.com <http://www.rsyslog.com/>`_ - the rsyslog site
+
+- `Paper on Syslog Server
+ Optimization <http://www.monitorware.com/Common/en/Articles/performance-optimizing-syslog-server.php>`_
diff --git a/source/tutorials/failover_syslog_server.rst b/source/tutorials/failover_syslog_server.rst
new file mode 100644
index 0000000..32fc66c
--- /dev/null
+++ b/source/tutorials/failover_syslog_server.rst
@@ -0,0 +1,72 @@
+**********************
+Failover Syslog Server
+**********************
+
+
+There are often situations where syslog data from the local system should be
+sent to a central syslogd (for consolidation, archival and whatever other
+reasons). A common problem is that messages are lost when the central syslogd
+goes down.
+Rsyslog has the capability to work with failover servers to prevent message
+loss. A prerequisite is that TCP based syslog or RELP forwarding is used to send
+to the central server. The reason is that with UDP there is no reliable way to
+detect the remote system has gone away.
+Let's assume you have a primary and two secondary central servers. Then, you
+can use the following config file excerpt to send data to them:
+
+.. code-block:: none
+
+ if($msg contains "error") then {
+ action(type="omfwd" target="primary-syslog.example.com" port="10514"
+ protocol="tcp")
+ action(type="omfwd" target="secondary-1-syslog.example.com" port="10514"
+ action.execOnlyWhenPreviousIsSuspended="on")
+ action(type="omfwd" target="secondary-2-syslog.example.com" port="10514"
+ action.execOnlyWhenPreviousIsSuspended="on")
+ action(type="omfile" tag="failover" file="/var/log/localbuffer"
+ action.execOnlyWhenPreviousIsSuspended="on")
+ }
+
+
+The action processes all messages that contain "error". It tries to forward
+every message to primary-syslog.example.com (via tcp). If it can not reach that
+server, it tries secondary-1-syslog.example.com, if that fails too, it tries
+secondary-2-syslog.example.com. If neither of these servers can be connected,
+the data is stored in /var/log/localbuffer. Please note that the secondaries
+and the local log buffer are only used if the one before them does not work.
+So ideally, /var/log/localbuffer will never receive a message. If one of the
+servers resumes operation, it automatically takes over processing again.
+
+**Important:** Failover will **not** work when you define queues on the actions.
+This is because a queue explicitely tells rsyslog that the action shall be
+processed asynchronously. With asynchronous processing you do not have any
+feedback capability. As such, the action will never fail.
+
+**If you would like to use a queue on the forwarding process as whole, the solution
+is** to put all actions into a ruleset and assign a queue to the ruleset. In
+that configuration, the ruleset is process asynchronously, but inside the
+rule set each action is processed synchronously and can provide feedback,
+which permits to detect failed actions.
+
+To do so, the above example can be rewritten as follows:
+
+.. code-block:: none
+
+ ruleset(name="forwarding" queue.type="linkedList" queue.filename="fwdq") {
+ action(type="omfwd" target="primary-syslog.example.com" port="10514"
+ protocol="tcp")
+ action(type="omfwd" target="secondary-1-syslog.example.com" port="10514"
+ action.execOnlyWhenPreviousIsSuspended="on")
+ action(type="omfwd" target="secondary-2-syslog.example.com" port="10514"
+ action.execOnlyWhenPreviousIsSuspended="on")
+ action(type="omfile" tag="failover" file="/var/log/localbuffer"
+ action.execOnlyWhenPreviousIsSuspended="on")
+ }
+
+ if($msg contains "error") then {
+ call forwarding
+ }
+
+
+Please note that the example could also be rewritten in several other ways. To
+keep things simple, we just provide one of those.
diff --git a/source/tutorials/gelf_forwarding.rst b/source/tutorials/gelf_forwarding.rst
new file mode 100644
index 0000000..21d9a0d
--- /dev/null
+++ b/source/tutorials/gelf_forwarding.rst
@@ -0,0 +1,70 @@
+GELF forwarding in rsyslog
+==========================
+
+*Written by Florian Riedl*
+
+Situation
+---------
+
+The current setup has a system with rsyslog as the central syslog server
+and a system with Graylog for storage and analyzing the log messages.
+Graylog expects the log messages to arrive in GELF (Graylog Extended Log
+Format).
+
+Changing the default log format to GELF
+---------------------------------------
+
+To make rsyslog send GELF we basically need to create a custom template.
+This template will define the format in which the log messages will get
+sent to Graylog.
+
+::
+
+ template(name="gelf" type="list") {
+ constant(value="{\"version\":\"1.1\",")
+ constant(value="\"host\":\"")
+ property(name="hostname")
+ constant(value="\",\"short_message\":\"")
+ property(name="msg" format="json")
+ constant(value="\",\"timestamp\":")
+ property(name="timegenerated" dateformat="unixtimestamp")
+ constant(value=",\"level\":\"")
+ property(name="syslogseverity")
+ constant(value="\"}")
+ }
+
+This is a typical representation in the list format with all the necessary
+fields and format definitions that Graylog expects.
+
+Applying the template to a syslog action
+----------------------------------------
+
+The next step is applying the template to our output action. Since we
+are forwarding log messages to Graylog, this is usually a syslog sending
+action.
+
+::
+
+ # syslog forwarder via UDP
+ action(type="omfwd" target="graylogserver" port="12201" protocol="udp" template="gelf")
+
+We now have a syslog forwarding action. This uses the omfwd module. Please
+note that the case above only works for UDP transport. When using TCP,
+Graylog expects a Nullbyte as message delimiter. So, to use TCP, you need to change delimiter via `TCP_FrameDelimiter <../configuration/modules/omfwd.html#tcp-framedelimiter>`_ option.
+
+::
+
+ # syslog forwarder via TCP
+ action(type="omfwd" target="graylogserver" port="12201" protocol="tcp" template="gelf" TCP_FrameDelimiter="0" KeepAlive="on")
+
+Conclusion
+----------
+
+With this quick and easy setup you can feed Graylog with the correct
+log message format so it can do its work. This case can be applied to
+a lot of different scenarios as well, but with different templates.
+
+This documentation is part of the `rsyslog <http://www.rsyslog.com/>`_
+project.
+
+
diff --git a/source/tutorials/hash_sampling.rst b/source/tutorials/hash_sampling.rst
new file mode 100644
index 0000000..4fe6ecf
--- /dev/null
+++ b/source/tutorials/hash_sampling.rst
@@ -0,0 +1,82 @@
+Hash-based Sampling
+===================
+
+
+Rsyslog supports various sampling mechanisms. These can be used on client systems to save servers from getting overwhelmed. Here we introduce a new sampling mechanism "Hash-based sampling".
+
+Let's consider the following setup of systems running services and generating logs.
+There are three services A, B and C.
+These services work together to create a request processing pipeline.
+User request lands up at system A, which processes the request, generates logs and forwards it to service B.
+B processes the request it received from A, generates logs and forwards it to C and so on and so forth.
+
+::
+
+ +-+-+-+-+-+-+ +-+ +-+ +-+ +-+-++-+-+
+ |UserRequest| -> |A| -> |B| -> |C| -> | Database |
+ +-+-+-+-+-+-+ +-+ +-+ +-+ +-+-++-+-+
+
+
+Consider three sample user requests
+ ::
+
+ {"request_id": "reqid1", "data": "payload_1_original"}
+ {"request_id": "reqid2", "data": "payload_2_original"}
+ {"request_id": "reqid3", "data": "payload_3_original"}
+
+Service A generated logs
+ ::
+
+ {"request_id": "reqid1", "datetime": "<time>", "Processing_state" : "A", "Exception" : "none"}
+ {"request_id": "reqid2", "datetime": "<time>", "Processing_state" : "A_prime", "Exception" : "Unknown flow"}
+ {"request_id": "reqid3", "datetime": "<time>", "Processing_state" : "A_double_prime", "Exception" : "Parsing Failed"}
+
+Service B generated logs
+ ::
+
+ {"request_id": "reqid1", "datetime": "<time>", "Processing_state" : "B", "Exception" : "none"}
+ {"request_id": "reqid2", "datetime": "<time>", "Processing_state" : "A_Failed_at_1st_Stage", "Exception" : "none"}
+ {"request_id": "reqid3", "datetime": "<time>", "Processing_state" : "B_Failed", "Exception" : "Field not found"}
+
+Service C generated logs
+ ::
+
+ {"request_id": "reqid1", "datetime": "<time>", "Processing_state" : "C", "Exception" : "none"}
+ {"request_id": "reqid2", "datetime": "<time>", "Processing_state" : "NO_OP", "Exception" : "none"}
+ {"request_id": "reqid3", "datetime": "<time>", "Processing_state" : "C_Failed", "Exception" : "NullPointer"}
+
+
+We can sample logs based on request_id thereby getting **all-or-none** logs associated with a request_id. This is a kind of transactional guarantee on logs for a request ID. This helps to create an end to end picture of pipeline even on sampled data.
+
+Using hash64mod for sampling
+ ::
+
+ if (hash64mod($!msg!request_id, 100) <= 30) then {
+ //send out
+ }
+
+With hash64mod sampling, we get sampled logs like
+ ::
+
+ {"request_id": "reqid3", "data": "payload_3_original"}
+ {"request_id": "reqid3", "datetime": "<time>", "Processing_state" : "A_double_prime", "Exception" : "Parsing Failed"}
+ {"request_id": "reqid3", "datetime": "<time>", "Processing_state" : "B_Failed", "Exception" : "Field not found"}
+ {"request_id": "reqid3", "datetime": "<time>", "Processing_state" : "C_Failed", "Exception" : "NullPointer"}
+
+We will get all-or-none logs associated to hash-string (request ID in this case or combination of field_1 & field_2 & field_3) giving a full view of a request's life cycle in the cluster across various systems. The only constraint in hash-based sampling is, it will work only if we have the same unique identifier (single field or combination of fields) in logs across services.
+
+Same as hash64mod, we can use hash64 to add hash as tags that can be used later to filter logs.
+
+Using hash64 for filtering later
+ ::
+
+ set $.hash = hash64($!msg!field_1 & $!msg!field_2 & $!msg!field_3)
+ set $!tag= $syslogtag & $.hash;
+ //send out
+
+Hash-based sampling is helpful on a single system too. Say a single process generates 4 log lines for each transaction it commits. We can get all-or-none guarantees around these 4 logs generated for each transaction. Thereby giving a complete picture of a transaction (while sampling).
+
+**Note**
+ * Hash-based sampling can be used only when logs have **same unique identifier** across services.
+ * Default hash implementation is djb2 hash and xxhash can be enabled using compile-time flag (hash implementation can change release to release, check changelog).
+ * For parsing log to generate json to act on individual fields use mmnormalize.
diff --git a/source/tutorials/high_database_rate.rst b/source/tutorials/high_database_rate.rst
new file mode 100644
index 0000000..6189943
--- /dev/null
+++ b/source/tutorials/high_database_rate.rst
@@ -0,0 +1,161 @@
+Handling a massive syslog database insert rate with Rsyslog
+===========================================================
+
+*Written by* `Rainer Gerhards <http://www.gerhards.net/rainer>`_
+*(2008-01-31)*
+
+Abstract
+--------
+
+**In this paper, I describe how log massive amounts of**
+`syslog <http://www.monitorware.com/en/topics/syslog/>`_ **messages to a
+database.**\ This HOWTO is currently under development and thus a bit
+brief. Updates are promised ;).*
+
+The Intention
+-------------
+
+Database updates are inherently slow when it comes to storing syslog
+messages. However, there are a number of applications where it is handy
+to have the message inside a database. Rsyslog supports native database
+writing via output plugins. As of this writing, there are plugins
+available for MySQL an PostgreSQL. Maybe additional plugins have become
+available by the time you read this. Be sure to check.
+
+In order to successfully write messages to a database backend, the
+backend must be capable to record messages at the expected average
+arrival rate. This is the rate if you take all messages that can arrive
+within a day and divide it by 86400 (the number of seconds per day).
+Let's say you expect 43,200,000 messages per day. That's an average rate
+of 500 messages per second (mps). Your database server MUST be able to
+handle that amount of message per second on a sustained rate. If it
+doesn't, you either need to add an additional server, lower the number
+of message - or forget about it.
+
+However, this is probably not your peak rate. Let's simply assume your
+systems work only half a day, that's 12 hours (and, yes, I know this is
+unrealistic, but you'll get the point soon). So your average rate is
+actually 1,000 mps during work hours and 0 mps during non-work hours. To
+make matters worse, workload is not divided evenly during the day. So
+you may have peaks of up to 10,000mps while at other times the load may
+go down to maybe just 100mps. Peaks may stay well above 2,000mps for a
+few minutes.
+
+So how the hack you will be able to handle all of this traffic
+(including the peaks) with a database server that is just capable of
+inserting a maximum of 500mps?
+
+The key here is buffering. Messages that the database server is not
+capable to handle will be buffered until it is. Of course, that means
+database insert are NOT real-time. If you need real-time inserts, you
+need to make sure your database server can handle traffic at the actual
+peak rate. But lets assume you are OK with some delay.
+
+Buffering is fine. But how about these massive amounts of data? That
+can't be hold in memory, so don't we run out of luck with buffering? The
+key here is that rsyslog can not only buffer in memory but also buffer
+to disk (this may remind you of "spooling" which gets you the right
+idea). There are several queuing modes available, offering different
+throughput. In general, the idea is to buffer in memory until the memory
+buffer is exhausted and switch to disk-buffering when needed (and only
+as long as needed). All of this is handled automatically and
+transparently by rsyslog.
+
+With our above scenario, the disk buffer would build up during the day
+and rsyslog would use the night to drain it. Obviously, this is an
+extreme example, but it shows what can be done. Please note that queue
+content survies rsyslogd restarts, so even a reboot of the system will
+not cause any message loss.
+
+How To Setup
+------------
+
+Frankly, it's quite easy. You just need to do is instruct rsyslog to use
+a disk queue and then configure your action. There is nothing else to
+do. With the following simple config file, you log anything you receive
+to a MySQL database and have buffering applied automatically.
+
+::
+
+ module(load="imuxsock") # provides support for local system logging
+
+ # provides UDP syslog reception
+ module(load="imudp")
+ input(type="imudp" port="514")
+
+ # Make sure this path exists and the user of the deamon has read/write/execute access
+ global(WorkDirectory="/var/spool/rsyslog") # default location for work (spool) files
+ main_queue(queue.fileName="mainq")
+
+ *.* action(type="ommysql" server="<hostname>" db="Syslog" uid="<database user name>" pwd="<database user password>"
+ action.resumeRetryCount="-1")
+ # for PostgreSQL replace :ommysql: by :ompgsql: below: *.* :ommysql:hostname,dbname,userid,password;
+
+The simple setup above has one drawback: the write database action is
+executed together with all other actions. Typically, local files are
+also written. These local file writes are now bound to the speed of the
+database action. So if the database is down, or there is a large
+backlog, local files are also not (or late) written.
+
+**There is an easy way to avoid this with rsyslog.** It involves a
+slightly more complicated setup. In rsyslog, each action can utilize its
+own queue. If so, messages are simply pulled over from the main queue
+and then the action queue handles action processing on its own. This
+way, main processing and the action are de-coupled. In the above
+example, this means that local file writes will happen immediately while
+the database writes are queued. As a side-note, each action can have its
+own queue, so if you would like to more than a single database or send
+messages reliably to another host, you can do all of this on their own
+queues, de-coupling their processing speeds.
+
+The configuration for the de-coupled database write involves just a few
+more commands:
+
+::
+
+ module(load="imuxsock") # provides support for local system logging
+
+ # provides UDP syslog reception
+ module(load="imudp")
+ input(type="imudp" port="514")
+
+ # Make sure this path exists and the user of the deamon has read/write/execute access
+ global(WorkDirectory="/var/spool/rsyslog") # default location for work (spool) files
+
+ module (load="ommysql")
+ *.* action(type="ommysql" server="<hostname>" db="Syslog" uid="<database user name>" pwd="<database user password>"
+ queue.filename="databasequeue" action.resumeRetryCount="-1")
+ )
+
+**This is the recommended configuration for this use case.** It requires
+rsyslog 8.1908.0 or above.
+
+In this example, the main message queue is NOT disk-assisted (there is
+no main_queue() object). We still could do that, but have
+not done it because there seems to be no need. The only slow running
+action is the database writer and it has its own queue. So there is no
+real reason to use a large main message queue (except, of course, if you
+expect \*really\* heavy traffic bursts).
+
+Note that you can modify a lot of queue performance parameters, but the
+above config will get you going with default values. If you consider
+using this on a real busy server, it is strongly recommended to invest
+some time in setting the tuning parameters to appropriate values.
+
+Feedback requested
+~~~~~~~~~~~~~~~~~~
+
+I would appreciate feedback on this tutorial. If you have additional
+ideas, comments or find bugs (I \*do\* bugs - no way... ;)), please `let
+me know <mailto:rgerhards@adiscon.com>`_.
+
+Revision History
+----------------
+
+- 2008-01-28 \* `Rainer Gerhards`_ \*
+ Initial Version created
+- 2008-01-28 \* `Rainer Gerhards`_ \*
+ Updated to new v3.11.0 capabilities
+- 2021-04-21 \* Stev Leibelt \*
+ Updated configuration section to non legacy format
+
diff --git a/source/tutorials/index.rst b/source/tutorials/index.rst
new file mode 100644
index 0000000..8a97d96
--- /dev/null
+++ b/source/tutorials/index.rst
@@ -0,0 +1,18 @@
+Tutorials
+=========
+
+.. toctree::
+ :maxdepth: 2
+
+ tls_cert_summary
+ tls
+ database
+ high_database_rate
+ reliable_forwarding
+ recording_pri
+ failover_syslog_server
+ log_rotation_fix_size
+ gelf_forwarding
+ log_sampling
+ random_sampling
+ hash_sampling
diff --git a/source/tutorials/log_rotation_fix_size.rst b/source/tutorials/log_rotation_fix_size.rst
new file mode 100644
index 0000000..d2d1570
--- /dev/null
+++ b/source/tutorials/log_rotation_fix_size.rst
@@ -0,0 +1,60 @@
+Log rotation with rsyslog
+=========================
+
+*Written by Michael Meckelein*
+
+Situation
+---------
+
+Your environment does not allow you to store tons of logs? You have
+limited disc space available for logging, for example you want to log to
+a 124 MB RAM usb stick? Or you do not want to keep all the logs for
+months, logs from the last days is sufficient? Think about log rotation.
+
+Log rotation based on a fixed log size
+--------------------------------------
+
+This small but hopefully useful article will show you the way to keep
+your logs at a given size. The following sample is based on rsyslog
+illustrating a simple but effective log rotation with a maximum size
+condition.
+
+Use Output Channels for fixed-length syslog files
+-------------------------------------------------
+
+Lets assume you do not want to spend more than 100 MB hard disc space
+for you logs. With rsyslog you can configure Output Channels to achieve
+this. Putting the following directive
+
+::
+
+ # start log rotation via outchannel
+ # outchannel definition
+ $outchannel log_rotation,/var/log/log_rotation.log, 52428800,/home/me/./log_rotation_script
+ # activate the channel and log everything to it
+ *.* :omfile:$log_rotation
+ # end log rotation via outchannel
+
+to rsyslog.conf instruct rsyslog to log everything to the destination
+file '/var/log/log\_rotation.log' until the give file size of 50 MB is
+reached. If the max file size is reached it will perform an action. In
+our case it executes the script /home/me/log\_rotation\_script which
+contains a single command:
+
+::
+
+ mv -f /var/log/log_rotation.log /var/log/log_rotation.log.1
+
+This moves the original log to a kind of backup log file. After the
+action was successfully performed rsyslog creates a new
+/var/log/log\_rotation.log file and fill it up with new logs. So the
+latest logs are always in log\_rotation.log.
+
+Conclusion
+----------
+
+With this approach two files for logging are used, each with a maximum
+size of 50 MB. So we can say we have successfully configured a log
+rotation which satisfies our requirement. We keep the logs at a
+fixed-size level of 100 MB.
+
diff --git a/source/tutorials/log_sampling.rst b/source/tutorials/log_sampling.rst
new file mode 100644
index 0000000..c8b9ddb
--- /dev/null
+++ b/source/tutorials/log_sampling.rst
@@ -0,0 +1,13 @@
+Log Sampling
+============
+
+Rsyslog supports various sampling mechanism.
+User can perform sampling while collecting logs from client systems and forward it to server systems for aggregation and persistence.
+
+Sampling strategies
+-------------------
+
+Rsyslog support following sampling strategies:-
+
+ - :doc:`Random sampling<./random_sampling>`
+ - :doc:`Hash based sampling<./hash_sampling>`
diff --git a/source/tutorials/random_sampling.rst b/source/tutorials/random_sampling.rst
new file mode 100644
index 0000000..3c7d5d3
--- /dev/null
+++ b/source/tutorials/random_sampling.rst
@@ -0,0 +1,16 @@
+Random sampling
+===============
+
+Rsyslog supports various sampling mechanisms. These can be used on client systems to save servers from getting overwhelmed. Here we introduce a new sampling mechanism "Random sampling".
+
+Let's consider a system that is generating logs at rate of 100 logs/sec.
+If we want to get 20% of these logs uniformly sampled we use random sampling.
+
+.. code-block:: none
+
+ set $.rand = random(100);
+ if ($.rand <= 20) then {
+ //send out
+ }
+
+Above config will collect 20% of logs generated.
diff --git a/source/tutorials/recording_pri.rst b/source/tutorials/recording_pri.rst
new file mode 100644
index 0000000..8ad0cfe
--- /dev/null
+++ b/source/tutorials/recording_pri.rst
@@ -0,0 +1,141 @@
+Recording the Priority of Syslog Messages
+=========================================
+
+*Written by* `Rainer Gerhards <https://rainer.gerhards.net>`_ *(2007-06-18)*
+
+Abstract
+--------
+
+**The so-called priority (PRI) is very important in syslog messages,
+because almost all filtering in syslog.conf is based on it.** However,
+many syslogds (including the Linux stock sysklogd) do not provide a way
+to record that value. In this article, I'll give a brief overview of how
+PRI can be written to a log file.
+
+Background
+----------
+
+The PRI value is a combination of so-called severity and facility. The
+facility indicates where the message originated from (e.g. kernel, mail
+subsystem) while the severity provides a glimpse of how important the
+message might be (e.g. error or informational). Be careful with these
+values: they are in no way consistent across applications (especially
+severity). However, they still form the basis of most filtering in
+syslog.conf. For example, the directive (aka "selector line)
+
+::
+
+ mail.* /var/log/mail.log
+
+means that messages with the mail facility should be stored to
+/var/log/mail.log, no matter which severity indicator they have (that is
+telling us the asterisk). If you set up complex conditions, it can be
+annoying to find out which PRI value a specific syslog message has. Most
+stock syslogds do not provide any way to record them.
+
+How is it done?
+---------------
+
+With `rsyslog <http://www.rsyslog.com/>`_, PRI recording is simple. All
+you need is the correct template. Even if you do not use rsyslog on a
+regular basis, it might be a handy tool for finding out the priority.
+
+Rsyslog provides a flexible system to specify the output formats. It is
+template-based. A template with the traditional syslog format looks as
+follows:
+
+::
+
+ $template TraditionalFormat,"%timegenerated% %HOSTNAME% %syslogtag%%msg:::drop-last-lf%\n"
+
+The part in quotes is the output formats. Things between percent-signs
+are so-called `messages properties <property_replacer.html>`_. They are
+replaced with the respective content from the syslog message when output
+is written. Everything outside of the percent signs is literal text,
+which is simply written as specified.
+
+Thankfully, rsyslog provides message properties for the priority. These
+are called "PRI", "syslogfacility" and "syslogpriority" (case is
+important!). They are numerical values. Starting with rsyslog 1.13.4,
+there is also a property "pri-text", which contains the priority in
+friendly text format (e.g. "local0.err<133>"). For the rest of this
+article, I assume that you run version 1.13.4 or higher.
+
+Recording the priority is now a simple matter of adding the respective
+field to the template. It now looks like this:
+
+::
+
+ $template TraditionalFormatWithPRI,"%pri-text%: %timegenerated% %HOSTNAME% %syslogtag%%msg:::drop-last-lf%\n"
+
+Now we have the right template - but how to write it to a file? You
+probably have a line like this in your syslog.conf:
+
+::
+
+ *.* -/var/log/messages.log
+
+It does not specify a template. Consequently, rsyslog uses the
+traditional format. In order to use some other format, simply specify
+the template after the semicolon:
+
+::
+
+ *.* -/var/log/messages.log;TraditionalFormatWithPRI
+
+That's all you need to do. There is one common pitfall: you need to
+define the template before you use it in a selector line. Otherwise, you
+will receive an error.
+
+Once you have applied the changes, you need to restart rsyslogd. It will
+then pick the new configuration.
+
+What if I do not want rsyslogd to be the standard syslogd?
+----------------------------------------------------------
+
+If you do not want to switch to rsyslog, you can still use it as a setup
+aid. A little bit of configuration is required.
+
+#. Download, make and install rsyslog
+#. copy your syslog.conf over to rsyslog.conf
+#. add the template described above to it; select the file that should
+ use it
+#. stop your regular syslog daemon for the time being
+#. run rsyslogd (you may even do this interactively by calling it with
+ the -n additional option from a shell)
+#. stop rsyslogd (press ctrl-c when running interactively)
+#. restart your regular syslogd
+
+That's it - you can now review the priorities.
+
+Some Sample Data
+----------------
+
+Below is some sample data created with the template specified above.
+Note the priority recording at the start of each line.
+
+::
+
+ kern.info<6>: Jun 15 18:10:38 host kernel: PCI: Sharing IRQ 11 with 00:04.0
+ kern.info<6>: Jun 15 18:10:38 host kernel: PCI: Sharing IRQ 11 with 01:00.0
+ kern.warn<4>: Jun 15 18:10:38 host kernel: Yenta IRQ list 06b8, PCI irq11
+ kern.warn<4>: Jun 15 18:10:38 host kernel: Socket status: 30000006
+ kern.warn<4>: Jun 15 18:10:38 host kernel: Yenta IRQ list 06b8, PCI irq11
+ kern.warn<4>: Jun 15 18:10:38 host kernel: Socket status: 30000010
+ kern.info<6>: Jun 15 18:10:38 host kernel: cs: IO port probe 0x0c00-0x0cff: clean.
+ kern.info<6>: Jun 15 18:10:38 host kernel: cs: IO port probe 0x0100-0x04ff: excluding 0x100-0x107 0x378-0x37f 0x4d0-0x4d7
+ kern.info<6>: Jun 15 18:10:38 host kernel: cs: IO port probe 0x0a00-0x0aff: clean.
+ local7.notice<189>: Jun 15 18:17:24 host dd: 1+0 records out
+ local7.notice<189>: Jun 15 18:17:24 host random: Saving random seed: succeeded
+ local7.notice<189>: Jun 15 18:17:25 host portmap: portmap shutdown succeeded
+ local7.notice<189>: Jun 15 18:17:25 host network: Shutting down interface eth1: succeeded
+ local7.notice<189>: Jun 15 18:17:25 host network: Shutting down loopback interface: succeeded
+ local7.notice<189>: Jun 15 18:17:25 host pcmcia: Shutting down PCMCIA services: cardmgr
+ user.notice<13>: Jun 15 18:17:25 host /etc/hotplug/net.agent: NET unregister event not supported
+ local7.notice<189>: Jun 15 18:17:27 host pcmcia: modules.
+ local7.notice<189>: Jun 15 18:17:29 host rc: Stopping pcmcia: succeeded
+ local7.notice<189>: Jun 15 18:17:30 host rc: Starting killall: succeeded
+ syslog.info<46>: Jun 15 18:17:33 host [origin software="rsyslogd" swVersion="1.13.3" x-pid="2464"] exiting on signal 15.
+ syslog.info<46>: Jun 18 10:55:47 host [origin software="rsyslogd" swVersion="1.13.3" x-pid="2367"][x-configInfo udpReception="Yes" udpPort="514" tcpReception="Yes" tcpPort="1470"] restart
+ user.notice<13>: Jun 18 10:55:50 host rger: test
+ syslog.info<46>: Jun 18 10:55:52 host [origin software="rsyslogd" swVersion="1.13.3" x-pid="2367"] exiting on signal 2.``
diff --git a/source/tutorials/reliable_forwarding.rst b/source/tutorials/reliable_forwarding.rst
new file mode 100644
index 0000000..a434ff1
--- /dev/null
+++ b/source/tutorials/reliable_forwarding.rst
@@ -0,0 +1,171 @@
+Reliable Forwarding of syslog Messages with Rsyslog
+===================================================
+
+*Written by* `Rainer Gerhards <https://rainer.gerhards.net/>`_
+*(2008-06-27)*
+
+Abstract
+--------
+
+**In this paper, I describe how to forward**
+`syslog <http://www.monitorware.com/en/topics/syslog/>`_ **messages
+(quite) reliable to a central rsyslog server.** This depends on rsyslog
+being installed on the client system and it is recommended to have it
+installed on the server system. Please note that industry-standard
+`plain TCP syslog protocol is not fully
+reliable <https://rainer.gerhards.net/2008/04/on-unreliability-of-plain-tcp-syslog.html>`_
+(thus the "quite reliable"). If you need a truly reliable solution, you
+need to look into RELP (natively supported by rsyslog).*
+
+The Intention
+-------------
+
+Whenever two systems talk over a network, something can go wrong. For
+example, the communications link may go down, or a client or server may
+abort. Even in regular cases, the server may be offline for a short
+period of time because of routine maintenance.
+
+A logging system should be capable of avoiding message loss in
+situations where the server is not reachable. To do so, unsent data
+needs to be buffered at the client while the server is offline. Then,
+once the server is up again, this data is to be sent.
+
+This can easily be accomplished by rsyslog. In rsyslog, every action runs
+on its own queue and each queue can be set to buffer data if the action
+is not ready. Of course, you must be able to detect that "the action is
+not ready", which means the remote server is offline. This can be
+detected with plain TCP syslog and RELP, but not with UDP. So you need
+to use either of the two. In this howto, we use plain TCP syslog.
+
+Please note that we are using rsyslog-specific features. They are
+required on the client, but not on the server. So the client system must
+run rsyslog (at least version 3.12.0), while on the server another
+syslogd may be running, as long as it supports plain tcp syslog.
+
+**The rsyslog queueing subsystem tries to buffer to memory. So even if
+the remote server goes offline, no disk file is generated.** File on
+disk are created only if there is need to, for example if rsyslog runs
+out of (configured) memory queue space or needs to shutdown (and thus
+persist yet unsent messages). Using main memory and going to the disk
+when needed is a huge performance benefit. You do not need to care about
+it, because, all of it is handled automatically and transparently by
+rsyslog.
+
+How To Setup
+------------
+
+First, you need to create a working directory for rsyslog. This is where
+it stores its queue files (should need arise). You may use any location
+on your local system.
+
+Next, you need to instruct rsyslog to use a disk queue and then
+configure your action. There is nothing else to do. With the following
+simple config file, you forward anything you receive to a remote server
+and have buffering applied automatically when it goes down. This must be
+done on the client machine.
+
+.. code-block:: linux-config
+
+ $ModLoad imuxsock # local message reception
+ $WorkDirectory /rsyslog/work # default location for work (spool) files
+ $ActionQueueType LinkedList # use asynchronous processing
+ $ActionQueueFileName srvrfwd # set file name, also enables disk mode
+ $ActionResumeRetryCount -1 # infinite retries on insert failure
+ $ActionQueueSaveOnShutdown on # save in-memory data if rsyslog shuts down
+ *.* @@server:port
+
+The port given above is optional. It may not be specified, in which case
+you only provide the server name. The "$ActionQueueFileName" is used to
+create queue files, should need arise. This value must be unique inside
+rsyslog.conf. No two rules must use the same queue file. Also, for
+obvious reasons, it must only contain those characters that can be used
+inside a valid file name. Rsyslog possibly adds some characters in front
+and/or at the end of that name when it creates files. So that name
+should not be at the file size name length limit (which should not be a
+problem these days).
+
+Please note that actual spool files are only created if the remote
+server is down **and** there is no more space in the in-memory queue. By
+default, a short failure of the remote server will never result in the
+creation of a disk file as a couple of hundred messages can be held in
+memory by default. [These parameters can be fine-tuned. However, then
+you need to either fully understand how the queue works (`read elaborate
+doc <http://www.rsyslog.com/doc-queues.html>`_) or use `professional
+services <http://www.rsyslog.com/professional-services/>`_ to
+have it done based on your specs ;) - what that means is that
+fine-tuning queue parameters is far from being trivial...]
+
+If you would like to test if your buffering scenario works, you need to
+stop, wait a while and restart your central server. Do **not** watch for
+files being created, as this usually does not happen and never happens
+immediately.
+
+Forwarding to More than One Server
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+If you have more than one server you would like to forward to, that's
+quickly done. Rsyslog has no limit on the number or type of actions, so
+you can define as many targets as you like. What is important to know,
+however, is that the full set of directives make up an action. So you
+can not simply add (just) a second forwarding rule, but need to
+duplicate the rule configuration as well. Be careful that you use
+different queue file names for the second action, else you will mess up
+your system.
+
+A sample for forwarding to two hosts looks like this:
+
+.. code-block:: linux-config
+
+ $ModLoad imuxsock # local message reception
+ $WorkDirectory /rsyslog/work # default location for work (spool) files
+
+ # start forwarding rule 1
+ $ActionQueueType LinkedList # use asynchronous processing
+ $ActionQueueFileName srvrfwd1 # set file name, also enables disk mode
+ $ActionResumeRetryCount -1 # infinite retries on insert failure
+ $ActionQueueSaveOnShutdown on # save in-memory data if rsyslog shuts down
+ *.* @@server1:port
+ # end forwarding rule 1
+
+ # start forwarding rule 2
+ $ActionQueueType LinkedList # use asynchronous processing
+ $ActionQueueFileName srvrfwd2 # set file name, also enables disk mode
+ $ActionResumeRetryCount -1 # infinite retries on insert failure
+ $ActionQueueSaveOnShutdown on # save in-memory data if rsyslog shuts down
+ *.* @@server2
+ # end forwarding rule 2
+
+Note the filename used for the first rule it is "srvrfwd1" and for the
+second it is "srvrfwd2". I have used a server without port name in the
+second forwarding rule. This was just to illustrate how this can be
+done. You can also specify a port there (or drop the port from server1).
+
+When there are multiple action queues, they all work independently.
+Thus, if server1 goes down, server2 still receives data in real-time.
+The client will **not** block and wait for server1 to come back online.
+Similarly, server1's operation will not be affected by server2's state.
+
+Some Final Words on Reliability ...
+-----------------------------------
+
+Using plain TCP syslog provides a lot of reliability over UDP syslog.
+However, plain TCP syslog is **not** a fully reliable transport. In
+order to get full reliability, you need to use the RELP protocol.
+
+Follow the next link to learn more about `the problems you may encounter
+with plain tcp
+syslog <https://rainer.gerhards.net/2008/04/on-unreliability-of-plain-tcp-syslog.html>`_.
+
+Feedback requested
+~~~~~~~~~~~~~~~~~~
+
+I would appreciate feedback on this tutorial. If you have additional
+ideas, comments or find bugs (I \*do\* bugs - no way... ;)), please `let
+me know <mailto:rgerhards@adiscon.com>`_.
+
+Revision History
+----------------
+
+- 2008-06-27 \* `Rainer Gerhards <https://rainer.gerhards.net/>`_ \*
+ Initial Version created
+
diff --git a/source/tutorials/tls.rst b/source/tutorials/tls.rst
new file mode 100644
index 0000000..54a07d9
--- /dev/null
+++ b/source/tutorials/tls.rst
@@ -0,0 +1,335 @@
+Encrypting Syslog Traffic with TLS (SSL) [short version]
+========================================================
+
+*Written by* `Rainer Gerhards <http://www.gerhards.net/rainer>`_
+*(2008-05-06)*
+
+Abstract
+--------
+
+**In this paper, I describe how to encrypt**
+`syslog <http://www.monitorware.com/en/topics/syslog/>`_
+**messages on the network.**
+Encryption is vital to keep the confidential content of
+syslog messages secure. I describe the overall approach and provide an
+HOWTO do it with `rsyslog's <http://www.rsyslog.com>`_ TLS features. 
+
+Please note that TLS is the more secure successor of SSL. While people
+often talk about "SSL encryption" they actually mean "TLS encryption".
+So don't look any further if you look for how to SSL-encrypt syslog. You
+have found the right spot.
+
+This is a quick guide. There is a more elaborate guide currently under
+construction which provides a much more secure environment. It is highly
+recommended to `at least have a look at it <rsyslog_secure_tls.html>`_.
+
+Background
+----------
+
+**Traditional syslog is a clear-text protocol. That means anyone with a
+sniffer can have a peek at your data.** In some environments, this is no
+problem at all. In others, it is a huge setback, probably even
+preventing deployment of syslog solutions. Thankfully, there are easy
+ways to encrypt syslog communication. 
+
+The traditional approach involves `running a wrapper like stunnel around
+the syslog session <rsyslog_stunnel.html>`_. This works quite well and
+is in widespread use. However, it is not tightly coupled with the main
+syslogd and some, even severe, problems can result from this (follow a
+mailing list thread that describes `total loss of syslog messages due to
+stunnel
+mode <http://lists.adiscon.net/pipermail/rsyslog/2008-March/000580.html>`_
+and the `unreliability of TCP
+syslog <http://rgerhards.blogspot.com/2008/04/on-unreliability-of-plain-tcp-syslog.html>`_).
+
+`Rsyslog supports syslog via GSSAP <gssapi.html>`_\ I since long to
+overcome these limitations. However, syslog via GSSAPI is a
+rsyslog-exclusive transfer mode and it requires a proper Kerberos
+environment. As such, it isn't a really universal solution. The
+`IETF <http://www.ietf.org/>`_ has begun standardizing syslog over plain
+tcp over TLS for a while now. While I am not fully satisfied with the
+results so far, this obviously has the  potential to become the
+long-term solution. The Internet Draft in question, syslog-transport-tls
+has been dormant for some time but is now (May of 2008) again being
+worked on. I expect it to turn into a RFC within the next 12 month (but
+don't take this for granted ;)). I didn't want to wait for it, because
+there obviously is need for TLS syslog right now (and, honestly, I have
+waited long enough...). Consequently, I have implemented the current
+draft, with some interpretations I made (there will be a compliance doc
+soon). So in essence, a TLS-protected syslog transfer mode is available
+right now. As a side-note, Rsyslog is the world's first implementation
+of syslog-transport-tls.
+
+Please note that in theory it should be compatible with other, non IETF
+syslog-transport-tls implementations. If you would like to run it with
+something else, please let us know so that we can create a compatibility
+list (and implement compatibility where it doesn't yet exist). 
+
+Overall System Setup
+--------------------
+
+Encryption requires a reliable stream. So It will not work over UDP
+syslog. In rsyslog, network transports utilize a so-called "network
+stream layer" (netstream for short). This layer provides a unified view
+of the transport to the application layer. The plain TCP syslog sender
+and receiver are the upper layer. The driver layer currently consists of
+the "ptcp" and "gtls" library plugins. "ptcp" stands for "plain tcp" and
+is used for unencrypted message transfer. It is also used internally by
+the gtls driver, so it must always be present on a system. The "gtls"
+driver is for GnutTLS, a TLS library. It is used for encrypted message
+transfer. In the future, additional drivers will become available (most
+importantly, we would like to include a driver for NSS).
+
+What you need to do to build an encrypted syslog channel is to simply
+use the proper netstream drivers on both the client and the server.
+Client, in the sense of this document, is the rsyslog system that is
+sending syslog messages to a remote (central) loghost, which is called
+the server. In short, the setup is as follows:
+
+**Client**
+
+- forwards messages via plain tcp syslog using gtls netstream driver to
+ central server on port 6514
+
+**Server**
+
+- accept incoming messages via plain tcp syslog using gtls netstream
+ driver on port 6514
+
+Setting up the system
+---------------------
+
+Server Setup
+~~~~~~~~~~~~
+
+At the server, you need to have a digital certificate. That certificate
+enables SSL operation, as it provides the necessary crypto keys being
+used to secure the connection. There is a set of default certificates in
+./contrib/gnutls. These are key.pem and cert.pem. These are good for
+testing. If you use it in production, it is very easy to break into your
+secure channel as everybody is able to get hold of your private key. So
+it is a good idea to generate the key and certificate yourself.
+
+You also need a root CA certificate. Again, there is a sample CA
+certificate in ./contrib/gnutls, named ca.cert. It is suggested to
+generate your own.
+
+To configure the server, you need to tell it where are its certificate
+files, to use the gtls driver and start up a listener. This is done as
+follows:
+
+ ::
+
+ # make gtls driver the default and set certificate files
+ global(
+ DefaultNetstreamDriver="gtls"
+ DefaultNetstreamDriverCAFile="/path/to/contrib/gnutls/ca.pem"
+ DefaultNetstreamDriverCertFile="/path/to/contrib/gnutls/cert.pem"
+ DefaultNetstreamDriverKeyFile="/path/to/contrib/gnutls/key.pem"
+ )
+
+ # load TCP listener
+ module(
+ load="imtcp"
+ StreamDriver.Name="gtls"
+ StreamDriver.Mode="1"
+ StreamDriver.Authmode="anon"
+ )
+
+ # start up listener at port 6514
+ input(
+ type="imtcp"
+ port="6514"
+ )
+
+This is all you need to do. You can use the rest of your rsyslog.conf
+together with this configuration. The way messages are received does not
+interfere with any other option, so you are able to do anything else you
+like without any restrictions.
+
+Restart rsyslogd. The server should now be fully operational.
+
+Client Setup
+~~~~~~~~~~~~
+
+The client setup is equally simple. You need less certificates, just the
+CA cert. 
+
+ ::
+
+ # certificate files - just CA for a client
+ global(DefaultNetstreamDriverCAFile="/path/to/contrib/gnutls/ca.pem")
+
+ # set up the action for all messages
+ action(type="omfwd" protocol="tcp" target="s.example.net" port="6514"
+ StreamDriver="gtls" StreamDriverMode="1" StreamDriverAuthMode="anon")
+
+Note that we use the regular TCP forwarding action here. There is
+nothing special, because the encryption is handled by the netstream
+driver. So I have just forwarded every message (\*.\*) for simplicity -
+you can use any of rsyslog's filtering capabilities (like
+expression-based filters or regular expressions).
+
+Done
+~~~~
+
+After following these steps, you should have a working secure syslog
+forwarding system. To verify, you can type "logger test" or a similar
+"smart" command on the client. It should show up in the respective
+server log file. If you dig out your sniffer, you should see that the
+traffic on the wire is actually protected.
+
+Certificates
+------------
+
+In order to be really secure, certificates are needed. This is a short
+summary on how to generate the necessary certificates with GnuTLS'
+certtool. You can also generate certificates via other tools, but as we
+currently support GnuTLS as the only TLS library, we thought it is a
+good idea to use their tools.
+
+Note that this section aims at people who are not involved with PKI at
+all. The main goal is to get them going in a reasonable secure way. 
+
+CA Certificate
+~~~~~~~~~~~~~~
+
+This is used to sign all of your other certificates. The CA cert must be
+trusted by all clients and servers. The private key must be
+well-protected and not given to any third parties. The certificate
+itself can (and must) be distributed. To generate it, do the following:
+
+#. generate the private key:
+
+ ::
+
+ certtool --generate-privkey --outfile ca-key.pem
+
+ This takes a short while. Be sure to do some work on your
+ workstation, it waits for random input. Switching between windows is
+ sufficient ;)
+
+#. now create the (self-signed) CA certificate itself:
+
+ ::
+
+ certtool --generate-self-signed --load-privkey ca-key.pem --outfile ca.pem
+
+ This generates the CA certificate. This command queries you for a
+ number of things. Use appropriate responses. When it comes to
+ certificate validity, keep in mind that you need to recreate all
+ certificates when this one expires. So it may be a good idea to use a
+ long period, eg. 3650 days (roughly 10 years). You need to specify
+ that the certificates belongs to an authority. The certificate is used
+ to sign other certificates.
+
+#. You need to distribute this certificate to all peers and you need to
+ point to it via the $DefaultNetstreamDriverCAFile config directive.
+ All other certificates will be issued by this CA.
+ Important: do only distribute the ca.pem, NOT ca-key.pem (the
+ private key). Distributing the CA private key would totally breach
+ security as everybody could issue new certificates on the behalf of
+ this CA.
+
+Individual Peer Certificate
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Each peer (be it client, server or both), needs a certificate that
+conveys its identity. Access control is based on these certificates. You
+can, for example, configure a server to accept connections only from
+configured clients. The client ID is taken from the client instances
+certificate. So as a general rule of thumb, you need to create a
+certificate for each instance of rsyslogd that you run. That instance
+also needs the private key, so that it can properly decrypt the traffic.
+Safeguard the peer's private key file. If somebody gets hold of it, it
+can maliciously pretend to be the compromised host. If such happens,
+regenerate the certificate and make sure you use a different name
+instead of the compromised one (if you use name-based authentication). 
+
+These are the steps to generate the individual certificates (repeat: you
+need to do this for every instance, do NOT share the certificates
+created in this step):
+
+#. generate a private key (do NOT mistake this with the CA's private key
+ - this one is different):
+
+ ::
+
+ certtool --generate-privkey --outfile key.pem
+
+ Again, this takes a short while.
+
+#. generate a certificate request:
+
+ ::
+
+ certtool --generate-request --load-privkey key.pem --outfile request.pem
+
+ If you do not have the CA's private key (because you are not
+ authorized for this), you can send the certificate request to the
+ responsible person. If you do this, you can skip the remaining steps,
+ as the CA will provide you with the final certificate. If you submit
+ the request to the CA, you need to tell the CA the answers that you
+ would normally provide in step 3 below.
+
+#. Sign (validate, authorize) the certificate request and generate the
+ instances certificate. You need to have the CA's certificate and
+ private key for this:
+
+ ::
+
+ certtool --generate-certificate --load-request request.pem --outfile cert.pem \ --load-ca-certificate ca.pem --load-ca-privkey ca-key.pem
+
+ Answer questions as follows: Cert does not belong to an authority; it
+ is a TLS web server and client certificate; the dnsName MUST be the
+ name of the peer in question (e.g. centralserver.example.net) - this
+ is the name used for authenticating the peers. Please note that you
+ may use an IP address in dnsName. This is a good idea if you would
+ like to use default server authentication and you use selector lines
+ with IP addresses (e.g. "\*.\* @@192.168.0.1") - in that case you
+ need to select a dnsName of 192.168.0.1. But, of course, changing the
+ server IP then requires generating a new certificate.
+
+After you have generated the certificate, you need to place it onto the
+local machine running rsyslogd. Specify the certificate and key via the
+$DefaultNetstreamDriverCertFile /path/to/cert.pem and
+$DefaultNetstreamDriverKeyFile /path/to/key.pem configuration
+directives. Make sure that nobody has access to key.pem, as that would
+breach security. And, once again: do NOT use these files on more than
+one instance. Doing so would prevent you from distinguishing between the
+instances and thus would disable useful authentication.
+
+Troubleshooting Certificates
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+If you experience trouble with your certificate setup, it may be useful
+to get some information on what is contained in a specific certificate
+(file). To obtain that information, do 
+
+::
+
+ $ certtool --certificate-info --infile cert.pem
+
+where "cert.pem" can be replaced by the various certificate pem files
+(but it does not work with the key files).
+
+Conclusion
+----------
+
+With minimal effort, you can set up a secure logging infrastructure
+employing TLS encrypted syslog message transmission.
+
+Feedback requested
+~~~~~~~~~~~~~~~~~~
+
+I would appreciate feedback on this tutorial. If you have additional
+ideas, comments or find bugs (I \*do\* bugs - no way... ;)), please `let
+me know <mailto:rgerhards@adiscon.com>`_.
+
+Revision History
+----------------
+
+- 2008-05-06 \* `Rainer Gerhards`_ \*
+ Initial Version created
+- 2008-05-26 \* `Rainer Gerhards`_ \*
+ added information about certificates
diff --git a/source/tutorials/tls_cert.jpg b/source/tutorials/tls_cert.jpg
new file mode 100644
index 0000000..920e998
--- /dev/null
+++ b/source/tutorials/tls_cert.jpg
Binary files differ
diff --git a/source/tutorials/tls_cert_100.jpg b/source/tutorials/tls_cert_100.jpg
new file mode 100644
index 0000000..beeedc5
--- /dev/null
+++ b/source/tutorials/tls_cert_100.jpg
Binary files differ
diff --git a/source/tutorials/tls_cert_ca.jpg b/source/tutorials/tls_cert_ca.jpg
new file mode 100644
index 0000000..f2da045
--- /dev/null
+++ b/source/tutorials/tls_cert_ca.jpg
Binary files differ
diff --git a/source/tutorials/tls_cert_ca.rst b/source/tutorials/tls_cert_ca.rst
new file mode 100644
index 0000000..f7127a4
--- /dev/null
+++ b/source/tutorials/tls_cert_ca.rst
@@ -0,0 +1,147 @@
+Setting up the CA
+=================
+
+The first step is to set up a certificate authority (CA). It must be
+maintained by a trustworthy person (or group) and approves the
+identities of all machines. It does so by issuing their certificates.
+In a small setup, the administrator can provide the CA function. What is
+important is the CA's private key is well-protected and machine
+certificates are only issued if it is know they are valid (in a
+single-admin case that means the admin should not issue certificates to
+anyone else except himself).
+
+The CA creates a so-called self-signed certificate. That is, it approves
+its own authenticity. This sounds useless, but the key point to understand
+is that every machine will be provided a copy of the CA's certificate.
+Accepting this certificate is a matter of trust. So by configuring the
+CA certificate, the administrator tells
+`rsyslog <http://www.rsyslog.com>`_ which certificates to trust. This is
+the root of all trust under this model. That is why the CA's private key
+is so important - everyone getting hold of it is trusted by our rsyslog
+instances.
+
+.. figure:: tls_cert_ca.jpg
+ :align: center
+ :alt:
+
+To create a self-signed certificate, use the following commands with
+GnuTLS (which is currently the only supported TLS library, what may
+change in the future). Please note that GnuTLS' tools are not installed
+by default on many platforms. Also, the tools do not necessarily come
+with the GnuTLS core package. If you do not have certtool on your
+system, check if there is package for the GnuTLS tools available (under
+Fedora, for example, this is named gnutls-utils-<version> and it is NOT
+installed by default).
+
+#. generate the private key:
+
+ ::
+
+ certtool --generate-privkey --outfile ca-key.pem
+
+ This takes a short while. Be sure to do some work on your
+ workstation, it waits for random input. Switching between windows is
+ sufficient ;)
+
+
+#. now create the (self-signed) CA certificate itself:
+
+ ::
+
+ certtool --generate-self-signed --load-privkey ca-key.pem --outfile ca.pem
+
+ This generates the CA certificate. This command queries you for a
+ number of things. Use appropriate responses. When it comes to
+ certificate validity, keep in mind that you need to recreate all
+ certificates when this one expires. So it may be a good idea to use a
+ long period, eg. 3650 days (roughly 10 years). You need to specify
+ that the certificates belongs to an authority. The certificate is
+ used to sign other certificates.
+
+Sample Screen Session
+~~~~~~~~~~~~~~~~~~~~~
+
+Text in red is user input. Please note that for some questions, there is
+no user input given. This means the default was accepted by simply
+pressing the enter key.
+
+::
+
+ [root@rgf9dev sample]# certtool --generate-privkey --outfile ca-key.pem --bits 2048
+ Generating a 2048 bit RSA private key...
+ [root@rgf9dev sample]# certtool --generate-self-signed --load-privkey ca-key.pem --outfile ca.pem
+ Generating a self signed certificate...
+ Please enter the details of the certificate's distinguished name. Just press enter to ignore a field.
+ Country name (2 chars): US
+ Organization name: SomeOrg
+ Organizational unit name: SomeOU
+ Locality name: Somewhere
+ State or province name: CA
+ Common name: someName (not necessarily DNS!)
+ UID:
+ This field should not be used in new certificates.
+ E-mail:
+ Enter the certificate's serial number (decimal):
+
+
+ Activation/Expiration time.
+ The certificate will expire in (days): 3650
+
+
+ Extensions.
+ Does the certificate belong to an authority? (Y/N): y
+ Path length constraint (decimal, -1 for no constraint):
+ Is this a TLS web client certificate? (Y/N):
+ Is this also a TLS web server certificate? (Y/N):
+ Enter the e-mail of the subject of the certificate: someone@example.net
+ Will the certificate be used to sign other certificates? (Y/N): y
+ Will the certificate be used to sign CRLs? (Y/N):
+ Will the certificate be used to sign code? (Y/N):
+ Will the certificate be used to sign OCSP requests? (Y/N):
+ Will the certificate be used for time stamping? (Y/N):
+ Enter the URI of the CRL distribution point:
+ X.509 Certificate Information:
+ Version: 3
+ Serial Number (hex): 485a365e
+ Validity:
+ Not Before: Thu Jun 19 10:35:12 UTC 2008
+ Not After: Sun Jun 17 10:35:25 UTC 2018
+ Subject: C=US,O=SomeOrg,OU=SomeOU,L=Somewhere,ST=CA,CN=someName (not necessarily DNS!)
+ Subject Public Key Algorithm: RSA
+ Modulus (bits 2048):
+ d9:9c:82:46:24:7f:34:8f:60:cf:05:77:71:82:61:66
+ 05:13:28:06:7a:70:41:bf:32:85:12:5c:25:a7:1a:5a
+ 28:11:02:1a:78:c1:da:34:ee:b4:7e:12:9b:81:24:70
+ ff:e4:89:88:ca:05:30:0a:3f:d7:58:0b:38:24:a9:b7
+ 2e:a2:b6:8a:1d:60:53:2f:ec:e9:38:36:3b:9b:77:93
+ 5d:64:76:31:07:30:a5:31:0c:e2:ec:e3:8d:5d:13:01
+ 11:3d:0b:5e:3c:4a:32:d8:f3:b3:56:22:32:cb:de:7d
+ 64:9a:2b:91:d9:f0:0b:82:c1:29:d4:15:2c:41:0b:97
+ Exponent:
+ 01:00:01
+ Extensions:
+ Basic Constraints (critical):
+ Certificate Authority (CA): TRUE
+ Subject Alternative Name (not critical):
+ RFC822name: someone@example.net
+ Key Usage (critical):
+ Certificate signing.
+ Subject Key Identifier (not critical):
+ fbfe968d10a73ae5b70d7b434886c8f872997b89
+ Other Information:
+ Public Key Id:
+ fbfe968d10a73ae5b70d7b434886c8f872997b89
+
+ Is the above information ok? (Y/N): y
+
+
+ Signing certificate...
+ [root@rgf9dev sample]# chmod 400 ca-key.pem
+ [root@rgf9dev sample]# ls -l
+ total 8
+ -r-------- 1 root root 887 2008-06-19 12:33 ca-key.pem
+ -rw-r--r-- 1 root root 1029 2008-06-19 12:36 ca.pem
+ [root@rgf9dev sample]#
+
+**Be sure to safeguard ca-key.pem!** Nobody except the CA itself needs
+to have it. If some third party obtains it, you security is broken!
diff --git a/source/tutorials/tls_cert_client.rst b/source/tutorials/tls_cert_client.rst
new file mode 100644
index 0000000..6361ef0
--- /dev/null
+++ b/source/tutorials/tls_cert_client.rst
@@ -0,0 +1,74 @@
+Setting up a client
+===================
+
+In this step, we configure a client machine. We from our scenario, we
+use zuse.example.net. You need to do the same steps for all other
+clients, too (in the example, that means turing.example.net). The client
+check's the server's identity and talks to it only if it is the expected
+server. This is a very important step. Without it, you would not detect
+man-in-the-middle attacks or simple malicious servers who try to get
+hold of your valuable log data.
+
+.. figure:: tls_cert_100.jpg
+ :align: center
+ :alt:
+
+Steps to do:
+
+- make sure you have a functional CA (`Setting up the
+ CA <tls_cert_ca.html>`_)
+- generate a machine certificate for zuse.example.net (follow
+ instructions in `Generating Machine
+ Certificates <tls_cert_machine.html>`_)
+- make sure you copy over ca.pem, machine-key.pem ad machine-cert.pem
+ to the client. Ensure that no user except root can access them
+ (**even read permissions are really bad**).
+- configure the client so that it checks the server identity and sends
+ messages only if the server identity is known. Please note that you
+ have the same options as when configuring a server. However, we now
+ use a single name only, because there is only one central server. No
+ using wildcards make sure that we will exclusively talk to that
+ server (otherwise, a compromised client may take over its role). If
+ you load-balance to different server identities, you obviously need to
+ allow all of them. It still is suggested to use explicit names.
+
+**At this point, please be reminded once again that your security needs
+may be quite different from what we assume in this tutorial. Evaluate
+your options based on your security needs.**
+
+Sample syslog.conf
+~~~~~~~~~~~~~~~~~~
+
+Keep in mind that this rsyslog.conf sends messages via TCP, only. Also,
+we do not show any rules to write local files. Feel free to add them.
+
+::
+
+ # make gtls driver the default and set certificate files
+ global(
+ DefaultNetstreamDriver="gtls"
+ DefaultNetstreamDriverCAFile="/path/to/contrib/gnutls/ca.pem"
+ DefaultNetstreamDriverCertFile="/path/to/contrib/gnutls/cert.pem"
+ DefaultNetstreamDriverKeyFile="/path/to/contrib/gnutls/key.pem"
+ )
+
+ # set up the action for all messages
+ action(
+ type="omfwd"
+ target="central.example.net"
+ protocol="tcp"
+ port="6514"
+ StreamDriver="gtls"
+ StreamDriverMode="1" # run driver in TLS-only mode
+ StreamDriverAuthMode="x509/name"
+ StreamDriverPermittedPeers="central.example.net"
+ )
+
+Note: the example above forwards every message to the remote server. Of
+course, you can use the normal filters to restrict the set of
+information that is sent. Depending on your message volume and needs,
+this may be a smart thing to do.
+
+**Be sure to safeguard at least the private key (machine-key.pem)!** If
+some third party obtains it, you security is broken!
+
diff --git a/source/tutorials/tls_cert_errmsgs.rst b/source/tutorials/tls_cert_errmsgs.rst
new file mode 100644
index 0000000..ff9d9f6
--- /dev/null
+++ b/source/tutorials/tls_cert_errmsgs.rst
@@ -0,0 +1,111 @@
+Error Messages
+==============
+
+This page covers error message you may see when setting up
+`rsyslog <http://www.rsyslog.com>`_ with TLS. Please note that many of
+the message stem back to the TLS library being used. In those cases,
+there is not always a good explanation available in rsyslog alone.
+
+A single error typically results in two or more message being emitted:
+(at least) one is the actual error cause, followed by usually one
+message with additional information (like certificate contents). In a
+typical system, these message should immediately follow each other in
+your log. Keep in mind that they are reported as syslog.err, so you need
+to capture these to actually see errors (the default rsyslog.conf's
+shipped by many systems will do that, recording them e.g. in
+/etc/messages).
+
+certificate invalid
+-------------------
+
+Sample:
+
+::
+
+ not permitted to talk to peer, certificate invalid: insecure algorithm
+
+This message may occur during connection setup. It indicates that the
+remote peer's certificate can not be accepted. The reason for this is
+given in the message part that is shown in red. Please note that this
+red part directly stems back to the TLS library, so rsyslog does
+actually not have any more information about the reason.
+
+With GnuTLS, the following reasons have been seen in practice:
+
+insecure algorithm
+^^^^^^^^^^^^^^^^^^
+
+The certificate contains information on which encryption algorithms are
+to be used. This information is entered when the certificate is created.
+Some older algorithms are no longer secure and the TLS library does not
+accept them. Thus the connection request failed. The cure is to use a
+certificate with sufficiently secure algorithms.
+
+Please note that no encryption algorithm is totally secure. It only is
+secure based on our current knowledge AND on computing power available.
+As computers get more and more powerful, previously secure algorithms
+become insecure over time. As such, algorithms considered secure today
+may not be accepted by the TLS library in the future.
+
+So in theory, after a system upgrade, a connection request may fail with
+the "insecure algorithm" failure without any change in rsyslog
+configuration or certificates. This could be caused by a new perception
+of the TLS library of what is secure and what not.
+
+GnuTLS error -64
+----------------
+
+Sample:
+
+::
+
+ unexpected GnuTLS error -64 in nsd_gtls.c:517: Error while reading file.
+
+This error points to an encoding error with the pem file in question.
+It means "base 64 encoding error". From my experience, it can be caused
+by a couple of things, some of them not obvious:
+
+- You specified a wrong file, which is not actually in .pem format
+- The file was incorrectly generated
+- I think I have also seen this when I accidentally swapped private key
+ files and certificate files. So double-check the type of file you are
+ using.
+- It may even be a result of an access (permission) problem. In theory,
+ that should lead to another error, but in practice it sometimes seems
+ to lead to this -64 error.
+
+info on invalid cert
+--------------------
+
+Sample:
+
+::
+
+ info on invalid cert: peer provided 1 certificate(s). Certificate 1 info: certificate valid from Wed Jun 18 11:45:44 2008 to Sat Jun 16 11:45:53 2018; Certificate public key: RSA; DN: C=US,O=Sample Corp,OU=Certs,L=Somewhere,ST=CA,CN=somename; Issuer DN: C=US,O=Sample Corp,OU=Certs,L=Somewhere,ST=CA,CN=somename,EMAIL=xxx@example.com; SAN:DNSname: machine.example.net;
+
+This is **not** an error message in itself. It always follows the actual
+error message and tells you what is seen in the peer's certificate. This
+is done to give you a chance to evaluate the certificate and better
+understand why the initial error message was issued.
+
+Please note that you can NOT diagnose problems based on this message
+alone. It follows in a number of error cases and does not pinpoint any
+problems by itself.
+
+invalid peer name
+-----------------
+
+Sample:
+
+::
+
+ # sender error
+ error: peer name not authorized - not permitted to talk to it. Names: DNSname: syslog.example.com; CN: syslog.example.com;
+
+ # receiver error
+ unexpected GnuTLS error -110 in nsd_gtls.c:536: The TLS connection was non-properly terminated.
+ netstream session 0x7fee240ef650 from X.X.X.X will be closed due to error
+
+This error is caused by the Subject Alternative Name or Common Name on the receivers certificate not matching any StreamDriverPermittedPeers (RainerScript) / $ActionSendStreamDriverPermittedPeers (Legacy Rsyslog). Either we need to update this parameter with the correct domain name / appropriate wildcard or change the AuthMode of the Stream Driver to be less strict (be sure to carefully read the documentation and understand the implications before taking this route).
+
+The receiver error is fairly generic and comes from the upstream GnuTLS library, because the sender has decided it's not authorized to talk to the remote peer over TLS it tears down the connection before any records are sent, this is treated as a premature termination by the library and it returns the given error.
diff --git a/source/tutorials/tls_cert_machine.rst b/source/tutorials/tls_cert_machine.rst
new file mode 100644
index 0000000..e04d171
--- /dev/null
+++ b/source/tutorials/tls_cert_machine.rst
@@ -0,0 +1,164 @@
+Generating the machine certificate
+==================================
+
+In this step, we generate certificates for each of the machines. Please
+note that both clients and servers need certificates. The certificate
+identifies each machine to the remote peer. The DNSName specified inside
+the certificate can
+
+be specified inside the $<object>PermittedPeer config statements.
+
+For now, we assume that a single person (or group) is responsible for
+the whole rsyslog system and thus it is OK if that single person is in
+possession of all machine's private keys. This simplification permits us
+to use a somewhat less complicated way of generating the machine
+certificates. So, we generate both the private and public key on the CA
+(which is NOT a server!) and then copy them over to the respective
+machines.
+
+If the roles of machine and CA administrators are split, the private key
+must be generated by the machine administrator. This is done via a
+certificate request. This request is then sent to the CA admin, which in
+turn generates the certificate (containing the public key). The CA admin
+then sends back the certificate to the machine admin, who installs it.
+That way, the CA admin never gets hold of the machine's private key.
+Instructions for this mode will be given in a later revision of this
+document.
+
+**In any case, it is vital that the machine's private key is protected.
+Anybody able to obtain that private key can impersonate as the machine
+to which it belongs, thus breaching your security.**
+
+Sample Screen Session
+~~~~~~~~~~~~~~~~~~~~~
+
+Text in red is user input. Please note that for some questions, there is
+no user input given. This means the default was accepted by simply
+pressing the enter key.
+
+**Please note:** you need to substitute the names specified below with
+values that match your environment. Most importantly,
+machine.example.net must be replaced by the actual name of the machine
+that will be using this certificate. For example, if you generate a
+certificate for a machine named "server.example.com", you need to use
+that name. If you generate a certificate for "client.example.com", you
+need to use this name. Make sure that each machine certificate has a
+unique name. If not, you can not apply proper access control.
+
+::
+
+ [root@rgf9dev sample]# certtool --generate-privkey --outfile key.pem --bits 2048
+ Generating a 2048 bit RSA private key...
+ [root@rgf9dev sample]# certtool --generate-request --load-privkey key.pem --outfile request.pem
+ Generating a PKCS #10 certificate request...
+ Country name (2 chars): US
+ Organization name: SomeOrg
+ Organizational unit name: SomeOU
+ Locality name: Somewhere
+ State or province name: CA
+ Common name: machine.example.net
+ UID:
+ Enter a dnsName of the subject of the certificate:
+ Enter the IP address of the subject of the certificate:
+ Enter the e-mail of the subject of the certificate:
+ Enter a challenge password:
+ Does the certificate belong to an authority? (y/N): n
+ Will the certificate be used for signing (DHE and RSA-EXPORT ciphersuites)? (y/N):
+ Will the certificate be used for encryption (RSA ciphersuites)? (y/N):
+ Is this a TLS web client certificate? (y/N): y
+ Is this also a TLS web server certificate? (y/N): y
+ [root@rgf9dev sample]# certtool --generate-certificate --load-request request.pem --outfile cert.pem --load-ca-certificate ca.pem --load-ca-privkey ca-key.pem
+ Generating a signed certificate...
+ Enter the certificate's serial number (decimal):
+
+
+ Activation/Expiration time.
+ The certificate will expire in (days): 1000
+
+
+ Extensions.
+ Do you want to honour the extensions from the request? (y/N):
+ Does the certificate belong to an authority? (Y/N): n
+ Will the certificate be used for IPsec IKE operations? (y/N):
+ Is this a TLS web client certificate? (Y/N): y
+ Is this also a TLS web server certificate? (Y/N): y
+ Enter the dnsName of the subject of the certificate: machine.example.net {This is the name of the machine that will use the certificate}
+ Enter the IP address of the subject of certificate:
+ Will the certificate be used for signing (DHE and RSA-EXPORT ciphersuites)? (Y/N):
+ Will the certificate be used for encryption (RSA ciphersuites)? (Y/N):
+ X.509 Certificate Information:
+ Version: 3
+ Serial Number (hex): 485a3819
+ Validity:
+ Not Before: Thu Jun 19 10:42:54 UTC 2008
+ Not After: Wed Mar 16 10:42:57 UTC 2011
+ Subject: C=US,O=SomeOrg,OU=SomeOU,L=Somewhere,ST=CA,CN=machine.example.net
+ Subject Public Key Algorithm: RSA
+ Modulus (bits 2048):
+ b2:4e:5b:a9:48:1e:ff:2e:73:a1:33:ee:d8:a2:af:ae
+ 2f:23:76:91:b8:39:94:00:23:f2:6f:25:ad:c9:6a:ab
+ 2d:e6:f3:62:d8:3e:6e:8a:d6:1e:3f:72:e5:d8:b9:e0
+ d0:79:c2:94:21:65:0b:10:53:66:b0:36:a6:a7:cd:46
+ 1e:2c:6a:9b:79:c6:ee:c6:e2:ed:b0:a9:59:e2:49:da
+ c7:e3:f0:1c:e0:53:98:87:0d:d5:28:db:a4:82:36:ed
+ 3a:1e:d1:5c:07:13:95:5d:b3:28:05:17:2a:2b:b6:8e
+ 8e:78:d2:cf:ac:87:13:15:fc:17:43:6b:15:c3:7d:b9
+ Exponent:
+ 01:00:01
+ Extensions:
+ Basic Constraints (critical):
+ Certificate Authority (CA): FALSE
+ Key Purpose (not critical):
+ TLS WWW Client.
+ TLS WWW Server.
+ Subject Alternative Name (not critical):
+ DNSname: machine.example.net
+ Subject Key Identifier (not critical):
+ 0ce1c3dbd19d31fa035b07afe2e0ef22d90b28ac
+ Authority Key Identifier (not critical):
+ fbfe968d10a73ae5b70d7b434886c8f872997b89
+ Other Information:
+ Public Key Id:
+ 0ce1c3dbd19d31fa035b07afe2e0ef22d90b28ac
+
+ Is the above information ok? (Y/N): y
+
+
+ Signing certificate...
+ [root@rgf9dev sample]# rm -f request.pem
+ [root@rgf9dev sample]# ls -l
+ total 16
+ -r-------- 1 root root 887 2008-06-19 12:33 ca-key.pem
+ -rw-r--r-- 1 root root 1029 2008-06-19 12:36 ca.pem
+ -rw-r--r-- 1 root root 1074 2008-06-19 12:43 cert.pem
+ -rw-r--r-- 1 root root 887 2008-06-19 12:40 key.pem
+ [root@rgf9dev sample]# # it may be a good idea to rename the files to indicate where they belong to
+ [root@rgf9dev sample]# mv cert.pem machine-cert.pem
+ [root@rgf9dev sample]# mv key.pem machine-key.pem
+ [root@rgf9dev sample]#
+
+Distributing Files
+~~~~~~~~~~~~~~~~~~
+
+Provide the machine with:
+
+- a copy of ca.pem
+- cert.pem
+- key.pem
+
+This is how the relevant part of rsyslog.conf looks on the target
+machine:
+
+````
+
+::
+
+ global(
+ DefaultNetstreamDriver="gtls"
+ DefaultNetstreamDriverCAFile="/path/to/contrib/gnutls/ca.pem"
+ DefaultNetstreamDriverCertFile="/path/to/contrib/gnutls/cert.pem"
+ DefaultNetstreamDriverKeyFile="/path/to/contrib/gnutls/key.pem"
+ )
+
+**Never provide anyone with ca-key.pem!** Also, make sure nobody but the
+machine in question gets hold of key.pem.
diff --git a/source/tutorials/tls_cert_scenario.rst b/source/tutorials/tls_cert_scenario.rst
new file mode 100644
index 0000000..86a5442
--- /dev/null
+++ b/source/tutorials/tls_cert_scenario.rst
@@ -0,0 +1,26 @@
+Sample Use Case: Single Central Log Server
+==========================================
+
+We have a quite simple use case. There is one central syslog server,
+named central.example.net. These server is being reported to by two
+Linux machines with name zuse.example.net and turing.example.net. Also,
+there is a third client - ada.example.net - which send both its own
+messages to the central server but also forwards messages receive from
+an UDP-only capable router. We have decided to use ada.example.net
+because it is in the same local network segment as the router and so we
+enjoy TLS' security benefits for forwarding the router messages inside
+the corporate network. All systems (except the router) use
+`rsyslog <http://www.rsyslog.com/>`_ as the syslog software.
+
+.. figure:: tls_cert_100.jpg
+ :align: center
+ :alt:
+
+Please note that the CA must not necessarily be connected to the rest of
+the network. Actually, it may be considered a security plus if it is
+not. If the CA is reachable via the regular network, it should be
+sufficiently secured (firewall rules et al). Keep in mind that if the
+CA's security is breached, your overall system security is breached.
+
+In case the CA is compromised, you need to regenerate the CA's
+certificate as well as all individual machines certificates.
diff --git a/source/tutorials/tls_cert_script.rst b/source/tutorials/tls_cert_script.rst
new file mode 100644
index 0000000..e3add83
--- /dev/null
+++ b/source/tutorials/tls_cert_script.rst
@@ -0,0 +1,159 @@
+Creating certificates with a script
+===================================
+
+*Written by* `Florian Riedl <https://www.adiscon.com>`_
+*(2019-09-12)*
+
+
+Overview
+--------
+
+This small article describes is a quick addon to the TLS guides. It describes
+in short words, how you can create some quick and dirty certificates for
+testing.
+
+**Disclaimer**: When creating certificates with the attached scripts and more or
+less default configurations, you cannot create secure certificates. You need to
+use more detailed configuration files to create secure certificates.
+
+
+Description
+-----------
+
+We created a few simple scripts and added configuration files from the sample
+configuration in the certtool man page. You can download them here:
+:download:`Download Scripts <cert-script.tar.gz>`.
+
+The tarball contains 6 files, 3 scripts and 3 configurations. To execute, you
+must make the scripts executable and have certtool installed via libgnutls.
+
+- Script 1 creates the CA key and certificate as outlined in `Setting up the CA
+ <tls_cert_ca.html>`_
+
+- Script 2 creates the `machine key and certificate <tls_cert_machine.html>`_ for
+ a client.
+
+- Script 3 creates the machine key and certificate for a server.
+
+These scripts can easily be combined into one. But, we decided to go for
+separate scripts so each step can be repeated separately if needed.
+
+After the scripts are executed, you should have 2 new files per script.
+Distribute the files to the machines as described before.
+
+
+Example
+-------
+
+Apart from executing the scripts, no extra input is required. All input from
+manual certificate creating can be done automatically via the configuration
+template in the cfg files.
+
+Sample output for the CA certificate generation.
+::
+
+ test@ubuntu:~/Documents$ ./1-generate-ca.sh
+ ** Note: Please use the --sec-param instead of --bits
+ Generating a 2048 bit RSA private key...
+ Generating a self signed certificate...
+ X.509 Certificate Information:
+ Version: 3
+ Serial Number (hex): 5d7a6351
+ Validity:
+ Not Before: Thu Sep 12 15:25:05 UTC 2019
+ Not After: Sun Sep 09 15:25:05 UTC 2029
+ Subject: C=US,O=Example,OU=Example,CN=CA-Cert
+ Subject Public Key Algorithm: RSA
+ Certificate Security Level: Low
+ Modulus (bits 2048):
+ 00:95:28:40:b6:4d:60:7c:cf:72:1d:17:36:b5:f1:11
+ 0d:42:05:e9:38:c7:6e:95:d9:42:02:c5:4b:f2:9d:e2
+ c8:31:ac:18:ae:55:f7:e0:4c:dd:6d:72:32:01:fa:1d
+ da:a1:3d:ad:c9:13:0a:68:3e:bc:40:6a:1e:f2:f7:65
+ f0:e9:64:fa:84:8b:96:15:b5:10:f3:99:29:14:ee:fc
+ 88:8d:41:29:8e:c7:9b:23:df:8b:a3:79:28:56:ed:27
+ 66:a4:9a:fa:75:47:67:0a:e2:f4:35:98:e8:9e:ad:35
+ c2:b2:17:8b:98:72:c4:30:58:fd:13:b6:f4:01:d0:66
+ 56:be:61:85:55:dc:91:b6:4e:0a:3f:d4:3f:40:fa:a8
+ 92:5e:c5:dd:75:da:c3:27:33:59:43:47:74:fe:d2:28
+ 14:49:62:ee:39:22:34:6b:2f:e8:d1:ba:e9:95:6d:29
+ d2:6f:8a:a2:fc:c8:da:f0:47:78:3b:2c:03:dc:fb:43
+ 31:9e:a1:cb:11:18:b9:0b:31:d3:86:43:68:f8:c4:bd
+ ab:90:13:33:75:e9:b5:ca:74:c3:83:98:e9:91:3d:39
+ fb:65:43:77:0b:b2:bc:3b:33:c2:91:7e:db:c3:a2:a1
+ 80:0b:a0:ce:cb:34:29:8b:24:52:25:aa:eb:bd:40:34
+ cb
+ Exponent (bits 24):
+ 01:00:01
+ Extensions:
+ Basic Constraints (critical):
+ Certificate Authority (CA): TRUE
+ Key Usage (critical):
+ Certificate signing.
+ Subject Key Identifier (not critical):
+ 6bbe9a650dbcaf5103c78daf8a2604d76a749f42
+ Other Information:
+ Public Key Id:
+ 6bbe9a650dbcaf5103c78daf8a2604d76a749f42
+
+
+
+ Signing certificate...
+
+Sample output for the machine certificate generation.
+::
+
+ test@ubuntu:~/Documents$ ./2-generate-client.sh
+ ** Note: Please use the --sec-param instead of --bits
+ Generating a 2048 bit RSA private key...
+ Generating a PKCS #10 certificate request...
+ Generating a signed certificate...
+ X.509 Certificate Information:
+ Version: 3
+ Serial Number (hex): 5d7a6402
+ Validity:
+ Not Before: Thu Sep 12 15:28:02 UTC 2019
+ Not After: Sun Sep 09 15:28:02 UTC 2029
+ Subject: C=US,O=Example,OU=Example,CN=Test Client
+ Subject Public Key Algorithm: RSA
+ Certificate Security Level: Low
+ Modulus (bits 2048):
+ 00:bd:7f:0b:20:2e:fe:f1:49:91:71:fa:f1:72:76:6b
+ c0:96:ce:e0:85:80:a3:6a:d2:9e:07:dd:02:94:4f:df
+ c8:34:13:7d:d1:8f:b8:1b:1f:cf:b8:b7:ae:2f:dd:9a
+ da:52:6e:a3:f4:73:20:63:32:46:c2:e1:94:73:6b:cd
+ b4:e4:82:46:25:b0:62:f9:12:28:4f:4f:76:23:5c:47
+ 1b:f9:61:cd:68:c1:c1:17:93:90:3c:d2:2b:6e:82:c2
+ a3:ca:80:b7:89:6e:b6:16:ae:47:05:e5:b4:07:bf:75
+ d9:bd:aa:fe:79:77:72:6e:af:ed:5b:97:d1:e0:00:ba
+ ab:6f:9e:1f:a6:d4:95:d7:d3:39:88:9b:58:88:28:a0
+ 7e:b6:fe:07:7e:68:ad:a1:d0:23:12:3d:96:b2:a8:8e
+ 73:66:c0:4f:10:a0:e5:9e:ab:2a:37:1d:83:b1:c3:e5
+ 7c:35:cc:20:05:7c:7e:41:89:f1:b3:6b:e4:00:f2:bc
+ 0b:08:55:07:b3:67:e4:14:1c:3c:64:1b:92:2d:d7:f0
+ f7:d4:dc:d7:63:1e:fd:e4:98:bc:6b:f1:1a:a9:af:05
+ 7a:94:52:f5:b5:36:f0:0c:c0:41:0a:39:b7:fb:b3:50
+ c1:ce:ee:24:56:61:77:9d:9e:e1:d0:e1:39:f0:cc:b6
+ 29
+ Exponent (bits 24):
+ 01:00:01
+ Extensions:
+ Basic Constraints (critical):
+ Certificate Authority (CA): FALSE
+ Key Purpose (not critical):
+ TLS WWW Client.
+ TLS WWW Server.
+ Subject Key Identifier (not critical):
+ 5a1a7316c4594cafafbeb45ddb49623af3a9f231
+ Authority Key Identifier (not critical):
+ 6bbe9a650dbcaf5103c78daf8a2604d76a749f42
+ Other Information:
+ Public Key Id:
+ 5a1a7316c4594cafafbeb45ddb49623af3a9f231
+
+
+
+ Signing certificate...
+
+**Be sure to safeguard ca-key.pem!** Nobody except the CA itself needs
+to have it. If some third party obtains it, you security is broken!
diff --git a/source/tutorials/tls_cert_server.rst b/source/tutorials/tls_cert_server.rst
new file mode 100644
index 0000000..8ca57d6
--- /dev/null
+++ b/source/tutorials/tls_cert_server.rst
@@ -0,0 +1,115 @@
+Setting up the Central Server
+=============================
+
+In this step, we configure the central server. We assume it accepts
+messages only via TLS protected plain tcp based syslog from those peers
+that are explicitly permitted to send to it. The picture below show our
+configuration. This step configures the server central.example.net.
+
+.. figure:: tls_cert_100.jpg
+ :align: center
+ :alt:
+
+**Important:** *Keep in mind that the order of configuration directives
+is very important in rsyslog. As such, the samples given below do only
+work if the given order is preserved. Re-ordering the directives can
+break configurations and has broken them in practice. If you intend to
+re-order them, please be sure that you fully understand how the
+configuration language works and, most importantly, which statements
+form a block together. Please also note that we understand the
+current configuration file format is ugly. However, there has been more
+important work in the way of enhancing it. If you would like to
+contribute some time to improve the config file language, please let us
+know. Any help is appreciated (be it doc or coding work!).*
+
+Steps to do:
+
+- make sure you have a functional CA (`Setting up the
+ CA <tls_cert_ca.html>`_)
+- generate a machine certificate for central.example.net (follow
+ instructions in `Generating Machine
+ Certificates <tls_cert_machine.html>`_)
+- make sure you copy over ca.pem, machine-key.pem ad machine-cert.pem
+ to the central server. Ensure that no user except root can access
+ them (**even read permissions are really bad**).
+- configure the server so that it accepts messages from all machines in
+ the example.net domain that have certificates from your CA.
+ Alternatively, you may also precisely define from which machine names
+ messages are accepted. See sample rsyslog.conf below.
+
+In this setup, we use wildcards to ease adding new systems. We permit
+the server to accept messages from systems whose names match
+\*.example.net.
+
+::
+
+ PermittedPeer["*.example.net"]
+
+This will match zuse.example.net and turing.example.net, but NOT
+pascal.otherdepartment.example.net. If the later would be desired, you
+can (and need) to include additional permitted peer config statements:
+
+::
+
+ PermittedPeer["*.example.net","*.otherdepartment.example.net","*.example.com"]
+
+As can be seen with example.com, the different permitted peers need NOT
+to be in a single domain tree. Also, individual machines can be
+configured. For example, if only zuse, turing and ada should be able to
+talk to the server, you can achieve this by:
+
+::
+
+ PermittedPeer["zuse.example.net","turing.example.net","ada.example.net"]
+
+As an extension to the (upcoming) IETF syslog/tls standard, you can
+specify some text together with a domain component wildcard. So
+"\*server.example.net", "server\*.example.net" are valid permitted
+peers. However "server\*Fix.example.net" is NOT a valid wildcard. The
+IETF standard permits no text along the wildcards.
+
+The reason we use wildcards in the default setup is that it makes it
+easy to add systems without the need to change the central server's
+configuration. It is important to understand that the central server
+will accept names **only** (no exception) if the client certificate was
+signed by the CA we set up. So if someone tries to create a malicious
+certificate with a name "zuse.example.net", the server will **not**
+accept it. So a wildcard is safe as long as you ensure CA security is
+not breached. Actually, you authorize a client by issuing the
+certificate to it.
+
+**At this point, please be reminded once again that your security needs
+may be quite different from what we assume in this tutorial. Evaluate
+your options based on your security needs.**
+
+Sample syslog.conf
+~~~~~~~~~~~~~~~~~~
+
+Keep in mind that this rsyslog.conf accepts messages via TCP, only. The
+only other source accepted is messages from the server itself.
+
+::
+
+ module(load="imuxsock") # local messages
+ module(load="imtcp" # TCP listener
+ StreamDriver.Name="gtls"
+ StreamDriver.Mode="1" # run driver in TLS-only mode
+ StreamDriver.Authmode="anon"
+ )
+
+ # make gtls driver the default and set certificate files
+ global(
+ DefaultNetstreamDriver="gtls"
+ DefaultNetstreamDriverCAFile="/path/to/contrib/gnutls/ca.pem"
+ DefaultNetstreamDriverCertFile="/path/to/contrib/gnutls/cert.pem"
+ DefaultNetstreamDriverKeyFile="/path/to/contrib/gnutls/key.pem"
+ )
+
+ # start up listener at port 6514
+ input(
+ type="imtcp"
+ port="6514"
+ )
+
+**Be sure to safeguard at least the private key (machine-key.pem)!** If
+some third party obtains it, you security is broken!
diff --git a/source/tutorials/tls_cert_summary.rst b/source/tutorials/tls_cert_summary.rst
new file mode 100644
index 0000000..52dae6d
--- /dev/null
+++ b/source/tutorials/tls_cert_summary.rst
@@ -0,0 +1,143 @@
+Encrypting Syslog Traffic with TLS (SSL)
+========================================
+
+Written by `Rainer Gerhards <https://rainer.gerhards.net>`_ (2008-07-03)
+
+.. toctree::
+ :maxdepth: 1
+
+ tls_cert_scenario
+ tls_cert_ca
+ tls_cert_machine
+ tls_cert_server
+ tls_cert_client
+ tls_cert_udp_relay
+ tls_cert_errmsgs
+ tls_cert_script
+
+Overview
+--------
+
+This document describes a secure way to set up rsyslog TLS. A secure
+logging environment requires more than just encrypting the transmission
+channel. This document provides one possible way to create such a secure
+system.
+
+Rsyslog's TLS authentication can be used very flexible and thus supports
+a wide range of security policies. This section tries to give some
+advise on a scenario that works well for many environments. However, it
+may not be suitable for you - please assess you security needs before
+using the recommendations below. Do not blame us if it doesn't provide
+what you need ;)
+
+Our policy offers these security benefits:
+
+- syslog messages are encrypted while traveling on the wire
+- the syslog sender authenticates to the syslog receiver; thus, the
+ receiver knows who is talking to it
+- the syslog receiver authenticates to the syslog sender; thus, the
+ sender can check if it indeed is sending to the expected receiver
+- the mutual authentication prevents man-in-the-middle attacks
+
+Our security goals are achieved via public/private key security. As such,
+it is vital that private keys are well protected and not accessible to
+third parties.
+
+If private keys have become known to third parties, the system does not
+provide any security at all. Also, our solution bases on X.509
+certificates and a (very limited) chain of trust. We have one instance
+(the CA) that issues all machine certificates. The machine certificate
+identifies a particular machine. While in theory (and practice), there
+could be several "sub-CA" that issues machine certificates for a
+specific administrative domain, we do not include this in our "simple yet
+secure" setup. If you intend to use this, rsyslog supports it, but then
+you need to dig a bit more into the documentation (or use the forum to
+ask). In general, if you depart from our simple model, you should have
+good reasons for doing so and know quite well what you are doing -
+otherwise you may compromise your system security.
+
+Please note that security never comes without effort. In the scenario
+described here, we have limited the effort as much as possible. What
+remains is some setup work for the central CA, the certificate setup for
+each machine as well as a few configuration commands that need to be
+applied to all of them. Probably the most important limiting factor in
+our setup is that all senders and receivers must support IETF's
+syslog-transport-tls standard (which is not finalized yet). We use
+mandatory-to-implement technology, yet you may have trouble finding all
+required features in some implementations. More often, unfortunately,
+you will find that an implementation does not support the upcoming IETF
+standard at all - especially in the "early days" (starting May 2008)
+when rsyslog is the only implementation of said standard.
+
+Fortunately, rsyslog supports almost every protocol that is out there
+in the syslog world. So in cases where transport-tls is not available on
+a sender, we recommend to use rsyslog as the initial relay. In that
+mode, the not-capable sender sends to rsyslog via another protocol, which
+then relays the message via transport-tls to either another interim
+relay or the final destination (which, of course, must by transport-tls
+capable). In such a scenario, it is best to try see what the sender
+support. Maybe it is possible to use industry-standard plain tcp syslog
+with it. Often you can even combine it with stunnel, which then, too,
+enables a secure delivery to the first rsyslog relay. If all of that is
+not possible, you can (and often must...) resort to UDP. Even though
+this is now lossy and insecure, this is better than not having the
+ability to listen to that device at all. It may even be reasonable secure
+if the uncapable sender and the first rsyslog relay communicate via a
+private channel, e.g. a dedicated network link.
+
+One final word of caution: transport-tls protects the connection between
+the sender and the receiver. It does not necessarily protect against
+attacks that are present in the message itself. Especially in a relay
+environment, the message may have been originated from a malicious
+system, which placed invalid hostnames and/or other content into it. If
+there is no provisioning against such things, these records may show up
+in the receivers' repository. -transport-tls does not protect against
+this (but it may help, properly used). Keep in mind that
+syslog-transport-tls provides hop-by-hop security. It does not provide
+end-to-end security and it does not authenticate the message itself
+(just the last sender).
+
+If you'd like to get all information very rapidly, the graphic below
+contains everything you need to know (from the certificate perspective)
+in a very condensed manner. It is no surprise if the graphic puzzles
+you. In this case, `simply read on <tls_cert_scenario.html>`_ for full
+instructions.
+
+.. figure:: tls_cert.jpg
+ :align: center
+ :alt: TLS/SSL protected syslog
+
+Summary
+~~~~~~~
+
+If you followed the steps outlined in this documentation set, you now
+have
+
+a reasonable (for most needs) secure setup for the following
+environment:
+
+.. figure:: tls_cert_100.jpg
+ :align: center
+ :alt:
+
+You have learned about the security decisions involved and which we made
+in this example. **Be once again reminded that you must make sure
+yourself that whatever you do matches your security needs!** There is no
+guarantee that what we generally find useful actually is. It may even be
+totally unsuitable for your environment.
+
+In the example, we created a rsyslog certificate authority (CA). Guard
+the CA's files. You need them whenever you need to create a new machine
+certificate. We also saw how to generate the machine certificates
+themselves and distribute them to the individual machines. Also, you have
+found some configuration samples for a server, a client and a syslog
+relay. Hopefully, this will enable you to set up a similar system in
+many environments.
+
+Please be warned that you defined some expiration dates for the
+certificates. After they are reached, the certificates are no longer
+valid and rsyslog will NOT accept them. At that point, syslog messages
+will no longer be transmitted (and rsyslogd will heavily begin to
+complain). So it is a good idea to make sure that you renew the
+certificates before they expire. Recording a reminder somewhere is
+probably a good idea.
diff --git a/source/tutorials/tls_cert_udp_relay.rst b/source/tutorials/tls_cert_udp_relay.rst
new file mode 100644
index 0000000..f0377a8
--- /dev/null
+++ b/source/tutorials/tls_cert_udp_relay.rst
@@ -0,0 +1,89 @@
+Setting up the UDP syslog relay
+===============================
+
+In this step, we configure the UDP relay ada.example.net. As a reminder,
+that machine relays messages from a local router, which only supports
+UDP syslog, to the central syslog server. The router does not talk
+directly to it, because we would like to have TLS protection for its
+sensitive logs. If the router and the syslog relay are on a sufficiently
+secure private network, this setup can be considered reasonable secure.
+In any case, it is the best alternative among the possible configuration
+scenarios.
+
+.. figure:: tls_cert_100.jpg
+ :align: center
+ :alt:
+
+Steps to do:
+
+- make sure you have a functional CA (`Setting up the
+ CA <tls_cert_ca.html>`_)
+- generate a machine certificate for ada.example.net (follow
+ instructions in `Generating Machine
+ Certificates <tls_cert_machine.html>`_)
+- make sure you copy over ca.pem, machine-key.pem ad machine-cert.pem
+ to the client. Ensure that no user except root can access them
+ (**even read permissions are really bad**).
+- configure the client so that it checks the server identity and sends
+ messages only if the server identity is known.
+
+These were essentially the same steps as for any `TLS syslog
+client <tls_cert_client.html>`_. We now need to add the capability to
+forward the router logs:
+
+- make sure that the firewall rules permit message reception on UDP
+ port 514 (if you use a non-standard port for UDP syslog, make sure
+ that port number is permitted).
+- you may want to limit who can send syslog messages via UDP. A great
+ place to do this is inside the firewall, but you can also do it in
+ rsyslog.conf via an $AllowedSender directive. We have used one in the
+ sample config below. Please be aware that this is a kind of weak
+ authentication, but definitely better than nothing...
+- add the UDP input plugin to rsyslog's config and start a UDP listener
+- make sure that your forwarding-filter permits to forward messages
+ received from the remote router to the server. In our sample
+ scenario, we do not need to add anything special, because all
+ messages are forwarded. This includes messages received from remote
+ hosts.
+
+**At this point, please be reminded once again that your security needs
+may be quite different from what we assume in this tutorial. Evaluate
+your options based on your security needs.**
+
+Sample syslog.conf
+~~~~~~~~~~~~~~~~~~
+
+Keep in mind that this rsyslog.conf sends messages via TCP, only. Also,
+we do not show any rules to write local files. Feel free to add them.
+
+::
+
+ # start a UDP listener for the remote router
+ module(load="imudp") # load UDP server plugin
+ $AllowedSender UDP, 192.0.2.1 # permit only the router
+ input(type="imudp"
+ port="514" # listen on default syslog UDP port 514
+ )
+
+ # make gtls driver the default and set certificate files
+ global(
+ DefaultNetstreamDriver="gtls"
+ DefaultNetstreamDriverCAFile="/path/to/contrib/gnutls/ca.pem"
+ DefaultNetstreamDriverCertFile="/path/to/contrib/gnutls/cert.pem"
+ DefaultNetstreamDriverKeyFile="/path/to/contrib/gnutls/key.pem"
+ )
+
+ # set up the action for all messages
+ action(
+ type="omfwd"
+ target="central.example.net"
+ protocol="tcp"
+ port="6514"
+ StreamDriver="gtls"
+ StreamDriverMode="1" # run driver in TLS-only mode
+ StreamDriverAuthMode="x509/name"
+ StreamDriverPermittedPeers="central.example.net"
+ )
+
+**Be sure to safeguard at least the private key (machine-key.pem)!** If
+some third party obtains it, you security is broken!