Skip to content

Commit 2960dae

Browse files
authored
Merge pull request #89 from vedetta-com/wip
- Add OpenPGP Web Key Service and Web Key Directory
2 parents 2bd5c0f + efdadf7 commit 2960dae

File tree

14 files changed

+259
-48
lines changed

14 files changed

+259
-48
lines changed

INSTALL.md

Lines changed: 119 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ sh /etc/netstart $(ifconfig egress | awk 'NR == 1{print $1;}' | sed 's/://')
7474

7575
Install packages:
7676
```sh
77-
pkg_add dovecot dovecot-pigeonhole dkimproxy rspamd opensmtpd-extras
77+
pkg_add dovecot dovecot-pigeonhole dkimproxy rspamd opensmtpd-extras gnupg-2.2.4
7878
```
7979

8080
*n.b.*: dovecot package comes with instructions for self-signed certificates, which are not used in this guide:
@@ -261,6 +261,7 @@ install -o root -g vmail -m 0640 -b src/var/dovecot/imapsieve/before/report-spam
261261
install -o root -g vmail -m 0750 -d src/var/dovecot/sieve/after /var/dovecot/sieve/after
262262
install -o root -g vmail -m 0750 -d src/var/dovecot/sieve/before /var/dovecot/sieve/before
263263
install -o root -g vmail -m 0640 -b src/var/dovecot/sieve/before/spamtest.sieve /var/dovecot/sieve/before/
264+
install -o root -g vmail -m 0640 -b src/var/dovecot/sieve/before/00-wks.sieve /var/dovecot/sieve/before/
264265

265266
install -o root -g wheel -m 0644 -b src/var/unbound/etc/unbound.conf /var/unbound/etc/
266267

@@ -270,6 +271,16 @@ install -o root -g daemon -m 0644 -b src/var/www/htdocs/mercury.example.com/inde
270271
install -o root -g daemon -m 0755 -d src/var/www/htdocs/mercury.example.com/mail /var/www/htdocs/$(hostname)/mail
271272
install -o root -g daemon -m 0644 -b src/var/www/htdocs/mercury.example.com/mail/config-v1.1.xml /var/www/htdocs/$(hostname)/mail/
272273

274+
install -o root -g daemon -m 0755 -d src/var/www/openpgpkey /var/www/openpgpkey
275+
install -o root -g daemon -m 0644 -b src/var/www/openpgpkey/policy /var/www/openpgpkey/
276+
install -o root -g daemon -m 0644 -b src/var/www/openpgpkey/submission-address /var/www/openpgpkey/
277+
278+
install -o vmail -g daemon -m 0755 -d src/var/www/openpgpkey/hu /var/www/openpgpkey/hu
279+
280+
install -o root -g wheel -m 0755 -d src/var/lib /var/lib
281+
install -o root -g wheel -m 0755 -d src/var/lib/gnupg /var/lib/gnupg
282+
install -o root -g wheel -m 2750 -d src/var/lib/gnupg/wks /var/lib/gnupg/wks
283+
273284
install -o root -g wheel -m 0644 -b src/root/.ssh/config /root/.ssh/
274285

275286
mkdir -m 700 /var/crash/rspamd
@@ -292,6 +303,7 @@ Compile sieve scripts:
292303
```sh
293304
sievec /var/dovecot/imapsieve/before/report-ham.sieve
294305
sievec /var/dovecot/imapsieve/before/report-spam.sieve
306+
sievec /var/dovecot/sieve/before/00-wks.sieve
295307
sievec /var/dovecot/sieve/before/spamtest.sieve
296308
```
297309

