by Mark, System Administrator Asarian-host.org 1. INTRODUCTION --------------- spf-milter is a Milter, which works with Sendmail 8.12 and up, and provides an SPF-compliant extension to the SMTP communication between your MTA and connecting clients. See http://spf.pobox.com/ for details about SPF itself. spf-milter is written entirely in Perl, and uses the native threaded Milter model. spf-milter is licensed under GPL. 2. PREREQUISITES ---------------- spf-milter requires: 1): Perl 5.8.x, or higher. 2): Perl modules: Sendmail::Milter (version 0.18) Mail::SPF::Query (at least version 1.99!) 3. INSTALLATION --------------- Since spf-milter is written in Perl, you need, for starters, Sendmail::Milter (at CPAN). The Milter API is threaded, so you need a thread-enabled Perl (compiled with -Duseithreads) as well. If you do not know whether you Perl supports threads, try and install Sendmail::Milter first. It will itself test the ithread functionality of your Perl for compatibility with Sendmail::Milter. I built and tested spf-milter under Perl, v5.8.0 built for i386-freebsd-thread-multi. Earlier versions of Perl versions may or may not be suitable. A) Sendmail You must be using Sendmail 8.12.x --------------------------------- Obtain the latest Sendmail 8.12.x source release from http://www.sendmail.org. Unpack it. Add the following lines to devtools/Site/site.config.m4: APPENDDEF(`conf_libmilter_ENVDEF', `-DMILTER') APPENDDEF(`conf_sendmail_ENVDEF', `-DMILTER') This enables the Milter functionality. Now build Sendmail as usual ("sh Build" in the sendmail/ directory). Add the following lines to your Sendmail "m4" configuration file (*.mc, in the cf/cf/ directory): define(`confMILTER_LOG_LEVEL',`9')dnl INPUT_MAIL_FILTER(`spf-milter', `S=local:/var/spf-milter/spf-milter.sock, F=T, T=C:4m;S:4m;R:8m;E:10m') Adjust the MILTER_LOG_LEVEL and T timings to your liking. Now build sendmail.cf as usual ("./Build sendmail.cf" in the cf/cf/ directory). Your newly generated sendmail.cf will now contain a section that looks like this: # Milter options O Milter.LogLevel=9 O Milter.macros.connect=j, _, {daemon_name}, {if_name}, {if_addr} O Milter.macros.helo={tls_version}, {cipher}, {cipher_bits}, {cert_subject}, {cert_issuer} O Milter.macros.envfrom=i, {auth_type}, {auth_authen}, {auth_ssf}, {auth_author}, {mail_mailer}, {mail_host}, {mail_addr} O Milter.macros.envrcpt={rcpt_mailer}, {rcpt_host}, {rcpt_addr} And this: ###################################################################### ###################################################################### ##### ##### MAILER DEFINITIONS ##### ###################################################################### ###################################################################### Xspf-milter, S=local:/var/spf-milter/spf-milter.sock, F=T, T=C:4m;S:4m;R:8m;E:10m Inspect your new sendmail.cf, to see whether it does indeed contain these things. B) Startup You are already ready to start spf-milter! :) Sendmail does not need to "find" the spf-milter script. You can run it from pretty much every location. The only thing sendmail needs to do, is to be able to find the local domain socket to connect to (spf-milter creates "/var/spf-milter/spf-milter.sock" per default). If you successfully followed the above steps, then your new sendmail.cf will contain the proper local socket name. Backup your old sendmail.cf. Now, stop sendmail, and copy the new sendmail.cf to its proper location. Now, start spf-milter first! Depending on where your thread-enabled Perl resides, of course, you can, in its simplest form, start spf-milter like this: /usr/local/threadedperl/bin/perl /usr/local/spf/sendmail-milter.pl milter We start spf-milter with at least one parameter, the user to run as. spf-milter expects to create/read/write its log, pid, and socket, all in /var/spf-milter/, and will itself create the directory, if need be, and set all appropriate permissions/ownerships. You cannot run spf-milter as root. If everything went okay, try 'ps ax', and your spf-milter will show up as: "spf-milter (perl)" Restart sendmail. Now you're done. :) C) Testing spf-milter functionality Perform two basic tests: 1) Make sure legitimate mail gets through! 2) Confirm that forged mail is rejected; forging mail from mengwong@vw.mailzone.com will do the trick (address used with permission). If properly rejected, you will get a 550 response, and a text with a reference to "http://spf.pobox.com/why.html? ..." in the line. N.B. The actual return-text may vary from MTA to MTA, but the 550 response code SHOULD always be the same (an extended SMTP code, '550', '5.7.1'). 4. COMMON QUESTIONS ANSWERED ---------------------------- 1) Why does spf-milter use the native threaded Milter model? Because Sendmail::Milter does. 2) How does spf-milter stay stable using ithreads? Instead of using a multiplexor to split threads over individual child processes (like MIMEDefang), spf-milter 'locks' (thread-locks) its callbacks, thus effectively serializing the threads; so you get much of the effect of what the MIMEDefang multiplexor does (kinda). And since the 'locked' attribute really prevents the threads from clobbering over one another, you can even use thread-unsafe package calls within those subs, like to DBI. 3) By serializing all callbacks, do you not reduce performance? Without locking the subroutines, Sendmail::Milter is simply way too unstable, and effectively unusable. However, since there are 10 callbacks in total, each thread is only serialized for those occassions when two threads try and access the same sub at the same time. Otherwise they run parallel too: one thread may acces the eom_callback whilst another enters the helo_callback, for instance. In fact, as long as all threads are just slightly out of phase with one another (one callback difference minimum), they all run nicely parallel. 4) Does spf-milter act prior to the DATA phase? Yes, spf-milter makes its SPF checks before the DATA phase; at envfrom_callback (at: "MAIL FROM:
"), or at envrcpt_callback (at: "RCPT TO: "), when running in "mx" mode. 5) Can spf-milter be used within the same sendmail configuration as MIMEDefang (and other Milters)? Yes. Quoting a bit from the libmilter documentation: +----------------------------------------+ | SPECIFYING FILTERS IN SENDMAIL CONFIGS | +----------------------------------------+ Filters are specified with a key letter ``X'' (for ``eXternal''). For example: Xfilter1, S=local:/var/run/f1.sock, F=R Xfilter2, S=inet6:999@localhost, F=T, T=C:10m;S:1s;R:1s;E:5m Xfilter3, S=inet:3333@localhost specifies three filters. Filters can be specified in your .mc file using the following: INPUT_MAIL_FILTER(`filter1', `S=local:/var/run/f1.sock, F=R') INPUT_MAIL_FILTER(`filter2', `S=inet6:999@localhost, F=T') INPUT_MAIL_FILTER(`filter3', `S=inet:3333@localhost') Which filters are invoked and their sequencing is handled by the InputMailFilters option: O InputMailFilters=filter1, filter2, filter3 This is is set automatically according to the order of the INPUT_MAIL_FILTER commands in your .mc file. Alternatively, you can reset its value by setting confINPUT_MAIL_FILTERS in your .mc file. This options causes the three filters to be called in the same order they were specified. - Mark System Administrator Asarian-host.org