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://www.openspf.org 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!) Mail::SRS (version 0.30) 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 define(`confMILTER_MACROS_HELO', confMILTER_MACROS_HELO`, {verify}')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}, {verify} 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/perl-threaded/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://www.openspf.org/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. SRS AND FAKE DSN DETECTION ----------------------------- A) Outline As of version 1.40, spf-milter comes with a new functionality: fake DSN detection. It is activated by the -S option; and, when enabled, will spot and REJECT unsigned DSN recipients. Signatures are based on SRS (Mail::SRS). This is an advanced option; it requires an MTA counterpart installation to sign outgoing envelope-from addresses, and should not be used unless you are well familiar with the entire scheme and its possible ramifications. The idea, in a nutshell, is as follows. Have an MTA sign all outgoing envelope-from addresses. Then, when we receive a DSN (bounce message with a MAIL FROM: <>), we will REJECT this DSN, unless the recipient was SRS signed. Based on the old "what goes around, comes around" adage (or rather, "what does not go around, should not come around"): if we do not ever send out unsigned envelope-from addresses, then we know we are dealing with a forgery when we receive an unsigned DSN recipient! Only use this when you have implemented an SRS signing scheme in your MTA, which will sign ALL outgoing envelope-from addresses. Unfortunately, spf-milter cannot do that for you, as the Milter specs do not allow for a method to change the envelope-from address. You may want to have a peek at my SRS + sendmail integration project, at: http://asarian-host.net/srs/sendmailsrs.htm B) How to use FAKE DSN DETECTION without SRS reversal in sendmail If your incoming mail server differs from your outgoing one, then there is way to use FAKE DSN DETECTION without setting up SRS reversal in the sendmail configuration for you incoming mail server. Since spf-milter handles your locally targeted SRS recipients, you would think that suffices. And it does. However, the Milter specification does not permit the changing of recipients at envrcpt_callback, and forces you to wait until eom_callback; thereby leaving an intermediate window, between callbacks, where sendmail itself will verify the recipients (upon return of envrcpt_callback), and conclude that your nice SRS0 bounce address does not exist on the system. The result? Sendmail will REJECT the recipient with a "User unknown" after all. The way to solve this, is to make use of sendmail's "plussed" user facility. Define two users (virtusertable), like so: SRS0+*@yourdomain.com user SRS1+*@yourdomain.com user (where "user" is the name of an existing user). This will provide the necessary "fallback" for the undefined in-between callback state. Mind you, these are 'dummy' addresses; they are never actually used for delivery; they are just there to prevent sendmail from bulking over your SRS addresses, in-between callbacks. Now that sendmail has these fallback wildcard addresses, spf-milter can proceed until eom_callback, where it will replace the SRS signed envelope recipient(s) with their reversed counterparts. For this to work, your SRS 'separator' character must be "+". Like so: my $srs = new Mail::SRS (Secret => 'yaddayadda', Separator => '+'); So that SRS0+, SRS1+ addresses are formed. C) Start-up considerations To use SRS on spf-milter, start it with the -S parameter; a minimum command line usage would be: ./sendmail-milter-spf-1.40.pl -S milter This will place spf-milter in FAKE DSN DETECTION mode, running as user "milter". There has been some discussion on whether people should become SRS1 forwarding hosts. To accomodate both parties, spf-milter can be started with an additional option, "-r". If set, spf-milter will relay non-locally resolving SRS0 addresses (reversed from SRS1 addresses). Per default, spf-milter only accepts locally resolving SRS0 addresses. If you want full SRS1 functionality, start spf-milter like so (minimal): ./sendmail-milter-spf-1.40.pl -S -r milter Whether you start spf-milter with -S or not, when relaying, spf-milter is always SRS aware (that is, when your own mailer is sending TO foreign SRS0, SRS1 addresses). The "-r" option, outside -S, only has meaning when relaying. 5. 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 ------- To unsubscribe, change your address, or temporarily deactivate your subscription, please go to http://v2.listbox.com/member/?listname=srs-discuss@v2.listbox.com