branches: front
Clone
clone: git://shithub.us/igor/tlssrv.sni gits://shithub.us/igor/tlssrv.sni
push: hjgit://shithub.us/igor/tlssrv.sni
patches to: igor@9lab.org
Last commit
6fbda982
– igor <igor@mux>
authored
on 2024/01/25 05:59
Fix typos and install in /bin instead of $user/bin.
About
# Tlssrv(8) with Server Name Indication (SNI) support
A variant of tlssrv(8) supporting the [Server Name Indication
(SNI)](https://en.wikipedia.org/wiki/Server_Name_Indication)
extension. With this extension it is possible to use *multiple* SSL
certificates with a *single* IP address.
# Installation
```
% git/clone git://shithub.us/igor/tlssrv.sni
% cd tlssrv.sni
% mk install
```
# Example Setup
The easiest way to fetch and renew a **TLS** certificate on
[9front](http://9front.org) is via
[acmed(8)](http://man.9front.org/8/acmed). We are going to
request 4 SSL certificates, that is `9lab.org`, `mux.9lab.org`,
`bytelabs.org`, and `mux.bytelabs.org`, backed by the same IP address.
Initially an account key must be generated (see
[acmed(8)](http://man.9front.org/8/acmed):
```
% ramfs -p ; cd /tmp
% auth/rsagen -t \
'service=acme role=sign hash=sha256 acct=igor@9lab.org' \
>account.key
% auth/rsa2jwk account.key \
>/sys/lib/tls/acmed/igor@9lab.org.pub
```
The `account.key` must be loaded into
[factotum(4)](http://man.9front.org/4/factotum); however, it is best
to store it in [secstore(1)](http://man.9front.org/1/secstore) instead
of storing it unencrypted on the file system:
```
% auth/secstore -g factotum
secstore password:
% cat account.key >> factotum
% auth/secstore -p factotum
secstore password:
% read -m factotum > /mnt/factotum/ctl
```
Please consult [secstore(1)](http://man.9front.org/1/secstore) as well
as the excellent [9front FQA secstore
documentation](http://fqa.9front.org/fqa8.html#8.4.7) if the above
doesn't make sense or doesn't work for you.
Next, generate a [rsa(8)](http://man.9front.org/8/rsa) key (i.e.
`certificate.key`) and store it in
[secstore(1)](http://man.9front.org/1/secstore):
```
% auth/rsagen -t 'service=tls role=client owner=*' \
>certificate.key
% auth/secstore -g factotum
secstore password:
% cat certificate.key >> factotum
% auth/secstore -p factotum
secstore password:
% read -m factotum > /mnt/factotum/ctl
```
See [rsa(8)](http://man.9front.org/8/rsa) and
[tlssrv(8)](http://man.9front.org/8/tlssrv) for more examples on how
to use RSA keys.
Now it is time to create certificate signing requests (i.e.
`mux.9lab.org.csr`):
```
% auth/rsa2csr 'CN=9lab.org' certificate.key \
>/sys/lib/tls/acmed/9lab.org.csr
% auth/rsa2csr 'CN=mux.9lab.org' certificate.key \
>/sys/lib/tls/acmed/mux.9lab.org.csr
% auth/rsa2csr 'CN=bytelabs.org' certificate.key \
>/sys/lib/tls/acmed/bytelabs.org.csr
% auth/rsa2csr 'CN=mux.bytelabs.org' certificate.key \
>/sys/lib/tls/acmed/mux.bytelabs.org.csr
```
Finally, the certificates for your domains can be fetched. This
requires [webfs(4)](http://man.9front.org/4/webfs) to be mounted as
the [ACME
protocol](https://en.wikipedia.org/wiki/Automatic_Certificate_Management_Environment)
uses HTTP to talk to the provider.
```
% webfs
% auth/acmed igor@9lab.org /sys/lib/tls/acmed/9lab.org.csr \
>/sys/lib/tls/acmed/9lab.org.crt
% auth/acmed igor@9lab.org /sys/lib/tls/acmed/mux.9lab.org.csr \
>/sys/lib/tls/acmed/mux.9lab.org.crt
% auth/acmed igor@9lab.org /sys/lib/tls/acmed/bytelabs.org.csr \
>/sys/lib/tls/acmed/bytelabs.org.crt
% auth/acmed igor@9lab.org /sys/lib/tls/acmed/mux.bytelabs.org.csr \
>/sys/lib/tls/acmed/mux.bytelabs.org.crt
```
The above incantation is also used to *renew* certificates. The
following is handy to display a certificate:
```
% auth/pemdecode 'CERTIFICATE' /sys/lib/tls/acmed/mux.9lab.org.crt | auth/x5092pub
key proto=rsa size=2048 ek=… n=… subject=mux.9lab.org
```
At last, to [listen(8)](http://man.9front.org/8/listen) on https port
443 for requests modify the file `/bin/service/tcp443` as follows:
```
% cat /bin/service/tcp443
#!/bin/rc
exec tlssrv -c/sys/lib/tls/acmed/9lab.org.crt -ltcp80 -r`{cat $3/remote} /bin/tcp80 `{cat $3/remote}>>[2]/sys/log/tcp80
```
If you already have `/bin/service/tcp443` with a certificate setup you
do not need any additional steps to enable SNI to work other than
ensuring your certificates are in the appropriate folder
`/sys/lib/tls/acmed/` using the right suffix (see Caveats section).
# Caveats
A main or fallback certificate can be specified to tlssrv(8) via the
`-c` option. If a Server Name Identifier SNI is provided, we attempt
to load its certificate from:
```
snprint(path, sizeof(path), "/sys/lib/tls/acmed/%s.crt", c->serverName);
```
That means the certificate has to be present in `/sys/lib/tls/acmed/`
with the name `SNI.crt`, where SNI is the the server name indicator
provided by the client.