1 [[!meta title="Certificates for services on our LAN"]]
3 # Let's Encrypt certs for services on our LAN
5 We use [Let's Encrypt] to acquire and renew certificates for basically
6 all services. However, some services are only exposed on the LAN, and
7 so certificate acquisition becomes a bit trickier.
9 [ACME], the protocol for interacting with [Let's Encrypt],
10 supports [DNS-01] authorization, so we can use that to acquire certs
11 without exposing services to the Internet.
13 [Let's Encrypt]: https://letsencrypt.org/
14 [DNS-01]: https://tools.ietf.org/html/draft-ietf-acme-acme-07#section-8.5
15 [ACME]: https://tools.ietf.org/html/draft-ietf-acme-acme-07
20 Let's say we need certificates for `metrics.mgmt.realraum.at`
22 `metrics.mgmt` will send DNS updates to `gw`. It only needs TXT records for
23 `_acme-challenge.metrics.mgmt.realraum.at` and they will be authenticated using
29 ### Generating a TSIG key
31 On the system running the services:
33 - Install `bind9utils` to have the not-so-aptly named `dnssec-keygen` tool.
34 - As `root`, generate an HMAC-SHA256 key and make it readable by `acme`:
36 # dnssec-keygen -K /etc/acme -a HMAC-SHA256 -b 256 \
37 -n USER metrics.mgmt.realraum.at.
38 Kmetrics.mgmt.realraum.at.+163+06888
40 # chown root:acme /etc/acme/K*
41 # chmod 0440 /etc/acme/K*
43 - Lookup the key, as we will need to put it in the NS' configuration
45 # cat /etc/acme/Kmetrics.mgmt.realraum.at.+163+06888.private
46 Private-key-format: v1.3
47 Algorithm: 163 (HMAC_SHA256)
48 Key: FG4v6Eya7utyJ1GxXm019kYBawN+jvfEWCC/7lIgraQ=
50 Created: 20171022235329
51 Publish: 20171022235329
52 Activate: 20171022235329
55 _Note:_ I selected HMAC-SHA256 because `gw.realraum.at` is running an
56 obsolete version of Bind9 that only supports HMAC or RSA.
57 In principle, the setup should be similar for asymetric signatures.
64 - `/etc/bind/keys.conf` should exist and be accessible to `root` and `bind`:
66 # touch /etc/bind/keys.conf
67 # chown root:bind /etc/bind/keys.conf
68 # chmod 0640 /etc/bind/keys.conf
70 - Check that `keys.conf` is included from `named.conf.local`:
72 # head /etc/bind/named.conf.local
73 include "/etc/bind/zones.rfc1918";
74 include "/etc/bind/keys.conf";
77 - Add the key descriptor to `keys.conf`:
79 # cat >> /etc/bind/keys.conf
80 key metrics.mgmt.realraum.at. {
81 algorithm HMAC-SHA256;
82 secret "4QZWZsLagxXaoBCAxDqbSZmoSjN5qJvZviadrPXkmvU=";
86 ### Setting up DNS updates
88 - Edit the zone description in `named.conf.local` to allow updates:
92 file "/etc/bind/db.realraum.at";
96 grant metrics.mgmt.realraum.at. name _acme-challenge.metrics.mgmt.realraum.at. TXT;
100 - The update journal for the zone should be writeable by `bind`:
102 # touch /etc/bind/db.realraum.at.jnl
103 # chown root:bind /etc/bind/db.realraum.at.jnl
104 # chmod 0660 /etc/bind/db.realraum.at.jnl
113 - `acmetool` is available from the official repos starting with Stretch.
114 - For earlier releases, Christian [has a package](https://build.spreadspace.org/)
116 Start with a working, [rootless acmetool setup].
118 _Note:_ On Debian, _hooks_ are located in `/etc/acme/hooks`, instead of
119 `/usr/lib/acme/hooks` or `/usr/libexec/acme/hooks`.
121 [acmetool]: https://hlandau.github.io/acme/
122 [rootless acmetool setup]: https://hlandau.github.io/acme/userguide#annex-root-configured-non-root-operation
125 ### Setting up the hook
127 An example hook using `nsupdate`
128 [already ships](https://github.com/hlandau/acme/blob/master/_doc/dns.hook)
131 - Install `dnsutils` (contains `nsupdate`)
132 - Link the hook from the documentation:
134 # ln -s ../../../usr/share/doc/acmetool/examples/dns.hook /etc/acme/
136 - Write the configuration for it:
138 # cat > /etc/default/acme-dns
139 NSUPDATE_ARGS="-k /etc/acme/Kmetrics.mgmt.realraum.at.+163+06888.key"
142 echo server 192.168.33.1
147 # sudo -u acme /etc/acme/hooks/dns.hook challenge-dns-start \
148 foo.example.com "" "foobar"
149 # sudo -u acme /etc/acme/hooks/dns.hook challenge-dns-start \
150 foo.example.com "" "foobar"
152 If either of those commands fail with an error,
153 check the DNS traffic (`tcpdump -vvv port 53`)
156 ### Certificate acquisition
158 Once everything is setup, getting a certificate from Let's Encrypt
161 # sudo -u acme acmetool want metrics.mgmt.realraum.at
164 ### Testing automated removal
166 Last thing, you should check that automatic renewal is setup and works:
168 - Is the cron job in place?
172 37 13 * * * /usr/bin/acmetool --batch reconcile
174 - Is the default hook for reloading services in place?
175 If you delete the certificate and key, then run `acmetool`,
176 do your services use the new certificate?
178 # [check the service's certificate fingerprint, with openssl s_client]
179 # rm -rf /var/lib/acme/keys/*
180 # sudo -u acme acmetool --batch reconcile
181 # [check the service's certificate fingerprint, they should differ]