Add dkim support

Julien LepillerWed Jul 24 18:55:04+0200 2019

eabb529

Add dkim support

modules/config/dns.scm

2424
  #:use-module (gnu services)
2525
  #:use-module (gnu services dns)
2626
  #:use-module (srfi srfi-1)
27+
  #:use-module (ice-9 textual-ports)
2728
  #:export (ipv4-reverse-master-zone
2829
            ipv6-reverse-master-zone
2930
            lepiller-master-zone

3334
            hermes
3435
            ene))
3536
37+
(define public-dkim
38+
  (apply
39+
    string-append
40+
    (string-split
41+
      (call-with-input-file "/etc/mail/dkim/public.key" get-string-all)
42+
      #\newline)))
43+
3644
(define-zone-entries lepiller.eu.zone
3745
;; Name         TTL Class Type Data
3846
  ("ene"        ""  "IN"  "A"     ene-ip4)

6270
  ("imap"       ""  "IN"  "CNAME" "courriel")
6371
  ("smtp"       ""  "IN"  "CNAME" "b.courriel")
6472
  ("@"          ""  "IN"  "TXT"   "v=spf1 mx a ~all")
65-
  ("@"          ""  "IN"  "SPF"   "v=spf1 mx a ~all"))
73+
  ("@"          ""  "IN"  "SPF"   "v=spf1 mx a ~all")
74+
  
75+
  ("dkim._domainkey" "" "IN" "TXT" (string-append "v=DKIM1; p=" public-dkim "; s=email; t=s")))
6676
6777
(define-zone-entries ipv4-reverse.zone
6878
  ("@" "" "IN" "PTR" "lepiller.eu.")

110120
    (zone (zone-file
111121
            (origin "lepiller.eu")
112122
            (entries lepiller.eu.zone)
113-
            (serial 2019041202)))))
123+
            (serial 2019072401)))))
114124
115125
(define lepiller-slave-zone
116126
  (knot-zone-configuration

modules/config/mail.scm

2424
  #:use-module (gnu services)
2525
  #:use-module (gnu services mail)
2626
  #:use-module (guix gexp)
27+
  #:use-module (services mail)
2728
  #:export (lepiller-mail-services))
2829
2930
(define aliases-file

5960
listen on " interface " port 25 tls pki lepiller.eu
6061
# For sending messages from outside of this server, you need to authenticate and
6162
# use TLS.
62-
listen on " interface " port 587 tls-require pki lepiller.eu auth <passwd>
63+
listen on " interface " port 587 tls-require pki lepiller.eu mask-source auth <passwd>
6364
# On this server, you only need to authenticate on one of the available ports,
6465
# and you may use TLS.
65-
listen on lo port 25 tls pki lepiller.eu auth <passwd>
66-
listen on lo port 587 tls pki lepiller.eu auth <passwd>
66+
listen on lo port 25 tls pki lepiller.eu mask-source auth <passwd>
67+
listen on lo port 587 tls pki lepiller.eu mask-source auth <passwd>
68+
listen on lo port 10028 tag DKIM_OUT # DKIMproxy
69+
70+
# Maybe it'll work better if we connect to gmail only with v4?
71+
limit mta for domain gmail.com inet4
6772
6873
# TODO: manage these files directly in the configuration?
6974
# If you edit the file, you have to run \"smtpctl update table aliases\"

7378
table blacklist file:" blacklist-file "
7479
7580
# We accept to relay any mail from authenticated users
76-
accept for any authenticated relay
81+
accept for any authenticated relay via smtp://127.0.0.1:10027
82+
accept tagged DKIM_OUT for any relay
7783
7884
# Then, we reject on some other conditions:
7985

8793
accept for local alias <aliases> deliver to maildir
8894
"))
8995
96+
(define (dkimproxy-conf domain)
97+
  (mixed-text-file "dkimproxy.out.conf" "
98+
# specify what address/port DKIMproxy should listen on
99+
listen    127.0.0.1:10027
100+
# specify what address/port DKIMproxy forwards mail to
101+
relay     127.0.0.1:10028
102+
# specify what domains DKIMproxy can sign for (comma-separated, no spaces)
103+
domain    " domain "
104+
# specify what signatures to add
105+
signature dkim(c=relaxed)
106+
signature domainkeys(c=nofws)
107+
# specify location of the private key
108+
keyfile   /etc/mail/dkim/private.key
109+
# specify the selector (i.e. the name of the key record put in DNS)
110+
selector  dkim
111+
"))
112+
90113
(define (lepiller-imap-service domain)
91114
  (service dovecot-service-type
92115
           (dovecot-configuration
93-
	     (mail-location "maildir:~/Maildir")
94-
	     (ssl-cert (string-append
95-
			 "</etc/letsencrypt/live/" domain "/fullchain.pem"))
96-
	     (ssl-key  (string-append
97-
			 "</etc/letsencrypt/live/" domain "/privkey.pem")))))
116+
             (mail-location "maildir:~/Maildir")
117+
             (ssl-cert (string-append
118+
                         "</etc/letsencrypt/live/" domain "/fullchain.pem"))
119+
             (ssl-key  (string-append
120+
                         "</etc/letsencrypt/live/" domain "/privkey.pem")))))
98121
99122
(define (lepiller-smtp-service interface domain)
100123
  (service opensmtpd-service-type
101-
	   (opensmtpd-configuration
102-
	     (config-file (opensmtpd-conf interface domain)))))
124+
           (opensmtpd-configuration
125+
             (config-file (opensmtpd-conf interface domain)))))
