1 1.1 tron <!doctype html public "-//W3C//DTD HTML 4.01 Transitional//EN" 2 1.1.1.7 christos "https://www.w3.org/TR/html4/loose.dtd"> 3 1.1 tron 4 1.1 tron <html> 5 1.1 tron 6 1.1 tron <head> 7 1.1 tron 8 1.1 tron <title>Postfix Before-Queue Content Filter </title> 9 1.1 tron 10 1.1.1.5 christos <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> 11 1.1.1.6 christos <link rel='stylesheet' type='text/css' href='postfix-doc.css'> 12 1.1 tron 13 1.1 tron </head> 14 1.1 tron 15 1.1 tron <body> 16 1.1 tron 17 1.1 tron <h1><img src="postfix-logo.jpg" width="203" height="98" ALT="">Postfix Before-Queue Content Filter </h1> 18 1.1 tron 19 1.1 tron <hr> 20 1.1 tron 21 1.1 tron <h2>WARNING </h2> 22 1.1 tron 23 1.1.1.2 tron <p> The before-queue content filtering feature described in this 24 1.1.1.2 tron document limits the amount of mail that a site can handle. See the 25 1.1.1.2 tron "<a href="#pros_cons">Pros and Cons</a>" section below for details. 26 1.1 tron </p> 27 1.1 tron 28 1.1 tron <h2>The Postfix before-queue content filter feature</h2> 29 1.1 tron 30 1.1 tron <p> As of version 2.1, the Postfix SMTP server can forward all 31 1.1 tron incoming mail to a content filtering proxy server that inspects all 32 1.1 tron mail BEFORE it is stored in the Postfix mail queue. It is roughly 33 1.1 tron equivalent in capabilities to the approach described in MILTER_README, 34 1.1 tron except that the latter uses a dedicated protocol instead of SMTP. 35 1.1 tron 36 1.1 tron <p> The before-queue content filter is meant to be used as follows: </p> 37 1.1 tron 38 1.1 tron <blockquote> 39 1.1 tron 40 1.1 tron <table> 41 1.1 tron 42 1.1 tron <tr> 43 1.1 tron 44 1.1.1.3 tron <td bgcolor="#f0f0ff" align="center" valign="middle" 45 1.1.1.3 tron width="10%"> Internet </td> 46 1.1 tron 47 1.1 tron <td align="center" valign="middle" width="5%"> <tt> -> </tt> </td> 48 1.1 tron 49 1.1.1.3 tron <td bgcolor="#f0f0ff" align="center" valign="middle" 50 1.1.1.3 tron width="10%"> <a href="smtpd.8.html">Postfix SMTP server</a> 51 1.1.1.3 tron </td> 52 1.1 tron 53 1.1 tron <td align="center" valign="middle" width="5%"> <tt> -> </tt> </td> 54 1.1 tron 55 1.1.1.3 tron <td bgcolor="#f0f0ff" align="center" valign="middle" 56 1.1.1.3 tron width="10%"> <b>Before</b> <b>queue</b> <b>filter</b> </td> 57 1.1 tron 58 1.1 tron <td align="center" valign="middle" width="5%"> <tt> -> </tt> </td> 59 1.1 tron 60 1.1.1.3 tron <td bgcolor="#f0f0ff" align="center" valign="middle" 61 1.1.1.3 tron width="10%"> <a href="smtpd.8.html">Postfix SMTP server</a> 62 1.1.1.3 tron </td> 63 1.1 tron 64 1.1 tron <td align="center" valign="middle" width="5%"> <tt> -> </tt> </td> 65 1.1 tron 66 1.1.1.3 tron <td bgcolor="#f0f0ff" align="center" valign="middle" 67 1.1.1.3 tron width="10%"> <a href="cleanup.8.html">Postfix cleanup 68 1.1.1.3 tron server</a> </td> 69 1.1 tron 70 1.1 tron <td align="center" valign="middle" width="5%"> <tt> -> </tt> </td> 71 1.1 tron 72 1.1.1.3 tron <td bgcolor="#f0f0ff" align="center" valign="middle" 73 1.1.1.3 tron width="10%"> Postfix queue </td> 74 1.1 tron 75 1.1 tron <td align="center" valign="middle" width="5%"> <tt> -< </tt> </td> 76 1.1 tron 77 1.1.1.3 tron <td bgcolor="#f0f0ff" align="center" valign="middle" 78 1.1.1.3 tron width="10%"> <a href="smtp.8.html">smtp</a><br> <a 79 1.1.1.3 tron href="local.8.html">local</a><br> <a 80 1.1.1.3 tron href="virtual.8.html">virtual</a> </td> 81 1.1 tron 82 1.1 tron </tr> 83 1.1 tron 84 1.1 tron </table> 85 1.1 tron 86 1.1 tron </blockquote> 87 1.1 tron 88 1.1 tron <p> The before-queue content filter is not to be confused with the 89 1.1 tron approach described in the FILTER_README document, where mail is 90 1.1 tron filtered AFTER it is stored in the Postfix mail queue. </p> 91 1.1 tron 92 1.1 tron <p> This document describes the following topics: </p> 93 1.1 tron 94 1.1 tron <ul> 95 1.1 tron 96 1.1 tron <li><a href="#principles">Principles of operation</a> 97 1.1 tron 98 1.1 tron <li><a href="#pros_cons">Pros and cons of before-queue content filtering</a> 99 1.1 tron 100 1.1 tron <li><a href="#config">Configuring the Postfix SMTP pass-through 101 1.1 tron proxy feature</a> 102 1.1 tron 103 1.1 tron <li><a href="#parameters">Configuration parameters</a> 104 1.1 tron 105 1.1 tron <li><a href="#protocol">How Postfix talks to the before-queue content 106 1.1 tron filter</a> 107 1.1 tron 108 1.1 tron </ul> 109 1.1 tron 110 1.1 tron <h2><a name="principles">Principles of operation</a></h2> 111 1.1 tron 112 1.1.1.2 tron <p> As shown in the diagram above, the before-queue filter sits 113 1.1.1.2 tron between two Postfix SMTP server processes. </p> 114 1.1.1.2 tron 115 1.1.1.2 tron <ul> 116 1.1.1.2 tron 117 1.1.1.2 tron <li> <p> The before-filter Postfix SMTP server accepts connections from the 118 1.1 tron Internet and does the usual relay access control, SASL authentication, 119 1.1 tron TLS negotiation, 120 1.1 tron RBL lookups, rejecting non-existent sender or recipient addresses, 121 1.1.1.2 tron etc. </p> 122 1.1.1.2 tron 123 1.1.1.2 tron <li> <p> The before-queue filter receives unfiltered mail content from 124 1.1 tron Postfix and does one of the following: </p> 125 1.1 tron 126 1.1 tron <ol> 127 1.1 tron 128 1.1 tron <li> <p> Re-inject the mail back into Postfix via SMTP, perhaps 129 1.1 tron after changing its content and/or destination. </p> 130 1.1 tron 131 1.1 tron <li> <p> Discard or quarantine the mail. </p> 132 1.1 tron 133 1.1 tron <li> <p> Reject the mail by sending a suitable SMTP status code 134 1.1 tron back to Postfix. Postfix passes the status back to the remote 135 1.1 tron SMTP client. This way, Postfix does not have to send a bounce 136 1.1 tron message. </p> 137 1.1 tron 138 1.1 tron </ol> 139 1.1 tron 140 1.1.1.2 tron <li> <p>The after-filter Postfix SMTP server receives mail from the 141 1.1 tron content filter. From then on Postfix processes the mail as usual. </p> 142 1.1 tron 143 1.1.1.2 tron </ul> 144 1.1.1.2 tron 145 1.1 tron <p> The before-queue content filter described here works just like 146 1.1 tron the after-queue content filter described in the FILTER_README 147 1.1 tron document. In many cases you can use the same software, within the 148 1.1 tron limitations as discussed in the "<a href="#pros_cons">Pros and 149 1.1 tron Cons</a>" section below. </p> 150 1.1 tron 151 1.1 tron <h2><a name="pros_cons">Pros and cons of before-queue content 152 1.1 tron filtering</a></h2> 153 1.1 tron 154 1.1 tron <ul> 155 1.1 tron 156 1.1 tron <li> <p> Pro: Postfix can reject mail before the incoming SMTP mail 157 1.1 tron transfer completes, so that Postfix does not have to send rejected 158 1.1 tron mail back to the sender (which is usually forged anyway). Mail 159 1.1 tron that is not accepted remains the responsibility of the remote SMTP 160 1.1 tron client. </p> 161 1.1 tron 162 1.1.1.6 christos <li> <p> Con: The smtpd(8) service before the smtpd_proxy_filter 163 1.1.1.6 christos cannot support features that involve header or body access, or that 164 1.1.1.6 christos involve queue file manipulation (i.e., anything that involves 165 1.1.1.6 christos processing by the cleanup(8) service). </p> 166 1.1.1.6 christos 167 1.1.1.6 christos <ul> 168 1.1.1.6 christos 169 1.1.1.6 christos <li> <p> No support for HOLD actions in Postfix smtpd access(5) 170 1.1.1.6 christos restrictions. </p> 171 1.1.1.6 christos 172 1.1.1.6 christos <li> <p> No support for smtpd_milters features that involve message 173 1.1.1.6 christos header or body content. </p> 174 1.1.1.6 christos 175 1.1.1.6 christos <li> <p> No support for receive_override_options. 176 1.1.1.6 christos 177 1.1.1.6 christos </ul> 178 1.1.1.6 christos 179 1.1.1.6 christos <p> Instead, specify those features with the smtpd(8) service behind 180 1.1.1.6 christos the smtpd_proxy_filter. In some cases, it may be possible to combine 181 1.1.1.6 christos a before-filter PREPEND action that emits a unique pattern (for 182 1.1.1.6 christos example containing the MTA domain name), with an after-filter 183 1.1.1.6 christos header_checks action that does what you want, and with an 184 1.1.1.6 christos smtp_header_checks IGNORE action that deletes the prepended header 185 1.1.1.6 christos from transit mail. </p> 186 1.1.1.6 christos 187 1.1 tron <li> <p> Con: The remote SMTP client expects an SMTP reply within 188 1.1 tron a deadline. As the system load increases, fewer and fewer CPU 189 1.1 tron cycles remain available to answer within the deadline, and eventually 190 1.1 tron you either have to stop accepting mail or you have to stop filtering 191 1.1 tron mail. It is for this reason that the before-queue content filter 192 1.1.1.2 tron limits the amount of mail that a site can handle. </p> 193 1.1 tron 194 1.1 tron <li> <p> Con: Content filtering software can use lots of memory 195 1.1.1.2 tron resources. You have to reduce the number of simultaneous content 196 1.1.1.2 tron filter processes so that a burst of mail will not drive your system 197 1.1.1.2 tron into the ground. </p> 198 1.1.1.2 tron 199 1.1.1.2 tron <ul> 200 1.1.1.2 tron 201 1.1.1.2 tron <li> <p> With Postfix versions 2.7 and later, SMTP clients will 202 1.1.1.2 tron experience an increase in the delay between the time the client 203 1.1.1.2 tron sends "end-of-message" and the time the Postfix SMTP server replies 204 1.1.1.2 tron (here, the number of before-filter SMTP server processes can be 205 1.1.1.2 tron larger than the number of filter processes). </p> 206 1.1.1.2 tron 207 1.1.1.2 tron <li> <p> With Postfix versions before 2.7, SMTP clients will 208 1.1.1.2 tron experience an increase in the delay before they can receive service 209 1.1.1.2 tron (here, the number of before-filter SMTP server processes is always 210 1.1.1.2 tron equal to the number of filter processes). </p> 211 1.1.1.2 tron 212 1.1.1.2 tron </ul> 213 1.1 tron 214 1.1 tron </ul> 215 1.1 tron 216 1.1 tron <h2><a name="config">Configuring the Postfix SMTP pass-through 217 1.1 tron proxy feature</a></h2> 218 1.1 tron 219 1.1 tron <p> In the following example, the before-filter Postfix SMTP server 220 1.1 tron gives mail to a content filter that listens on localhost port 10025. 221 1.1 tron The after-filter Postfix SMTP server receives mail from the content 222 1.1 tron filter via localhost port 10026. From then on mail is processed as 223 1.1 tron usual. </p> 224 1.1 tron 225 1.1 tron <p> The content filter itself is not described here. You can use 226 1.1 tron any filter that is SMTP enabled. For non-SMTP capable content 227 1.1 tron filtering software, Bennett Todd's SMTP proxy implements a nice 228 1.1.1.5 christos Perl-based framework. See: 229 1.1.1.5 christos https://web.archive.org/web/20151022025756/http://bent.latency.net/smtpprox/ 230 1.1.1.5 christos or https://github.com/jnorell/smtpprox/ </p> 231 1.1 tron 232 1.1 tron <blockquote> 233 1.1 tron 234 1.1 tron <table border="0"> 235 1.1 tron 236 1.1 tron <tr> 237 1.1 tron 238 1.1 tron <td bgcolor="#f0f0ff" align="center" valign="middle" 239 1.1 tron width="10%"> Internet </td> 240 1.1 tron 241 1.1 tron <td align="center" valign="middle" width="5%"> <tt> -> </tt> </td> 242 1.1 tron 243 1.1.1.3 tron <td bgcolor="#f0f0ff" align="center" valign="middle" 244 1.1.1.3 tron width="10%"> <a href="smtpd.8.html">Postfix SMTP server on 245 1.1.1.3 tron port 25</a> </td> 246 1.1 tron 247 1.1 tron <td align="center" valign="middle" width="5%"> <tt> -> </tt> </td> 248 1.1 tron 249 1.1.1.3 tron <td bgcolor="#f0f0ff" align="center" valign="middle" 250 1.1.1.3 tron width="10%"> filter on localhost port 10025 </td> 251 1.1 tron 252 1.1 tron <td align="center" valign="middle" width="5%"> <tt> -> </tt> </td> 253 1.1 tron 254 1.1.1.3 tron <td bgcolor="#f0f0ff" align="center" valign="middle" 255 1.1.1.3 tron width="10%"> <a href="smtpd.8.html">Postfix SMTP server on 256 1.1.1.3 tron localhost port 10026</a> </td> 257 1.1 tron 258 1.1 tron <td align="center" valign="middle" width="5%"> <tt> -> </tt> </td> 259 1.1 tron 260 1.1.1.3 tron <td bgcolor="#f0f0ff" align="center" valign="middle" 261 1.1.1.3 tron width="10%"> <a href="cleanup.8.html">Postfix cleanup 262 1.1.1.3 tron server</a> </td> 263 1.1 tron 264 1.1 tron <td align="center" valign="middle" width="5%"> <tt> -> </tt> </td> 265 1.1 tron 266 1.1 tron <td bgcolor="#f0f0ff" align="center" valign="middle" 267 1.1 tron width="10%"> Postfix incoming queue </td> 268 1.1 tron 269 1.1 tron </tr> 270 1.1 tron 271 1.1 tron </table> 272 1.1 tron 273 1.1 tron </blockquote> 274 1.1 tron 275 1.1 tron <p> This is configured by editing the master.cf file: </p> 276 1.1 tron 277 1.1 tron <blockquote> 278 1.1 tron <pre> 279 1.1 tron /etc/postfix/master.cf: 280 1.1 tron # ============================================================= 281 1.1 tron # service type private unpriv chroot wakeup maxproc command 282 1.1 tron # (yes) (yes) (yes) (never) (100) 283 1.1 tron # ============================================================= 284 1.1 tron # 285 1.1 tron # Before-filter SMTP server. Receive mail from the network and 286 1.1 tron # pass it to the content filter on localhost port 10025. 287 1.1 tron # 288 1.1 tron smtp inet n - n - 20 smtpd 289 1.1 tron -o smtpd_proxy_filter=127.0.0.1:10025 290 1.1 tron -o smtpd_client_connection_count_limit=10 291 1.1.1.3 tron # Postfix 2.7 and later performance feature. 292 1.1.1.3 tron # -o smtpd_proxy_options=speed_adjust 293 1.1 tron # 294 1.1 tron # After-filter SMTP server. Receive mail from the content filter 295 1.1 tron # on localhost port 10026. 296 1.1 tron # 297 1.1 tron 127.0.0.1:10026 inet n - n - - smtpd 298 1.1 tron -o smtpd_authorized_xforward_hosts=127.0.0.0/8 299 1.1 tron -o smtpd_client_restrictions= 300 1.1 tron -o smtpd_helo_restrictions= 301 1.1 tron -o smtpd_sender_restrictions= 302 1.1.1.3 tron # Postfix 2.10 and later: specify empty smtpd_relay_restrictions. 303 1.1.1.3 tron -o smtpd_relay_restrictions= 304 1.1 tron -o smtpd_recipient_restrictions=permit_mynetworks,reject 305 1.1 tron -o smtpd_data_restrictions= 306 1.1 tron -o mynetworks=127.0.0.0/8 307 1.1 tron -o receive_override_options=no_unknown_recipient_checks 308 1.1 tron </pre> 309 1.1 tron </blockquote> 310 1.1 tron 311 1.1 tron <p> Note: do not specify spaces around the "=" or "," characters. </p> 312 1.1 tron 313 1.1 tron <p> The before-filter SMTP server entry is a modified version of the 314 1.1 tron default Postfix SMTP server entry that is normally configured at 315 1.1 tron the top of the master.cf file: </p> 316 1.1 tron 317 1.1 tron <ul> 318 1.1 tron 319 1.1 tron <li> <p> The number of SMTP sessions is reduced from the default 320 1.1 tron 100 to only 20. This prevents a burst of mail from running your 321 1.1 tron system into the ground with too many content filter processes. </p> 322 1.1 tron 323 1.1 tron <li> <p> The "-o smtpd_client_connection_count_limit=10" prevents 324 1.1 tron one SMTP client from using up all 20 SMTP server processes. 325 1.1 tron This limit is not necessary if you receive all mail from a 326 1.1 tron trusted relay host. </p> 327 1.1 tron 328 1.1 tron <p> Note: this setting is available in Postfix version 2.2 and 329 1.1 tron later. Earlier Postfix versions will ignore it. </p> 330 1.1 tron 331 1.1 tron <li> <p> The "-o smtpd_proxy_filter=127.0.0.1:10025" tells the 332 1.1.1.2 tron before-filter SMTP server that it should give incoming mail to 333 1.1 tron the content filter that listens on localhost TCP port 10025. 334 1.1 tron 335 1.1.1.2 tron <li> <p> The "-o smtpd_proxy_options=speed_adjust" tells the 336 1.1.1.2 tron before-filter SMTP server that it should receive an entire email 337 1.1.1.2 tron message before it connects to a content filter. This reduces 338 1.1.1.2 tron the number of simultaneous filter processes. </p> 339 1.1.1.2 tron 340 1.1.1.2 tron <p> NOTE 1: When this option is turned on, a content filter must 341 1.1.1.2 tron not <i>selectively</i> reject recipients of a multi-recipient 342 1.1.1.2 tron message. Rejecting all recipients is OK, as is accepting all 343 1.1.1.2 tron recipients. </p> 344 1.1.1.2 tron 345 1.1.1.2 tron <p> NOTE 2: This feature increases the minimum amount of free 346 1.1.1.2 tron queue space by $message_size_limit. The extra space is needed 347 1.1.1.2 tron to save the message to a temporary file. </p> 348 1.1.1.2 tron 349 1.1.1.2 tron <li> <p> Postfix ≥ 2.3 supports both TCP and UNIX-domain filters. 350 1.1 tron The above filter could be specified as "inet:127.0.0.1:10025". 351 1.1 tron To specify a UNIX-domain filter, specify "unix:<i>pathname</i>". 352 1.1 tron A relative pathname is interpreted relative to the Postfix queue 353 1.1 tron directory. </p> 354 1.1 tron 355 1.1 tron </ul> 356 1.1 tron 357 1.1 tron <p> The after-filter SMTP server is a new master.cf entry: </p> 358 1.1 tron 359 1.1 tron <ul> 360 1.1 tron 361 1.1 tron <li> <p> The "127.0.0.1:10026" makes the after-filter SMTP 362 1.1 tron server listen 363 1.1 tron on the localhost address only, without exposing it to the 364 1.1 tron network. NEVER expose the after-filter SMTP server to the 365 1.1 tron Internet :-) </p> 366 1.1 tron 367 1.1 tron <li> <p> The "-o smtpd_authorized_xforward_hosts=127.0.0.0/8" 368 1.1 tron allows the after-filter SMTP server to receive remote SMTP 369 1.1.1.2 tron client information from the before-filter SMTP server, so that 370 1.1 tron the after-filter Postfix daemons log the remote SMTP client 371 1.1 tron information instead of logging localhost[127.0.0.1]. </p> 372 1.1 tron 373 1.1 tron <li> <p> The other after-filter SMTP server settings avoid 374 1.1 tron duplication of work that is already done in the "before filter" 375 1.1 tron SMTP server. </p> 376 1.1 tron 377 1.1 tron </ul> 378 1.1 tron 379 1.1 tron <p> By default, the filter has 100 seconds to do its work. If it 380 1.1 tron takes longer then Postfix gives up and reports an error to the 381 1.1.1.5 christos remote SMTP client. You can increase this time limit (see the <a href="#parameters">"Configuration 382 1.1.1.5 christos parameters"</a> section below) but doing so is pointless because you 383 1.1 tron can't control when the remote SMTP client times out. </p> 384 1.1 tron 385 1.1 tron <h2><a name="parameters">Configuration parameters</a></h2> 386 1.1 tron 387 1.1 tron <p> Parameters that control proxying: </p> 388 1.1 tron 389 1.1 tron <ul> 390 1.1 tron 391 1.1 tron <li> <p> smtpd_proxy_filter (syntax: host:port): The host and TCP 392 1.1 tron port of the before-queue content filter. When no host or host: 393 1.1 tron is specified here, localhost is assumed. </p> 394 1.1 tron 395 1.1 tron <li> <p> smtpd_proxy_timeout (default: 100s): Timeout for connecting 396 1.1 tron to the before-queue content filter and for sending and receiving 397 1.1 tron commands and data. All proxy errors are logged to the maillog 398 1.1 tron file. For privacy reasons, all the remote SMTP client sees is "451 399 1.1 tron Error: queue file write error". It would not be right to disclose 400 1.1 tron internal details to strangers. </p> 401 1.1 tron 402 1.1 tron <li> <p> smtpd_proxy_ehlo (default: $myhostname): The hostname to 403 1.1 tron use when sending an EHLO command to the before-queue content filter. 404 1.1 tron </p> 405 1.1 tron 406 1.1 tron </ul> 407 1.1 tron 408 1.1 tron <h2><a name="protocol">How Postfix talks to the before-queue content 409 1.1 tron filter</a></h2> 410 1.1 tron 411 1.1 tron <p> The before-filter Postfix SMTP server connects to the content 412 1.1 tron filter, delivers one message, and disconnects. While sending mail 413 1.1 tron into the content filter, Postfix speaks ESMTP but uses no command 414 1.1 tron pipelining. Postfix generates its own EHLO, XFORWARD (for logging 415 1.1 tron the remote client IP address instead of localhost[127.0.0.1]), DATA 416 1.1 tron and QUIT commands, and forwards unmodified copies of all the MAIL 417 1.1 tron FROM and RCPT TO commands that the before-filter Postfix SMTP server 418 1.1 tron didn't reject itself. 419 1.1 tron Postfix sends no other SMTP commands. </p> 420 1.1 tron 421 1.1 tron <p> The content filter should accept the same MAIL FROM and RCPT 422 1.1 tron TO command syntax as the before-filter Postfix SMTP server, and 423 1.1 tron should forward the commands without modification to the after-filter 424 1.1 tron SMTP server. If the content filter or after-filter SMTP server 425 1.1 tron does not support all the ESMTP features that the before-filter 426 1.1 tron Postfix SMTP server supports, then the missing features must be 427 1.1 tron turned off in the before-filter Postfix SMTP server with the 428 1.1 tron smtpd_discard_ehlo_keywords parameter. </p> 429 1.1 tron 430 1.1 tron <p> When the filter rejects content, it should send a negative SMTP 431 1.1 tron response back to the before-filter Postfix SMTP server, and it 432 1.1 tron should abort the connection with the after-filter Postfix SMTP 433 1.1 tron server without completing the SMTP conversation with the after-filter 434 1.1 tron Postfix SMTP server. </p> 435 1.1 tron 436 1.1 tron </body> 437 1.1 tron 438 1.1 tron </html> 439