Adding DKIM to news articles #gnus #dkim

🕥︎ - 2020-07-04

Recently I had a monologue on the Gnus development list, where I lamented the munging of the From: header in my emails to the Emacs development mailing list when sent through Gmane using nntp, and proceeded to solve the problem.

Since then I've discovered, and fixed, a line-ending problem, so I thought I would document the entire solution in a little more detail here.

There are three steps to perform on the machine running Gnus (in this case, my laptop):

Install and configure opendkim, generate key

Installing is just sudo apt install opendkim.

In /etc/opendkim/ I have three files:

internalhosts containing the IP-addresses of my laptop (where Gnus runs):

keytable defining where to find the key corresponding to a domain:

koldfront.dk koldfront.dk:news:/etc/dkimkeys/koldfront.dk.news.private

and finally signingtable, saying what addresses to sign with what domain:

*@koldfront.dk koldfront.dk

In /etc/opendkim.conf I have changed these lines:

Selector news
SignatureAlgorithm rsa-sha256
InternalHosts /etc/opendkim/internalhosts
KeyTable /etc/opendkim/keytable
SigningTable refile:/etc/opendkim/signingtable

Generate key

To generate the key, I went to the directory /etc/dkimkeys, and ran this command:

opendkim-genkey -b 2048 -d koldfront.dk -s koldfront.dk.news

Notice that I am using the selector news, separate from the selector my mail server uses to sign outgoing email (mail). This way I don't have to share, and keep in sync, private keys between the machines.

Make sure the generated private key, koldfront.dk.news.private is owned by opendkim.opendkim and has permissions -rw-------.

Also generated by the command is a file called koldfront.dk.news.txt, this contains the information that goes in DNS.

Update DNS

I run my own DNS servers, so I copied the content of the .txt file to my bind zonefile /etc/bind/db.koldfront.dk, with a slight adjustment to the "hostname". I think that is necessary because of the -s argumen I gave opendkim-genkey - I had to change koldfront.dk.news._domainkey IN TXT to news._domainkey.koldfront.dk. IN TXT.

After remembering to bump the serial field in the zonefile, it's just a matter of telling bind to reload the zone, so it can be resigned for DNSSEC and distributed to the two other DNS servers, i.e. rndc reload koldfront.dk IN internet.

Integration in Gnus

The final step is to make Gnus sign outgoing news articles - to do that I added a function to the message-send-news-hook, which runs opendkim, as the opendkim user, on the article, and adds the header generated to it.

(add-hook 'message-send-news-hook 'asjo-add-dkim-signature)
(defun asjo-add-dkim-signature ()
  "Add a DKIM-signature: header"
    (insert (asjo-generate-dkim-signature))))

(defun asjo-generate-dkim-signature ()
  "Genedate DKIM signature from current buffer by calling opendkim."
    (shell-command-on-region (point-min) (point-max) "sudo -u opendkim /usr/sbin/opendkim -bs -t - | awk 'NR > 1' | sed 's/\r//'" " *asjo-generate-dkim-output")
    (with-current-buffer " *asjo-generate-dkim-output"

The thing I missed in the first iteration was that opendkim outputs lines ending with \r\n, and Gnus expects just \n in the article buffer, so I had to strip them.

I found this when I posted to an nntp-based blog-engine I am developing, which balked at the line endings!


When I write to the Emacs development list via Gmane/nntp, the From:-lines are no longer munged, as that is only necessary if SPF fails (it does almost by definition for a mailing list forwarding emails) and there were no DKIM-signature - and I've now added the latter.


Unfortunately it's not really feasible for this to work "out-of-the-box" in a news reader, because the public key needs to be added to DNS, which - while simple - is not something the news reader can do automatically.

I guess the installation could be made "less systemwide" by having the key in my home directory and using a configuration referring to that, but since I'm the primary user of my laptop, it's fine.

Add comment

To avoid spam many websites make you fill out a CAPTCHA, or log in via an account at a corporation such as Twitter, Facebook, Google or even Microsoft GitHub.

I have chosen to use a more old school method of spam prevention.

To post a comment here, you need to:

¹ Such as Thunderbird, Pan, slrn or Gnus (part of Emacs).