From 362705bbcda2e415234e1c11d5e5e92b74aeb3f4 Mon Sep 17 00:00:00 2001 From: Matt Birkholz Date: Sun, 11 Jan 2026 14:15:54 -0700 Subject: [PATCH] Implement DMARC, DKIM on Front. --- README.org | 120 +++++++++++++++++++++++++++++++- roles_t/front/handlers/main.yml | 7 ++ roles_t/front/tasks/main.yml | 75 ++++++++++++++++++++ 3 files changed, 200 insertions(+), 2 deletions(-) diff --git a/README.org b/README.org index f9d5a3a..00918b4 100644 --- a/README.org +++ b/README.org @@ -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 diff --git a/roles_t/front/handlers/main.yml b/roles_t/front/handlers/main.yml index e51d031..cdd096a 100644 --- a/roles_t/front/handlers/main.yml +++ b/roles_t/front/handlers/main.yml @@ -18,6 +18,13 @@ command: newaliases tags: actualizer +- name: Restart OpenDKIM. + become: yes + systemd: + service: opendkim + state: restarted + tags: actualizer + - name: Restart Dovecot. become: yes systemd: diff --git a/roles_t/front/tasks/main.yml b/roles_t/front/tasks/main.yml index 3b08c80..c31cf1e 100644 --- a/roles_t/front/tasks/main.yml +++ b/roles_t/front/tasks/main.yml @@ -176,6 +176,81 @@ 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 -- 2.47.3