1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
|
---
title: "Authenticating Your Mailserver With SPF and DKIM"
date: 2022-09-14T18:52:08+05:30
highlight: true
---
I recently did a video on setting up an email server, with Postfix for SMTP and
Dovecot for IMAP, which you can check out [here.](https://odysee.com/@MikunoNaka:d/self-hosting-email-server:0)
Now this much isn't enough since you want to make sure no one can spoof your domain and/or tamper with the content of your E-mails.
This is where SPF (Sender Policy Framework) and DKIM (DomainKeys Identified Mail) come to the rescue.
## What are SPF and DKIM?
SPF is used to limit which servers are allowed to send emails from your domain. It protects your domain against domain spoofing.
Even if you don't use E-mail on your domain, I recommend using SPF to specify that you won't be sending any emails from this particular domain,
so no one can spoof your domain and pretend to be you while sending emails.
DKIM can be used to sign the emails with a key pair (where the public key is added to your domain's TXT records) so your E-mails' contents cannot be tampered with.
OpenDKIM is an open source implementation of DKIM, we will be setting up OpenDKIM in this tutorial
(because I have a natural urge to use anything which has "open" in its name)
### Setting up SPF for outgoing emails on your domain
You need to add a TXT record to your domain containing the SPF syntax. the SPF record should always start with the SPF version number you are using.
For me it is `v=spf1`. Then, you can add all the SPF "mechanisms" that need to be evaluated in order to identify the E-mail.
Most of the time you just need one or two mechanisms, which are `mx` or `mx:your-domain.tld` and `ip4:your_servers_ipv4` and `ip6:your_servers_ipv6`
(you don't need all of them, it's kinda overkill)
- `mx` means the email is legit if it comes from a server which is in the MX Records of this domain
- `mx:your-domain.tld` means the email is legit if it comes from a server which is in the MX Records of your-domain.tld
- `ip4:ipv4_address` means the email is legit if the sending server has this particular IPv4 address
- `ip6:ipv6_address` means the email is legit if the sending server has this particular IPv6 address
You can prepend any of these with `-` to *reject* emails which meet this condition (by default it *accepts* the ones passing this condition); You can use `-all` to make sure
all the other unauthorised emails don't pass the SPF test.
So this is what a valid SPF record would look like:
```
v=spf1 mx -all
```
Now I did say using all of these at ones is pretty overkill, but here is what mine looks like:
```
v=spf1 mx ip4:172.105.59.60 ip6:2400:8904::f03c:93ff:feac:ca67 mx:m.vidhukant.xyz -all
```
I don't think using many mechanisms is a bad thing, so you can just copy mine and replace the IP4 and IP6 addresses with your server's IP4 and IP6 addresses.
Which is enough for most usecases. To apply this SPF record just add a TXT record to your root domain. It should look like this:
![SPF Record Screenshot](/images/spf-record-example.png)
**NOTE:** If you are using multiple domains for a single mail server, you should use the exact same SPF record for all the domains.
If you don't plan to use E-mail with any of your domains, set the SPF record to `v=spf1 -all`.
ALWAYS add this to your root domain since it tells every receiving server that this domain doesn't
send E-mails and if you receive one that means it's probably malicious.
[This website](https://www.spf-record.com/syntax) has all of the other info about structuring an SPF record.
### Setting up DKIM (OpenDKIM)
#### Install the necessary packages
``` fish
apt install opendkim opendkim-tools
```
#### Configure OpenDKIM
The OpenDKIM config file located at `/etc/opendkim.conf` should look like this:
```
Syslog yes
SyslogSuccess yes
Canonicalization relaxed/simple
Mode sv
SubDomains no
OversignHeaders From
Socket local:/var/spool/postfix/opendkim/opendkim.sock
PidFile /var/run/opendkim/opendkim.pid
AutoRestart yes
AutoRestartRate 10/1M
Background yes
DNSTimeout 5
SignatureAlgorithm rsa-sha256
UserID opendkim
UMask 002
KeyTable /etc/opendkim/key.table
SigningTable refile:/etc/opendkim/signing.table
ExternalIgnoreList /etc/opendkim/trusted.hosts
InternalHosts /etc/opendkim/trusted.hosts
TrustAnchorFile /usr/share/dns/root.key
```
This is what works for me on Debian 11. The data files for OpenDKIM will be stored in `/etc/opendkim/`. If you want to store them anywhere else,
edit the `KeyTable`, `SigningTable`, `ExternalIgnoreList`, `InternalHosts` parameters in `/etc/opendkim.conf`
#### Setting up the Signing Table
Make a list of all the domains you want to handle E-mails for, and add them to `/etc/opendkim/signing.table` like this:
```
*@example.tld mail._domainkey.example.tld
```
Replace both occurances of example.tld to your domain name, and mail to whichever subdomain sends emails. `mail._domainkey.example.tld` would act
as the DKIM selector for example.tld
If you have any other subdomain set up for the mail server (for example I have `m.vidhukant.xyz` while the standard would be `mail.vidhukant.xyz`),
replace "mail" with that.
You can add as many domains you want, But don't add domains which won't be sending emails.
#### Setting up the Key Table
Now edit `/etc/opendkim/key.table` and add lines for each domain like this:
```
mail._domainkey.example.tld example.tld:mail:/etc/opendkim/keys/example.private
```
Add one line like this for all the domains added to the signing.table file, replace `mail` and `example.tld` respectively.
Decide a short name for the private key for this domain, `/etc/opendkim/keys/example.private` in this example holds the private key for `example.tld`
You should decide different names for each domain you're adding and remember that name, you will need that later.
#### Setting up the Trusted Hosts
Edit the `/etc/opendkim/trusted.hosts` file and add these contents:
```
127.0.0.1
::1
localhost
hostname
hostname.example.tld
*.example.tld
```
Replace hostname with your server's hostname (defined in `/etc/hostname`), and example.tld with your domain. If you have more than one domain,
you can append those to the file prepended with a `*.`, just like in `*.example.tld`.
No need to add another entry for `hostname.example.tld`, just append `*.yourdomain.tld` to the file as many times (for as many domains) you want.
#### Set file permissions
Make sure opendkim user has access to the required files/directories:
``` fish
chmod u=rw,go=r /etc/opendkim.conf
chown -R opendkim:opendkim /etc/opendkim
chmod -R go-rwx /etc/opendkim/keys
```
#### Generating the keys
Run this command, replacing example.tld with your domain name, and mail with the subdomain for email:
``` fish
opendkim-genkey -b 2048 -h rsa-sha256 -r -s mail -d example.tld -v
mv /etc/opendkim/mail.private /etc/opendkim/keys/example.private
mv /etc/opendkim/mail.txt /etc/opendkim/keys/example.txt
```
Replace "example" in the `example.private` and `example.txt` files with the short name you entered for the domain in the `key.table` file.
Repeat this step for all the domains if you have multiple of them!
**NOTE:** Never share the contents of the generated ".private" files!
#### Start OpenDKIM
``` fish
systemctl restart opendkim
```
#### Add the TXT Records
Read the contents of the TXT file generated by `opendkim-genkey`:
``` fish
cat /etc/opendkim/keys/example.txt
```
The output would be something like this:
```
mail._domainkey IN TXT ( "v=DKIM1; h=sha256; k=rsa; "
"p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxzNTZydyFiNljq/Md1cXNEqemKDk9CKhZGHSzEH6x0zxtdcv5ROzaytJ4OsatDOdk+Pygkj6Qq9PiLCc3HlWPTcvMEs+M8YvRergTATFNoAmXLXvpbi+DD0oXAsbz2dM/klObY9OSNlJqFpzmGjgRbtSnvCbot8Smg5LreCjmkuHo/sxyynRHGwRHUM6jokm2YGIGATZBIVqtS"
"jM418Gtxx9MZUbwcQTlchk1hSQgbXlAAl5tagle3bq/2GwrwrdaghRH750qLjnBQhzdFnH+GjHTmRl2drQ/2zG1L0GlufipZ1UkWulidox2RtIykv2VxDlBYb77G4PAiiJsSar+wIDAQAB" ) ; ----- DKIM key mail for example.tld
```
Carefully delete everything outside the parenthesis (including the parenthesis) and join all three lines into one.
Now, remove all the quotes and also the whitespaces between line 2 and 3, so both lines get merged into one, without any space between them.
The result should look like this:
```
v=DKIM1; h=sha256; k=rsa; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxzNTZydyFiNljq/Md1cXNEqemKDk9CKhZGHSzEH6x0zxtdcv5ROzaytJ4OsatDOdk+Pygkj6Qq9PiLCc3HlWPTcvMEs+M8YvRergTATFNoAmXLXvpbi+DD0oXAsbz2dM/klObY9OSNlJqFpzmGjgRbtSnvCbot8Smg5LreCjmkuHo/sxyynRHGwRHUM6jokm2YGIGATZBIVqtSjM418Gtxx9MZUbwcQTlchk1hSQgbXlAAl5tagle3bq/2GwrwrdaghRH750qLjnBQhzdFnH+GjHTmRl2drQ/2zG1L0GlufipZ1UkWulidox2RtIykv2VxDlBYb77G4PAiiJsSar+wIDAQAB
```
This is your public key for DKIM.
Now go to your DNS editor, click on Add TXT Record, the hostname should be `mail._domainkey` or whatever the first few characters the original example.txt showed.
In the value field copy and paste the public key. Make sure there are no errors.
#### Configuring postfix to use OpenDKIM
Set up postfix to process outgoing E-mails with OpenDKIM
``` fish
postconf -e "milter_default_action = accept"
postconf -e "milter_protocol = 6"
postconf -e "smtpd_milters = local:opendkim/opendkim.sock"
postconf -e "non_smtpd_milters = local:opendkim/opendkim.sock"
```
Add this to your `/etc/default/opendkim` file to set the socket for postfix
```
SOCKET="local:/var/spool/postfix/opendkim/opendkim.sock"
```
And then create the socket directory
``` fish
mkdir /var/spool/postfix/opendkim
chown opendkim:postfix /var/spool/postfix/opendkim
```
#### Testing if DKIM is working
Wait for the DNS records to propagate (shouldn't take long!) and send an email with your SMTP server, on the receiving end, your email client should have an option
to "view source" or "show email headers", open that, you should see a `DKIM-Signature:` field there.
You can now send a test email to a GMail account, and on the GMail web app you can view the email's source.
It will show detailed information about your DKIM and SPF setup. GMail is by far the best test to verify
that your authentication mechanisms (SPF, DKIM, etc) are working properly.
## Use DMARC to tell receiving servers how to handle your email
Domain-based Message Authentication, Reporting and Conformance, short for DMARC can be used to specify a set of instructions for the receiving email servers on how
to handle the email. You can use it to specify which authentication mechanism (SPF, DKIM or both) is in place, what to do with emails which fail authentication
(you can reject, send, or quarantine them), how to check the `From: ` field of the email. It can also be used by receiving servers to report back to your own server,
in case any of the checks fail.
All DMARC records start with `v=DMARC1`, and the `p=` field would specify what to do with emails that fail the SPF or the DKIM test. `p=` can have these three values:
- none: do nothing
- quarantine: quarantine the email (e.g send it to the spam folder)
- reject: reject the incoming email
It is best to use `p=none` while testing your SPF and DKIM records, after that you can choose between `p=reject` or `p=quarantine`.
You can also optionally use `rua=mailto:your_email` to get DMARC fail reports to your email. Just replace `your_email` with your E-mail.
You can specify multiple E-mail addresses seperated with a comma.
Here's what an example DMARC record should look like:
```
v=DMARC1; p=quarantine; rua=mailto:user@example.com
```
Add this to your domain's TXT records and set the hostname to `_dmarc` and you should be good to go!
Use [this](https://appmaildev.to/en/dkim) DKIM test to test your SPF, DKIM and DMARC configuration.
|