@@ -341,6 +353,112 @@ pfctl -f /etc/pf.conf
341353
rcctl restart sshd dkimproxy_out rspamd dovecot smtpd
342354
```
343355

356+
### OpenPGP Web Key Service ([WKS](https://tools.ietf.org/html/draft-koch-openpgp-webkey-service-05))
357+
358+
An important aspect of using OpenPGP is trusting the (public) key. Off-channel key exchange is not always practical, OpenPGP DANE protocol lacks confidentially, HKPS' a mess, and keybase is wicked. OpenPGP proposed a new protocol to automate and build trust in the process of exchanging public keys.
359+
360+
Web Key Service has two main functions for our Email Service:
361+
1. Allow all users to locate and retreive public keys by email address using HTTPS
362+
2. Allow local user's email client to automatically publish and revoke public keys
363+
364+
Self-hosting has the advantage of full authority on the user mail addresses for their domain name. By design, only one WKS can exist for a domain name. Furthermore, only local users can make requests to WKS Submission Address, and replies to local users only. Moreover, the service automatically verifies the sender is in possesion of the secret key, before publishing their public key. Self-hosting the public key server finally makes OpenPGP oportunistic encryption user friendly.
365+
366+
To get started, a GnuPG 2.1 safe configuration is provided: [`gpg.conf`](src/home/puffy/.gnupg/gpg.conf)
367+
368+
Web Key Service maintains a Web Key Directory (WKD) which needs the following configuration for each *virtual* domain:
369+
```sh
370+
mkdir -m 755 /var/lib/gnupg/wks/example.com
371+
chown vmail:vmail /var/lib/gnupg/wks/example.com
372+
373+
cd /var/lib/gnupg/wks/example.com
374+
375+
ln -sf /var/www/openpgpkey/hu .
376+
chown -h vmail:vmail hu
377+
378+
ln -s /var/www/openpgpkey/submission-address .
379+
chown -h vmail:vmail submission-address
380+
381+
doas -u vmail \
382+
env -i HOME=/var/vmail \
383+
gpg-wks-server --list-domains
384+
```
385+
386+
Web Key Service uses a Submission Address, which needs the following configuration:
387+
388+
Add *virtual* password for the Submission Address:
389+
```sh
390+
smtpctl encrypt
391+
> secret
392+
> $2b$...encrypted...passphrase...
393+
vi /etc/mail/passwd
394+
> key-submission@example.com:$2b$...encrypted...passphrase...::::::
395+
```
396+
397+
Create the submission key:
398+
```sh
399+
doas -u vmail \
400+
env -i HOME=/var/vmail \
401+
gpg2 --batch --passphrase '' --quick-gen-key key-submission@example.com
402+
```
403+
404+
Verify:
405+
```sh
406+
doas -u vmail \
407+
env -i HOME=/var/vmail \
408+
gpg2 -K --with-fingerprint
409+
```
410+
411+
List the z-Base-32 encoded SHA-1 hash of the mail address' local-part (i.e. key-submission):
412+
doas -u vmail \
413+
env -i HOME=/var/vmail \
414+
gpg2 --with-wkd-hash -K key-submission@example.com
415+
> 54f6ry7x1qqtpor16txw5gdmdbbh6a73@example.com
416+
```
417+
418+
Publish the key, using the hash of the string "key-submission" (i.e. 54f6ry7x1qqtpor16txw5gdmdbbh6a73):
419+
```sh
420+
doas -u vmail \
421+
env -i HOME=/var/vmail \
422+
gpg2 -o /var/lib/gnupg/wks/example.com/hu/54f6ry7x1qqtpor16txw5gdmdbbh6a73 \
423+
--export-options export-minimal --export key-submission@example.com
424+
```
425+
426+
*n.b.*: To delete this key:
427+
```sh
428+
gpg2 --delete-secret-key "key-submission@example.com"
429+
gpg2 --delete-key "key-submission@example.com"
430+
```
431+
432+
Expire non confirmed publication requests:
433+
```sh
434+
crontab -e
435+
```
436+
```console
437+
30 11 * * * doas -u vmail env -i HOME=/var/vmail /usr/local/bin/gpg-wks-server --cron
438+
```
439+
440+
*n.b.*: [Enigmail](https://www.enigmail.net)/Thunderbird, [Kmail](https://userbase.kde.org/KMail) and [Mutt](http://www.mutt.org/) (perhaps other MUA) support the Web Key Service. Once published, a communication partner's MUA automatically downloads the public key (if their GnuPG 2.1 --enable-wks-tools) with the following `gpg.conf` directive:
441+
```console
442+
auto-key-locate wkd
443+
```
444+
445+
The key can be manually retreived too:
446+
```sh
447+
gpg2 --auto-key-locate clear,wkd --locate-keys puffy@example.com
448+
```
449+
450+
To simply check a key:
451+
```sh
452+
$(gpgconf --list-dirs libexecdir)/gpg-wks-client --check puffy@example.com
453+
```
454+
455+
Or a hex listing:
456+
```sh
457+
gpg-connect-agent --dirmngr --hex 'wkd_get puffy@example.com' /bye
458+
```
459+
460+
*n.b*: If the same local-part of an email address exists for multiple domains (e.g. **puffy**@example.com and **puffy**@example.net), the hash of the string will be the same and each key publication overwrites the same file. The *workaround* is using **+tags** to create a secondary UID (e.g. puffy**+enc**@example.com) for the key, and go through the process of key submission and confirmation using the MUA interface with the tagged email address (e.g. puffy**+enc**@example.com).
461+
344462
### Logs
345463

346464
```console

README.md

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,12 +25,13 @@ Root your Inbox :mailbox_with_mail:
2525
- Flexible: switching roles is easy, making the process of changing VPS hosts a breeze (no downtime)
2626
- DMARC (with DKIM and SPF) email-validation system, to detect and prevent email spoofing
2727
- Uncensored DNS validating resolver from root nameservers
28+
- OpenPGP Web Key Service with Web Key Directory, the most trusted and secure key exchange protocol
2829
- MUA Autoconfiguration, for modern clients
2930
- Daily (spartan) stats, to keep track of things
3031
- Your sieve scripts and managesieve configuration, let's get started
3132

3233
## Considerations
33-
By design, email message headers need to be public, for exchanges to happen. The body of the message can be encrypted by the user, if desired. Moreover, there is no way to prevent the host from having access to the virtual machine. Therefore, [full disk encryption](https://www.openbsd.org/faq/faq14.html#softraidFDE) (at rest) may not be necessary.
34+
By design, email message headers need to be public, for exchanges to happen. The body of the message can be [encrypted](INSTALL.md#openpgp-web-key-service-wks) by the user, if desired. Moreover, there is no way to prevent the host from having access to the virtual machine. Therefore, [full disk encryption](https://www.openbsd.org/faq/faq14.html#softraidFDE) (at rest) may not be necessary.
3435

3536
Given our low memory requirements, and the single-purpose concept of email service, Roundcube or other web-based IMAP email clients should be on a different VPS.
3637

@@ -49,7 +50,7 @@ See the [**Installation Guide**](INSTALL.md) for details.
4950

5051
Install packages:
5152
```sh
52-
pkg_add dovecot dovecot-pigeonhole dkimproxy rspamd opensmtpd-extras
53+
pkg_add dovecot dovecot-pigeonhole dkimproxy rspamd opensmtpd-extras gnupg-2.2.4
5354
```
5455
Add users:
5556
```sh
@@ -146,6 +147,28 @@ Each *virtual* autoconfig subdomain has record type CNAME pointing to Autoconfig
146147
autoconfig.example.net. 86400 IN CNAME mercury.example.com.
147148
```
148149

150+
#### OpenPGP Web Key Directory ([WKD](https://tools.ietf.org/html/draft-koch-openpgp-webkey-service-05))
151+
Each WKD subdomain has record type CNAME pointing to Web Key Server:
152+
```console
153+
wkd.example.com. 86400 IN CNAME mercury.example.com.
154+
```
155+
156+
Each *virtual* WKD subdomain has record type CNAME pointing to Web Key Server:
157+
```console
158+
wkd.example.net. 86400 IN CNAME mercury.example.com.
159+
```
160+
161+
#### SRV Records for OpenPGP Web Key Directory
162+
Each domain has record type SRV for WKD subdomain
163+
```console
164+
_openpgpkey._tcp.example.com 86400 IN SRV 0 0 443 wkd.example.com
165+
```
166+
167+
Each *virtual* domain has record type SRV for *virtual* WKD subdomain
168+
```console
169+
_openpgpkey._tcp.example.net 86400 IN SRV 0 0 443 wkd.example.net
170+
```
171+
149172
#### SRV Records for [Locating Email Services](https://tools.ietf.org/html/rfc6186)
150173
Each domain and *virtual* domain has record types SRV for simple MUA auto-configuration:
151174
```console

UPGRADE.md

Lines changed: 74 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,26 @@
11
# caesonia (beta)
22
*Open*BSD Email Service - Upgrade an existing installation
33

4-
[`6.3.0-beta`](https://github.com/vedetta-com/caesonia/tree/v6.3.0-beta) to [`6.3.1-beta`](https://github.com/vedetta-com/caesonia/tree/v6.3.1-beta)
4+
[`6.3.1-beta`](https://github.com/vedetta-com/caesonia/tree/v6.3.1-beta) to [`6.3.2-beta`](https://github.com/vedetta-com/caesonia/tree/v6.3.2-beta)
55

66
> Upgrades are only supported from one release to the release immediately following it. Read through and understand this process before attempting it. For critical or physically remote machines, test it on an identical, local system first. -- [OpenBSD Upgrade Guide](https://www.openbsd.org/faq/index.html)
77
88
## Upgrade Guide
99

10-
Split TLS and non-TLS configuration, update TLS cipher strength and key exchange (score A+ with 100% on every [ssllabs.com](https://www.ssllabs.com/ssltest/) test while supporting all devices), and improve Mozilla [Autoconfiguration](https://developer.mozilla.org/en-US/docs/Mozilla/Thunderbird/Autoconfiguration) with the following `httpd.conf` changes:
10+
### Introducing OpenPGP Web Key Service (WKS) to OpenBSD
11+
12+
To start implementing Web Key Service, please make sure the new DNS [prerequisites](README.md#openpgp-web-key-directory-wkd) are met.
13+
14+
```sh
15+
pkg_add gnupg-2.2.4
16+
```
17+
18+
Edit [`/etc/httpd.conf`](src/etc/httpd.conf) to add a WKD alias and location:
1119
```console
1220
# Host:443
1321
server "mercury.example.com" {
1422
alias "autoconfig.*"
23+
alias "wkd.*"
1524

1625
listen on $IPv4 tls port https
1726
listen on $IPv6 tls port https
@@ -35,6 +44,13 @@ server "mercury.example.com" {
3544

3645
block
3746

47+
# OpenPGP Web Key Directory
48+
location "/.well-known/openpgpkey/*" {
49+
root "/openpgpkey"
50+
root strip 2
51+
pass
52+
}
53+
3854
location "/*" {
3955
root "/htdocs/mercury.example.com"
4056
pass
@@ -44,66 +60,82 @@ server "mercury.example.com" {
4460
# Host:80
4561
server "mercury.example.com" {
4662
alias "autoconfig.*"
63+
alias "wkd.*"
64+
...
65+
```
4766

48-
listen on $IPv4 port http
49-
listen on $IPv6 port http
50-
51-
tcp nodelay
52-
connection { max requests 500, timeout 3600 }
67+
Add WKD LetsEncrypt certificate:
68+
```sh
69+
acme-client -vr mercury.example.com
70+
```
5371

54-
log { access "access.log", error "error.log" }
72+
Edit [`/etc/acme-client.conf`](src/etc/acme-client.conf) to add every service (virtual) WKD subdomains as alternat
73+
ive names:
74+
```console
75+
...
76+
alternative names { \
77+
autoconfig.example.com \
78+
autoconfig.example.net \
79+
wkd.example.com \
80+
wkd.example.net }
81+
...
82+
```
5583

56-
block
84+
```sh
85+
acme-client -v mercury.example.com
86+
get-ocsp.sh mercury.example.com
87+
```
5788

58-
location "/.well-known/acme-challenge/*" {
59-
root "/acme"
60-
root strip 2
61-
pass
62-
}
89+
Edit [`/etc/doas.conf`](src/etc/doas.conf) to add WKS permissions:
90+
```console
91+
# WKS: expire non confirmed publication requests
92+
permit nopass root as vmail cmd env args \
93+
-i HOME=/var/vmail /usr/local/bin/gpg-wks-server --cron
94+
```
6395

64-
# Mozilla Autoconfiguration
65-
location "/mail/*" {
66-
block return 302 "https://autoconfig.example.com$REQUEST_URI"
67-
}
96+
Edit [`/var/cron/tabs/root`](src/var/cron/tabs/root) to add WKS expiration:
97+
```console
98+
30 11 * * * doas -u vmail env -i HOME=/var/vmail /usr/local/bin/gpg-wks-server --cron
99+
```
68100

69-
location "/*" {
70-
root "/htdocs/mercury.example.com"
71-
pass
72-
}
73-
}
101+
Edit [`/etc/mail/smtpd.conf`](src/etc/mail/smtpd.conf) to add WKS table:
102+
```console
103+
table wks-recipients { "key-submission@example.com" } # OpenPGP WKS Submission Address
74104
```
75105

76-
Update TLS (cipher strength) for dovecot:
106+
OpenPGP Web Key Service (WKS) Trust Management for primary and backup MX:
77107
```sh
78-
sed -i 's/HIGH:!aNULL/HIGH:!AES128:!kRSA:!aNULL/' /etc/dovecot/conf.d/10-ssl.conf
108+
sed -i 's/accept tagged MTA from any/& recipient ! <wks-recipients>/g' /etc/mail/smtpd.conf
79109
```
80110

81-
LetsEncrypt certificate updates, now with service *virtual* subdomains:
111+
Add OpenPGP Web Key Service (WKS) Submission Address
82112
```sh
83-
acme-client -vr mercury.example.com
84-
sed -i 's/autoconfig.example.com/& autoconfig.example.net/' /etc/acme-client.conf
85-
acme-client -v mercury.example.com
86-
get-ocsp.sh mercury.example.com
87-
rcctl restart smtpd dovecot
113+
echo "key-submission@example.com \tvmail" >> /etc/mail/virtual
88114
```
89115

90-
Update crontab to restart smtpd and dovecot on certificate update:
116+
Install OpenPGP Web Key Service (WKS) Server Tool:
91117
```sh
92-
crontab -e
93-
```
94-
```console
95-
20 6 * * * acme-client mercury.example.com && /usr/local/bin/get-ocsp.sh mercury.example.com && rcctl restart smtpd dovecot
118+
install -o root -g vmail -m 0640 -b src/var/dovecot/sieve/before/00-wks.sieve /var/dovecot/sieve/before/
119+
sievec /var/dovecot/sieve/before/00-wks.sieve
96120
```
97121

98-
Increase waiting for reply timeout to 120s, giving rspamd ample time to tell the truth:
122+
Install OpenPGP Web Key Directory:
99123
```sh
100-
sed -i 's|/bin/rspamc|& -t 120|' /etc/mail/smtpd.conf
101-
rcctl restart smtpd
124+
install -o root -g daemon -m 0755 -d src/var/www/openpgpkey /var/www/openpgpkey
125+
install -o root -g daemon -m 0644 -b src/var/www/openpgpkey/policy /var/www/openpgpkey/
126+
install -o root -g daemon -m 0644 -b src/var/www/openpgpkey/submission-address /var/www/openpgpkey/
127+
128+
install -o vmail -g daemon -m 0755 -d src/var/www/openpgpkey/hu /var/www/openpgpkey/hu
129+
130+
install -o root -g wheel -m 0755 -d src/var/lib /var/lib
131+
install -o root -g wheel -m 0755 -d src/var/lib/gnupg /var/lib/gnupg
132+
install -o root -g wheel -m 2750 -d src/var/lib/gnupg/wks /var/lib/gnupg/wks
102133
```
103134

104-
New rspamd statistics update script, to relearn Spam/ from all users:
135+
Follow the [Web Key Service Configuration Guide](INSTALL.md#openpgp-web-key-service-wks) to finish the upgrade.
136+
137+
Restart:
105138
```sh
106-
install -o root -g wheel -m 0550 -b src/usr/local/bin/learn_all_spam.sh /usr/local/bin/
107-
learn_all_spam.sh
139+
rcctl restart smtpd dovecot httpd
108140
```
109141

src/etc/acme-client.conf

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,11 @@ authority letsencrypt-staging {
1313

1414
# (!) Add every service (virtual) subdomains as alternative names
1515
domain mercury.example.com {
16-
alternative names { autoconfig.example.com autoconfig.example.net }
16+
alternative names { \
17+
autoconfig.example.com \
18+
autoconfig.example.net \
19+
wkd.example.com \
20+
wkd.example.net }
1721
domain key "/etc/ssl/acme/private/mercury.example.com.key"
1822
domain certificate "/etc/ssl/acme/mercury.example.com.crt"
1923
domain full chain certificate "/etc/ssl/acme/mercury.example.com.fullchain.pem"

src/etc/doas.conf

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,3 +15,7 @@ permit keepenv :wheel
1515

1616
# Allow dsync replication
1717
permit nopass dsync as vmail cmd doveadm
18+
19+
# WKS: expire non confirmed publication requests
20+
permit nopass root as vmail cmd env args \
21+
-i HOME=/var/vmail /usr/local/bin/gpg-wks-server --cron

0 commit comments

Comments
 (0)