Greetings,
Firstly, thanks to all who work on opendmarc to make a great system available for free to help us in the battle against spoofing and spam.
I have implemented opendmarc 1.3.0 on CentOS 6.5 and it seems to be running pretty smoothly, except for emails from LinkedIn where all their emails are failing DMARC.
DKIM and SPF both pass. The implicit alignment modes for DKIM and SPF for linkedin.com are both relaxed, so I would have expected it to pass.
Here is a sample failure report (recipient details changed to protect ID):
This is an authentication failure report for an email message received from IP
108.174.3.163 on Fri, 12 Sep 2014 08:57:07 +0000 (UTC).
Feedback-Type: auth-failure
Version: 1
User-Agent: OpenDMARC-Filter/1.3.0
Auth-Failure: dmarc
Authentication-Results: keynetworks.com.au; dmarc=fail header.from=linkedin.com
Original-Envelope-Id: D8F9E10201A
Original-Mail-From: s-2tb1dndgbx25h8izhubaqseokbm4i0678uuel31g93c6xgf1ma3xwvvo@bounce.linkedin.com
Source-IP: 108.174.3.163
Reported-Domain: linkedin.com
Authentication-Results: do1.keynetworks.com.au; dkim=pass
reason="1024-bit key" header.d=linkedin.com header.i=@linkedin.com
header.b=T9w8op23; dkim-adsp=pass
Received: from mailc-ac.linkedin.com (mailc-ac.linkedin.com [108.174.3.163])
(using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits))
(No client certificate requested)
by do1.keynetworks.com.au (Postfix) with ESMTPS id D8F9E10201A
for recipient@example.com; Fri, 12 Sep 2014 08:57:05 +0000 (UTC)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linkedin.com;
s=proddkim1024; t=1410483033;
bh=OfTXunuICFIC7aOGb8ebXu+urnPn3Dve16H8j9Lvzwk=;
h=From:Subject:MIME-Version:Content-Type:To:Date:X-LinkedIn-Class:
X-LinkedIn-Template:X-LinkedIn-fbl;
b=T9w8op23jiQHKtLKjH0l3MGI1kGFUXWkCJZ81pn4BoF6CLRI6fYdL5FRVj8AhJYAM
qapSYWMPKLqF/CY/SVeYmOyn+BvFmjHqNZFlBrvXot31X3CZefUYyfyyVqRZj5k4yy
TvdE5aA8J2PvYt5Jys8GNYavaUhxxmZpfQ74U1o0=
From: Australian IT Industry groups-noreply@linkedin.com
Message-ID: 1873904081.3804075.1410483033317.JavaMail.app@ela4-app8033.prod
Subject: The Hitchhiker's Guide on How to Buy FPGA
MIME-Version: 1.0
Content-Type: multipart/alternative;
boundary="----=_Part_3804071_988667024.1410483033308"
To: Mr Recipient recipient@example.com
Date: Fri, 12 Sep 2014 00:50:33 +0000 (UTC)
X-LinkedIn-Class: GROUPDIGEST
X-LinkedIn-Template: b2_anet_digest_weekly
X-LinkedIn-fbl: s-2tb1dndgbx25h8izhubaqseokbm4i0678uuel31g93c6xgf1ma3xwvvo
X-LinkedIn-Id: 1jhv6k-hzyt4xfm-67
Here are the headers of the orinial email (recipient details changed to protect ID):
From - Fri Sep 12 09:14:09 2014
X-Account-Key: account4
X-UIDL: 0000149e52a86afd
X-Mozilla-Status: 0001
X-Mozilla-Status2: 00000000
X-Mozilla-Keys:
Return-Path: s-2tb1dndgbx25h8izhubaqseokbm4i0678uuel31g93c6xgf1ma3xwvvo@bounce.linkedin.com
Delivered-To: recipient@example.com
Received: from localhost (unknown [127.0.0.1])
by do1.keynetworks.com.au (Postfix) with ESMTP id D1B7C102171;
Fri, 12 Sep 2014 08:57:12 +0000 (UTC)
X-Spam-Flag: NO
X-Spam-Score: -5.623
X-Spam-Level:
X-Spam-Status: No, score=-5.623 tagged_above=-99 required=5
tests=[BAYES_00=-1.9, DATE_IN_PAST_06_12=1.543, DKIM_SIGNED=0.1,
DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, HTML_MESSAGE=0.001,
RCVD_IN_RP_CERTIFIED=-3, RCVD_IN_RP_SAFE=-2, RP_MATCHES_RCVD=-0.166,
SPF_HELO_PASS=-0.001, SPF_PASS=-0.001, URIBL_BLOCKED=0.001]
autolearn=ham
Authentication-Results: do1.keynetworks.com.au (amavisd-new);
dkim=pass (1024-bit key) header.d=linkedin.com
Received: from do1.keynetworks.com.au ([127.0.0.1])
by localhost (do1.keynetworks.com.au [127.0.0.1]) (amavisd-new, port 10024)
with ESMTP id qvFUsyKQcG1X; Fri, 12 Sep 2014 08:57:07 +0000 (UTC)
X-Greylist: delayed 427 seconds by postgrey-1.34 at do1.keynetworks.com.au; Fri, 12 Sep 2014 08:57:05 UTC
DMARC-Filter: OpenDMARC Filter v1.3.0 do1.keynetworks.com.au D8F9E10201A
Authentication-Results: keynetworks.com.au; dmarc=fail header.from=linkedin.com
Authentication-Results: keynetworks.com.au; spf=pass smtp.mailfrom=s-2tb1dndgbx25h8izhubaqseokbm4i0678uuel31g93c6xgf1ma3xwvvo@bounce.linkedin.com
Received: from mailc-ac.linkedin.com (mailc-ac.linkedin.com [108.174.3.163])
(using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits))
(No client certificate requested)
by do1.keynetworks.com.au (Postfix) with ESMTPS id D8F9E10201A
for recipient@example.com; Fri, 12 Sep 2014 08:57:05 +0000 (UTC)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linkedin.com;
s=proddkim1024; t=1410483033;
bh=OfTXunuICFIC7aOGb8ebXu+urnPn3Dve16H8j9Lvzwk=;
h=From:Subject:MIME-Version:Content-Type:To:Date:X-LinkedIn-Class:
X-LinkedIn-Template:X-LinkedIn-fbl;
b=T9w8op23jiQHKtLKjH0l3MGI1kGFUXWkCJZ81pn4BoF6CLRI6fYdL5FRVj8AhJYAM
qapSYWMPKLqF/CY/SVeYmOyn+BvFmjHqNZFlBrvXot31X3CZefUYyfyyVqRZj5k4yy
TvdE5aA8J2PvYt5Jys8GNYavaUhxxmZpfQ74U1o0=
From: Australian IT Industry groups-noreply@linkedin.com
Message-ID: 1873904081.3804075.1410483033317.JavaMail.app@ela4-app8033.prod
Subject: The Hitchhiker's Guide on How to Buy FPGA
MIME-Version: 1.0
Content-Type: multipart/alternative;
boundary="----=_Part_3804071_988667024.1410483033308"
To: Mr Recipient recipient@example.com
Date: Fri, 12 Sep 2014 00:50:33 +0000 (UTC)
X-LinkedIn-Class: GROUPDIGEST
X-LinkedIn-Template: b2_anet_digest_weekly
X-LinkedIn-fbl: s-2tb1dndgbx25h8izhubaqseokbm4i0678uuel31g93c6xgf1ma3xwvvo
X-LinkedIn-Id: 1jhv6k-hzyt4xfm-67
Opendmarc 1.3.0 was compiled from source with the following configure options:
./configure --prefix=/ --exec-prefix=/usr/local --with-spf --with-spf2-include=/usr/include/spf2 --with-spf2-lib=/usr/lib64/libspf2.so
Here is opendmarc.conf:
##
## opendmarc.conf -- configuration file for OpenDMARC filter
##
## Copyright (c) 2012-2014, The Trusted Domain Project. All rights reserved.
##
## AuthservID (string)
## defaults to MTA name
##
## Sets the "authserv-id" to use when generating the Authentication-Results:
## header field after verifying a message. If the string "HOSTNAME" is
## provided, the name of the host running the filter (as returned by the
## gethostname(3) function) will be used.
#
AuthservID keynetworks.com.au
## AuthservIDWithJobID { true | false }
## default "false"
##
## If "true", requests that the authserv-id portion of the added
## Authentication-Results header fields contain the job ID of the message
## being evaluated.
#
# AuthservIDWithJobID false
## AutoRestart { true | false }
## default "false"
##
## Automatically re-start on failures. Use with caution; if the filter fails
## instantly after it starts, this can cause a tight fork(2) loop.
#
AutoRestart true
## AutoRestartCount n
## default 0
##
## Sets the maximum automatic restart count. After this number of automatic
## restarts, the filter will give up and terminate. A value of 0 implies no
## limit.
#
# AutoRestartCount 0
## AutoRestartRate n/t[u]
## default (no limit)
##
## Sets the maximum automatic restart rate. If the filter begins restarting
## faster than the rate defined here, it will give up and terminate. This
## is a string of the form n/t[u] where n is an integer limiting the count
## of restarts in the given interval and t[u] defines the time interval
## through which the rate is calculated; t is an integer and u defines the
## units thus represented ("s" or "S" for seconds, the default; "m" or "M"
## for minutes; "h" or "H" for hours; "d" or "D" for days). For example, a
## value of "10/1h" limits the restarts to 10 in one hour. There is no
## default, meaning restart rate is not limited.
#
AutoRestartRate 10/1h
## Background { true | false }
## default "true"
##
## Causes opendmarc to fork and exits immediately, leaving the service
## running in the background.
#
# Background true
## BaseDirectory (string)
## default (none)
##
## If set, instructs the filter to change to the specified directory using
## chdir(2) before doing anything else. This means any files referenced
## elsewhere in the configuration file can be specified relative to this
## directory. It's also useful for arranging that any crash dumps will be
## saved to a specific location.
#
BaseDirectory /var/run/opendmarc
## ChangeRootDirectory (string)
## default (none)
##
## Requests that the operating system change the effective root directory of
## the process to the one specified here prior to beginning execution.
## chroot(2) requires superuser access. A warning will be generated if
## UserID is not also set.
#
# ChangeRootDirectory /var/chroot/opendmarc
## CopyFailuresTo (string)
## default (none)
##
## Requests addition of the specified email address to the envelope of
## any message that fails the DMARC evaluation.
#
CopyFailuresTo <removed>
## DNSTimeout (integer)
## default 5
##
## Sets the DNS timeout in seconds. A value of 0 causes an infinite wait.
## (NOT YET IMPLEMENTED)
#
# DNSTimeout 5
## EnableCoredumps { true | false }
## default "false"
##
## On systems that have such support, make an explicit request to the kernel
## to dump cores when the filter crashes for some reason. Some modern UNIX
## systems suppress core dumps during crashes for security reasons if the
## user ID has changed during the lifetime of the process. Currently only
## supported on Linux.
#
# EnableCoreDumps false
## FailureReports { true | false }
## default "false"
##
## Enables generation of failure reports when the DMARC test fails and the
## purported sender of the message has requested such reports. Reports are
## formatted per RFC6591.
#
FailureReports true
## FailureReportsBcc (string)
## default (none)
##
## When failure reports are enabled and one is to be generated, always
## send one to the address(es) specified here. If a failure report is
## requested by the domain owner, the address(es) are added in a Bcc: field.
## If no request is made, they address(es) are used in a To: field. There
## is no default.
#
FailureReportsBcc <removed>
## FailureReportsOnNone { true | false }
## default "false"
##
## Supplements the "FailureReports" setting by generating reports for
## domains that advertise "none" policies. By default, reports are only
## generated (when enabled) for sending domains advertising a "quarantine"
## or "reject" policy.
#
FailureReportsOnNone false
## FailureReportsSentBy string
## default "USER@HOSTNAME"
##
## Specifies the email address to use in the From: field of failure
## reports generated by the filter. The default is to use the userid of
## the user running the filter and the local hostname to construct an
## email address. "postmaster" is used in place of the userid if a name
## could not be determined.
#
FailureReportsSentBy <removed>
## HistoryFile path
## default (none)
##
## If set, specifies the location of a text file to which records are written
## that can be used to generate DMARC aggregate reports. Records are groups
## of rows containing information about a single received message, and
## include all relevant information needed to generate a DMARC aggregate
## report. It is expected that this will not be used in its raw form, but
## rather periodically imported into a relational database from which the
## aggregate reports can be extracted by a tool such as opendmarc-import(8).
#
HistoryFile /var/run/opendmarc/opendmarc.dat
## IgnoreAuthenticatedClients { true | false }
## default "false"
##
## If set, causes mail from authenticated clients (i.e., those that used
## SMTP AUTH) to be ignored by the filter.
#
IgnoreAuthenticatedClients true
## IgnoreHosts path
## default (internal)
##
## Specifies the path to a file that contains a list of hostnames, IP
## addresses, and/or CIDR expressions identifying hosts whose SMTP
## connections are to be ignored by the filter. If not specified, defaults
## to "127.0.0.1" only.
#
# IgnoreHosts /usr/local/etc/opendmarc/ignore.hosts
## IgnoreMailFrom domain[,...]
## default (none)
##
## Gives a list of domain names whose mail (based on the From: domain) is to
## be ignored by the filter. The list should be comma-separated. Matching
## against this list is case-insensitive. The default is an empty list,
## meaning no mail is ignored.
#
IgnoreMailFrom <removed>
## MilterDebug (integer)
## default 0
##
## Sets the debug level to be requested from the milter library.
#
# MilterDebug 0
## PidFile path
## default (none)
##
## Specifies the path to a file that should be created at process start
## containing the process ID.
##
#
PidFile /var/run/opendmarc/opendmarc.pid
## PublicSuffixList path
## default (none)
##
## Specifies the path to a file that contains top-level domains (TLDs) that
## will be used to compute the Organizational Domain for a given domain name,
## as described in the DMARC specification. If not provided, the filter will
## not be able to determine the Organizational Domain and only the presented
## domain will be evaluated.
#
# PublicSuffixList path
## RecordAllMessages { true | false }
## default "false"
##
## If set and "HistoryFile" is in use, all received messages are recorded
## to the history file. If not set (the default), only messages for which
## the From: domain published a DMARC record will be recorded in the
## history file.
#
# RecordAllMessages false
## RejectFailures { true | false }
## default "false"
##
## If set, messages will be rejected if they fail the DMARC evaluation, or
## temp-failed if evaluation could not be completed. By default, no message
## will be rejected or temp-failed regardless of the outcome of the DMARC
## evaluation of the message. Instead, an Authentication-Results header
## field will be added.
#
# RejectFailures false
## ReportCommand string
## default "/usr/sbin/sendmail -t"
##
## Indicates the shell command to which failure reports should be passed for
## delivery when "FailureReports" is enabled.
#
# ReportCommand /usr/sbin/sendmail -t
## RequiredHeaders { true | false }
## default "false"
##
## If set, the filter will ensure the header of the message conforms to the
## basic header field count restrictions laid out in RFC5322, Section 3.6.
## Messages failing this test are rejected without further processing. A
## From: field from which no domain name could be extracted will also be
## rejected.
#
# RequiredHeaders false
## Socket socketspec
## default (none)
##
## Specifies the socket that should be established by the filter to receive
## connections from sendmail(8) in order to provide service. socketspec is
## in one of two forms: local:path, which creates a UNIX domain socket at
## the specified path, or inet:port[@host] or inet6:port[@host] which creates
## a TCP socket on the specified port for the appropriate protocol family.
## If the host is not given as either a hostname or an IP address, the
## socket will be listening on all interfaces. This option is mandatory
## either in the configuration file or on the command line. If an IP
## address is used, it must be enclosed in square brackets.
#
Socket inet:8893@localhost
## SoftwareHeader { true | false }
## default "false"
##
## Causes the filter to add a "DMARC-Filter" header field indicating the
## presence of this filter in the path of the message from injection to
## delivery. The product's name, version, and the job ID are included in
## the header field's contents.
#
SoftwareHeader true
## SPFIgnoreResults { true | false }
## default "false"
##
## Causes the filter to ignore any SPF results in the header of the
## message. This is useful if you want the filter to perfrom SPF checks
## itself, or because you don't trust the arriving header.
#
SPFIgnoreResults true
## SPFSelfValidate { true | false }
## default false
##
## Enable internal spf checking with --with-spf
## To use libspf2 instead: --with-spf --with-spf2-include=path --with-spf2-lib=path
##
## Causes the filter to perform a fallback SPF check itself when
## it can find no SPF results in the message header. If SPFIgnoreResults
## is also set, it never looks for SPF results in headers and
## always performs the SPF check itself when this is set.
#
SPFSelfValidate true
## Syslog { true | false }
## default "false"
##
## Log via calls to syslog(3) any interesting activity.
#
Syslog true
## SyslogFacility facility-name
## default "mail"
##
## Log via calls to syslog(3) using the named facility. The facility names
## are the same as the ones allowed in syslog.conf(5).
#
SyslogFacility mail
## TemporaryDirectory path
## default /var/tmp
##
## Specifies the directory in which temporary files should be written.
#
# TemporaryDirectory /var/tmp
## TrustedAuthservIDs string
## default HOSTNAME
##
## Specifies one or more "authserv-id" values to trust as relaying true
## upstream DKIM and SPF results. The default is to use the name of
## the MTA processing the message. To specify a list, separate each entry
## with a comma. The key word "HOSTNAME" will be replaced by the name of
## the host running the filter as reported by the gethostname(3) function.
#
# TrustedAuthservIDs HOSTNAME
## UMask mask
## default (none)
##
## Requests a specific permissions mask to be used for file creation. This
## only really applies to creation of the socket when Socket specifies a
## UNIX domain socket, and to the HistoryFile and PidFile (if any); temporary
## files are normally created by the mkstemp(3) function that enforces a
## specific file mode on creation regardless of the process umask. See
## umask(2) for more information.
#
# UMask 077
## UserID user[:group]
## default (none)
##
## Attempts to become the specified userid before starting operations.
## The process will be assigned all of the groups and primary group ID of
## the named userid unless an alternate group is specified.
#
UserID opendmarc
Any ideas as to why DMARC fails on this message?
Thanks
Steve
For the benefit of others who may be having similar problems, here is the solution.
Although DKIM and SPF were passing, align_dkim and align_spf were failing (both were 5 in opendmarc.dat).
The mail log included entries like:
Sep 21 04:50:07 do1 opendkim[902]: 8FD95102172: DKIM verification successful
Sep 21 04:50:07 do1 opendmarc[14961]: 8FD95102172 ignoring Authentication-Results at 0 from do1.keynetworks.com.au
The reason the DKIM authentication results were being ignored was because of a misconfiguration in opendmarc.conf.
It was:
AuthservID keynetworks.com.au
It should be:
AuthservID do1.keynetworks.com.au
which is the FQDN of the host.
After restarting opendmarc, align_dkim passed with 4, although align_spf is still failing on LinkedIn.
DKIM alignment had been failing on all messages, but most passed DMARC because of SPF alignment. LinkedIn was also failing SPF alignment, hence it was failing DMARC.
The opendmarc.conf listed above has also been changed to add:
PublicSuffixList /etc/effective_tld_names.dat
which was fetched from https://publicsuffix.org/list/effective_tld_names.dat
I still don't understand why SPF alignment is failing on LinkedIn, since its SPF alignment mode is relaxed and it is passing SPF, as can be seen from opendmarc.dat:
job 3837B1020BB
reporter do1.keynetworks.com.au
received 1411441591
ipaddr 108.174.3.154
from linkedin.com
mfrom bounce.linkedin.com
dkim linkedin.com 0
spf 0
pdomain linkedin.com
policy 15
rua mailto:d@rua.agari.com
rua mailto:dmarc_agg@auth.returnpath.net
pct 100
adkim 114
aspf 114
p 114
sp 0
align_dkim 4
align_spf 5
action 2
What's left seems to be the alignment problem with SPF. I'll see if I can reproduce this.
You need to set:
TrustedAuthservIDs do1.keynetworks.com.au,keynetworks.com.au
Note that your DKIM Authentication-Results field uses one name and your SPF field uses the other. You have to trust both.
Hi Murray,
Thanks for looking into this. I tried your suggestion and added
TrustedAuthservIDs do1.keynetworks.com.au,keynetworks.com.au
to opendmarc.conf. But, after restarting opendmarc, I still get the same results:
job B7EDA102D90
reporter do1.keynetworks.com.au
received 1423295442
ipaddr 108.174.6.153
from linkedin.com
mfrom bounce.linkedin.com
dkim linkedin.com 0
spf 0
pdomain linkedin.com
policy 15
rua mailto:d@rua.agari.com
rua mailto:dmarc_agg@auth.returnpath.net
pct 100
adkim 114
aspf 114
p 114
sp 0
align_dkim 4
align_spf 5
action 2
Note that there is no problem from Gmail:
job 854FB102D90
reporter do1.keynetworks.com.au
received 1423299183
ipaddr 209.85.216.178
from gmail.com
mfrom gmail.com
dkim gmail.com 0
spf 0
pdomain gmail.com
policy 15
rua mailto:mailauth-reports@google.com
pct 100
adkim 114
aspf 114
p 110
sp 0
align_dkim 4
align_spf 4
action 2
Also, since I have set
SPFIgnoreResults false
and
SPFSelfValidate true
I would expect that Opendmarc would sort out SPF validation internally and not rely on any upstream results.
Thanks
Steve
Your configuration file shows you're not set up to use a public suffix list. Without this, opendmarc can't tell that "bounce.linkedin.com" (the SPF domain) should count as valid for "linkedin.com" (the From domain). That explains why DKIM is aligned but SPF is not.
Give that a go and see if the problem continues.
Not long after posting that initial config file, I did update it to use the PublicSuffixList. This is my current config:
AuthservID do1.keynetworks.com.au
AutoRestart true
AutoRestartRate 10/1h
BaseDirectory /var/run/opendmarc
CopyFailuresTo <removed>
FailureReports true
FailureReportsBcc <removed>
FailureReportsOnNone false
FailureReportsSentBy <removed>
HistoryFile /var/run/opendmarc/opendmarc.dat
IgnoreAuthenticatedClients true
PidFile /var/run/opendmarc/opendmarc.pid
PublicSuffixList /etc/effective_tld_names.dat
RejectFailures false
Socket inet:8893@localhost
SoftwareHeader true
SPFIgnoreResults false
SPFSelfValidate true
Syslog true
SyslogFacility mail
TrustedAuthservIDs do1.keynetworks.com.au,keynetworks.com.au
UserID opendmarc</removed></removed></removed>
The public suffix list was fetched from:
https://publicsuffix.org/list/effective_tld_names.dat
It has been like this for some months now - the only change being TrustedAuthservIDs according to your suggestion.
Thanks
Steve
I was able to reproduce your issue when the public suffix list is not used. Adding it fixes the problem in my tests.
I took your configuration file, commented out the FailureReports stuff and IgnoreAuthenticatedClients, and set it up to use local paths; no other changes. It produced this from v1.3.1.Beta0 in test mode, which I think is what's expected:
job DEBUG-i
reporter DEBUG-j
received 1423516420
ipaddr 127.0.0.1
from linkedin.com
mfrom example.org
dkim linkedin.com 0
spf 0
pdomain linkedin.com
policy 15
rua mailto:d@rua.agari.com
rua mailto:dmarc_agg@auth.returnpath.net
pct 100
adkim 114
aspf 114
p 114
sp 0
align_dkim 4
align_spf 4
action 2
I'll attach the sample message I used.
Sample input message producing correct history file output.
I tried the following:
Downloaded and compiled libspf2-1.2.10 (was previously linking opendmarc against libspf2-1.2.9-1.el6.rf.x86_64).
Downloaded and compiled opendmarc-1.3.1.Beta0.
Changed permissions on /etc/effective_tld_names.dat from 640 to 644 (owner=root, group=opendmarc).
None of these resolved the problem.
A couple of questions:
Does opendmarc expect any particular format for PublicSuffixList? I'm using it exactly as it is from https://publicsuffix.org/list/effective_tld_names.dat
Why is mfrom = example.org in your example, while it is bounce.linkedin.com in the real case?
Thanks
Steve
1) It should take the public suffix list exactly as you download it. You would
see an error logged if there's any problem reading or parsing the file.
2) Ah, right. The test mode has some things hard-coded to certain defaults.
Repeating those tests with overrides to match your arriving mail yields:
dmarc.0.txt: "spf 6" (see attachment "opendmarc.dat.6")
dmarc.-1.txt: "spf 0" (see attachment "opendmarc.dat.0")
Is this more like what you expect?
The other attachment:
That's with Beta1, which I'll post shortly.
Any improvement with Beta1?
No, still the same:
job 4BA90102489
reporter do1.keynetworks.com.au
received 1423703404
ipaddr 108.174.3.145
from linkedin.com
mfrom bounce.linkedin.com
dkim linkedin.com 0
spf 0
pdomain linkedin.com
policy 15
rua mailto:d@rua.agari.com
rua mailto:dmarc_agg@auth.returnpath.net
pct 100
adkim 114
aspf 114
p 114
sp 0
align_dkim 4
align_spf 5
action 2
I can't seem to reproduce the situation you've got with 1.3.0 or 1.3.1.Beta1 other than by disabling the public suffix list checks. It appears that it can't tell that bounce.linkedin.com is a subdomain of linkedin.com, causing the SPF alignment failure. Apart from that, this all looks right.
Also of note, "action 2" does mean "accept", so this isn't failing DMARC (which was part of your original report) because DKIM is passing and is aligned.
1.3.1.Beta1 also has a fatal error now that fires if your public suffix list is absent, unreadable, or otherwise unusable. Since that's not firing for you, I'm at a loss to see what's going on here.
Is there any way that we can get debug information out during normal execution (i.e. not test mode) that shows details on how the align_spf result is obtained?
Is this result:
spf 0
indicating that libspf2 has given the thumbs up?
BTW, I have changed SPFIgnoreResults to true. It made no difference, but just want to keep you updated with my current config.
Test mode uses the same calls as production mode, with some stub values since there's no SMTP session from which to get a few details. You can overcome the stub values with environment variables, but even doing so I couldn't reproduce your problem.
Have you tried it in test mode? Basically, with 1.3.1.Beta1:
1) copy your configuration file to something else
2) in the copy, change the HistoryFile to something else
3) grab a message that causes the problem, and put that in a file; delete any leading "From " line since that's part of the mailbox, not the message
4) set environment variables as follows:
OPENDMARC_TEST_CLIENTHOST=<client_hostname>
OPENDMARC_TEST_CLIENTIP=<client_ip_address>
OPENDMARC_TEST_HELONAME=<client_helo_name>
OPENDMARC_TEST_ENVFROM=<mail_from_address>
5) opendmarc -t <messagefile> -c <secondconffile></secondconffile></messagefile></mail_from_address></client_helo_name></client_ip_address></client_hostname>
If everything was done properly, you will see a single record in your second history file. It should, in theory, reproduce exactly what you're seeing.
Murray, please let me know where I am going wrong.
I copied opendmarc.conf to /tmp/test.conf
In test.conf I changed HistoryFile to /tmp/opendmarc.dat
I also changed BaseDirectory to /tmp since I ran it as another non-priviledged user.
I set the following environment variables:
OPENDMARC_TEST_HELONAME=mailb-fc.linkedin.com
OPENDMARC_TEST_CLIENTHOST=mailb-fc.linkedin.com
OPENDMARC_TEST_CLIENTIP=199.101.162.73
OPENDMARC_TEST_ENVFROM=9umdn5y34qzdmyogaqoefpia3hm916hl6lnoy@bounce.linkedin.com
This is the result:
opendmarc -t test.eml -c test.conf -vv
opendmarc: mlfi_connect() returned SMFIS_CONTINUE
opendmarc: mlfi_helo() returned SMFIS_CONTINUE
opendmarc: test.eml: mlfi_envfrom() returned SMFIS_ACCEPT
However, no /tmp/opendmarc.dat is generated.
I've tried test.eml unmodified and also deleted various headers down to the From: line, but the result is the same.
Below is a copy of the message, with names changed to protect the innocent...
X-Account-Key: account4
X-UIDL: 00008aec52a86afd
X-Mozilla-Status: 0001
X-Mozilla-Status2: 00000000
X-Mozilla-Keys:
Return-Path: s-4sedef6z84xmzn2dger9umdn5y34qzdmyogaqoefpia3hm916hl6lnoy@bounce.linkedin.com
Delivered-To: joe@keynetworks.com.au
Received: from localhost (unknown [127.0.0.1])
by do1.keynetworks.com.au (Postfix) with ESMTP id 69CC3102489
for alias@keynetworks.com.au; Thu, 19 Feb 2015 03:31:31 +0000 (UTC)
X-Spam-Flag: NO
X-Spam-Score: -4.467
X-Spam-Level:
X-Spam-Status: No, score=-4.467 tagged_above=-99 required=5
tests=[BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1,
DKIM_VALID_AU=-0.1, DNS_FROM_AHBL_RHSBL=2.699, HTML_MESSAGE=0.001,
RCVD_IN_RP_CERTIFIED=-3, RCVD_IN_RP_SAFE=-2, RP_MATCHES_RCVD=-0.166,
SPF_HELO_PASS=-0.001, SPF_PASS=-0.001, URIBL_BLOCKED=0.001]
autolearn=ham
Authentication-Results: do1.keynetworks.com.au (amavisd-new);
dkim=pass (1024-bit key) header.d=linkedin.com
Received: from do1.keynetworks.com.au ([127.0.0.1])
by localhost (do1.keynetworks.com.au [127.0.0.1]) (amavisd-new, port 10024)
with ESMTP id b1wi5F_UhsiW for alias@keynetworks.com.au;
Thu, 19 Feb 2015 11:31:29 +0800 (AWST)
X-Greylist: delayed 62 seconds by postgrey-1.34 at do1.keynetworks.com.au; Thu, 19 Feb 2015 11:31:28 AWST
DMARC-Filter: OpenDMARC Filter v1.3.1 do1.keynetworks.com.au 85763100018
Received: from mailb-fc.linkedin.com (mailb-fc.linkedin.com [199.101.162.73])
(using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits))
(No client certificate requested)
by do1.keynetworks.com.au (Postfix) with ESMTPS id 85763100018
for alias@keynetworks.com.au; Thu, 19 Feb 2015 11:31:28 +0800 (AWST)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linkedin.com;
s=proddkim1024; t=1424316660;
bh=2eNeXnqw/wtk18QOdyP7q2NvlNALSpzGQhSxp2T1cv8=;
h=From:Subject:MIME-Version:Content-Type:To:Date:X-LinkedIn-Class:
X-LinkedIn-Template:X-LinkedIn-fbl;
b=JVTu7A7v3yNQiv7naHBVXgw77rJhiBJxyHdVeV78BecLora4I6lgPC1A3268REXDo
MmLucELT7mAmBiIkyb+N2+GuVIYbRqK8JVwAUjYmFLq7lbDsNf7ZPGfF1ga1jfN9Gx
aewOusY7fPU7XJvJ5ZuW9tZp0ThxrSzxj9gf5SzQ=
From: Joe Soap via LinkedIn member@linkedin.com
Reply-To:
Joe Soap via LinkedIn ac48e61f-99be-4763-83c5-e44a854da0e0@reply.linkedin.com
Message-ID: 1020405797.8786266.1424316659569.JavaMail.app@lva1-app7587.prod
Subject: Test
MIME-Version: 1.0
Content-Type: multipart/alternative;
boundary="----=_Part_8786264_1396857040.1424316659566"
To: Test Er alias@keynetworks.com.au
Date: Thu, 19 Feb 2015 03:30:59 +0000 (UTC)
X-LinkedIn-Class: MBR-TO-MBR
X-LinkedIn-Template: mebc_snackified_01
X-LinkedIn-fbl: s-4sedef6z84xmzn2dger9umdn5y34qzdmyogaqoefpia3hm916hl6lnoy
X-LinkedIn-Id: 65gzfd-i6blcwoj-68
------=_Part_8786264_1396857040.1424316659566
Content-Type: text/plain;charset=UTF-8
Content-Transfer-Encoding: quoted-printable
Content-ID: text-body
Test
Is IgnoreAuthenticatedClients set? If so, you need to turn it off for the test. That causes mlfi_envfrom() to short-circuit, as you're observing in that output.
Ah, ok. Now I get this:
job DEBUG-i
reporter DEBUG-j
received 1424414105
ipaddr 199.101.162.73
from linkedin.com
mfrom bounce.linkedin.com
dkim linkedin.com 0
spf 0
pdomain linkedin.com
policy 15
rua mailto:d@rua.agari.com
rua mailto:dmarc_agg@auth.returnpath.net
pct 100
adkim 114
aspf 114
p 114
sp 0
align_dkim 4
align_spf 4
action 2
So, in test mode, it is happy with SPF alignment, but not in production mode. Where to now?
Try upgrading to 1.3.1 (just released) and see if it still recurs with that same configuration. If so, we'll have to try running a debug build in production and attach gdb to it. The back-and-forth we'll need to do to narrow it down will be annoying but necessary.
I get the same result with 1.3.1 .
Am I correct in assuming that "spf 0" means that libspf2 returned "SPF pass"?
A lot of things were fixed in 1.3.2, which I just pushed. I would try it again with that. If you still have trouble, re-post here and we can try to track it down.
To answer your question, "0" does mean a pass in that context. It's one of the ARES_RESULT_* constants from opendmarc/opendmarc-ar.h. "4" is also a pass for the two "align" values.