Dies ist eine alte Version des Dokuments!
SPF - Sender Policy Framework
Mit Hilfe von SPF1) kann definiert werden, welche Mailserver für welche Domains eMails verschickt werden (können), oder nicht, oder anders ausgedrückt, soll das Fälschen von Absender-Angaben mit Hilfe von SPF erschwert werden. Genauer gesagt schreibt das SPF fest, welcher MTA2) abgehend für den Versandt von e-Mails einer Domain zugelassen ist. Wichtige Hinweise zu SPF findet man bei Bedarf im RFC 4408 oder auch auf der Webseite von openspf.org.
Mit SPF soll hauptsächlich Absenderadressfälschungen verhindert werden, nicht jedoch direkt Spam zu bekämpfen. Dieses here Ziel wirft bei genauerer Betrachtung viele Fragen auf und erzeugt bei manchen Mailserver-Betreibern nicht gerade viel Begeisterungsstürme. Probleme tauchen mit unter bei Mailumleitungen, Mailinglisten und/oder WebFormularen auf. Auch wird bei sehr konservativen SPF-Definition die Möglichkeit verhindert, eMails mit eigener Absender-eMail-Adresse über einen dritten Rechner zu versenden. Es wäre also nur möglich eMails auch über den Mail-Server zu versenden, auf dem auch das Postfach liegt! Speziell auch Beim Versand über ein z.B. WebFormular, oder eine Web-Grußkarte über einen Drittanbieter wäre dann kein Versand mehr möglich!
Beim SPF wird ein TXT-Record in der Zonendatei der betreffenden (Mail)Domain eingetragen. Dort wird definiert, welche SMTP-Server berechtigt sind, Nachrichten der (Mail)Domain zu verschicken. Mailserver können dann bei der Annahme der eMails abfragen, ob der sendende Mailserver überhaupt berechtigt ist, diese Nachricht zu verschicken.
<uml w=800>
title Mailversand einer eMail\n skin BlueModern participant „\n Mail-Server mx01.nausch.org \n“ as links participant „\n Mail-Server mx1.tachtler.net \n“ as mitte participant „\n DNS-Server von nausch.org \n“ as rechts
links → mitte : connect von mx01.nausch.org zu mx1.tachtler.net note left : \n Verbindungsaufbau \n vom Quell- zum \n Zielserver \n links ←- mitte : . 220 mx1.tachtler.net ESMTP Postfix links –> mitte : HELO mx01.nausch.org links ←- mitte : . 250 mx1.tachtler.net links –> mitte : MAIL FROM:django@nausch.org links ←- mitte : . 250 2.1.0 Ok mitte → rechts : host -t TXT nausch.org note right : \n Abfrage der \n SPF-Records \n mitte ← rechts : nausch.org descriptive text „v=spf1 ip4:217.91.103.190/32 mx ?all“ note left : \n Der Mailserver mit der \n IP 217.91.103.190 ist berechtigt \n eMails der Mail-Domain \n nausch.org zu versenden \n links –> mitte : RCPT TO:klaus@tachtler.net links ←- mitte : . 250 2.1.0 Ok
links –> mitte : Übermittlung der Nachricht links ←- mitte : 250 2.0.0 Ok: queued as 5950581 note left : \n Beenden der Verbindung \n
</uml>
Weitere Informationen rund um SPF findet man im übrigen auf der Wikipedia Seite.
Definition unseres SPF-Records
Aus den eingangs genannten Gründen sollte eine Sender Policy Framework Definition so gewählt werden, das auch weiterhin Nachrichten umgeleitet, Mailinglisten oder bei Bedarf Webformulare genutzt werden können.
Ein SPF-Record beinhaltet mehrere Angaben, die jeweils von links nach rechts ausgewertet werden. Der erste Wert gibt an, welche SPF-Version genutzt wird, aktuell SPF-Version „v=spf1“. Anschließend können mehrere IPv4- und/oder IPv6-Adressen angegeben werden, die entweder berechtigt oder vom Mailversand ausgeschlossen sein sollen. Diese Berechtigung wird dabei über einen Qualifier definiert. Es stehen folgende Werte zur Verfügung:
- + : positiv Die nachfolgende IP-Adresse ist als legitimer Sender definiert. Wird kein Qualifer angegeben, wird automatisch der Wert + herangezogen (Defaulteinstellung).
- - : negativ Die nachfolgende IP-Adresse definiert ein nicht autorisiertes Sendesystem Fail die Direktive definiert nicht autorisierte Sender
- ? : neutral Über die Rechtmäßigkeit des Sendesystems kann nichts ausgesagt werden; Der Sender muß daher akzeptiert werden.
- ~ : soft-fail Die nachfolgende IP-Adresse definiert ein nicht autorisiertes Sendesystem. Das Empfangssystem soll jedoch die Annahme der Nachricht dennoch annehmen (Test-Qualifier).
Neben der IP-Adressangabe mittels ip4 bzw.ip6, gibt es noch vier weitere Parameter, die im SPF-Record Anwendung finden.
- a definiert einen A-Record der Domäne
- mx definiert eine IP-Adresse, die im MX-Record der Domäne definiert wurde.
- all Alle anderen IP-Adressen, also den Rest der weiten Welt.
- include Einbinden einer weiteren SPF-Abfrage.
In der Regel wird man bei der Definition folgenden Festlegung treffen: eMails werden normalerweise immer von den IP-Adressen des zuständigen Mailserver versandt, können aber auch von anderen Servern verschickt werden. Als SPF-Record ergibt das dann „v=spf1 ip4:217.91.103.190/32 mx ?all“ im Falle des Mailservers mx01.nausch.org mit der IP-Adresse: 217.91.103.190
Wir tragen also bei unserem zuständigen DNS entsprechend die richtigen Daten ein.
nausch.org IN TXT "v=spf1 ip4:217.91.103.190/32 mx ?all"
Über die URL SPF Record Testing Tools kann man online bei Bedarf testen, ob der SPF-Eintrag soweit richtig ist.
SPF-Bewertung bei der Mailannahme
Neben der Befragung von Black-/White-Listen, dem Nutzen von Greylisting oder policyd-weight, können wir SPF bei der Bewertung von eingehenden Sendungen heranziehen. Wir greifen bei der SPF-Bewertung auf den Postfix Poliyd-Daemon pypolicyd-spf einem Python-Script zurück. Wir finden diesen Daemon im EPEL-Repository.
Installation
Das RPM-Paket aus dem EPEL-Repository installieren wir am einfachsten mittels yum.
# yum install pypolicyd-spf
Was uns das Paket alles mitbringt, zeigt uns wie immer der Aufruf von rpm -qil <paketname>
# rpm -qil pypolicyd-spf
Name : pypolicyd-spf Relocations: (not relocatable) Version : 1.2 Vendor: Fedora Project Release : 3.el6 Build Date: Mon 12 Aug 2013 04:54:00 AM CEST Install Date: Sun 16 Mar 2014 10:33:12 AM CET Build Host: buildvm-05.phx2.fedoraproject.org Group : Unspecified Source RPM: pypolicyd-spf-1.2-3.el6.src.rpm Size : 102907 License: ASL 2.0 Signature : RSA/8, Wed 14 Aug 2013 05:28:11 PM CEST, Key ID 3b49df2a0608b895 Packager : Fedora Project URL : https://launchpad.net/pypolicyd-spf Summary : SPF Policy Server for Postfix (Python implementation) Description : pypolicyd-spf is a Postfix policy engine for Sender Policy Framework (SPF) checking. It is implemented in pure Python and uses the python-spf (pyspf) module. This SPF policy server implementation provides flexible options for different receiver policies and sender whitelisting to enable it to support a very wide range of requirements. /etc/python-policyd-spf /etc/python-policyd-spf/policyd-spf.conf /usr/lib/python2.6/site-packages/policydspfsupp.py /usr/lib/python2.6/site-packages/policydspfsupp.pyc /usr/lib/python2.6/site-packages/policydspfsupp.pyo /usr/lib/python2.6/site-packages/policydspfuser.py /usr/lib/python2.6/site-packages/policydspfuser.pyc /usr/lib/python2.6/site-packages/policydspfuser.pyo /usr/lib/python2.6/site-packages/pypolicyd_spf-1.2-py2.6.egg-info /usr/libexec/postfix/policyd-spf /usr/share/doc/pypolicyd-spf-1.2 /usr/share/doc/pypolicyd-spf-1.2/CHANGES /usr/share/doc/pypolicyd-spf-1.2/COPYING /usr/share/doc/pypolicyd-spf-1.2/README /usr/share/doc/pypolicyd-spf-1.2/README.per_user_whitelisting /usr/share/doc/pypolicyd-spf-1.2/policyd-spf.conf.commented /usr/share/man/man1/policyd-spf.1.gz /usr/share/man/man5/policyd-spf.conf.5.gz /usr/share/man/man5/policyd-spf.peruser.5.gz
Hinweise zur Konfiguration
Hilfreiche Hinweise zur nötigen Konfiguration finden wir reichlich bei dem gut Dokumentiertem Projekt. Erste Anlaufstelle ist hierbei die Datei README.
# less /usr/share/doc/pypolicyd-spf-1.2/README
Python Postfix Policy for SPF (python-policy-spf) 1.2 Python based policy daemon for Postfix SPF checking Tumgreyspf source Copyright © 2004-2005, Sean Reifschneider, tummy.com, ltd. <jafo@tummy.com> python-policyd-spf changes Copyright © 2007-2012 Scott Kitterman <scott@kitterman.com> <https://launchpad.net/pypolicyd-spf> Documentation inputs: Copyright © 2004-2005, Sean Reifschneider, tummy.com, ltd. <jafo@tummy.com> 2003-2004 Meng Weng Wong <mengwong@pobox.com> from postfix-policyd-spf-perl Copyright © 2007-2013 Scott Kitterman <scott@kitterman.com> Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. ================= This is python-policyd-spf, an external policy checker for the postfix mail server. It will use pyspf to check SPF records to determine if email should be rejected by your server. To install from the tar.gz (if this software has been packaged for your distribution, the packaged version is recommended and should be installed using your normal distribution packaging tools): 1. Extract the package from the tarball (tar -xvvzf ...) 2. Enter the package directory (cd ...) 3. python setup.py build 4. As root python setup.py install It requires Python (python2.6, python2.7, or python3.2+), the pyspf (python-spf) library version 2.0 or higher, and (for Python versions before python3.3, the ipaddr module - for python3.3 and later the built-in ipaddress module is used). If pyspf not available through your packaging system, it can be downloaded from: http://sourceforge.net/projects/pymilter/ If ipaddr not available through your packaging system, it can be downloaded from: http://code.google.com/p/ipaddr-py/downloads/list To use the optional RFC 5451 Authentication-Results header, the authres module is also needed. It can be downloaded from pypi or from: https://launchpad.net/authentication-results-python Nothing is configured by default, so this will not interact with Postfix until it has been set up. See man 1 policyd-spf for information on setting up and using this policy server. See man 5 policyd-spf.conf for configuration file information.
policyd-spf
# man policyd-spf
policy-spf(1) policy-spf(1) NAME python-policyd-spf - pure-Python Postfix policy daemon for SPF checking VERSION 1.1.1 USAGE NOTE: Depending on the packaging and distribution, the exact path to the executable may vary. $ policyd-spf (Start using installed config file) $ policyd-spf -h (Display usage message) $ policyd-spf /etc/policyd-spf/policyd-spf.conf (Config file name to use) Configuration options are described in the sample configuration file provided with the pack- age (policyd-spf.conf.commented) and in policyd-spf.conf(5). The provided setup.py installs an uncommented configuration file in /etc/policyd-spf/. Additionally, whitelisting certain IP addresses or IP addresses used by listed domains from SPF checks is supported. Skipping SPF checks for local submission or trusted relays is also provided. The sample configuration file and policyd-spf.conf(5) shows the format to use. OTHER DOCUMENTATION This documentation assumes you have read Postfix’s README_FILES/ SMTPD_POLICY_README and are generally familiar with Sender Policy Framework (SPF). See RFC 4408 for details. See man 5 policyd-spf.conf for configuration file information. man 5 policyd-spf.peruser provides documentation on setting up and using different configura- tion options on a per user (mail reciepient) basis. SYNOPSIS python-policyd-spf is a Postfix SMTPd policy daemon for SPF checking. It is implemented in pure Python and uses the pyspf module. The SPF web site is http://www.openspf.org/. The Postfix configuration must be changed to check SPF. DESCRIPTION Logging is sent to syslogd. Each time a Postfix SMTP server process is started it connects to the policy service socket and Postfix runs one instance of this Python script. By default, a Postfix SMTP server pro- cess terminates after 100 seconds of idle time, or after serving 100 clients. Thus, the cost of starting this Python script is smoothed over time The default policy_time_limit is 1000 seconds. This may be too short for some SMTP transac- tions to complete. As recommended in SMTPD_POLICY_README, this should be extended to 3600 seconds. To do so, set "policy_time_limit = 3600" in /etc/postfix/main.cf. Messages that get a Fail SPF result will be rejected. Messages that get a Permerror are, by default, treated as if they had no SPF record. Messages that get a Temperror result are, by default, treated as if they had no SPF record, but can (and probably should) be deferred if otherwise permitted. Messages that get other SPF results (Pass, None, Neutral, Softfail) will have the SPF Received header prepended. Note: Spamasassisn 3.2 and follow will use this header for spam scoring so there is no need to configure a separate SPF check in these Spa- massassin versions. See Spamassassin documentation for details. Default Mail From rejection/deferal criteria are, by design, conservative. Default HELO check actions are to reject mail with other than Pass/None. HELO records are much simpler than Mail From records and rejecting based on HELO checking does not present a false positive risk. These settings are a matter of local policy and should be adjusted to meet the requirements of site administrators. See policyd-spf.conf(5) for configuration file details. LOGGING Policyd-spf will log messages to syslog about it’s activities. The "debugLevel" value in "policyd-spf.conf" can be increased to get additional information to be logged. When set to a value of "0", only test results (SPF hits/misses) are logged. Results will be returned to Postfix and logged as a warning by Postfix also. For logging by this policy server, look for "policyd-spf" in your mail log files. TESTING THE POLICY DAEMON Testing the policy daemon To test the policy daemon by hand, execute: policyd-spf Each query is a bunch of attributes. Order does not matter, and the daemon uses only a few of all the attributes shown below: request=smtpd_access_policy protocol_state=RCPT protocol_name=SMTP helo_name=some.domain.tld queue_id=8045F2AB23 instance=12345.6789 sender=foo@bar.tld recipient=bar@foo.tld client_address=1.2.3.4 client_name=another.domain.tld [empty line] The policy daemon will answer in the same style, with an attribute list followed by a empty line: action=dunno [empty line] POSTFIX INTEGRATION 1. Add the following to /etc/postfix/master.cf: policyd-spf unix - n n - 0 spawn user=nobody argv=/usr/bin/policyd-spf NOTE: Check the path to both the installed Python interpreter and policyd-spf. These vary from system to system. To use non-default settings, you must also add the config file (see above and policyd-spf.conf(5) for details). If you run other services with user nobody, create a dedicated user for this policy server and use that instead. 2. Configure the Postfix policy service in /etc/postfix/main.cf: smtpd_recipient_restrictions = ... reject_unauth_destination check_policy_service unix:private/policyd-spf ... policyd-spf_time_limit = 3600 NOTE: Specify check_policy_service AFTER reject_unauth_destination or else your system can become an open relay. 3. Reload Postfix. SEE ALSO policyd-spf.conf(5), policyd-spf.peruser(5), python-spf, <http://www.openspf.org>, RFC 4408 AUTHORS This version of python-policyd-spf was written by Copyright © 2007-2012 Scott Kitterman <scott@kitterman.com>. It is derived from Tumgreyspf, written by Sean Reifschneider, tummy.com, ltd <jafo@tummy.com>. Portions of the documentation were written by Meng Weng Wong <mengwong@pobox.com>. This man-page was created by Scott Kitterman <scott@kitterman.com>. 2012-03-17 policy-spf(1)
policyd-spf.conf
# man 5 policyd-spf.conf
policy-spf.conf(5) policy-spf.conf(5) NAME python-policyd-spf - pure-Python Postfix policy daemon for SPF checking VERSION 1.1.1 USAGE Usage: policyd-spf [/etc/policyd-spf/policyd-spf.conf] OTHER DOCUMENTATION This documentation assumes you have read Postfix’s README_FILES/ SMTPD_POLICY_README and are generally familiar with Sender Policy Framework (SPF). See RFC 4408 for details. man 1 policyd-spf provides general operation documentation for this package. man 5 policyd-spf.peruser provides documentation on setting up and using different configura- tion options on a per user (mail reciepient) basis. SYNOPSIS python-policyd-spf operates with a default installed configuration file and set of default configuration options that are used if the configuration file cannot be found. These options can be changed by changing the installed configuration files or through giving a path to an alternate configuration file. DESCRIPTION Configuration options are described here and in the configuration file provided with the package. The provided setup.py installs this configuration file in /etc/policyd-spf/. Additionally, whitelisting certain IP addresses from SPF checks is supported. This man page and the sample configuration file show the format to use. These options can be adjusted on a per user (mail recipient) basis. Details on per user settings can be found in policyd- spf.peruser(5). OPTIONS LOGGING "debugLevel" controls the amount of information logged by the policy server. The default, 1, logs no debugging messages, just basic SPF results and errors generated through the policy server. This value can be increased up to 5 (values higher than 5 will not cause an error, but will not log any additional information). debug level 2 adds a log message if no client address (IP address from which the connection was made), Mail From addresss, or HELO/EHLO name is received by the policy server, and logs SPF results for each Mail From and HELO check. debug level 3 generates a log message each time the policy server starts and each time it exits, as well as logging a copy of the exact header returned to Postfix to be prepended into the message. Each time the policy server starts, debug level 3 also logs the configuration information used by the policy server. debug level 4 logs the complete data set received by Postfix via the policy interface and when the end of the entry is read. debug level 5 is used to debug config file processing and can only be set in code and not via the config file. If debug level is 0, then the policy server logs errors only. Default: debugLevel = 1 TEST OPERATION The policy server can operate in a test only mode. This allows you to see the potential impact of SPF checking in your mail logs without rejecting mail. Headers are prepended in messages, but message delivery is not affected. This mode is not enabled by default. To enable it, set defaultSeedOnly = 0. Default: defaultSeedOnly = 1 HELO/EHLO CHECKING HELO check rejection policy options are: SPF_Not_Pass (default) - Reject if result not Pass, None, or Temperror (alternatively put, reject if the SPF result is Fail, Softfail, Neutral, PermError). Unlike Mail From checking, there are no standard e-mail use cases where a HELO check should not Pass if there is an SPF record for the HELO name (transparent forwarding, for example, is not an issue). Technically this option is not fully RFC 4408 compliant since the SPF check for the Mail From identity is mandatory and Neutral and None results must be treated the same. HELO/EHLO is known first in the SMTP dialogue and there is no practical reason to waste resources on Mail From checks if the HELO check will already cause the message to be rejected. These deviations should not cause interoperability problems when used for HELO. Softfail - Reject on HELO Softfail or Fail. Technically this option is not fully RFC 4408 compliant since the Mail From identity is mandatory, but HELO/ EHLO is known first in the SMTP dialogue and there is no practical reason to waste resources on Mail From checks if the HELO check will already cause the message to be rejected. Fail - Reject only on HELO Fail. Technically this option is not fully RFC 4408 compliant since the Mail From identity is mandatory, but HELO/EHLO is known first in the SMTP dialogue and there is no practical reason to waste resources on Mail From checks if the HELO check will already cause the message to be rejected. Null - Only reject HELO Fail for Null sender (SPF Classic). This is the approach used by the pre-RFC 4408 reference implementation and many of the pre- RFC specifications. Use of at least this option (SPF_Not_Pass or Fail) are preferred) is highly recommended. False - Never reject on HELO, append header only. This is useful for post-SMTP spam filters such as SpamAssassin. No_Check - Never check HELO. This is only recommended if you are calling the policy server twice (once for HELO checks and once for Mail From) with two different configuration files. This approach is useful to get both the HELO and Mail From headers prepended to a message. Default: HELO_reject = SPF_Not_Pass HELO/EHLO PASS RESTRICTION HELO Pass Restriction allows integration with other Postfix access controls by provding a user supplied name of a postfix access restriction to be applied to a message when the HELO checking result is Pass. The indicated restriction must be an action as defined for a Post- fix SMTP server access table access(5) and explained in the Postfix RESTRICTION CLASS README. The README.per_user_whitelisting file provided with this distribution provides examples. Note: A helo pass restriction will be the returned result even if the mail from result would cause the message to be rejected. Example: HELO_pass_restriction = helo_passed_spf Default: None Mail From CHECKING Mail From rejection policy options are: SPF_Not_Pass - Reject if result not Pass/None/Tempfail. This option is not RFC 4408 compliant since the mail with an SPF Neutral result is treated differently than mail with no SPF record and Softfail results are not supposed to cause mail rejection. Global use of this option is not recommended. Use per-domain if needed (per-domain usage described below). Softfail - Reject on HELO Softfail or Fail. Technically this option is not fully RFC 4408 compliant since Softfail results are not supposed to cause mail rejection. Global use of this option is not recommended. Use per-domain if needed (per-domain usage described below). Fail (default) - Reject on Mail From Fail. False - Never reject on Mail From, append header only. This is useful for post-SMTP spam filters such as SpamAssassin. No_Check - Never check Mail From/Return Path. This is only recommended if you are calling the policy server twice (once for HELO checks and once for Mail From) with two different con- figuration files. This approach is useful to get both the HELO and Mail From headers prepended to a message. It could also be used to do HELO checking only (because HELO check- ing has a lower false positive risk than Mail From checking), but this approach would not be fully RFC 4408 compliant since the Mail From identity is mandatory. Default: Mail_From_reject = Fail Mail From PASS RESTRICTION Mail From Pass Restriction allows integration with other Postfix access contlols by provding a user supplied name of a postfix access restriction to be applied to a message when the HELO checking result is Pass. The indicated restriction must be an action as defined for a Post- fix SMTP server access table access(5) and explained in the Postfix RESTRICTION CLASS README. Note: A mail from pass restriction will be the returned result even if the helo result would cause the message to be rejected. Example: mail_from_pass_restriction = mfrom_passed_spf Default: None Limit Rejections To Domains That Send No Mail No_Mail - Only reject when SPF indicates the host/domain sends no mail. This option will only cause mail to be rejected if the HELO/Mail From record is "v=spf1 -all". This option is use- ful for rejecting mail in situations where the tolerance for rejecting wanted mail is very low. It operates on both HELO and Mail From identities if set. Default: No_Mail = False Domain Specific Receiver Policy Using this option, a list of domains can be defined for special processing when messages do not Pass SPF. This can be useful for commonly spoofed domains that are not yet publishing SPF records with -all. Specifically, if mail from a domain in this list has a Neutral/Soft- fail result, it will be rejected (as if it had a Fail result). This option is not supported by RFC 4408, but if needed, it is better to do it on a per-domain basis rather than globally. Example: Reject_Not_Pass_Domains = aol.com,hotmail.com Default: None Permanent Error Processing Policy for rejecting due to SPF PermError options are: True - Reject the message if the SPF result (for HELO or Mail From) is PermError. This has a higher short-term false positive risk, but does result in senders getting feedback that they have a problem with their SPF record. False - Treat PermError the same as no SPF record at all. This is consistet with the pre-RFC usage (the pre-RFC name for this error was "Unknown"). This is a global option that affects both HELO and Mail From scopes when checks for that scope are enabled. The only per scope setting that can over-ride this is Mail_From/HELO_reject = False/ Default: PermError_reject = False Temporary Error Processing Policy for deferring messages due to SPF TempError options are: True - Defer the message if the SPF result (for HELO or Mail From) is TempError. This is the traditional usage and has proven useful in reducing acceptance of unwanted messages. Some- times spam senders do not retry. Sometimes by the time a message is retried the sending IP has made it onto a DNS RBL and can then be rejected. This is not the default because it is possible for some DNS errors that are classified as "Temporary" per RFC 4408 to be permanent in the sense that they require operator intervention to correct. This is a global option that affects both HELO and Mail From scopes when checks for that scope are enabled. The only per scope setting that can over-ride this is Mail_From/HELO_reject = False/ False - Treat TempError the same as no SPF record at all. This is the default to minimize false positive risk. Default: TempError_Defer = False Prospective SPF Check Prospective SPF checking - Check to see if mail sent from the defined IP address would pass. This is useful for outbound MTAs to avoid sending mail that would Fail SPF checks when received. Disable HELO checking when using this option. It’s only potentially useful for Mail From checking. SPF Received headers are not added when this option is used. Prospective = 192.168.0.4 Default: None LOCAL SPF BYPASS LIST Do not check SPF for localhost addresses - add to skip addresses to skip SPF for internal networks if desired. Defaults are standard IPv4 and IPv6 localhost addresses. This can also be used, to allow mail from local clients submitting mail to an MTA also acting as a Mail Submission Agent (MSA) to be skipped. An x-header is prepended indicating SPF checks were skipped due to a local address. This is a trace header only. Note the lack of spaces in the list. Default: skip_addresses = 127.0.0.0/8,::ffff:127.0.0.0/104,::1 SPF IP WHITELIST A comma separated CIDR Notation list of IP addresses to skip SPF checks for. Use this list to whitelist trusted relays (such as a secondary MX and trusted forwarders). An x-header is prepended indicating the IP was whitelisted against SPF checks. This is a trace header only. Note the lack of spaces in the list. Example: Whitelist = 192.168.0.0/31,192.168.1.0/30 Default: None SPF DOMAIN WHITELIST Domain_Whitelist: List of domains whose sending IPs should be whitelisted from SPF checks. Use this to list trusted forwarders by domain name. Client IP addresses are tested against SPF records published by the listed domains. This is useful for large forwarders with com- plex outbound infrastructures and SPF records. This option is less scalable than the SPF IP Whitelist. An x-header is prepended indicating the IP was whitelisted against SPF checks. This is a trace header only. This option does nothing if the domain does not have an SPF record. In this case use the SPF IP Whitelist described above or Domain_Whitelist_PTR (below). Note the lack of spaces in the list. Example: Domain_Whitelist = pobox.com,trustedforwarder.org Default: None PTR DOMAIN WHITELIST Domain_Whitelist_PTR: List of domains (and subdomains) whose sending IPs should be whitelisted from SPF checks based on PTR match of the domain. Use this to list trusted for- warders by domain name if they do not publish SPF records. Client IP addresses PTR names are tested to see if they match the listed domains. This is useful for large forwarders with complex outbound infrastructures, but no SPF records and predictable host naming. Matching is done using the same rules as the SPF PTR mechanism as described in RFC 4408. List the parent domain and all subdomains will match. This option is less scalable than the SPF IP Whitelist. An x-header is prepended indicating the IP was whitelisted against SPF checks. This is a trace header only. This option does nothing if the host does not have a PTR record record. In this case use the SPF IP Whitelist described above. Note the lack of spaces in the list. Example: Domain_Whitelist_PTR = yahoo.com,yahoogroups.com Default: None RESULTS HEADER The standard method for documenting SPF results in a message (for consumption by downstream processes) is the Received-SPF header defined in RFC 4408. This is the default header to use. Results can also be documented in the Authentication-Results header defined by RFC 5451. The default is Received-SPF (SPF), but inclusion of Authentication-Results (AR) headers as an alternative to Received-SPF can be specified. If there is a requirement to prepend both Received-SPF and Authentication- Results headers, then it must be done by processing the message with more than one instance of the policy server using different configuration files with different Header_Type settings. Examples: Header_Type = SPF or Header_Type = AR Default: SPF Authentications Results Authentication Identifier Every Authentication-Results header field has an authentication identifier field (’Auth- serv_Id’). This is similar in syntax to a fully-qualified domain name. See policyd-spf.conf.5 and RFC 5451 paragraph 2.3 for details. Default is None. Authserv-Id must be provided if Header_Type ’AR’ is used. The authentication identifier field provides a unique identifier that refers to the authenti- cating service within a given administrative domain. The identifier MUST be unique to that domain. This identifier is intended to be machine-readable and not necessarily meaningful to users. Example: Authserv_Id = mx.example.com SEE ALSO man 1 policyd-spf, man 5 policyd-spf.peruser, python-spf, <http://www.openspf.net>, RFC 4408, RFC 5451 AUTHORS This version of pypolicyd-spf was written by Copyright © 2007-2012, Scott Kitterman <scott@kitterman.com>. It is derived from Tumgreyspf, written by Sean Reifschneider, tummy.com, ltd <jafo@tummy.com>. Portions of the documentation were written by Meng Weng Wong <mengwong@pobox.com>. This man-page was created by Scott Kitterman <scott@kitterman.com>. 2012-03-17 policy-spf.conf(5)
policyd-spf.peruser
# man 5 policyd-spf.peruser
policy-spf.peruser(5) policy-spf.peruser(5) NAME python-policyd-spf - pure-Python Postfix policy daemon for SPF checking VERSION 1.0 USAGE Usage: policyd-spf [/etc/policyd-spf/policyd-spf.conf] OTHER DOCUMENTATION This documentation assumes you have read Postfix’s README_FILES/ SMTPD_POLICY_README and are generally familiar with Sender Policy Framework (SPF). See RFC 4408 for details. man 1 policyd-spf provides general operation documentation for this package. See man 5 policyd-spf.conf for configuration file information. SYNOPSIS python-policyd-spf operates with a default installed configuration file and set of default configuration options that are used if the configuration file cannot be found. These options can be changed by changing the installed configuration files or through giving a path to an alternate configuration file. Additionally, different configurations can be provided on a per user basis. This man page describes setup and user of per user (mail recipient) configurations. Currently these con- figurations can either be stored in a text file or a Berkeley DB (libdb) datase. If there is sufficient interest, other data storage methods may be supported in the future. DESCRIPTION Use of per-user configuration is defined in the application configuration file with the set- ting "Per_User". The value of the setting gives the type and location of the per-user con- figuration information. Currently supported types are text and bsddb. User is defined an email address of a recipient of the message. All options available at the application level (See man 5 policyd-spf.conf) can be adjusted on a per-user basis. Per-user checks can only be done as part of smtpd_recipient_restric- tions. Per-user actions are not possible at other stages of the SMTP dialogue. The user is not yet known for smtpd_client_restrictions, smtpd_helo_restrictions, or smtpd_sender_restrictions. If used during smtpd_data_restrictions or smtpd_end_of_data_restrictions, the entire message will be available only if the message was only to a single recipient. If per-user configurations are used when recipient information is not available, warnings will be logged and the per-user information will be ignored. In addition to specifying individual users, regular expression matching is also available, but may have performance implications since the entire user table has to be traversed for each message recipient. OPTIONS Text Per-User Configuration File The text file option is useful for testing and when only a small number of users require per- user configurations. It is specified in the main configuration file: "Per_User = text,/etc/pypolicyd-spf/userconf" Lines beginning with "#" are treated as comments and ignored. The location of the file is determined by the system administrator. No default file is provided in or installed by the package. The configuration of the file is a comma separated combination of user and configuration information, with one line per user’s configuration information (NOTE: due to man page for- mating requirements, these lines are wrapped - in the config file, it must be one line per user): postmaster@example.com,Mail_From_reject=No_Check|PermEr- ror_reject=False|HELO_reject=SPF_Not_Pass|defaultSeedOnly=1|debu- gLevel=5|skip_addresses=127.0.0.0/8,::ffff:127.0.0.0//104,::1//128|TempError_Defer=False strict@example.com,PermError_rejec=True|HELO_reject=SPF_Not_Pass|TempError_Defer=True It is not necessary to specify all configuration parameters for each user, only those that are different than the overall configuration need to be specified. If the specified per user configuration file is missing, an error is logged and the global configuration is used instead. SEE ALSO man 1 policyd-spf, man 5 policyd-spf.conf, python-spf, <http://www.openspf.org>, RFC 4408 AUTHORS This version of pypolicyd-spf was written by Copyright © 2007-2011, Scott Kitterman <scott@kitterman.com>. It is derived from Tumgreyspf, written by Sean Reifschneider, tummy.com, ltd <jafo@tummy.com>. This man-page was created by Scott Kitterman <scott@kitterman.com>. 2012-03-17 policy-spf.peruser(5)
Konfiguration
Im RPM-Paket wird zwar eine Konfigurationsdatei schon an die richtige Stelle /etc/python-policyd-spf kopiert, aber die Vorgabedatei kommentierte Musterdatei policyd-spf.conf.commented im Verzeichnis /usr/share/doc/pypolicyd-spf-1.2/ enthält doch wesentliche Hinweise und Tips.
Wir kopieren uns also daher diese Musterdatei an die richtige Stelle im Verzeichnis /etc/.
# cp /usr/share/doc/pypolicyd-spf-1.2/policyd-spf.conf.commented /etc/python-policyd-spf/policyd-spf.conf -y
Anschließende bearbeiten wir diese Datei mit unserem Editor der Wahl. Als wichtigen ersten Schrittsetzen wir die Option defaultSeedOnly auf den wert 0. Somit ist schon mal sichergestellt, dass wir bis zum endgültigen Produktivbetrieb die Annahme von Mails fälschlicher weise ablehnen. Fernen Passen wir noch den Loglevel und die Angaben zum eigenen Netzwerk/IP-Adressbereich an.
# vim /etc/python-policyd-spf/policyd-spf.conf
- /etc/python-policyd-spf/policyd-spf.conf
# Amount of debugging information logged. 0 logs no debugging messages # 5 includes all debug messages. # Django : 2014-03-16 # default: debugLevel = 1 debugLevel = 1debugLevel = 5 # If set to 0, no messages are rejected by SPF. This allows you to see the # potential impact of SPF checking in your mail logs without rejecting mail. # Django : 2014-03-16 # default: defaultSeedOnly = 1 defaultSeedOnly = 0 # HELO check rejection policy. Options are: # HELO_reject = SPF_Not_Pass (default) - Reject if result not Pass/None/Tempfail. # HELO_reject = Softfail - Reject if result Softfail and Fail # HELO_reject = Fail - Reject on HELO Fail # HELO_reject = Null - Only reject HELO Fail for Null sender (SPF Classic) # HELO_reject = False - Never reject/defer on HELO, append header only. # HELO_reject = No_Check - Never check HELO. HELO_reject = SPF_Not_Pass # HELO pass restriction policy. # HELO_pass_restriction = helo_passed_spf - Apply the given restriction when # the HELO checking result is Pass. The given restriction must be an # action as defined for a Postfix SMTP server access table access(5). #HELO_pass_restriction # Mail From rejection policy. Options are: # Mail_From_reject = SPF_Not_Pass - Reject if result not Pass/None/Tempfail. # Mail_From_reject = Softfail - Reject if result Softfail and Fail # Mail_From_reject = Fail - Reject on Mail From Fail (default) # Mail_From_reject = False - Never reject/defer on Mail From, append header only # Mail_From_reject = No_Check - Never check Mail From/Return Path. Mail_From_reject = Fail # Reject only from domains that send no mail. Options are: # No_Mail = False - Normal SPF record processing (default) # No_Mail = True - Only reject for "v=spf1 -all" records # Mail From pass restriction policy. # Mail_From_pass_restriction = mfrom_passed_spf - Apply the given # restriction when the Mail From checking result is Pass. The given # restriction must be an action as defined for a Postfix SMTP server # access table access(5). #Mail_From_pass_restriction # Reject mail for Netural/Softfail results for these domains. # Recevier policy option to reject mail from certain domains when SPF is not # Pass/None even if their SPF record does not produce a Fail result. This # Option does not change the effect of PermError_reject or TempError_Defer # Reject_Not_Pass_Domains = aol.com,hotmail.com # Policy for rejecting due to SPF PermError. Options are: # PermError_reject = True # PermError_reject = False PermError_reject = False # Policy for deferring messages due to SPF TempError. Options are: # TempError_Defer = True # TempError_Defer = False TempError_Defer = False # Prospective SPF checking - Check to see if mail sent from the defined IP # address would pass. # Prospective = 192.168.0.4 # Do not check SPF for localhost addresses - add to skip addresses to # skip SPF for internal networks if desired. Defaults are standard IPv4 and # IPv6 localhost addresses. # Django : 2014-03-16 # default: skip_addresses = 127.0.0.0/8,::ffff:127.0.0.0/104,::1 skip_addresses = 127.0.0.1/32,10.0.0.0/24,10.0.10.0/28 # Whitelist: CIDR Notation list of IP addresses not to check SPF for. # Example (default is no whitelist): # Whitelist = 192.168.0.0/31,192.168.1.12 # Domain_Whitelist: List of domains whose sending IPs (defined by passing # their SPF check should be whitelisted from SPF. # Example (default is no domain whitelist): # Domain_Whitelist = pobox.com,trustedforwarder.org # Domain_Whitelist_PTR: List of domains to whitelist against SPF checks base # on PTR match. # Example (default is no PTR whitelist) # Domain_Whitelist_PTR = yahoo.com # Type of header to insert to document SPF result. Can be RFC 4408 # Received-SPF (SPF) or RFC 5451 Authentication Results (AR). It cannot be # both. # Examples: (default is Received-SPF): # Header_Type = AR # Header_Type = SPF # Every Authentication-Results header field has an authentication identifier # field ('Authserv_Id'). This is similar in syntax to a fully-qualified domain # name. See policyd-spf.conf.5 and RFC 5451 paragraph 2.3 for details. # Default is None. Authserv-Id must be provided if Header_Type 'AR' is used. # Authserv_Id = mx.example.com
In der Konfigurationsdatei master.cf unseres Postfix-Mailserver tragen wir nun nachfolgende Zeilen ein.
#
- /etc/postfix/master.cf
... # Django : 2014-03-16 # SPF-Check policy unix - n n - - spawn user=nobody argv=/usr/libexec/postfix/policyd-spf # ...
In der Konfigurationsdatei main.cf unseres Postfix-Mailserver ergänzen wir nun noch unsere smtpd_recipient_restrictions und tragen von den RBL-Checks noch ein.
# vim /etc/postfix/main.cf
- /etc/postfix/main.cf
... # Django : 2014-03-16 # SPF Check check_policy_service unix:private/policy, # policy_time_limit = 3600, ...
Anschließend starten wir unseren Postfix-Mailserver einmal durch, damit unsere Konfigurationsänderungen aktiv werden.
Tests und Logging
Zum Testen schicken wir uns von einem fremden Mailserver aus, der einen gültigen SPF-Record vorweisen kann eine eMail an unseren Mailserver und beobachten unser Maillog. Beim gesetzten Loglevel 5 wird entsprechend ausfürlich berichtet.
# less /var/log/maillog
Mar 16 12:17:01 vml000080 policyd-spf[12354]: Starting Mar 16 12:17:01 vml000080 policyd-spf[12354]: Read line: "request=smtpd_access_policy" Mar 16 12:17:01 vml000080 policyd-spf[12354]: Read line: "protocol_state=RCPT" Mar 16 12:17:01 vml000080 policyd-spf[12354]: Read line: "protocol_name=ESMTP" Mar 16 12:17:01 vml000080 policyd-spf[12354]: Read line: "client_address=80.241.60.212" Mar 16 12:17:01 vml000080 policyd-spf[12354]: Read line: "client_name=mx1.mailbox.org" Mar 16 12:17:01 vml000080 policyd-spf[12354]: Read line: "reverse_client_name=mx1.mailbox.org" Mar 16 12:17:01 vml000080 policyd-spf[12354]: Read line: "helo_name=mx1.mailbox.org" Mar 16 12:17:01 vml000080 policyd-spf[12354]: Read line: "sender=n3rd@mailbox.org" Mar 16 12:17:01 vml000080 policyd-spf[12354]: Read line: "recipient=django@nausch.org" Mar 16 12:17:01 vml000080 policyd-spf[12354]: Read line: "recipient_count=0" Mar 16 12:17:01 vml000080 policyd-spf[12354]: Read line: "queue_id=" Mar 16 12:17:01 vml000080 policyd-spf[12354]: Read line: "instance=2fef.5325882d.9ad5b.0" Mar 16 12:17:01 vml000080 policyd-spf[12354]: Read line: "size=2054" Mar 16 12:17:01 vml000080 policyd-spf[12354]: Read line: "etrn_domain=" Mar 16 12:17:01 vml000080 policyd-spf[12354]: Read line: "stress=" Mar 16 12:17:01 vml000080 policyd-spf[12354]: Read line: "sasl_method=" Mar 16 12:17:01 vml000080 policyd-spf[12354]: Read line: "sasl_username=" Mar 16 12:17:01 vml000080 policyd-spf[12354]: Read line: "sasl_sender=" Mar 16 12:17:01 vml000080 policyd-spf[12354]: Read line: "ccert_subject=" Mar 16 12:17:01 vml000080 policyd-spf[12354]: Read line: "ccert_issuer=" Mar 16 12:17:01 vml000080 policyd-spf[12354]: Read line: "ccert_fingerprint=" Mar 16 12:17:01 vml000080 policyd-spf[12354]: Read line: "encryption_protocol=TLSv1.2" Mar 16 12:17:01 vml000080 policyd-spf[12354]: Read line: "encryption_cipher=AECDH-AES256-SHA" Mar 16 12:17:01 vml000080 policyd-spf[12354]: Read line: "encryption_keysize=256" Mar 16 12:17:01 vml000080 policyd-spf[12354]: Read line: "" Mar 16 12:17:01 vml000080 policyd-spf[12354]: Found the end of entry Mar 16 12:17:01 vml000080 policyd-spf[12354]: Config: {'Mail_From_reject': 'Fail', 'PermError_reject': 'False',, 'HELO_reject': 'SPF_Not_Pass', 'Header_Type': 'SPF', 'defaultSeedOnly': 0, 'debugLevel': 5, 'skip_addresses': '127.0.0.1/32,10.0.0.0/24', 'TempError_Defer': 'False'} Mar 16 12:17:01 vml000080 policyd-spf[12354]: Cached data for this instance: [] Mar 16 12:17:01 vml000080 policyd-spf[12354]: spfcheck: pyspf result: "['None', '', 'helo']" Mar 16 12:17:01 vml000080 policyd-spf[12354]: None; identity=helo; client-ip=80.241.60.212; helo=mx1.mailbox.org; envelope-from=n3rd@mailbox.org; receiver=django@nausch.org Mar 16 12:17:01 vml000080 policyd-spf[12354]: spfcheck: pyspf result: "['Pass', 'sender SPF authorized', 'mailfrom']" Mar 16 12:17:01 vml000080 policyd-spf[12354]: Pass; identity=mailfrom; client-ip=80.241.60.212; helo=mx1.mailbox.org; envelope-from=n3rd@mailbox.org; receiver=django@nausch.org Mar 16 12:17:01 vml000080 policyd-spf[12354]: Action: prepend: Text: Received-SPF: Pass (sender SPF authorized) identity=mailfrom; client-ip=80.241.60.212; helo=mx1.mailbox.org; envelope-from=n3rd@mailbox.org; receiver=django@nausch.org
Im Mailheader der empfangenen eMail findet sich dann auch ein entsprechender Eintrag:
Received-SPF: Pass (sender SPF authorized) identity=mailfrom; client-ip=80.241.60.212; helo=mx1.mailbox.org; envelope-from=n3rd@mailbox.org; receiver=django@nausch.org
Bei einem produktiven System wird man meist mit dem Loglevel=1 ausreichende Informationen vorfinden.
Mar 16 13:19:05 vml000080 policyd-spf[14906]: Config: {'Mail_From_reject': 'Fail', 'PermError_reject': 'False', 'HELO_reject': 'SPF_Not_Pass', 'Header_Type': 'SPF', 'defaultSeedOnly': 0, 'debugLevel': 3, 'skip_addresses': '127.0.0.1/32,10.0.0.0/24', 'TempError_Defer': 'False'} Mar 16 13:19:05 vml000080 policyd-spf[14906]: spfcheck: pyspf result: "['None', '', 'helo']" Mar 16 13:19:05 vml000080 policyd-spf[14906]: None; identity=helo; client-ip=80.241.60.212; helo=mx1.mailbox.org; envelope-from=n3rd@mailbox.org; receiver=django@nausch.org Mar 16 13:19:05 vml000080 policyd-spf[14906]: spfcheck: pyspf result: "['Pass', 'sender SPF authorized', 'mailfrom']" Mar 16 13:19:05 vml000080 policyd-spf[14906]: Pass; identity=mailfrom; client-ip=80.241.60.212; helo=mx1.mailbox.org; envelope-from=n3rd@mailbox.org; receiver=django@nausch.org Mar 16 13:19:05 vml000080 policyd-spf[14906]: Action: prepend: Text: Received-SPF: Pass (sender SPF authorized) identity=mailfrom; client-ip=80.241.60.212; helo=mx1.mailbox.org; envelope-from=n3rd@mailbox.org; receiver=django@nausch.org
SRS - Sender Rewriting Scheme
Zu Beginn dieses Artikels wurde bereits darauf hingewiesen, dass mit unter Probleme auftauchen bei der Mailumleitungen, Mailinglisten und/oder WebFormularen auf. Mit SRS3) kann ein Mailserver die eMail-Adresse im Envelop umschreiben und anpassen.
… coming soon…
<uml w=800>
title Mailversand einer eMail\n skin BlueModern participant „\n Mail-Server mx01.nausch.org \n“ as links participant „\n Mail-Server mx1.tachtler.net \n“ as mitte participant „\n DNS-Server von nausch.org \n“ as rechts
links → mitte : connect von mx01.nausch.org zu mx1.tachtler.net note left : \n Verbindungsaufbau \n vom Quell- zum \n Zielserver \n links ←- mitte : . 220 mx1.tachtler.net ESMTP Postfix links –> mitte : HELO mx01.nausch.org links ←- mitte : . 250 mx1.tachtler.net links –> mitte : MAIL FROM:django@nausch.org links ←- mitte : . 250 2.1.0 Ok mitte → rechts : host -t TXT nausch.org note right : \n Abfrage der \n SPF-Records \n mitte ← rechts : nausch.org descriptive text „v=spf1 ip4:217.91.103.190/32 mx ?all“ note left : \n Der Mailserver mit der \n IP 217.91.103.190 ist berechtigt \n eMails der Mail-Domain \n nausch.org zu versenden \n links –> mitte : RCPT TO:klaus@tachtler.net links ←- mitte : . 250 2.1.0 Ok
links –> mitte : Übermittlung der Nachricht links ←- mitte : 250 2.0.0 Ok: queued as 5950581 note left : \n Beenden der Verbindung \n
</uml>
… coming soon…