restic / rest-server

Rest Server is a high performance HTTP server that implements restic's REST backend API.
BSD 2-Clause "Simplified" License
958 stars 141 forks source link

Secure default or configurable TLS settings #251

Open DarkSpir opened 1 year ago

DarkSpir commented 1 year ago

Output of rest-server --version

rest-server version rest-server 0.12.1 compiled with go1.20.5 on linux/amd64

What should rest-server do differently?

If rest-server runs with --tls option and proper certificates it provides an https service on the configured port (or 8000/tcp by default). But it accepts insecure cipher suits and TLS versions. I used nmap to probe the servers capabilities:

nmap -sV --script ssl-enum-ciphers -p 8000 appsrv.domain.tld
Starting Nmap 7.92 ( https://nmap.org ) at 2023-08-23 16:25 CEST
Nmap scan report for appsrv.domain.tld (192.168.238.44)
Host is up (0.00027s latency).

PORT     STATE SERVICE      VERSION
8000/tcp open  ssl/http-alt
| fingerprint-strings: 
|   FourOhFourRequest: 
|     HTTP/1.0 404 Not Found
|     Content-Type: text/plain; charset=utf-8
|     X-Content-Type-Options: nosniff
|     Date: Wed, 23 Aug 2023 14:26:42 GMT
|     Content-Length: 10
|     Found
|   GenericLines, Help, Kerberos, LPDString, RTSPRequest, SSLSessionReq, TLSSessionReq, TerminalServerCookie: 
|     HTTP/1.1 400 Bad Request
|     Content-Type: text/plain; charset=utf-8
|     Connection: close
|     Request
|   GetRequest, HTTPOptions: 
|     HTTP/1.0 405 Method Not Allowed
|     Allow: POST
|     Content-Type: text/plain; charset=utf-8
|     X-Content-Type-Options: nosniff
|     Date: Wed, 23 Aug 2023 14:26:16 GMT
|     Content-Length: 19
|_    Method Not Allowed
| ssl-enum-ciphers: 
|   TLSv1.0: 
|     ciphers: 
|       TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA (secp256r1) - A
|       TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA (secp256r1) - A
|       TLS_RSA_WITH_AES_128_CBC_SHA (rsa 2048) - A
|       TLS_RSA_WITH_AES_256_CBC_SHA (rsa 2048) - A
|       TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA (secp256r1) - C
|       TLS_RSA_WITH_3DES_EDE_CBC_SHA (rsa 2048) - C
|     compressors: 
|       NULL
|     cipher preference: server
|     warnings: 
|       64-bit block cipher 3DES vulnerable to SWEET32 attack
|   TLSv1.1: 
|     ciphers: 
|       TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA (secp256r1) - A
|       TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA (secp256r1) - A
|       TLS_RSA_WITH_AES_128_CBC_SHA (rsa 2048) - A
|       TLS_RSA_WITH_AES_256_CBC_SHA (rsa 2048) - A
|       TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA (secp256r1) - C
|       TLS_RSA_WITH_3DES_EDE_CBC_SHA (rsa 2048) - C
|     compressors: 
|       NULL
|     cipher preference: server
|     warnings: 
|       64-bit block cipher 3DES vulnerable to SWEET32 attack
|   TLSv1.2: 
|     ciphers: 
|       TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 (secp256r1) - A
|       TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (secp256r1) - A
|       TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (secp256r1) - A
|       TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA (secp256r1) - A
|       TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA (secp256r1) - A
|       TLS_RSA_WITH_AES_128_GCM_SHA256 (rsa 2048) - A
|       TLS_RSA_WITH_AES_256_GCM_SHA384 (rsa 2048) - A
|       TLS_RSA_WITH_AES_128_CBC_SHA (rsa 2048) - A
|       TLS_RSA_WITH_AES_256_CBC_SHA (rsa 2048) - A
|       TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA (secp256r1) - C
|       TLS_RSA_WITH_3DES_EDE_CBC_SHA (rsa 2048) - C
|     compressors: 
|       NULL
|     cipher preference: server
|     warnings: 
|       64-bit block cipher 3DES vulnerable to SWEET32 attack
|   TLSv1.3: 
|     ciphers: 
|       TLS_AKE_WITH_CHACHA20_POLY1305_SHA256 (ecdh_x25519) - A
|       TLS_AKE_WITH_AES_128_GCM_SHA256 (ecdh_x25519) - A
|       TLS_AKE_WITH_AES_256_GCM_SHA384 (ecdh_x25519) - A
|     cipher preference: server
|_  least strength: C

What are you trying to do? What is your use case?

I'm security-focused and try to avoid insecure encryption settings in my services. In this particular case I'd prefer TLSv1.2 as the minimal allowed TLS version and absolute no 3DES based cipher suites. I have no experience with Go but I tried to figure out the code to see if I can suggest changes with more secure values. Unfortunately I failed here so I can't prepare a pull request in this case.

My usual approach would be letting the service provide http and use a reverse proxy like traefik or nginx to add tls with secure settings and a central certificate management. But in this one particular installation it would add another dependency to the service which is otherwise not necessary/installed on the system.

Did rest-server help you today? Did it make you happy in any way?

This last question is awesome. Please keep it. I'm using restic for quite some time now and until now I made my repositories accessible via NFS shares. The REST server makes remote access simpler and easier to handle via remote connections (I can forward the port on NAT or add proxies in front of it, there is so much more I can do with a simple webservice than with an NFS server). I have not checked the performance yet but it should have less overhead and thus should be faster than NFS is. Thank you for making rest-server!