How to create a working TLS connection to rest-server

Hi,

I am trying to use rest-server 0.13.0 with TLS in a local network and restic 0.18.0. I could use SSH but would like to use the --append-only feature of rest-server.

But I get the error: “tls: failed to verify certificate: x509: certificate is not valid for any names, but wanted to match myhost”. This is most likely my wrong usage of openssl and certificates and not rest-server’s fault. But I hope someone could help me out.

Details:
I start the rest-server with:

/home/user/bin/rest-server --path /path/to/restic --listen ":8019" \
--append-only  --tls --tls-cert /home/user/rest-cert.pem \
--tls-key /home/user/rest-key.pem

I generated the TLS key and certificate with:

openssl req -utf8 -newkey rsa:4096 -nodes -keyout "rest-key.pem" -out "rest-req.pem" \
  -addext "subjectAltName = IP:192.168.0.123,DNS:myhost" \
  -subj "/C=DE/ST=Y/L=Z/O=O/OU=Rs/CN=myhost/emailAddress=restic@myhost"

# 3. Use CA's private key to sign web server's CSR and get signed certificate
openssl x509 -req -in "rest-req.pem" -days 190 -CA "ca-cert.pem" \
  -CAkey "ca-key.pem" -CAcreateserial -out "rest-cert.pem"

And I use this repo: rest:https://myhost:8019.

But restic says:

failed to verify certificate: x509: certificate is not valid for any names, but wanted to match myhost

and the rest-server says:

http: TLS handshake error from 192.168.0.2:50128: remote error: tls: bad certificate

I also tried “myhost” and “myhost.local” and only “IP:192.168.0.123” as subjectAltName. What is wrong here?

If you have a domain, you could get a valid tls certificate from let’s encrypt via a dns challenge. Such certificates should work on the client right away.
Otherwise, this thread seem to cover what you are intending to do: Unable to use TLS client certificate

Assuming this isn’t the only service you need to setup behind TLS, you can also use a local certification server.

There IS a bit of a learning curve, but once it’s setup, it works like a charm

Does openssl x509 -text -in rest-cert.pem show both the IP and DNS name?
How exactly are you calling restic, in particular how do you pass the CA cert to it?

1 Like

Try to copy self-signed CA certificate (ca-cert.pem from your example) to client. Use it when run backups (or any restic command) command restic backup --cacert PATH_TO_CA_CERT/ca-cert.pem ...

Thank you all, @konrad @creativeprojects @MichaelEischer @Ilya, for your replies. I currently can’t look into it. But I will come back to this and try all your suggestions.

No, it did not and that seems to be expected behavior. This excellent tutorial quotes the man pages:

Extensions in certificates are not transferred to certificate requests and vice versa.

So I need to add the subjectAltName part when creating the certificate (openssl x509 …) instead of when creating the certification request (openssl req …).

I tried both --cacert path/to/ca-cert.pem and export RESTIC_CACERT=path/to/ca-cert.pem.

Now, it works! Thank you, @MichaelEischer for asking the right questions!


For those interested in my working solution:

openssl req -newkey rsa -keyout rest-key.pem -out rest-req.csr -config req.conf
openssl x509 -req -in rest-req.csr -days 190 \
  -CA ca-cert.pem -CAkey ca-key.pem -CAcreateserial -out rest-cert.pem \
  -extensions req_ext -extfile req.conf

with req.conf

[req]
prompt = no
default_bits = 4096
utf8 = yes
distinguished_name = dn
req_extensions = req_ext

[dn]
C = DE
ST = State
L = City
O = Org
OU = Unit
CN = Server
emailAddress = me@example.com

[req_ext]
subjectAltName = @alt_names

[alt_names]
DNS.1 = my.local
IP.1 = 192.168.0.5