]> birchwood-abbey.net Git - Institute/commitdiff
Implement DMARC, DKIM on Front.
authorMatt Birkholz <matt@birchwood-abbey.net>
Sun, 11 Jan 2026 21:15:54 +0000 (14:15 -0700)
committerMatt Birkholz <matt@birchwood-abbey.net>
Sun, 11 Jan 2026 21:15:54 +0000 (14:15 -0700)
README.org
roles_t/front/handlers/main.yml
roles_t/front/tasks/main.yml

index f9d5a3a7afee8ee7535a5f3cd5a3434ef0edbe0d..00918b472e1260b49382ca5833ca3691f0ac845a 100644 (file)
@@ -171,14 +171,34 @@ Core.  Core relays other messages to its smarthost, Front, which is
 declared by the institute's SPF (Sender Policy Framework) DNS record
 to be the only legitimate sender of institute emails.  Thus the
 Internet sees the institute's outgoing email coming from a server at
-an address matching the domain's SPF record.  The institute does /not/
-sign outgoing emails per DKIM (Domain Keys Identified Mail) yet.
+an address matching the domain's SPF record.
 
 #+CAPTION: Example Small Institute SPF Record
 #+BEGIN_SRC conf
 TXT    v=spf1 ip4:159.65.75.60 -all
 #+END_SRC
 
+The institute signs 100% of its outgoing emails per DKIM (Domain Keys
+Identified Mail) and publishes a DMARC DNS record indicating that
+non-compliant emails should be rejected and can be reported to the
+postmaster.
+
+#+CAPTION: Example Small Institute DMARC Record (truncated)
+#+BEGIN_SRC conf
+v=DMARC1;p=reject;pct=100;rua=mailto:postmaster+dmarc@small.example...
+#+END_SRC
+
+#+CAPTION: Example Small Institute DKIM
+
+It publishes the key used to sign outgoing email in a DKIM record, a
+~TXT~ record on the name ~default._domainkey.small.example.org~.  The
+example record below specifies 256bit hashing and no sub-domains.
+
+#+CAPTION: Example Small Institute DKIM Record (truncated)
+#+BEGIN_SRC conf
+v=DKIM1;h=sha256;t=s;p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA...
+#+END_SRC
+
 There are a number of configuration settings that, for
 interoperability, should be in agreement on the Postfix servers and
 the campus clients.  Policy also requires certain settings on both
@@ -1756,6 +1776,102 @@ created by a more specialized role.
   tags: actualizer
 #+END_SRC
 
+** Configure OpenDKIM
+
+Front uses OpenDKIM to sign outgoing emails.  It does not verify
+incoming emails (yet).  The following tasks install and configure
+OpenDKIM, and Postfix.
+
+#+CAPTION: [[file:roles_t/front/tasks/main.yml][=roles_t/front/tasks/main.yml=]]
+#+BEGIN_SRC conf :tangle roles_t/front/tasks/main.yml :noweb no-export
+
+- name: Install OpenDKIM.
+  become: yes
+  apt: pkg=opendkim
+
+- name: Install DKIM private key.
+  become: yes
+  copy:
+    src: "../Secret/opendkim/default.private"
+    dest: "/etc/dkimkeys/default.private"
+    owner: opendkim
+    group: opendkim
+    mode: u=rw,g=,o=
+
+- name: Add postfix to opendkim group.
+  become: yes
+  user:
+    name: postfix
+    append: yes
+    groups: opendkim
+
+- name: Create opendkim/ in Postfix chroot.
+  become: yes
+  file:
+    path: /var/spool/postfix/opendkim
+    state: directory
+    owner: opendkim
+    group: opendkim
+
+- name: Configure OpenDKIM.
+  become: yes
+  lineinfile:
+    path: /etc/opendkim.conf
+    regexp: "^{{ item.name }}\t"
+    line: "{{ item.name }}\t\t{{ item.value }}"
+  loop:
+  - { name: "Mode", value: "\ts" }
+  - { name: "Domain", value: "\tbirchwood-abbey.net" }
+  - { name: "Selector", value: "default" }
+  - { name: "KeyFile", value: "\t/etc/dkimkeys/default.private" }
+  - name: "Socket"
+    value: "\tlocal:/var/spool/postfix/opendkim/opendkim.sock"
+  - name: "InternalHosts"
+    value: >-
+      127.0.0.1,
+      {{ private_net_cidr }},
+      {{ public_wg_net_cidr }},
+      {{ campus_wg_net_cidr }}
+  notify: Restart OpenDKIM.
+
+- name: Start OpenDKIM.
+  become: yes
+  systemd:
+    service: opendkim
+    state: started
+  tags: actualizer
+
+- name: Enable OpenDKIM.
+  become: yes
+  systemd:
+    service: opendkim
+    enabled: yes
+
+- name: Configure Postfix for OpenDKIM.
+  become: yes
+  lineinfile:
+    path: /etc/postfix/main.cf
+    regexp: "^ *{{ item.p }} *="
+    line: "{{ item.p }} = {{ item.v }}"
+  loop:
+  - { p: "milter_default_action", v: "accept" }
+  - { p: "milter_protocol", v: "6" }
+  - { p: "smtpd_milters", v: "local:opendkim/opendkim.sock" }
+  - { p: "non_smtpd_milters", v: '$smtpd_milters' }
+  notify: Restart Postfix.
+#+END_SRC
+
+#+CAPTION: [[file:roles_t/front/handlers/main.yml][=roles_t/front/handlers/main.yml=]]
+#+BEGIN_SRC conf :tangle roles_t/front/handlers/main.yml
+
+- name: Restart OpenDKIM.
+  become: yes
+  systemd:
+    service: opendkim
+    state: restarted
+  tags: actualizer
+#+END_SRC
+
 ** Configure Dovecot IMAPd
 
 Front uses Dovecot's IMAPd to allow user Fetchmail jobs on Core to
