An Update on DKIM Signing and SE Linux Policy

In my previous post about DKIM [1] I forgot to mention one critical item, how to get Postfix to actually talk to the DKIM milter. This wasn’t a bad thing because it turned out that I hadn’t got it right.

I had configured the DKIM milter on the same line as the milters for ClamAV and SpamAssassin – in the smtpd_milters section. This was fine for relaying outbound mail via my server but didn’t work for locally generated mail. For locally generated mail Postfix has a directive named non_smtpd_milters which you need to use. So it seems that a fully functional Postfix DKIM milter configuration requires adding the following two lines to /etc/postfix/main.cf:

smtpd_milters = unix:/var/run/dkim-filter/dkim-filter.sock
non_smtpd_milters = unix:/var/run/dkim-filter/dkim-filter.sock

This also required an update to the SE Linux policy. When I was working on setting up DKIM I also wrote SE Linux policy to allow it and also wrote policy for the ClamAV milter. That policy is now in Debian/Unstable and has been approved for Lenny. So I now need to build a new policy package that allows the non_smtpd_milter access to the DKIM milter and apply for it to be included in Lenny.

SE Linux in Lenny is going to be really good. I think that I’ve already made the SE Linux support in the pre-release (*) of Lenny significantly better than Etch plus all my extra updates is. More testers would be appreciated, and more people joining the coding would be appreciated even more.

(*) I use the term pre-release to refer to the fact that the Lenny repository is available for anyone to download packages.

7

Installing DKIM and Postfix in Debian

I have just installed Domain Key Identified Mail (DKIM) [1] on my mail server. In summary the purpose is to allow public-key signing of all mail that goes out from your domain so that the recipient can verify it’s authenticity (and optionally reject forgeries). It also means that you can verify inbound mail. A weakness of DKIM is that it is based on the DNS system (which has many issues and will continue to have them until DNSSEC becomes widely adopted). But it’s better than nothing and it’s not overly difficult to install.

The first thing to do before installing DKIM is to get a Gmail account. Gmail gives free accounts and does DKIM checks. If you use Iceweasel or another well supported browser then you can click on “Show Details” from the message view which then gives fields “mailed-by” and “signed-by” which indicate the DKIM status. If you use a less supported browser such as Konqueror then you have to click on the “Show Original” link to see the headers and inspect the DKIM status there (you want to see dkim=pass in the Authentication-Results header). Also Gmail signs outbound mail so it can be used to test verification of received mail.

The next thing to do is to install the DKIM Milter. To make things exciting this is packaged for Debian under the name dkim-filter so that reasonable searches for such functionality (such as a search for milter or dkim-milter – the upstream project name) will fail.

After installing the package you must generate a key, I used the command “dkim-genkey -d coker.com.au -s 2008” to generate a key for my domain. It seems that the domain is currently only used as a comment but I prefer to use all reasonable parameters for such things. The -s option is for a selector, which is a way of specifying multiple valid signing keys. It’s apparently fairly common to use a different key every year. But other options include having multiple mail servers for a domain and giving each one a selector. The dkim-genkey command produces two files, one is named 2008.txt and can be copied into a BIND zone file. The other is named 2008.private and is used by the DKIM signing server.

Here is a sample of the most relevant parts of the config file /etc/dkim-filter.conf for signing mail for a single domain:

Domain coker.com.au
KeyFile /etc/dkim/2008.private
Selector 2008

The file /etc/default/dkim-filter needs to be modified to specify how it will listen for connections from the MTA, I uncommented the line SOCKET=”local:/var/run/dkim-filter/dkim-filter.sock”.

One issue is that the Unix domain socket file will by default not be accessible to Postfix, I devised a work-around for this and documented it in Debian bug report #499364 [2] (I’ve hacked a chgrp command into the init script, ideally the GID would be an option in a config file).

A basic configuration of dkim-milter will sign mail for one domain. If you want to sign mail for more than one domain you have to comment out the configuration for a single domain in /etc/dkim-filter.conf and instead use the option KeyList file to specify a file with a list of domains (the dkim-filter.conf(5) man page documents this). The one confusing issue is that the selector is taken to be the basename of the file which contains the secret key (they really should have added an extra field). This means that if you have an obvious naming scheme for selectors (such as the current year) then you need a different directory for each domain to contain the key.

