1<!doctype html public "-//W3C//DTD HTML 4.01 Transitional//EN"
2  "https://www.w3.org/TR/html4/loose.dtd">
3
4<html>
5
6<head>
7
8<title>Postfix TLSRPT notification Howto</title>
9
10<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
11<link rel='stylesheet' type='text/css' href='postfix-doc.css'>
12
13</head>
14
15<body>
16
17<h1><img src="postfix-logo.jpg" width="203" height="98" ALT="">Postfix TLSRPT Howto</h1>
18
19<hr>
20
21<h2> Table of Contents </h2>
22
23<ul>
24
25<li> <a href="#intro"> Introduction </a> </li>
26<li> <a href="#building"> Building Postfix with TLSRPT support </a>
27<li> <a href="#using"> Turning on TLSRPT </a> </li>
28<li> <a href="#logging"> TLSRPT Status logging </a> </li>
29<li> <a href="#delivering"> Delivering TLSRPT summaries via email</a> </li>
30<li> <a href="#mta-sts"> MTA-STS Support via smtp_tls_policy_maps </a> </li>
31<li> <a href="#limitations"> Limitations </a></li>
32<li> <a href="#credits"> Credits </a> </li>
33
34</ul>
35
36<h2> <a name="intro"> Introduction </a> </h2>
37
38<p> The TLSRPT protocol is defined in <a href="https://tools.ietf.org/html/rfc8460">RFC 8460</a>. With this, an email
39receiving domain can publish a policy in DNS, and request daily
40summary reports for successful and failed SMTP over TLS connections
41to that domain's MX hosts. Support for TLSRPT was added in Postfix
423.10. </p>
43
44<p> A policy for domain <tt>example.com</tt> could look like this: </p>
45
46<blockquote>
47<pre>
48_smtp._tls.example.com. IN TXT "v=TLSRPTv1; rua=mailto:smtp-tls-report@example.com"
49</pre>
50</blockquote>
51
52<p> Instead of <tt>mailto:</tt>, a policy may specify an <tt>https:</tt>
53destination. </p>
54
55<p> The diagram below shows how Postfix TLS handshake success and
56failure events are collected and processed into daily summary
57reports. </p>
58
59<blockquote>
60
61<table>
62
63<tr> <td align="center" bgcolor="#f0f0ff"> Postfix SMTP and TLS
64client engines </td> <td> <tt> &rarr; </tt> </td>
65
66<td align="center" bgcolor="#f0f0ff"> <a
67href="https://github.com/sys4/libtlsrpt">TLSRPT client library </a>
68(linked into Postfix) </td> <td> <tt> &rarr; </tt> </td>
69
70<td align="center" bgcolor="#f0f0ff"> <a
71href="https://github.com/sys4/tlsrpt-reporter">TLSRPT collector,
72fetcher, and summary generator</a> </td> <td> <tt> &rarr; </tt>
73</td>
74
75<td align="center" bgcolor="#f0f0ff"> Email or HTTP delivery </td>
76</tr>
77
78</table>
79
80</blockquote>
81
82<ul>
83
84<li> <p> The Postfix SMTP and TLS client engines will generate a
85"success" or "failure" event for each TLS handshake, </p>
86
87<li> <p> They will pass those events to an in-process TLSRPT client
88library that sends data over a local socket to </p>
89
90<li> <p> A local TLSRPT collector that runs on each Postfix machine.
91A TLSRPT fetcher gathers information from individual collectors,
92and a central TLSRPT report generator produces daily summary reports.
93</p>
94
95</ul>
96
97<p> The TLSRPT client library, and the infrastructure to collect,
98fetch, and report TLSRPT information, are implemented and maintained
99by sys4 at <a href="https://github.com/sys4/libtlsrpt">https://github.com/sys4/libtlsrpt</a> and
100<a href="https://github.com/sys4/tlsrpt-reporter">https://github.com/sys4/tlsrpt-reporter</a>, respectively. </p>
101
102<p> The Postfix implementation supports TLSRPT or domains with DANE
103(Postfix built-in) and MTA-STS (through an <a href="#mta-sts">
104smtp_tls_policy_maps plug-in</a>). </p>
105
106<p> The Postfix <a href="smtp.8.html">smtp(8)</a> client process implements the SMTP client
107engine. With "<a href="postconf.5.html#smtp_tls_connection_reuse">smtp_tls_connection_reuse</a> = no", the <a href="smtp.8.html">smtp(8)</a> client
108process also implements the TLS client engine. With
109"<a href="postconf.5.html#smtp_tls_connection_reuse">smtp_tls_connection_reuse</a> = yes", the <a href="smtp.8.html">smtp(8)</a> client process
110delegates TLS processing to a Postfix <a href="tlsproxy.8.html">tlsproxy(8)</a> process. Either
111way, Postfix will generate the exact same TLSRPT events. </p>
112
113<h2> <a name="building"> Building Postfix with TLSRPT support </a>
114</h2>
115
116<p> These instructions assume that you build Postfix from source
117code as described in the <a href="INSTALL.html">INSTALL</a> document. Some modification may
118be required if you build Postfix from a vendor-specific source
119package. </p>
120
121<p> The Postfix TLSRPT client builds on a TLSRPT library which may
122be available as a built package (rpm, deb, etc.), or which you can
123build from source code from: </p>
124
125<blockquote>
126<p> <a href="https://github.com/sys4/libtlsrpt">https://github.com/sys4/libtlsrpt</a> </p>
127</blockquote>
128
129<p> The library is typically installed as a header file in
130/usr/local/include/tlsrpt.h and an object library in
131/usr/local/lib/libtlsrpt.a or /usr/local/lib/libtlsrpt.so. The
132actual pathnames will depend on OS platform conventions. </p>
133
134<p> In order to build Postfix with TLSRPT support, you will need
135to add compiler options <tt>-DUSE_TLSRPT</tt> (to build with TLSRPT
136support) and <tt>-I</tt> (with the directory containing the tlsrpt.h
137header file), and you will need to add linker options to link with
138the TLSRPT client library, for example: </p>
139
140<blockquote>
141<pre>
142make -f Makefile.init makefiles \
143  "CCARGS=-DUSE_TLSRPT -I/usr/local/include" \
144  "AUXLIBS=-L/usr/local/lib -Wl,-rpath,/usr/local/lib -ltlsrpt"
145</pre>
146</blockquote>
147
148<p> (On Solaris systems you may need to use "<tt>-Wl,-R</tt>" instead
149of "<tt>-Wl,-rpath</tt>".) </p>
150
151<p> Then, just run 'make'. </p>
152
153<blockquote>
154
155<p> Note: if your build command line already has CCARGS or AUXLIBS
156settings, then simply append the above settings to the existing CCARGS
157or AUXLIBS values: </p>
158
159<pre>
160make -f Makefile.init makefiles \
161  "CCARGS=... -DUSE_TLSRPT -I/usr/local/include" \
162  "AUXLIBS=... -L/usr/local/lib -Wl,-rpath,/usr/local/lib -ltlsrpt"
163</pre>
164</blockquote>
165
166<h2> <a name="using"> Turning on TLSRPT </a> </h2>
167
168<p> After installing Postfix TLSRPT support, you can enable TLSRPT
169support in <a href="postconf.5.html">main.cf</a> like this: </p>
170
171<blockquote>
172<pre>
173<a href="postconf.5.html#smtp_tlsrpt_enable">smtp_tlsrpt_enable</a> = yes
174<a href="postconf.5.html#smtp_tlsrpt_socket_name">smtp_tlsrpt_socket_name</a> = path/to/socket
175</pre>
176</blockquote>
177
178<p> The <a href="postconf.5.html#smtp_tlsrpt_socket_name">smtp_tlsrpt_socket_name</a> parameter specifies either an
179absolute pathname, or a pathname that is relative to $<a href="postconf.5.html#queue_directory">queue_directory</a>.
180</p>
181
182<p> Notes: </p>
183
184<ul>
185
186<li> <p> The recommended socket location is still to be determined.
187A good socket location would be under the Postfix queue directory,
188for example: "<a href="postconf.5.html#smtp_tlsrpt_socket_name">smtp_tlsrpt_socket_name</a> = run/tlsrpt/tlsrpt.sock".
189The advantage of using a relative name is that it will work equally
190well whether or not Postfix chroot is turned on. </p>
191
192<li> <p> Regardless of whether Postfix chroot is enabled, the TLSRPT
193receiver (<tt>tlsrpt_collectd</tt>) will need to be configured with
194the socket's absolute pathname. </p>
195
196<li> <p> Do not specify a TLSRPT socket location under a Postfix socket
197directory such as <tt>private</tt> or <tt>public</tt>. Only Postfix
198programs should create sockets there. </p>
199
200</ul>
201
202<p> For details on how to run the TLSRPT collection and reporting
203infrastructure, see the documentation at
204<a href="https://github.com/sys4/tlsrpt-reporter">https://github.com/sys4/tlsrpt-reporter</a>.
205
206<h2> <a name="logging"> TLSRPT Status logging </a> </h2>
207
208<p> With TLSRPT support turned on, the Postfix TLSRPT client will
209not only report an event to an invisible daily success/fail summary
210queue, but it will also log a visible record to the mail logfile.
211</p>
212
213<p> Below are a few examples of logging from a Postfix SMTP client
214or tlsproxy daemon: </p>
215
216<blockquote>
217<pre>
218TLSRPT: status=success, domain=example.com, receiving_mx=mail.example.com[ipaddr]
219&nbsp;
220TLSRPT: status=failure, domain=example.org, receiving_mx=mail.example.org[ipaddr],
221    failure_type=starttls_not_supported
222&nbsp;
223TLSRPT: status=failure, domain=example.net, receiving_mx=mail.example.net[ipaddr],
224    failure_type=validation_failure, failure_reason=self-signed_certificate
225</pre>
226</blockquote>
227
228<p> Notes: </p>
229
230<ul>
231
232<li> <p> Postfix logs and reports the TLSRPT status only for TLS
233handshakes on a new SMTP connection. There is no TLS handshake, and
234thus no TLSRPT status logging, when an SMTP connection is reused.
235Such connections have Postfix SMTP client logging like this: </p>
236
237<pre>
238Verified <b>TLS connection reused</b> to mail.example.com[ipaddr]:25:
239    TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)
240&nbsp;
241Untrusted <b>TLS connection reused</b> to mail.example.com[ipaddr]:25:
242    TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)
243</pre>
244
245<li> <p> By default, Postfix does not report the TLSRPT status for
246a TLS handshake that reuses a previously-negotiated TLS session
247(there would be no new information to report). Specify
248"<a href="postconf.5.html#smtp_tlsrpt_skip_reused_handshakes">smtp_tlsrpt_skip_reused_handshakes</a> = no" to report the TLSRPT
249status for all TLS handshakes. This may be useful for troubleshooting.
250</p>
251
252<li> <p> Postfix logging for certificate verification failures may
253differ between new or reused TLS sessions. </p>
254
255<ul>
256
257<li> <p> New TLS session:
258</p>
259
260<pre>
261TLSRPT: status=failure, domain=example.org, receiving_mx=mail.example.org[ipaddr],
262    <b>failure_type=validation_failure</b>, <b>failure_reason=self-signed_certificate</b>
263</pre>
264
265<li> <p> Reused TLS session: </p>
266
267<pre>
268mail.example.org[ipaddr]:25: <b>re-using session</b> with untrusted peer
269    credential, look for details earlier in the log
270TLSRPT: status=failure, domain=example.org, receiving_mx=mail.example.org[ipaddr],
271    <b>failure_type=certificate_not_trusted</b>
272</pre>
273
274</ul>
275
276<p> The logging may differ because a reused TLS session does not
277have the details for why TLS authentication failed. </p>
278
279</ul>
280
281<h2> <a name="delivering"> Delivering TLSRPT summaries via email</a> </h2>
282
283<p> <a href="https://datatracker.ietf.org/doc/html/rfc8460#section-3">RFC
2848460 Section 3</a> specifies that an MTA must not enforce TLS
285security when sending failure reports via email. </p>
286
287<p> Options:
288
289<ul>
290
291<li> <p> In an email report, specify the "<b>TLS-Required: no</b>"
292message header,
293defined in <a href="https://tools.ietf.org/html/rfc8689">RFC 8689</a>, to reduce the Postfix SMTP client TLS security
294level to "<b>may</b>" (that is, do not verify remote SMTP server
295certificates, and fall back to plaintext if TLS is unavailable).
296<br> <br> This feature is available in Postfix 3.10 and later. If
297your outbound MTAs run an older version, you can use one of the
298options described below. </p>
299
300<li> <p> Do nothing. When TLS security enforcement is required but
301fails, a TLSRPT summary message will be delayed
302until the problem is addressed, or until the message expires
303in the mail queue. Keep in mind that TLSRPT is not a real-time
304monitoring service; it takes on average 12 hours before a failure
305is reported through TLSRPT. </p>
306
307<li> <p> On outbound MTAs that don't support the "<b>TLS-Required:
308no</b>" header feature (such as Postfix 3.9 and earlier), disable
309TLS security enforcement for the sender of TLSRPT summaries.
310Implement the configuration below on outbound MTA instances (replace
311noreply-smtp-tls-reporting@example.com with your actual report
312generator's sender address): </p>
313
314<pre>
315/etc/postfix/<a href="postconf.5.html">main.cf</a>:
316    # Limitation: this setting is overruled with <a href="postconf.5.html#transport_maps">transport_maps</a>.
317    <a href="postconf.5.html#sender_dependent_default_transport_maps">sender_dependent_default_transport_maps</a> = <a href="DATABASE_README.html#types">inline</a>:{
318        { noreply-smtp-tls-reporting@example.com = allow-plaintext } }
319&nbsp
320/etc/postfix/<a href="master.5.html">master.cf</a>:
321    # service name    type    private unpriv  chroot  wakeup  maxproc command
322    allow-plaintext   unix    -       -       -       -       -       smtp
323        -o { <a href="postconf.5.html#smtp_tls_security_level">smtp_tls_security_level</a> = may }
324        -o { <a href="postconf.5.html#smtp_tls_policy_maps">smtp_tls_policy_maps</a> = <a href="DATABASE_README.html#types">static</a>:may }
325</pre>
326
327</ul>
328
329<h2> <a name="mta-sts"> MTA-STS Support via smtp_tls_policy_maps
330</a></h2>
331
332<p> Postfix supports MTA-STS though an <a href="postconf.5.html#smtp_tls_policy_maps">smtp_tls_policy_maps</a> policy
333plugin, which replies with a TLS security level and name=value
334attributes with certificate matching requirements. Postfix 3.10 and
335later extend the policy plugin response with additional name=value
336attributes that are needed for TLSRPT. </p>
337
338<p> Examples of <a href="postconf.5.html#smtp_tls_policy_maps">smtp_tls_policy_maps</a> plugins with MTA-STS support
339are: </p>
340
341<ul>
342
343<li> <p> <a href="https://github.com/Zuplu/postfix-tlspol">
344postfix-tlspol</a>, supports domains with DANE (using Postfix
345built-in DANE), and domains with MTA-STS. </p>
346
347<li> <p> <a href="https://github.com/Snawoot/postfix-mta-sts-resolver">
348postfix-mta-sts-resolver</a>, supports domains with MTA-STS as of
349release 1.5.0 (February 2025). </p>
350
351</ul>
352
353<p> Both plugins can generate the additional name=value attributes
354that Postfix needs for TLSRPT support (as of February 2025). This
355is enabled by setting a <tt>tlsrpt</tt> boolean in a plugin
356configuration file.  This setting is safe with Postfix 3.10 and
357later, even if Postfix TLSRPT support is disabled (at build time
358or at run time). Postfix versions 3.9 and earlier will report a
359policy error with "<tt>invalid attribute name</tt>". </p>
360
361<p> The examples in the text below apply to this MTA-STS policy example
362given in <a
363href="https://datatracker.ietf.org/doc/html/rfc8461#section-3.2">
364RFC 8461 Section 3.2</a>: </p>
365
366<blockquote>
367<pre>
368version: STSv1
369mode: enforce
370mx: mail.example.com
371mx: *.example.net
372mx: backupmx.example.com
373max_age: 604800
374</pre>
375</blockquote>
376
377<p> The list of supported attributes is given below. Instead of
378<tt>name=value</tt>, specify <tt>{ name = value }</tt> when a value
379may contain whitespace. A policy response may contain line breaks.
380</p>
381
382<ul>
383
384<li> <p> <tt> policy_type=<i>type</i> </tt> </p>
385
386<p> Specify <tt>sts</tt> or <tt>no-policy-found</tt>. </p>
387
388<p> Example: <tt>policy_type=sts</tt> </p> </li>
389
390<li> <p> <tt> policy_domain=<i>name</i> </tt> </p>
391
392<p> The domain that the MTA-STS policy applies to. </p>
393
394<p> Example: <tt>policy_domain=example.com</tt> </p>
395
396</li>
397
398<li> <p> <tt> { policy_string = <i>value</i> } </tt> </p>
399
400<p> Specify one <tt>policy_string</tt> instance for each MTA-STS
401policy feature, enclosed inside "{" and "}" to protect whitespace
402in attribute values. <p>
403
404<p> Example: <tt> { policy_string = version: STSv1 } { policy_string
405= mode: enforce } ...</tt> </p>
406
407<p> The above form ignores whitespace after the opening "{", around
408the "=", and before the closing "}".</p> </li>
409
410<li> <p> <tt> mx_host_pattern=<i>pattern</i> </tt> </p>
411
412<p> Specify one <tt>mx_host_pattern</tt> instance for each "mx:" feature
413in the MTA-STS policy. </p>
414
415<p> Example: <tt>mx_host_pattern=mail.example.com
416mx_host_pattern=*.example.net ...</tt> </p> </li>
417
418<li> <p> <tt> policy_failure=<i>type</i> </tt> </p>
419
420<p> If specified, forces MTA-STS policy enforcement to fail with
421the indicated error, even if a server certificate would satisfy
422conventional PKI constraints. Valid errors are <tt>sts-policy-fetch-error,
423sts-policy-invalid</tt>, <tt>sts-webpki-invalid</tt>, or the less
424informative <tt>validation-failure</tt>. </p>
425
426<p> Example: <tt>policy_failure=sts-webpki-invalid</tt> </p> </li>
427
428<li> <p> <tt> policy_ttl=<i>time</i> </tt> (deprecated) </p>
429
430<p> This attribute is deprecated. The <i>time</i> value is not used,
431and support for this attribute will eventually be removed from the
432code. </p> </li>
433
434</ul>
435
436<p> Notes: </p>
437
438<ul>
439
440<li> <p> Postfix 3.10 and later will accept these additional
441attributes in an MTA-STS response even if Postfix TLSRPT support
442is disabled (at build time or at run time). With Postfix TLSRPT
443support turned off, Postfix may still use the <tt>policy_failure</tt>
444attribute, and will ignore the attributes that are used only for
445TLSRPT. </p>
446
447<li> <p> It is an error to specify these attributes for a non-STS
448policy. </p>
449
450</ul>
451
452<h2> <a name="limitations"> Limitations </a></h2>
453
454<p> The Postfix TLSRPT implementation reports only TLS handshake
455success or failure. It does not report failure to connect, or
456connections that break before or after a TLS handshake. </p>
457
458<p> The Postfix TLSRPT implementation reports at most one final TLS
459handshake status (either 'success' or 'failure') per SMTP connection.
460Postfix TLSRPT will not report a recoverable failure and then later
461report a final status of 'success' for that same connection. The
462reason is that it's too complicated to filter TLS errors and to
463report error details from the TLS engine back to the SMTP protocol
464engine. It just is not how Postfix works internally. </p>
465
466<h2> <a name="credits"> Credits </a> </h2>
467
468<ul>
469
470<li> The TLSRPT client library, and the infrastructure to collect,
471fetch, and report TLSRPT information, are implemented and maintained
472by sys4. </li>
473
474<li> Wietse Venema implemented the integration with Postfix.
475</li>
476
477</ul>
478
479</body>
480
481</html>
482