index e51d031efe9f9998dc00ff9a6c01eff66361d7bd..cdd096afcd29bbb232aaaed80c9388fa7107ed54 100644 (file)
   command: newaliases
   tags: actualizer
 
+- name: Restart OpenDKIM.
+  become: yes
+  systemd:
+    service: opendkim
+    state: restarted
+  tags: actualizer
+
 - name: Restart Dovecot.
   become: yes
   systemd:
index 3b08c80594eb61ec035d02b4da0ce7436bc8f30c..c31cf1e28cae3e0f24a53ba2d51852072134e725 100644 (file)
     marker: "# {mark} INSTITUTE MANAGED BLOCK"
   notify: New aliases.
 
+- name: Install OpenDKIM.
+  become: yes
+  apt: pkg=opendkim
+
+- name: Install DKIM private key.
+  become: yes
+  copy:
+    src: "../Secret/opendkim/default.private"
+    dest: "/etc/dkimkeys/default.private"
+    owner: opendkim
+    group: opendkim
+    mode: u=rw,g=,o=
+
+- name: Add postfix to opendkim group.
+  become: yes
+  user:
+    name: postfix
+    append: yes
+    groups: opendkim
+
+- name: Create opendkim/ in Postfix chroot.
+  become: yes
+  file:
+    path: /var/spool/postfix/opendkim
+    state: directory
+    owner: opendkim
+    group: opendkim
+
+- name: Configure OpenDKIM.
+  become: yes
+  lineinfile:
+    path: /etc/opendkim.conf
+    regexp: "^{{ item.name }}\t"
+    line: "{{ item.name }}\t\t{{ item.value }}"
+  loop:
+  - { name: "Mode", value: "\ts" }
+  - { name: "Domain", value: "\tbirchwood-abbey.net" }
+  - { name: "Selector", value: "default" }
+  - { name: "KeyFile", value: "\t/etc/dkimkeys/default.private" }
+  - name: "Socket"
+    value: "\tlocal:/var/spool/postfix/opendkim/opendkim.sock"
+  - name: "InternalHosts"
+    value: >-
+      127.0.0.1,
+      {{ private_net_cidr }},
+      {{ public_wg_net_cidr }},
+      {{ campus_wg_net_cidr }}
+  notify: Restart OpenDKIM.
+
+- name: Start OpenDKIM.
+  become: yes
+  systemd:
+    service: opendkim
+    state: started
+  tags: actualizer
+
+- name: Enable OpenDKIM.
+  become: yes
+  systemd:
+    service: opendkim
+    enabled: yes
+
+- name: Configure Postfix for OpenDKIM.
+  become: yes
+  lineinfile:
+    path: /etc/postfix/main.cf
+    regexp: "^ *{{ item.p }} *="
+    line: "{{ item.p }} = {{ item.v }}"
+  loop:
+  - { p: "milter_default_action", v: "accept" }
+  - { p: "milter_protocol", v: "6" }
+  - { p: "smtpd_milters", v: "local:opendkim/opendkim.sock" }
+  - { p: "non_smtpd_milters", v: '$smtpd_milters' }
+  notify: Restart Postfix.
+
 - name: Install Dovecot IMAPd.
   become: yes
   apt: pkg=dovecot-imapd