As an example here is the line from the KeyList file for my domain:
*@coker.com.au:coker.com.au:/etc/dkim/coker.com.au/2008

Now one problem that we have is that list servers will usually append text to the body of a message and thus break the signature. The correct way of solving this is to have the list server sign the mail it sends out and have a header indicating the signature status of the original message. But there are a lot of list servers that won’t be updated for a long time.

The work-around is to put the following line in /etc/dkim-filter.conf:
BodyLengths yes

This means that the signature will cover a specified number of bytes of body data, and any extra which is appended will be ignored when it comes time to verify the message. This means of course that a hostile third party could append some bogus data without breaking the signature. In the case of plain text this isn’t so bad, but when the recipient defaults to having HTML email it could have some interesting possibilities. I wonder whether it would be prudent to configure my MUA to always send both HTML and plain-text versions of my mail so that an attacker can’t append hostile HTML.

It’s a pity that Gmail (which appears to have the most popular implementation of DKIM) doesn’t allow setting that option. So far the only message I have received that failed DKIM checks was sent from a Gmail account to a Debian mailing list.

Ideally it would be possible to have the messages sent to mailing lists not be signed or have the length field used. That would require a signing practice based on recipient which is functionality is not available in dkim-milter (but which possibly could be implemented as Postfix configuration although I don’t know how). Implementing this would not necessarily require knowing all the lists that mail might be sent to, it seems that a large portion of the world’s list traffic is sent to addresses that match the string “@lists.” which can be easily recognised. For a service such as Gmail it would be easy to recognise list traffic from the headers of received messages and then treat messages sent to those domains differently.

As the signature status is based on the sending address it would be possible for me to use different addresses for sending to mailing lists to avoid the signatures (the number of email addresses in use in my domain is small enough that having a line for each address to sign will not be a great inconvenience). Most MUAs have some sort of functionality to automatically choose a sender address that is in some way based on the recipient address. I’ll probably do this eventually, but for the moment I’ll just use the BodyLengths option, while it does reduce the security a bit it’s still a lot better than having no DKIM checks.

4

SpamAssassin During SMTP

For some time people have been telling me about the benefits of SpamAssassin (SA). I have installed it once for a client (at their demand and against my recommendation) but was not satisfied with the result (managing the spam folder was too complex for their users).

The typical configuration of SA has it run after mail has been accepted by the server. Messages that it regards as spam are put into a spam folder. This means that when someone phones you about some important message you didn’t receive then you have to check that folder. Someone who sends mail to a user who has such a SA configuration can not expect that the message will either be received or rejected (thus giving them a bounce message).

Even worse it seems to be quite common for technical users to train the Bayesian part of SA on messages from the spam folder – without reviewing them! Submitting a folder of spam that has been carefully reviewed for Bayesian training can increase the accuracy of classification (including taking account for locality and language differences in spam). Submitting a folder which is not reviewed means that when a false-positive gets into that folder (which will eventually happen) it is used as training for spam recognition thus increasing the incidence of false-positives!

Spam has been becoming more of a problem for me recently, on a typical day between 20 and 40 spam messages would get past the array of DNSBL services I use and be re-sent to pass the grey-listing. Also I have been receiving complaints from people who want to send email to me about some of the DNSBL and RHSBL services I use (the rfc-ignorant.org service gets a lot of complaints – there are a huge number of ignorant and lazy people running mail servers).

So now I have installed spamassassin-milter to have SA run during the SMTP protocol. Then if SA checks indicate that the message is SPAM my mail server can just reject the message with a 55x which will cause the sending mail server to generate a local bounce (if it’s a legitimate message) or to just be discard it in the case of a spam server. Here is how to set it up on Debian/Lenny and CentOS 5:

Install the package yum install spamass-milter or apt-get install spamass-milter spamassassin spamc (spamassassin seems to be installed by default on CentOS). On a Debian system the milter will be setup and running. On CentOS you have to run the following commands:
useradd -m -c "Spamassassin Milter" -s /bin/false spamass-milter
mkdir /var/run/spamass-milter
chown spamass-milter /var/run/spamass-milter
chmod 711 /var/run/spamass-milter
echo SOCKET="/var/run/spamass-milter/spamass.sock" >> /etc/sysconfig/spamass-milter

