2021-09-26 08:40:02 +02:00
|
|
|
# EasyWKS
|
|
|
|
|
|
|
|
### OpenPGP WKS for Human Beings
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
This is a work-in-progress project. See ROADMAP.md for details
|
|
|
|
|
|
|
|
## What is WKD/WKS?
|
|
|
|
|
|
|
|
Due to all the issues involved with the PGP key servers we're using today, GnuPG introduced a feature named [**Web Key
|
|
|
|
Discovery**][wkd] (WKD): Instead of searching for keys on the usual key servers, WKD is taking a **fully**
|
|
|
|
decentralized and federated approach, where each mail domain is responsible for hosting its users public keys on an
|
|
|
|
HTTPS web directory. For example, in order to retrieve the key for `john.doe@example.org`, they key can be located at
|
|
|
|
|
|
|
|
https://openpgpkey.example.org/.well-known/openpgpkey/example.org/hu/iy9q119eutrkn8s1mk4r39qejnbu3n5q?l=john.doe
|
|
|
|
|
|
|
|
In order to get the keys there, GnuPG developed an email-based protocol named [**Web Key Service**][wks] (WKS), which
|
|
|
|
lets users publish their public keys once they have proven ownership of the key using an email-based challenge-responce
|
|
|
|
mechanism.
|
|
|
|
|
|
|
|
At the time, WKS and WKD aren't yet part of the OpenPGP standard, but there's an [IETF Draft RFC][ietf] that's being
|
|
|
|
updated from time to time.
|
|
|
|
|
|
|
|
## Why EasyWKS?
|
|
|
|
|
|
|
|
I've experienced the WKS standard to be extremely cumbersome to conform to. The tools shipped with GnuPG,
|
|
|
|
`gpg-wks-server` and `gpg-wks-client` are usable well enough as long as you have shell access on a mailserver and pipe
|
|
|
|
the output of `gpg-wks-client` into `sendmail`. However, I'm usually doing my email via SMTP using a variety of
|
|
|
|
clients.
|
|
|
|
|
|
|
|
No matter which client I tried, I did not manage to get them to send mails in the format required by `gpg-wks-server`.
|
|
|
|
Even pasting the output of `gpg-wks-client` into `openssl s_client` after manually performing SMTP auth proved to be
|
|
|
|
difficult in case any line of the PGP-encrypted message happened to start with `Q` or `R`.
|
|
|
|
|
|
|
|
So I decided to write a WKS server that's much more lenient regarding the exact format of the mails it receives.
|
|
|
|
Instead of enforcing the strict format mandated by the standard, EasyWKS only requires:
|
|
|
|
|
|
|
|
- For the initial submission request: An unsigned & encrypted PGP/MIME message anywhere in the MIME tree, and the
|
|
|
|
ASCII-armored PGP-Key anywhere inside the encrypted message.
|
|
|
|
- For the confirmation response: A signed & encrypted PGP/MIME message anywhere in the MIME tree, and the
|
|
|
|
confirmation response anywhere inside the encrypted message.
|
|
|
|
|
|
|
|
This makes EasyWKS usable with every mail client, no matter whether WKS support is built-in or not.
|
|
|
|
|
|
|
|
EasyWKS aims to be a drop-in replacement for gpg-wks-server; see "Bootstrapping" below to learn how to migrate from
|
|
|
|
gpg-wks-server to EasyWKS.
|
|
|
|
|
|
|
|
## Requirements
|
|
|
|
|
|
|
|
- Python 3.6 or newer
|
|
|
|
- PyYAML
|
|
|
|
- bottle.py
|
|
|
|
- PGPy
|
|
|
|
|
|
|
|
## License
|
|
|
|
|
|
|
|
MIT
|
|
|
|
|
|
|
|
## Setup
|
|
|
|
|
|
|
|
### Installation
|
|
|
|
|
|
|
|
TODO
|
|
|
|
|
|
|
|
Create a cronjob, e.g. in `/etc/cron.d/easywks`
|
|
|
|
|
|
|
|
```crontab
|
|
|
|
0 3 * * * webkey /path/to/easywks clean
|
|
|
|
```
|
|
|
|
|
|
|
|
### Configuration
|
|
|
|
|
|
|
|
Configuration is done in `/etc/easywks.yml` (or any other place as specified by `--config`)
|
|
|
|
|
|
|
|
```yaml
|
|
|
|
---
|
2021-09-29 00:44:07 +02:00
|
|
|
# EasyWKS works inside this directory. Its PGP keys as well# as all
|
|
|
|
# the submitted and published keys are stored here.
|
2021-09-26 08:40:02 +02:00
|
|
|
directory: /var/lib/easywks
|
2021-09-29 00:44:07 +02:00
|
|
|
|
|
|
|
# Number of seconds after which a pending submission request is
|
|
|
|
# considered stale and should be removed by easywks clean.
|
2021-09-26 08:40:02 +02:00
|
|
|
pending_lifetime: 604800
|
2021-09-29 00:44:07 +02:00
|
|
|
|
|
|
|
# Some clients (including recent versions of gpg-wks-client follow an
|
|
|
|
# older version of the WKS standard where signing the confirmation
|
|
|
|
# response is only recommended, but not required. Set this option to
|
|
|
|
# true if you want to accept such unsigned responses.
|
|
|
|
permit_unsigned_response: false
|
|
|
|
|
|
|
|
# Port configuration for the webserver. Put this behind an
|
2021-09-26 08:40:02 +02:00
|
|
|
# HTTPS-terminating reverse proxy!
|
2021-09-29 00:44:07 +02:00
|
|
|
httpd:
|
|
|
|
host: 127.0.0.1
|
|
|
|
port: 8080
|
|
|
|
|
2021-09-26 11:12:01 +02:00
|
|
|
# Defaults to stdout, supported: stdout, smtp
|
|
|
|
mailing_method: smtp
|
2021-09-29 00:44:07 +02:00
|
|
|
|
2021-09-26 11:12:01 +02:00
|
|
|
# Configure smtp client options
|
|
|
|
smtp:
|
|
|
|
# Connect to this SMTP server to send a mail.
|
2021-09-26 17:11:05 +02:00
|
|
|
host: localhost
|
2021-09-26 11:12:01 +02:00
|
|
|
port: 25
|
|
|
|
# if tls=True, starttls is ignored
|
|
|
|
tls: false
|
|
|
|
starttls: false
|
|
|
|
# Omit username/password if authentication is not needed.
|
|
|
|
username: webkey
|
|
|
|
password: SuperS3curePassword123
|
2021-09-26 17:11:05 +02:00
|
|
|
# Configure the LMTP server
|
2021-09-27 23:40:10 +02:00
|
|
|
lmtpds:
|
2021-09-26 17:11:05 +02:00
|
|
|
host: "::1"
|
|
|
|
port: 8024
|
2021-09-26 08:40:02 +02:00
|
|
|
# Every domain served by EasyWKS must be listed here
|
|
|
|
domains:
|
|
|
|
example.org:
|
2021-09-29 00:44:07 +02:00
|
|
|
# Users send their requests to this address. It's up to you to
|
|
|
|
# make sure that the mails sent their get handed to EasyWKS.
|
2021-09-27 23:40:10 +02:00
|
|
|
submission_address: webkey@example.org
|
2021-09-29 00:44:07 +02:00
|
|
|
# If you want the PGP key for this domain to be password-
|
|
|
|
# protected, or if you're supplying your own password-protected
|
|
|
|
# key, set the passphrase here:
|
2021-09-26 08:40:02 +02:00
|
|
|
passphrase: "Correct Horse Battery Staple"
|
|
|
|
# Defaults are gpgwks@<domain> and no password protection.
|
|
|
|
example.com: {}
|
|
|
|
```
|
|
|
|
|
|
|
|
### Bootstrapping
|
|
|
|
|
|
|
|
Run `easywks init` (as the correct user) to initialize all files and directories. This will also generate a PGP key for
|
|
|
|
each domain, stored in `<workdir>/<domain>/key.pgp`. If you want to, you can replace this key by a key you generated
|
|
|
|
yourself. If your key is password-protected, you have to supply the passphrase in the config file or remove the
|
|
|
|
password protection.
|
|
|
|
|
|
|
|
If you are migrating from gpg-wks-server to EasyWKS, you can point EasyWKS to gpg-wks-server's working directory
|
|
|
|
(usually `/var/lib/gnupg/wks`). EasyWKS uses the same directory layout and file formats as gpg-wks-server, so it should
|
|
|
|
be able to take over where gpg-wks-server stopped. The only thing you need to do is to export the private keys from the
|
|
|
|
GnuPG keyring and write them to their domain's `key.pgp`.
|
|
|
|
|
|
|
|
### Webserver Setup
|
|
|
|
|
|
|
|
There are generally two ways to get WKD working:
|
|
|
|
|
|
|
|
- The gpg-wks-server approach, i.e. regularly copying the `hu` directories from EasyWKS' working directory to the
|
|
|
|
webroot.
|
|
|
|
- Running the EasyWKS web server behind a Reverse Proxy, e.g. using the follwing systemd unit:
|
|
|
|
|
|
|
|
```unit file (systemd)
|
|
|
|
[Unit]
|
2021-09-26 17:11:05 +02:00
|
|
|
Description=OpenPGP WKS for Human Beings - HTTP Server
|
2021-09-26 08:40:02 +02:00
|
|
|
|
|
|
|
[Service]
|
|
|
|
Type=simple
|
|
|
|
ExecStart=/path/to/easywks webserver
|
|
|
|
Restart=on-failure
|
|
|
|
User=webkey
|
|
|
|
Group=webkey
|
|
|
|
WorkingDirectory=/var/lib/easywks
|
|
|
|
|
|
|
|
[Install]
|
|
|
|
WantedBy=multi-user.target
|
|
|
|
```
|
|
|
|
|
|
|
|
Once this service is up and running, you can configure your webserver to proxy requests to EasyWKS. E.g. with Apache2:
|
|
|
|
|
|
|
|
```
|
|
|
|
ProxyPass /.well-known/openpgpkey/ http://127.0.0.1:8080/.well-known/openpgpkey/
|
|
|
|
ProxyPassReverse /.well-known/openpgpkey/ http://127.0.0.1:8080/.well-known/openpgpkey/
|
|
|
|
```
|
|
|
|
|
|
|
|
Note that the webserver built into EasyWKS validates that the `?l=<uid>` matches the uid hash (the last URL component).
|
|
|
|
|
|
|
|
### MTA Setup
|
|
|
|
|
|
|
|
#### Postfix
|
|
|
|
|
2021-09-26 17:11:05 +02:00
|
|
|
You can either connect EasyWKS using a pipe transport or as a LMTP server.
|
|
|
|
|
|
|
|
##### Pipe Transport
|
|
|
|
|
2021-09-26 08:40:02 +02:00
|
|
|
Add an entry in `/etc/postfix/master.cf`:
|
|
|
|
|
|
|
|
```
|
|
|
|
webkey unix - n n - - pipe
|
2021-09-26 11:12:01 +02:00
|
|
|
flags=DRhu user=webkey argv=/path/to/easywks process
|
2021-09-26 08:40:02 +02:00
|
|
|
```
|
|
|
|
|
2021-09-26 17:11:05 +02:00
|
|
|
Then tell postfix to forward mails to the submission addresses to said transport, e.g. in `/etc/postfix/transport`:
|
|
|
|
|
|
|
|
```
|
|
|
|
# The colon at the end is important, it lets postfix know
|
|
|
|
# that "webkey" is a transport, not a name
|
|
|
|
gpgwks@example.org webkey:
|
|
|
|
webkey@example.com webkey:
|
|
|
|
```
|
|
|
|
|
2021-09-26 11:12:01 +02:00
|
|
|
Configure EasyWKS to send outgoing mails via SMTP.
|
|
|
|
|
2021-09-26 17:11:05 +02:00
|
|
|
##### LMTP Server
|
|
|
|
|
|
|
|
Configure EasyWKS to run the LMTP server, e.g. using the following systemd unit:
|
|
|
|
|
|
|
|
```unit file (systemd)
|
|
|
|
[Unit]
|
|
|
|
Description=OpenPGP WKS for Human Beings - LMTP Server
|
|
|
|
|
|
|
|
[Service]
|
|
|
|
Type=simple
|
|
|
|
ExecStart=/path/to/easywks lmtpd
|
|
|
|
Restart=on-failure
|
|
|
|
User=webkey
|
|
|
|
Group=webkey
|
|
|
|
WorkingDirectory=/var/lib/easywks
|
|
|
|
|
|
|
|
[Install]
|
|
|
|
WantedBy=multi-user.target
|
|
|
|
```
|
|
|
|
|
|
|
|
Also configure EasyWKS to send outgoing mails via SMTP.
|
|
|
|
|
|
|
|
Then tell postfix to forward mails to the submission addresses to said transport, e.g. in `/etc/postfix/transport`:
|
|
|
|
|
|
|
|
```
|
|
|
|
gpgwks@example.org lmtp:localhost:10024
|
|
|
|
webkey@example.com lmtp:localhost:10024
|
|
|
|
```
|
2021-09-26 08:40:02 +02:00
|
|
|
|
|
|
|
[wkd]: https://wiki.gnupg.org/WKD
|
|
|
|
[wks]: https://wiki.gnupg.org/WKS
|
|
|
|
[ietf]: https://datatracker.ietf.org/doc/html/draft-koch-openpgp-webkey-service-12
|