1 unstable release
0.1.0 | Mar 1, 2019 |
---|
#1313 in Cryptography
45KB
948 lines
Do not use yet
Trust-ACME orders and manages certificates. DNS challenges and DANE are done with Trust-DNS.
User's trust should be founded on strong defaults and only a few chosen dependencies.
Currently it just reads its config file and orders all configured certificates without further logic.
TODO
- verify whether this tutorial is actually working or not
- cleanup code
- reload services only at the end of processing all certs
- better error handling
- reintroduce (some) tests
- reuse one TCP connection to Trust-DNS
- order url should be stored in a certs/example.com.txt file to check validity/revocation status on each run.
- example.com_next.crt should be ordered 7 days before regular expiration, to have a smooth TLSA transition. Revocation would still hurt.
- option to provide a manually generated rsa key for postfix
- cleanup of certs/keys that are unknown to the config
- command line arguments
- having a Trust-DNS systemd service to offer DNS-over-TLS
- reconsider folder structure and everything
Non-Goals
- Dependency terror
- Using OpenSSL
- Insecure HTTP challenges
- Hard to read code
How to test
First we set up a Trust-DNS server. Warning: This config is a personal flavor.
# curl https://sh.rustup.rs -sSf | sh
# source $HOME/.cargo/env
# cargo install kt -f
# cargo install trust-dns-server --git https://github.com/bluejekyll/trust-dns --features dnssec-ring -f
# mkdir /etc/trust-dns; mkdir /etc/trust-dns/zones; mkdir /etc/trust-dns/keys
# kt generate ed25519 --out /etc/trust-dns/keys/dns_auth.pk8
# kt generate p384 --out /etc/trust-dns/keys/example.com.pk8
nano /etc/trust-dns/config.toml
listen_addrs_ipv4 = ["your public ipv4 address"]
listen_addrs_ipv6 = ["::1", "your public ipv6 address"]
listen_port = 53
[[zones]]
zone = "example.com"
zone_type = "Master"
enable_dnssec = true
stores = { type = "sqlite", zone_file_path = "example.com", journal_file_path = "example.com.jrnl", allow_update = true }
keys = [{key_path="keys/example.com.pk8", algorithm="ECDSAP384SHA384", is_zone_signing_key=true}, {key_path="keys/dns_auth.pk8", algorithm="ED25519", is_zone_update_auth=true}]
(Official examples don't use inline tables for keys
; I just prefer to have compact zone configs.)
nano /etc/trust-dns/zones/example.com
@ 86400 IN SOA ns1.example.com. hostmaster.example.com. (
201903010 ; Serial
3600 ; Refresh
600 ; Retry
86400 ; Expire
600) ; Negative TTL
@ 86400 IN NS ns1.example.com.
@ 86400 IN NS ns2.example.com.
@ 86400 IN MX 5 mail.example.com.
@ 86400 IN TXT "v=spf1 mx -all"
@ 86400 IN CAA 0 issue "letsencrypt.org; validationmethods=dns-01"
@ 86400 IN CAA 0 iodef "mailto:hostmaster@example.com"
@ 86400 IN AAAA ::1
www 86400 IN AAAA ::1
www 86400 IN MX 0 .
ns1 86400 IN AAAA ::1
ns1 86400 IN A 127.0.0.1
ns1 86400 IN MX 0 .
ns2 86400 IN AAAA ::1
ns2 86400 IN A 127.0.0.1
ns2 86400 IN MX 0 .
mail 86400 IN AAAA ::1
mail 86400 IN A 127.0.0.1
Let's check how it goes:
# cd /etc/trust-dns; named --config /etc/trust-dns/config.toml --zonedir /etc/trust-dns/zones
As long we don't have a nice systemd service:
# cat << EOF > /root/trust-dns.sh
#!/bin/bash
cd /etc/trust-dns; screen -dmS trust-dns named --config /etc/trust-dns/config.toml --zonedir /etc/trust-dns/zones
EOF
# chmod +x /root/trust-dns.sh
How to get the DNSKEY for your DNS provider to make DNSSEC actually working?
$ dig DNSKEY example.com @trust-dns-server-ip +short +nosplit
You just want to try it out with a sub domain as zone and need to generate a DS record? Use https://filippo.io/dnskey-to-ds/.
Let's proceed and install trust-acme:
# cargo install trust-acme -f
# mkdir /etc/trust-acme; mkdir /etc/trust-acme/certs
# kt generate p384 --out /etc/trust-acme/letsencrypt_account.pk8
nano /etc/trust-acme/config.toml
[ca.letsencrypt]
directory = "https://acme-staging-v02.api.letsencrypt.org/directory"
account_key = "/etc/trust-acme/letsencrypt_account.pk8"
account_email = "hostmaster@example.com"
[trustdns.default]
server = "[::1]:53"
auth_key = "/etc/trust-dns/keys/dns_auth.pk8"
[[cert]]
zone = "example.com"
# whether there should be an additional openssl-style pem key (example.com.key)
pem_key = true
reload = ["nginx"]
san = [
{ name = "example.com", tcp = [443] },
{ name = "www.example.com", tcp = [443] },
]
#[[cert]]
#zone = "example.com"
#reload = ["trust-dns"]
#
#[[cert.san]]
#name = "ns.example.com"
#tcp = [853]
#udp = [853]
If you comment out directory
, the real Let's Encrypt will be used. For simplicity regarding TLSA records it's currently not possible to have SAN entries from different zones. At the moment, only ECDSA P-384 certificates are supported.
To order, just run:
# trust-acme
A certificate's first SAN entry will be used as its file name:
Certificate path: /etc/trust-acme/certs/example.com.crt
Key path (Rustls): /etc/trust-acme/certs/example.com.pk8
Key path (OpenSSL): /etc/trust-acme/certs/example.com.key
Dependencies
~35MB
~779K SLoC