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