1176348Smarcel<!doctype html public "-//W3C//DTD HTML 4.01 Transitional//EN" 2176348Smarcel "http://www.w3.org/TR/html4/loose.dtd"> 3176348Smarcel 4176348Smarcel<html> 5176348Smarcel 6176348Smarcel<head> 7176348Smarcel 8176348Smarcel<title>Postfix SMTP Access Policy Delegation </title> 9176348Smarcel 10176348Smarcel<meta http-equiv="Content-Type" content="text/html; charset=us-ascii"> 11176348Smarcel 12176348Smarcel</head> 13176348Smarcel 14176348Smarcel<body> 15176348Smarcel 16176348Smarcel<h1><img src="postfix-logo.jpg" width="203" height="98" ALT="">Postfix SMTP Access Policy Delegation </h1> 17176348Smarcel 18176348Smarcel<hr> 19176348Smarcel 20176348Smarcel<h2>Purpose of Postfix SMTP access policy delegation</h2> 21176348Smarcel 22176348Smarcel<p> The Postfix SMTP server has a number of built-in mechanisms to 23176348Smarcelblock or accept mail at specific SMTP protocol stages. As of version 24176348Smarcel2.1, Postfix can delegate policy decisions to an external server 25176348Smarcelthat runs outside Postfix. </p> 26176348Smarcel 27176348Smarcel<p> With this policy delegation mechanism, a simple <a href="#greylist"> 28176348Smarcelgreylist </a> policy can be implemented with only a dozen lines of 29176348SmarcelPerl, as is shown at the end of this document. A complete example 30176348Smarcelcan be found in the Postfix source code, in the directory 31176348Smarcelexamples/smtpd-policy. </p> 32176348Smarcel 33176348Smarcel<p> Another example of policy delegation is the SPF policy server 34176348Smarcelat http://www.openspf.org/Software. </p> 35176348Smarcel 36176348Smarcel<p> Policy delegation is now the preferred method for adding policies 37177108Srajto Postfix. It's much easier to develop a new feature in few lines 38177108Srajof Perl, Python, Ruby, or TCL, than trying to do the same in C code. 39177108SrajThe difference in 40177108Srajperformance will be unnoticeable except in the most demanding 41177108Srajenvironments. On active systems a policy daemon process is used 42177108Srajmultiple times, for up to $max_use incoming SMTP connections. </p> 43177108Sraj 44177108Sraj<p> This document covers the following topics: </p> 45177108Sraj 46177108Sraj<ul> 47176348Smarcel 48176348Smarcel<li><a href="#protocol">Policy protocol description</a> 49176348Smarcel 50176348Smarcel<li><a href="#client_config">Policy client/server configuration</a> 51176348Smarcel 52177152Sobrien<li><a href="#greylist">Example: greylist policy server</a> 53176348Smarcel 54177152Sobrien<li><a href="#frequent">Greylisting mail from frequently forged domains</a> 55177152Sobrien 56177152Sobrien<li><a href="#all_mail">Greylisting all your mail</a> 57176348Smarcel 58177152Sobrien<li><a href="#maintenance">Routine greylist maintenance</a> 59177152Sobrien 60176348Smarcel<li><a href="#greylist_code">Example Perl greylist server</a> 61176348Smarcel 62177152Sobrien</ul> 63177152Sobrien 64176348Smarcel<h2><a name="protocol">Protocol description</a></h2> 65176348Smarcel 66176348Smarcel<p> The Postfix policy delegation protocol is really simple. The 67176348Smarcelclient request is a sequence of name=value attributes separated by 68176348Smarcelnewline, and is terminated by an empty line. The server reply is 69176348Smarcelone name=value attribute and it, too, is terminated by an empty 70177152Sobrienline. </p> 71176348Smarcel 72177152Sobrien<p> Here is an example of all the attributes that the Postfix SMTP 73server sends in a delegated SMTPD access policy request: </p> 74 75<blockquote> 76<pre> 77<b>Postfix version 2.1 and later:</b> 78request=smtpd_access_policy 79protocol_state=RCPT 80protocol_name=SMTP 81helo_name=some.domain.tld 82queue_id=8045F2AB23 83sender=foo@bar.tld 84recipient=bar@foo.tld 85recipient_count=0 86client_address=1.2.3.4 87client_name=another.domain.tld 88reverse_client_name=another.domain.tld 89instance=123.456.7 90<b>Postfix version 2.2 and later:</b> 91sasl_method=plain 92sasl_username=you 93sasl_sender= 94size=12345 95ccert_subject=solaris9.porcupine.org 96ccert_issuer=Wietse+20Venema 97ccert_fingerprint=C2:9D:F4:87:71:73:73:D9:18:E7:C2:F3:C1:DA:6E:04 98<b>Postfix version 2.3 and later:</b> 99encryption_protocol=TLSv1/SSLv3 100encryption_cipher=DHE-RSA-AES256-SHA 101encryption_keysize=256 102etrn_domain= 103<b>Postfix version 2.5 and later:</b> 104stress= 105[empty line] 106</pre> 107</blockquote> 108 109<p> Notes: </p> 110 111<ul> 112 113 <li> <p> The "request" attribute is required. In this example 114 the request type is "smtpd_access_policy". </p> 115 116 <li> <p> The order of the attributes does not matter. The policy 117 server should ignore any attributes that it does not care about. 118 </p> 119 120 <li> <p> When the same attribute name is sent more than once, 121 the server may keep the first value or the last attribute value. 122 </p> 123 124 <li> <p> When an attribute value is unavailable, the client 125 either does not send the attribute, sends the attribute with 126 an empty value ("name="), or sends a zero value ("name=0") in 127 the case of a numerical attribute. </p> 128 129 <li> <p> The "recipient" attribute is available in the "RCPT 130 TO" stage. It is also available in the "DATA" and "END-OF-MESSAGE" 131 stages if Postfix accepted only one recipient for the current 132 message. </p> 133 134 <li> <p> The "recipient_count" attribute (Postfix 2.3 and later) 135 is non-zero only in the "DATA" and "END-OF-MESSAGE" stages. It 136 specifies the number of recipients that Postfix accepted for 137 the current message. </p> 138 139 <li> <p> The client address is an IPv4 dotted quad in the form 140 1.2.3.4 or it is an IPv6 address in the form 1:2:3::4:5:6. 141 </p> 142 143 <li> <p> For a discussion of the differences between reverse 144 and verified client_name information, see the 145 reject_unknown_client_hostname discussion in the postconf(5) 146 document. </p> 147 148 <li> <p> An attribute name must not contain "=", null or newline, 149 and an attribute value must not contain null or newline. </p> 150 151 <li> <p> The "instance" attribute value can be used to correlate 152 different requests regarding the same message delivery. These 153 requests are sent over the same policy connection (unless the 154 policy daemon terminates the connection). Once Postfix sends 155 a query with a different instance attribute over that same 156 policy connection, the previous message delivery is either 157 completed or aborted. </p> 158 159 <li> <p> The "size" attribute value specifies the message size 160 that the client specified in the MAIL FROM command (zero if 161 none was specified). With Postfix 2.2 and later, it specifies 162 the actual message size when the client sends the END-OF-DATA 163 command. 164 </p> 165 166 <li> <p> The "sasl_*" attributes (Postfix 2.2 and later) specify 167 information about how the client was authenticated via SASL. 168 These attributes are empty in case of no SASL authentication. 169 </p> 170 171 <li> <p> The "ccert_*" attributes (Postfix 2.2 and later) specify 172 information about how the client was authenticated via TLS. 173 These attributes are empty in case of no certificate authentication. 174 As of Postfix 2.2.11 these attribute values are encoded as 175 xtext: some characters are represented by +XX, where XX is the 176 two-digit hexadecimal representation of the character value. With 177 Postfix 2.6 and later, the decoded string is an UTF-8 string 178 without non-printable ASCII characters. </p> 179 180 <li> <p> The "encryption_*" attributes (Postfix 2.3 and later) 181 specify information about how the connection is encrypted. With 182 plaintext connections the protocol and cipher attributes are 183 empty and the keysize is zero. </p> 184 185 <li> <p> The "etrn_domain" attribute is defined only in the 186 context of the ETRN command, and specifies the ETRN command 187 parameter. </p> 188 189 <li> <p> The "stress" attribute is either empty or "yes". See 190 the STRESS_README document for further information. </p> 191 192</ul> 193 194<p> The following is specific to SMTPD delegated policy requests: 195</p> 196 197<ul> 198 199 <li> <p> Protocol names are ESMTP or SMTP. </p> 200 201 <li> <p> Protocol states are CONNECT, EHLO, HELO, MAIL, RCPT, 202 DATA, END-OF-MESSAGE, VRFY or ETRN; these are the SMTP protocol 203 states where 204 the Postfix SMTP server makes an OK/REJECT/HOLD/etc. decision. 205 </p> 206 207</ul> 208 209<p> The policy server replies with any action that is allowed in a 210Postfix SMTPD access(5) table. Example: </p> 211 212<blockquote> 213<pre> 214action=defer_if_permit Service temporarily unavailable 215[empty line] 216</pre> 217</blockquote> 218 219<p> This causes the Postfix SMTP server to reject the request with 220a 450 temporary error code and with text "Service temporarily 221unavailable", if the Postfix SMTP server finds no reason to reject 222the request permanently. </p> 223 224<p> In case of trouble the policy server must not send a reply. 225Instead the server must log a warning and disconnect. Postfix will 226retry the request at some later time. </p> 227 228<h2><a name="client_config">Policy client/server configuration</a></h2> 229 230<p> The Postfix delegated policy client can connect to a TCP socket 231or to a UNIX-domain socket. Examples: </p> 232 233<blockquote> 234<pre> 235inet:127.0.0.1:9998 236unix:/some/where/policy 237unix:private/policy 238</pre> 239</blockquote> 240 241<p> The first example specifies that the policy server listens on 242a TCP socket at 127.0.0.1 port 9998. The second example specifies 243an absolute pathname of a UNIX-domain socket. The third example 244specifies a pathname relative to the Postfix queue directory; use 245this for policy servers that are spawned by the Postfix master 246daemon. </p> 247 248<p> To create a policy service that listens on a UNIX-domain socket 249called "policy", and that runs under control of the Postfix spawn(8) 250daemon, you would use something like this: </p> 251 252<blockquote> 253<pre> 254 1 /etc/postfix/master.cf: 255 2 policy unix - n n - 0 spawn 256 3 user=nobody argv=/some/where/policy-server 257 4 258 5 /etc/postfix/main.cf: 259 6 smtpd_recipient_restrictions = 260 7 ... 261 8 reject_unauth_destination 262 9 check_policy_service unix:private/policy 26310 ... 26411 policy_time_limit = 3600 265</pre> 266</blockquote> 267 268<p> NOTES: </p> 269 270<ul> 271 272<li> <p> Lines 2, 11: the Postfix spawn(8) daemon by default kills 273its child process after 1000 seconds. This is too short for a 274policy daemon that may need to run for as long as the SMTP server 275process that talks to it. The default time limit is overruled in 276main.cf with an explicit "policy_time_limit" setting. The name of 277the parameter is the name of the master.cf entry ("policy") 278concatenated with the "_time_limit" suffix. See spawn(8) for 279more information about the time limit parameter. </p> 280 281<li> <p> Line 2: specify a "0" process limit instead of the default 282"-", to avoid "connection refused" and other problems when the smtpd 283process limit exceeds the default_process_limit setting. </p> 284 285<li> <p> Lines 8, 9: always specify "check_policy_service" AFTER 286"reject_unauth_destination" or else your system could become an 287open relay. </p> 288 289<li> <p> Solaris UNIX-domain sockets do not work reliably. Use 290TCP sockets instead: </p> 291 292</ul> 293 294<blockquote> 295<pre> 296 1 /etc/postfix/master.cf: 297 2 127.0.0.1:9998 inet n n n - 0 spawn 298 3 user=nobody argv=/some/where/policy-server 299 4 300 5 /etc/postfix/main.cf: 301 6 smtpd_recipient_restrictions = 302 7 ... 303 8 reject_unauth_destination 304 9 check_policy_service inet:127.0.0.1:9998 30510 ... 30611 127.0.0.1:9998_time_limit = 3600 307</pre> 308</blockquote> 309 310<p> Other configuration parameters that control the client side of 311the policy delegation protocol: </p> 312 313<ul> 314 315<li> <p> smtpd_policy_service_max_idle (default: 300s): The amount 316of time before the Postfix SMTP server closes an unused policy 317client connection. </p> 318 319<li> <p> smtpd_policy_service_max_ttl (default: 1000s): The amount 320of time before the Postfix SMTP server closes an active policy 321client connection. </p> 322 323<li> <p> smtpd_policy_service_timeout (default: 100s): The time 324limit to connect to, send to or receive from a policy server. </p> 325 326</ul> 327 328<h2><a name="greylist">Example: greylist policy server</a></h2> 329 330<p> Greylisting is a defense against junk email that is described at 331http://www.greylisting.org/. The idea was discussed on the 332postfix-users mailing list <a 333href="http://archives.neohapsis.com/archives/postfix/2002-03/0846.html"> 334one year before it was popularized</a>. </p> 335 336<p> The file examples/smtpd-policy/greylist.pl in the Postfix source 337tree implements a simplified greylist policy server. This server 338stores a time stamp for every (client, sender, recipient) triple. 339By default, mail is not accepted until a time stamp is more than 34060 seconds old. This stops junk mail with randomly selected sender 341addresses, and mail that is sent through randomly selected open 342proxies. It also stops junk mail from spammers that change their 343IP address frequently. </p> 344 345<p> Copy examples/smtpd-policy/greylist.pl to /usr/libexec/postfix 346or whatever location is appropriate for your system. </p> 347 348<p> In the greylist.pl Perl script you need to specify the 349location of the greylist database file, and how long mail will 350be delayed before it is accepted. The default settings are: 351</p> 352 353<blockquote> 354<pre> 355$database_name="/var/mta/greylist.db"; 356$greylist_delay=60; 357</pre> 358</blockquote> 359 360<p> The /var/mta directory (or whatever you choose) should be 361writable by "nobody", or by whatever username you configure below 362in master.cf for the policy service. </p> 363 364<p> Example: </p> 365 366<blockquote> 367<pre> 368# mkdir /var/mta 369# chown nobody /var/mta 370</pre> 371</blockquote> 372 373<p> Note: DO NOT create the greylist database in a world-writable 374directory such as /tmp or /var/tmp, and DO NOT create the greylist 375database in a file system that may run out of space. Postfix can 376survive "out of space" conditions with the mail queue and with the 377mailbox store, but it cannot survive a corrupted greylist database. 378If the file becomes corrupted you may not be able to receive mail 379at all until you delete the file by hand. </p> 380 381<p> The greylist.pl Perl script can be run under control by 382the Postfix master daemon. For example, to run the script as user 383"nobody", using a UNIX-domain socket that is accessible by Postfix 384processes only: </p> 385 386<blockquote> 387<pre> 3881 /etc/postfix/master.cf: 3892 policy unix - n n - 0 spawn 3903 user=nobody argv=/usr/bin/perl /usr/libexec/postfix/greylist.pl 3914 3925 /etc/postfix/main.cf: 3936 policy_time_limit = 3600 394</pre> 395</blockquote> 396 397<p> Notes: </p> 398 399<ul> 400 401<li> <p> Line 3: Specify "greylist.pl -v" for verbose logging of 402each request and reply. </p> 403 404<li> <p> Lines 2, 6: the Postfix spawn(8) daemon by default kills 405its child process after 1000 seconds. This is too short for a 406policy daemon that may run for as long as an SMTP client is connected 407to an SMTP server process. The default time limit is overruled in 408main.cf with an explicit "policy_time_limit" setting. The name of 409the parameter is the name of the master.cf entry ("policy") 410concatenated with the "_time_limit" suffix. </p> 411 412<li> <p> Line 2: specify a "0" process limit instead of the default 413"-", to avoid "connection refused" and other problems when the smtpd 414process limit exceeds the default_process_limit setting. </p> 415 416</ul> 417 418<p> On Solaris you must use inet: style sockets instead of unix: 419style, as detailed in the "<a href="#client_config">Policy 420client/server configuration</a>" section above. </p> 421 422<blockquote> 423<pre> 4241 /etc/postfix/master.cf: 4252 127.0.0.1:9998 inet n n n - 0 spawn 4263 user=nobody argv=/usr/bin/perl /usr/libexec/postfix/greylist.pl 4274 4285 /etc/postfix/main.cf: 4296 127.0.0.1:9998_time_limit = 3600 430</pre> 431</blockquote> 432 433<p> To invoke this service you would specify "check_policy_service 434inet:127.0.0.1:9998". </p> 435 436<h2><a name="frequent">Greylisting mail from frequently forged domains</a></h2> 437 438<p> It is relatively safe to turn on greylisting for specific 439domains that often appear in forged email. At some point 440in cyberspace/time a list of frequently 441forged MAIL FROM domains could be found at 442http://www.monkeys.com/anti-spam/filtering/sender-domain-validate.in. 443 444<blockquote> 445<pre> 446 1 /etc/postfix/main.cf: 447 2 smtpd_recipient_restrictions = 448 3 reject_unlisted_recipient 449 4 ... 450 5 reject_unauth_destination 451 6 check_sender_access hash:/etc/postfix/sender_access 452 7 ... 453 8 smtpd_restriction_classes = greylist 454 9 greylist = check_policy_service unix:private/policy 45510 45611 /etc/postfix/sender_access: 45712 aol.com greylist 45813 hotmail.com greylist 45914 bigfoot.com greylist 46015 ... <i>etcetera</i> ... 461</pre> 462</blockquote> 463 464<p> NOTES: </p> 465 466<ul> 467 468<li> <p> Line 9: On Solaris you must use inet: style sockets 469instead of unix: style, as detailed in the "<a href="#greylist">Example: 470greylist policy server</a>" section above. </p> 471 472<li> <p> Line 6: Be sure to specify "check_sender_access" AFTER 473"reject_unauth_destination" or else your system could become an 474open mail relay. </p> 475 476<li> <p> Line 3: With Postfix 2.0 snapshot releases, 477"reject_unlisted_recipient" is called "check_recipient_maps". 478Postfix 2.1 understands both forms. </p> 479 480<li> <p> Line 3: The greylist database gets polluted quickly with 481bogus addresses. It helps if you protect greylist lookups with 482other restrictions that reject unknown senders and/or recipients. 483</p> 484 485</ul> 486 487<h2><a name="all_mail">Greylisting all your mail</a></h2> 488 489<p> If you turn on greylisting for all mail you will almost certainly 490want to make exceptions for mailing lists that use one-time sender 491addresses, because such mailing lists can pollute your greylist 492database relatively quickly. </p> 493 494<blockquote> 495<pre> 496 1 /etc/postfix/main.cf: 497 2 smtpd_recipient_restrictions = 498 3 reject_unlisted_recipient 499 4 ... 500 5 reject_unauth_destination 501 6 check_sender_access hash:/etc/postfix/sender_access 502 7 check_policy_service unix:private/policy 503 8 ... 504 9 50510 /etc/postfix/sender_access: 50611 securityfocus.com OK 50712 ... 508</pre> 509</blockquote> 510 511<p> NOTES: </p> 512 513<ul> 514 515<li> <p> Line 7: On Solaris you must use inet: style sockets 516instead of unix: style, as detailed in the "<a href="#greylist">Example: 517greylist policy server</a>" section above. </p> 518 519<li> <p> Lines 6-7: Be sure to specify check_sender_access and 520check_policy_service AFTER reject_unauth_destination or else your 521system could become an open mail relay. </p> 522 523<li> <p> Line 3: The greylist database gets polluted quickly with 524bogus addresses. It helps if you precede greylist lookups with 525restrictions that reject unknown senders and/or recipients. </p> 526 527</ul> 528 529<h2><a name="maintenance">Routine greylist maintenance</a></h2> 530 531<p> The greylist database grows over time, because the greylist server 532never removes database entries. If left unattended, the greylist 533database will eventually run your file system out of space. </p> 534 535<p> When the status file size exceeds some threshold you can simply 536rename or remove the file without adverse effects; Postfix 537automatically creates a new file. In the worst case, new mail will 538be delayed by an hour or so. To lessen the impact, rename or remove 539the file in the middle of the night at the beginning of a weekend. 540</p> 541 542<h2><a name="greylist_code">Example Perl greylist server</a></h2> 543 544<p> This is the Perl subroutine that implements the example greylist 545policy. It is part of a general purpose sample policy server that 546is distributed with the Postfix source as 547examples/smtpd-policy/greylist.pl. </p> 548 549<pre> 550# 551# greylist status database and greylist time interval. DO NOT create the 552# greylist status database in a world-writable directory such as /tmp 553# or /var/tmp. DO NOT create the greylist database in a file system 554# that can run out of space. 555# 556$database_name="/var/mta/greylist.db"; 557$greylist_delay=60; 558 559# 560# Auto-whitelist threshold. Specify 0 to disable, or the number of 561# successful "come backs" after which a client is no longer subject 562# to greylisting. 563# 564$auto_whitelist_threshold = 10; 565 566# 567# Demo SMTPD access policy routine. The result is an action just like 568# it would be specified on the right-hand side of a Postfix access 569# table. Request attributes are available via the %attr hash. 570# 571sub smtpd_access_policy { 572 my($key, $time_stamp, $now); 573 574 # Open the database on the fly. 575 open_database() unless $database_obj; 576 577 # Search the auto-whitelist. 578 if ($auto_whitelist_threshold > 0) { 579 $count = read_database($attr{"client_address"}); 580 if ($count > $auto_whitelist_threshold) { 581 return "dunno"; 582 } 583 } 584 585 # Lookup the time stamp for this client/sender/recipient. 586 $key = 587 lc $attr{"client_address"}."/".$attr{"sender"}."/".$attr{"recipient"}; 588 $time_stamp = read_database($key); 589 $now = time(); 590 591 # If new request, add this client/sender/recipient to the database. 592 if ($time_stamp == 0) { 593 $time_stamp = $now; 594 update_database($key, $time_stamp); 595 } 596 597 # The result can be any action that is allowed in a Postfix access(5) map. 598 # 599 # To label the mail, return ``PREPEND headername: headertext'' 600 # 601 # In case of success, return ``DUNNO'' instead of ``OK'', so that the 602 # check_policy_service restriction can be followed by other restrictions. 603 # 604 # In case of failure, return ``DEFER_IF_PERMIT optional text...'', 605 # so that mail can still be blocked by other access restrictions. 606 # 607 syslog $syslog_priority, "request age %d", $now - $time_stamp if $verbose; 608 if ($now - $time_stamp > $greylist_delay) { 609 # Update the auto-whitelist. 610 if ($auto_whitelist_threshold > 0) { 611 update_database($attr{"client_address"}, $count + 1); 612 } 613 return "dunno"; 614 } else { 615 return "defer_if_permit Service temporarily unavailable"; 616 } 617} 618</pre> 619 620</body> 621 622</html> 623