On CentOS edit /etc/init.d/spamass-milter and change the daemon start line to ‘runuser – spamass-milter -s /bin/bash -c "/usr/sbin/spamass-milter -p $SOCKET -f $EXTRA_FLAGS"‘ Then add the following lines below it:
chown postfix:postfix /var/run/spamass-milter/spamass.sock
chmod 660 /var/run/spamass-milter/spamass.sock

The spamass-milter program talks to the SpamAssassin daemon spamd.

On both Debian and CentOS run the command “useradd -c Spamassassin -m -s /bin/false spamassassin” to create an account for SA. The Debian bug #486914 [1] has a request to have SA not run as root by default.

On CentOS it seems that SA wants to use a directory under the spamass-milter home directory, the following commands alllow this. It would be good to have it not do that, or maybe it would be better to have the one Unix account used for SA and the milter.
chmod 711 ~spamass-milter
mkdir ~spamassassin/.spamassassin
chown spamassassin ~spamassassin/.spamassassin

On Debian edit the file /etc/default/spamassassin and add “-u spamassassin -g spamassassin” to the OPTIONS line. On CentOS edit the file /etc/sysconfig/spamassassin and add “-u spamassassin -g spamassassin” to the SPAMDOPTIONS line.

To enable the daemons, on CentOS you need to run “chkconfig spamass-milter on ; chkconfig spamassassin on“, on Debian edit the file /etc/default/spamassassin and set ENABLED=1.

Now start the daemons, on CentOS use the command “service spamassassin start ; service spamass-milter start“, on Debian use the command “/etc/init.d/spamassassin start“.

Now you have to edit the mail server configuration, for Postfix on CentOS the command “postconf -e smtpd_milters=unix:/var/run/spamass-milter/spamass.sock” will do it, for Postfix on Debian the command “postconf -e smtpd_milters=unix:/var/spool/postfix/spamass/spamass.sock” will do it.

Now restart Postfix and it should be working.

For correct operation you need to ensure that the score needed for a bounce is specified as the same number in both the spamass-milter and SA configuration. If you have a lower number for the spamass-milter configuration (as is the default in Debian) then bounces can be generated – you should never generate a bounce for a spam. The config file /etc/default/spamass-milter allows you to specify the score for rejecting mail, I am currently using a score of 5. Any changes to the score need matching changes to /etc/mail/spamassassin/local.cf (which has a default required_score of 5 in Debian).

You can grep for “spamd..result..Y” in your mail log to see entries for messages that were rejected.

One problem that I have with this configuration on Debian (not on CentOS) is that spamd is logging messages such as “spamd: handle_user unable to find user: ‘russell’“. I don’t want it to look for ~russell when processing mail for russell@coker.com.au because I have a virtual domain set up and the delivery mailbox has a different name. Ideally I could configure it to know the mapping between users and mailboxes (maybe by parsing the /etc/postfix/virtual.db file). But having it simply not attempt to access per-user configuration would be good too. Any suggestions would be appreciated.

Now that I have SpamAssassin running it seems that I am getting about 5 spams a day, the difference is significant. The next thing I will do is make some of the DNSBL checks that are prone to false-positives become SpamAssassin scores instead.

When I started writing this post I was not planning to compare the sys-admin experiences of CentOS and Debian. But it does seem that there is less work involved in the task of installing Debian packages.

18

Moving a Mail Server

Nowadays it seems that most serious mail servers (IE mail servers suitable for running an ISP) use one file per message. In the old days (before about 1996) almost all Internet email was stored in Mbox format [1]. In Mbox you have a large number of messages in a single file, most users would have a single file with all their mail and the advanced users would have multiple files for storing different categories of mail. A significant problem with Mbox is that it was necessary to read the entire file to determine how many messages were stored, as determining the number of messages was the first thing that was done in a POP connection this caused significant performance problems for POP servers. Even more serious problems occurred when messages were deleted as the Mbox file needed to be compacted.

Maildir is a mail storage method developed by Dan Bernstein based around the idea of one file per message [2]. It solves the performance problems of Mbox and also solves some reliability issues (file locking is not needed). It was invented in 1996 and has since become widely used in Unix messaging systems.

The Cyrus IMAP server [3] uses a format similar to Maildir. The most significant difference is that the Cyrus data is regarded as being private to the Cyrus system (IE you are not supposed to mess with it) while Maildir is designed to be used by any tools that you wish (EG my Maildir-Bulletin project [4]).