126+
127+
(define (lepiller-dkim-service domain)
128+
  (service dkimproxy-out-service-type
129+
           (dkimproxy-out-configuration
130+
             (config-file (dkimproxy-conf domain)))))
103131
104132
(define* (lepiller-mail-services #:key interface domain)
105133
  (list
106134
    (lepiller-smtp-service interface domain)
107-
    (lepiller-imap-service domain)))
135+
    (lepiller-imap-service domain)
136+
    (lepiller-dkim-service domain)))
137+

modules/packages/perl.scm unknown status 1

1+
;;; GNU Guix --- Functional package management for GNU
2+
;;; Copyright ?? 2019 Julien Lepiller <julien@lepiller.eu>
3+
;;;
4+
;;; This file is part of GNU Guix.
5+
;;;
6+
;;; GNU Guix is free software; you can redistribute it and/or modify it
7+
;;; under the terms of the GNU General Public License as published by
8+
;;; the Free Software Foundation; either version 3 of the License, or (at
9+
;;; your option) any later version.
10+
;;;
11+
;;; GNU Guix is distributed in the hope that it will be useful, but
12+
;;; WITHOUT ANY WARRANTY; without even the implied warranty of
13+
;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14+
;;; GNU General Public License for more details.
15+
;;;
16+
;;; You should have received a copy of the GNU General Public License
17+
;;; along with GNU Guix.  If not, see <http://www.gnu.org/licenses/>.
18+
19+
(define-module (packages perl)
20+
  #:use-module ((guix licenses) #:prefix license:)
21+
  #:use-module (gnu packages)
22+
  #:use-module (guix packages)
23+
  #:use-module (guix download)
24+
  #:use-module (guix utils)
25+
  #:use-module (guix build-system gnu)
26+
  #:use-module (guix build-system perl)
27+
  #:use-module (gnu packages networking)
28+
  #:use-module (gnu packages perl)
29+
  #:use-module (gnu packages perl-check)
30+
  #:use-module (gnu packages tls)
31+
  #:use-module (gnu packages web))
32+
33+
(define-public perl-mail-authenticationresults
34+
  (package
35+
    (name "perl-mail-authenticationresults")
36+
    (version "1.20180923")
37+
    (source (origin
38+
              (method url-fetch)
39+
              (uri (string-append
40+
                     "mirror://cpan/authors/id/M/MB/MBRADSHAW/"
41+
                     "Mail-AuthenticationResults-" version ".tar.gz"))
42+
              (sha256
43+
               (base32
44+
                "1g1wym9vcbhldwvi4w5pl0fhd4jh2icj975awf4wr5xmkli9mxbz"))))
45+
    (build-system perl-build-system)
46+
    (native-inputs
47+
     `(("perl-test-exception" ,perl-test-exception)))
48+
    (home-page "https://metacpan.org/release/Mail-AuthenticationResults")
49+
    (synopsis "Object Oriented Authentication-Results Headers")
50+
    (description "Mail::AuthenticationResults parses the message header field
51+
that indicates the message authentication status as per RFC7601.  This module
52+
is not fully compliant with the RFC but it tries to implement most styles of
53+
Authentication-Results header seen in the wild.")
54+
    (license license:perl-license)))
55+
56+
(define-public perl-net-dns-resolver-mock
57+
  (package
58+
    (name "perl-net-dns-resolver-mock")
59+
    (version "1.20171219")
60+
    (source (origin
61+
              (method url-fetch)
62+
              (uri (string-append
63+
                     "mirror://cpan/authors/id/M/MB/MBRADSHAW/"
64+
                     "Net-DNS-Resolver-Mock-" version ".tar.gz"))
65+
              (sha256
66+
               (base32
67+
                "0m3rxpkv1b9121srvbqkrgzg4m8mnydiydqv34in1i1ixwrl6jn9"))))
68+
    (build-system perl-build-system)
69+
    (propagated-inputs
70+
     `(("perl-net-dns" ,perl-net-dns)))
71+
    (home-page "https://metacpan.org/release/Net-DNS-Resolver-Mock")
72+
    (synopsis "Mock a DNS Resolver object for testing")
73+
    (description "Net::DNS::Resolver::Mock is a a subclass of
74+
@code{Net::DNS::Resolver} which parses a zonefile for it's data source.  It is
75+
primarily for use in testing.")
76+
    (license license:perl-license)))
77+
78+
(define-public perl-mail-dkim
79+
  (package
80+
    (name "perl-mail-dkim")
81+
    (version "0.55")
82+
    (source (origin
83+
              (method url-fetch)
84+
              (uri (string-append
85+
                     "mirror://cpan/authors/id/M/MB/MBRADSHAW/Mail-DKIM-"
86+
                     version
87+
                     ".tar.gz"))
88+
              (sha256
89+
               (base32
90+
                "18nsh1ff6fkns4xk3y2ixmzmadgggydj11qkzj6nlnq2hzqxsafz"))))
91+
    (build-system perl-build-system)
92+
    (propagated-inputs
93+
     `(("perl-crypt-openssl-rsa" ,perl-crypt-openssl-rsa)
94+
       ("perl-mail-authenticationresults" ,perl-mail-authenticationresults)
95+
       ("perl-mailtools" ,perl-mailtools)
96+
       ("perl-net-dns" ,perl-net-dns)
97+
       ("perl-net-dns-resolver-mock" ,perl-net-dns-resolver-mock)
98+
       ("perl-test-requiresinternet" ,perl-test-requiresinternet)
99+
       ("perl-yaml-libyaml" ,perl-yaml-libyaml)))
100+
    (home-page "https://metacpan.org/release/Mail-DKIM")
101+
    (synopsis "Signs/verifies Internet mail with DKIM/DomainKey signatures")
102+
    (description "Mail::DKIM is a Perl module that implements the new Domain
103+
Keys Identified Mail (DKIM) standard, and the older Yahoo! DomainKeys standard,
104+
both of which sign and verify emails using digital signatures and DNS records.
105+
Mail-DKIM can be used by any Perl program that wants to provide support for
106+
DKIM and/or DomainKeys.")
107+
    (license license:gpl3+)))
108+
109+
(define-public dkimproxy
110+
  (package
111+
    (name "dkimproxy")
112+
    (version "1.4.1")
113+
    (source (origin
114+
              (method url-fetch)
115+
              (uri (string-append
116+
                     "mirror://sourceforge/dkimproxy/dkimproxy/"
117+
                     version "/dkimproxy-" version ".tar.gz"))
118+
              (sha256
119+
               (base32
120+
                "1gc5c7lg2qrlck7b0lvjfqr824ch6jkrzkpsn0gjvlzg7hfmld75"))))
121+
    (build-system gnu-build-system)
122+
    (arguments
123+
     `(#:phases
124+
       (modify-phases %standard-phases
125+
         (add-after 'install 'make-wrapper
126+
           (lambda* (#:key inputs outputs #:allow-other-keys)
127+
             (let ((out (assoc-ref outputs "out")))
128+
               (for-each
129+
                 (lambda (prog)
130+
                   (wrap-program (string-append out "/bin/" prog)
131+
                     `("PERL5LIB" ":" prefix
132+
                       (,(string-append (assoc-ref inputs "perl-mail-dkim")
133+
                                        "/lib/perl5/site_perl")
134+
                        ,(string-append (assoc-ref inputs "perl-mailtools")
135+
                                        "/lib/perl5/site_perl")
136+
                        ,(string-append (assoc-ref inputs "perl-crypt-openssl-rsa")
137+
                                        "/lib/perl5/site_perl")
138+
                        ,(string-append (assoc-ref inputs "perl-net-dns")
139+
                                        "/lib/perl5/site_perl")
140+
                        ,(string-append (assoc-ref inputs "perl-net-server")
141+
                                        "/lib/perl5/site_perl")))))
142+
                 '("dkimproxy.in" "dkimproxy.out")))
143+
             #t)))))
144+
    (inputs
145+
     `(("perl" ,perl)
146+
       ("perl-crypt-openssl-rsa" ,perl-crypt-openssl-rsa)
147+
       ("perl-mailtools" ,perl-mailtools)
148+
       ("perl-mail-dkim" ,perl-mail-dkim)
149+
       ("perl-net-dns" ,perl-net-dns)
150+
       ("perl-net-server" ,perl-net-server)))
151+
    (home-page "http://dkimproxy.sourceforge.net/")
152+
    (synopsis "SMTP-proxy for DKIM signing and verifying")
153+
    (description "DKIMproxy is an SMTP-proxy that signs and/or verifies emails,
154+
using the @code{Mail::DKIM} module.  It is designed for Postfix, but should
155+
work with any mail server.  It comprises two separate proxies, an outbound
156+
proxy for signing outgoing email, and an inbound proxy for verifying signatures
157+
of incoming email.  With Postfix, the proxies can operate as either
158+
@code{Before-Queue} or @code{After-Queue} content filters.")
159+
    (license license:gpl3+)))

modules/services/mail.scm unknown status 1

1+
;;; GNU Guix --- Functional package management for GNU
2+
;;; Copyright ?? 2019 Julien Lepiller <julien@lepiller.eu>
3+
;;;
4+
;;; This file is part of GNU Guix.
5+
;;;
6+
;;; GNU Guix is free software; you can redistribute it and/or modify it
7+
;;; under the terms of the GNU General Public License as published by
8+
;;; the Free Software Foundation; either version 3 of the License, or (at
9+
;;; your option) any later version.
10+
;;;
11+
;;; GNU Guix is distributed in the hope that it will be useful, but
12+
;;; WITHOUT ANY WARRANTY; without even the implied warranty of
13+
;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14+
;;; GNU General Public License for more details.
15+
;;;
16+
;;; You should have received a copy of the GNU General Public License
17+
;;; along with GNU Guix.  If not, see <http://www.gnu.org/licenses/>.
18+
;;;
19+
;;; Some of the help text was taken from the default dovecot.conf files.
20+
21+
(define-module (services mail)
22+
  #:use-module (gnu services)
23+
  #:use-module (gnu services base)
24+
  #:use-module (gnu services configuration)
25+
  #:use-module (gnu services shepherd)
26+
  #:use-module (gnu system pam)
27+
  #:use-module (gnu system shadow)
28+
  #:use-module (gnu packages admin)
29+
  #:use-module (guix gexp)
30+
  #:use-module (guix records)
31+
  #:use-module (ice-9 match)
32+
  #:use-module (packages perl)
33+
  #:export (dkimproxy-out-service-type
34+
35+
            dkimproxy-out-configuration
36+
            dkimproxy-out-configuration-package
37+
            dkimproxy-out-configuration-config-file))
38+
39+
(define-record-type* <dkimproxy-out-configuration>
40+
  dkimproxy-out-configuration make-dkimproxy-out-configuration
41+
  dkimproxy-out-configuration?
42+
  (package     dkimproxy-out-configuration-package
43+
               (default dkimproxy))
44+
  (config-file dkimproxy-out-configuration-config-file
45+
               (default %default-dkimproxy-out-configuration-config-file)))
46+
47+
(define %default-dkimproxy-out-configuration-config-file
48+
  (plain-file "dkimproxy_out.conf" "
49+
# specify what address/port DKIMproxy should listen on
50+
listen    127.0.0.1:10027
51+
# specify what address/port DKIMproxy forwards mail to
52+
relay     127.0.0.1:10028
53+
# specify what domains DKIMproxy can sign for (comma-separated, no spaces)
54+
domain    mail.example.com 
55+
# specify what signatures to add
56+
signature dkim(c=relaxed)
57+
signature domainkeys(c=nofws)
58+
# specify location of the private key
59+
# It can be generated with for instance:
60+
# mkdir /etc/mail/dkim
61+
# openssl genrsa -out /etc/mail/dkim/private.key 1024
62+
# openssl rsa -in /etc/mail/dkim/private.key -pubout -out /etc/mail/dkim/public.key
63+
keyfile   /etc/mail/dkim/private.key
64+
# specify the selector (i.e. the name of the key record put in DNS)
65+
selector  selector1
66+
"))
67+
68+
(define dkimproxy-out-shepherd-service
69+
  (match-lambda
70+
    (($ <dkimproxy-out-configuration> package config-file)
71+
     (list (shepherd-service
72+
             (provision '(dkimproxy-out))
73+
             (requirement '(loopback))
74+
             (documentation "Outbound DKIM proxy.")
75+
             (start (let ((proxy (file-append package "/bin/dkimproxy.out")))
76+
                      #~(make-forkexec-constructor
77+
                          (list #$proxy (string-append "--conf_file=" #$config-file)
78+
                                "--pidfile=/var/run/dkimproxy.out.pid"
79+
                                "--user=dkimproxy" "--group=dkimproxy")
80+
                          #:pid-file "/var/run/dkimproxy.out.pid")))
81+
             (stop #~(make-kill-destructor)))))))
82+
83+
(define %dkimproxy-accounts
84+
  (list (user-group
85+
          (name "dkimproxy")
86+
          (system? #t))
87+
        (user-account
88+
          (name "dkimproxy")
89+
          (group "dkimproxy")
90+
          (system? #t)
91+
          (comment "Dkimproxy user")
92+
          (home-directory "/var/empty")
93+
          (shell (file-append shadow "/sbin/nologin")))))
94+
95+
(define dkimproxy-out-service-type
96+
  (service-type
97+
    (name 'dkimproxy-out)
98+
    (extensions
99+
      (list (service-extension account-service-type
100+
                               (const %dkimproxy-accounts))
101+
            (service-extension shepherd-root-service-type
102+
                               dkimproxy-out-shepherd-service)))))

systems/hermes.scm

2222
(use-modules (gnu services web))
2323
(use-modules (config certbot) (config dns) (config mail) (config network) (config os))
2424
25+
26+
;; NOTE: this config contains out-of band files.
27+
;; To (re-)generate /etc/mail/dkim/private.key, run:
28+
;; openssl genrsa -out /etc/mail/dkim/private.key 2048
29+
;; openssl rsa -in /etc/mail/dkim/private.key -pubout -out /etc/mail/dkim/public.key
30+
;; chmod 440 /etc/mail/dkim/private.key
31+
;;
32+
;; To (re-)generate /etc/knot/secrets.conf, run:
33+
;; keymgt -t lepiller-key > /etc/knot/secrets.conf
34+
2535
(operating-system
2636
  (inherit (tyreunom-os "hermes"))
2737
  (bootloader