One down-side to such formats that many people don’t realise (except at the worst time) is the the difficulty in performing backups. As a test I used LVM volume stored on a RAID-1 array of two 20G 7200rpm IDE disks with 343M of data used (according to “df -h” and 39358 inodes in use (as there were 5000 accounts with maildir storage that means 25,000 directories for the home directories and Maildir directories). So there were 14,358 files. To create a tar file of that (written to /dev/null via dd to avoid tar’s optimisation of /dev/null) took 230.6 seconds, 105MB of data was transferred for a transfer rate of 456KB/s. It seems that tar stores the data in a more space efficient manner than the Ext3 filesystem (105MB vs 343MB). For comparison either of the two disks can deliver 40MB/s for the inner tracks. So it seems that unless the amount of used space is less than 1% of the total disk space it will be faster to transfer a filesystem image.

If you have disks that are faster than your network (EG old IDE disks can sustain 40MB/s transfer rates on machines with 100baseT networking and RAID arrays can easily sustain hundreds of megabytes a second on machines with gigabit Ethernet networking) then compression has the potential to improve the speed. Of course the fastest way of transferring such data is to connect the disks to the new machine, this is usually possible when using IDE disks but the vast number of combinations of SCSI bus, disk format, and RAID controller makes it almost impossible on systems with hardware RAID.

The first test I made of compression was on a 1GHz Athlon system which could compress (via gzip -1) 100M of data with four seconds of CPU time. This means that compression has the potential to reduce the overall transfer time (the machine in question has 100baseT networking and no realistic option of adding Gig-E).

The next test I made was on a 3.2GHz Pentium-4 Xeon system. It compressed 1000M of data in 77 seconds (it didn’t have the same data as the Athlon system so it can’t be directly compared), as 1000M would take something like 10 or 12 seconds to transfer at Gig-E speeds that obviously isn’t a viable option.

The gzip -1 compression however compressed the data to 57% of it’s original size, the fact that it compresses so well with gzip -1 suggests to me that there might be a compression method that uses less CPU time while still getting a worth-while amount of compression. If anyone can suggest such a compression method then I would be very interested to try it out. The goal would be a program that can compress 1G of data in significantly less than 10 seconds on a 3.2GHz P4.

Without compression the time taken to transfer 500G of data at Gig-E speeds will probably approach two hours. Not a good amount of down-time for a service that runs 24*7. Particularly given that some time would be spent in getting the new machine to actually use the data.

As for how to design a system to not have these problems, I’ll write a future post with some ideas for how to alleviate that.

20

Conditions of Sending Email

Update: Due to the popularity of this post I have created a T-Shirt and put it on sale at http://www.cafepress.com/email_eula .

Update: Unlike most of my blog content I permit anyone to copy most or all of this post for commercial use (this includes blogs with google advertising) as long as they correctly identify me as the author. Usually I only allow such mirroring for non-commercial sites.

Update: I now have a copy of this post at http://doc.coker.com.au/legal/conditions-email/ which I will modify if necessary.

I have previously written about using a SMTP protocol level disclaimer to trump any legalistic sigs [1].

The conditions of sending mail to my server are now as follows:

  1. A signature will in no way restrict my use of your message. You sent the message to me because you want me to read it (it was not mis-sent, my mail server does not accept mis-addressed mail). I will keep the message as long as I like either deliberately or because I forgot to delete it.
  2. I reserve the right to publish any email that is threatening (including any threats of legal action). I don’t like being threatened and part of my defence is to publish such threats at an appropriate time. Anyone who is considering the possibility of threatening me should consider when their threat may re-appear.
  3. I reserve the right to publish any email that is abusive/profane, is a confession of criminal or unethical behaviour, or is evidence that the sender is a liar or insane.
  4. I reserve the right to forward all amusing email to my friends for their enjoyment.

My mail server will now provide the URL of this page to everyone who connects at the first stage of the SMTP protocol. When a mail server continues the connection that indicates acceptance of these conditions.

This doesn’t mean that I wildly forward email and business discussions are kept confidential of course. I expect that most people don’t keep mail secret when it matches the conditions in my list above, unlike most people I’m publishing the list of reasons.

2

A New Spam Trick

One item on my todo list is to set up a bunch of email addresses on sub-domains of domains that I am responsible for (with the consent of all people involved of course) and perform various actions to get the addresses noticed by spammers and measure how effective the various anti-spam measures are. As part of such tests I would click on every URL in every message sent to some accounts and see what difference it makes. My plan is to run a set of Xen virtual machines with different configurations of some common anti-spam measures used in MTAs and see how they fare with sets of accounts with similar publicity. I am not aware of any work having been done in this area (a quick Google search turned up nothing). There are many honeypots for tracking spam sources, matching email address harvesting to spamming, etc. But I’m not aware of any research into the effectiveness of various methods of combatting spam by setting up multiple honeypots. Please inform me via comments if I have missed something!

The most common advice about spam is to NEVER click on the URL that supposedly removes you from a list. By clicking on such a URL the spammer can recognise that you actually read the email and therefore know that it’s a live address and a good target for more spam. I am not aware of any good studies proving this, which is why it’s one of the things I’d like to investigate. A counter theory (for which there is also a lack of evidence AFAIK) is that spammers used to measure delivery etc but now that bot-nets are large and cheap it’s easier to just send mail to all possible addresses.

Even though I am not aware of any great evidence to support the idea I avoid clicking on URLs in spam messages. Refraining from hitting the spam web-sites can’t do any harm (it’s not as if the meager contribution to their system load caused by my web browser will cause them a problem).

But today I was tricked. A spammer subscribed me to a mailman mailing list, as I am subscribed to many lists (about half of which use mailman) the fact that I didn’t recognise the list name didn’t necessarily mean that I hadn’t signed up to it. After signing in I saw the list archives which had only one post concerning spam. I unsubscribed (there was no other reasonable option open to me) and sent the mailman message to SpamCop.

This technique will probably be effective for a while. People will think that they subscribes to a list and forgot about it and that it’s just another list that doesn’t have strong anti-spam measures. That should greatly increase the amount of time taken to black-list the spam server.

So from now on if I receive a spam via a mailing list that I am not familiar with then I’ll send it to SpamCop immediately. Also this is yet another good reason for not subscribing people to mailing lists without their consent (a practice that is far too common – it’s really not difficult to send someone an email asking whether they would like to join the list). If you subscribe me to a list without prior discussion and the first post I receive on the list is a spam then it will be sent to SpamCop and this might result in you being black-listed.

2

new release of postal

Today I have released a significant new version of my mail server benchmark Postal! The list of changes is below:

  • Added new program bhm to listen on port 25 and send mail to /dev/null. This allows testing mail relay systems.
  • Fixed a minor bug in reporting when compiled without SSL.
  • Made postal write the date header in correct RFC2822 format.
  • Removed the name-expansion feature, it confused many people and is not needed now that desktop machines typically have 1G of RAM. Now postal and rabid can have the same user-list file.
  • Moved postal-list into the bin directory.
  • Changed the thread stack size to 32K (used to be the default of 10M) to save virtual memory size (not that this makes much difference to anything other than the maximum number of threads on i386).
  • Added a minimum message size option to Postal (now you can use fixed sizes).
  • Added a Postal option to specify a list of sender addresses separately to the list of recipient addresses.
  • Removed some unnecessary error messages.
  • Handle EINTR to allow ^Z and “bg” from the command line. I probably don’t handle all cases, but now that I agree that failure to handle ^Z is an error I expect bug reports.
  • Made the test programs display output on the minute, previously they displayed once per minute (EG 11:10:35) while now it will be 11:10:00. This also means that the first minute reported will have something less than 60 seconds of data – this does not matter as a mail server takes longer than that to get up to speed.
  • Added support for GNUTLS and made the Debian package build with it. Note that BHM doesn’t yet work correctly with TLS.
  • Made the programs exit cleanly.

Thanks to Inumbers for sponsoring the development of Postal.

I presented a paper on mail server performance at OSDC 2006 that was based on the now-released version of Postal.

I’ve been replying to a number of email messages in my Postal backlog, some dating back to 2001. Some of the people had changed email address during that time so I’ll answer their questions in my blog instead.

/usr/include/openssl/kssl.h:72:18: krb5.h: No such file or directory
In file included from /usr/include/openssl/ssl.h:179

One problem reported by a couple of people is having the above error when compiling on an older Red Hat release (RHL or RHEL3). Running ./configure –disable-ssl should work-around that problem (at the cost
of losing SSL support). As RHEL3 is still in support I plan to fix this bug eventually.

There was a question about how to get detailed information on what Postal does. All three programs support the options -z and -Z to log details of what they do. This isn’t convenient if you only want a small portion of the data but can be used to obtain any information you desire.

One user reported that options such as -p5 were not accepted. Apparently their system had a broken implementation of the getopt(3) library call used to parse command-line parameters.

4

email disclaimers

Andre Pang blogs about the annoyance of email disclaimers. For a while I had a .sig indicating that it was a condition of sending email to me that the sender agrees to legalistic terms in their .sig being inapplicable to me.

220 smtp.sws.net.au ESMTP Postfix – by sending email to this server you agree that any legalistic sig in your message does not apply to anyone who receives the message through this service.

Now I have changed my Postfix greeting to the above. Anyone who sends me mail agrees that their .sig does not apply to me. Suggestions for improvements to the above text are welcome.

more about MX records

day 10 of the beard

In response to my previous post someone pointed out that MX records have an obvious benefit of offering multiple servers at different priority levels.

I don’t believe that this is a benefit for many machines on the modern Internet. Most systems that have secondary MX records implement them poorly, they have less SPAM checks on the secondary MX server, and it often doesn’t even have a canonical user-list! This is a really serious problem, spammers apparently often target the secondary MX server (I don’t have evidence for this but many people assert it to be true and it would obviously work so is likely to be true) and it’s well known that spammers often guess account names (a quick scan of the logs of any mail server will prove this). These factors combine to make a secondary MX server without a canonical list of user-names a serious spam problem, it will receive mail and then bounce it to innocent third parties (the vast majority of spam has a forged sender nowadays).

If you have the ability to run a well configured secondary MX server with a canonical list of valid account names (which must be maintained independently of the master mail server for obvious reasons) then there is the issue of why you would want to do so. What problem does it solve? In the early days of the Internet mail storage machines were often end-nodes on the network, many hops away from the central well-connected machines. This meant that sometimes connections would time-out or the hop count (which was smaller then than it is now) would be exceeded. Having a well connected server being a secondary MX server was a significant advantage for a small mail server in those times (by todays servers almost all the mail servers of 1993 are small and the biggest servers of 1993 were medium sized by today’s standards).

I just did a quick search for machines with secondary MX records (IE multiple MX records at different priorities). The only significant mail service with such configuration that I could find was gmail. Hotmail.com, ibm.com, microsoft.com, aol.com, and zonnet.nl all have multiple MX records at the same priority – this is a cluster of primary mail servers not a primary/secondary configuration. The evidence suggests that mail servers such as hotmail.com do not benefit from a secondary MX record, so I doubt that any other domain needs it either.

In response to a comment on my previous post, I have previously mentioned in mailing lists the issue of spammers attacking secondary MX servers, but I couldn’t see it when reviewing my blog archives.

Above is day 10 of the beard.

MX vs A record

One issue that has been the topic of some pointless discussion is whether a mail server should have an A record or an MX record. Mail can be delivered to a domain that has no MX record but simply an A record pointing to an IP address. But the most common practice is to have an MX record pointing to the name of the machine that serves the mail. A common use for this is to have a bulk mail hosting machine with multiple MX records pointing at it, which then allows you to have matching forward and reverse DNS entries for the machine name.

If you have no MX record for a domain then Postfix will do the following DNS requests:

IP postfix.34245 > DNS.domain:  3448+ MX? example.com. (32)
IP postfix.34261 > DNS.domain:  50123+ A? example.com. (32)

If you have an MX record then it does the following:

IP postfix.34675 > DNS.domain:  29942+ MX? example.com. (32)
IP postfix.34675 > DNS.domain:  33294+ A? mail.example.com. (37)

Now if there are multiple domains on a bulk mail hosting system then the A record might already be in a local cache on the sending machine, so having bulk mail hosting with MX records may reduce the number of DNS lookups, with the minumum number of lookups being half plus one.

If there is no bulk mail hosting then an MX record would still offer some slight benefits if the positive responses are cached for longer than negative responses. This would mean less lookups which gives faster and more reliable delivery of mail plus being more friendly to the net. I don’t know what the cache behaviour is in this regard so I’m not sure if this would actually give a benefit (I’m sure someone will comment with the answer).

Now regardless of these issues I think that using an MX record is the better option. It’s what most software expects and saves you from the excitement of discovering corner case bugs in various software that’s out there on the net.