Clon1998 / mobileraker

A Flutter mobile app for Klipper/Moonraker
Other
471 stars 51 forks source link

Support for remote connections with mTLS auth #333

Open boecko opened 7 months ago

boecko commented 7 months ago

Feature Request

Problem Description

I'm getting TLSV1_ALERT_CERTIFCATE_REQUIRED when i'm trying to connect to my remote moonraker-installation with the ios-app. I've installed a client certificate in my iphone and verified that it's working in plain safari with my moonraker-domain.

Proposed Solution

Consider implementing client certs for remote authentifcation.

Additional Context

The klipper remote domain is handled by a haproxy-installation, which serves as remote proxy for a ton of things. Here is a simplified config to clarify the setup

frontend https-in                                                                                                                                                                            
    mode tcp                                                                                                                                                                                 
    bind :443                                                                                                                                                                                
    tcp-request inspect-delay 5s                                                                                                                                                             
    tcp-request content accept if { req_ssl_hello_type 1 }                                                                                                                                                                                                                                                                                                                                
    acl with_clientcert req.ssl_sni -i klipper.mydomain.com                                                                                                                                                                                                                                                                                                                            
    use_backend respin-tls-term-clientcert if with_clientcert                                                                                                                                    
   default_backend respin-tls-term                                                                                                                                                          

backend respin-tls-term                                                                                                                                                                      
    mode tcp                                                                                                                                                                                 
    option http-server-close                                                                                                                                                                     
    server loopback-for-tls abns@haproxy-tls-term send-proxy-v2        # without client cert. not related to the issue                                                                                                                      

backend respin-tls-term-clientcert                                                                                                                                                               
    mode tcp                                                                                                                                                                                 
    option http-server-close                                                                                                                                                                 
    server loopback-for-tls abns@haproxy-tls-term-clientcert send-proxy-v2                                                                                                                   

frontend http-in-clientcert                                                                                                                                                                  
    mode http                                                                                                                                                                                
    bind abns@haproxy-tls-term-clientcert accept-proxy ssl crt /etc/haproxy/certs/mydomain.com.bundle.pem verify required ca-file /etc/haproxy/certs/intermediate-ca.crt ca-verify-file /etc/ssl/cacert.pem alpn h2,http/1.1  
    acl is_klipper     hdr_beg(host) -i klipper                                                                                                                                              
    acl is_webcam      path_beg /webcam/                                                                                                                                                     
    acl is_webcam_hls  path_beg /hls/                                                                                                                                                        
    acl is_webcam_hls  path_beg /jpeg/                                                                                                                                                                                                                                                                                              
    acl is_moonraker path_beg  /websocket                                                                                                                                                      
    acl is_moonraker path_beg  /printer                                                                                                                                                        
    acl is_moonraker path_beg  /api                                                                                                                                                            
    acl is_moonraker path_beg  /access                                                                                                                                                         
    acl is_moonraker path_beg  /machine                                                                                                                                                        
    acl is_moonraker path_beg  /server                                                                                                         

    use_backend octopi_webcam if is_klipper is_webcam                                                                                                                                        
    use_backend octopi_webcam_hls if is_klipper is_webcam_hls                                                                                                                                
    use_backend moonraker_be if is_klipper is_moonraker                                                                                                                                      
    use_backend fluidd_be if is_klipper  

.. backend and lots of stuff
Clon1998 commented 7 months ago

Can you upload your certificate ? I assume the main issue is that the certificate is using TLS V1, which the web client I am using does not like.

Edit: I just woke up lol. Obviously, TLS versions and X509 Certs are not related/can be configured like that.

boecko commented 7 months ago

Here is the relevant output of openssl s_client -showcerts -verify 5 -connect klipper.mydomain.com:443

CONNECTED(00000003)
---
Certificate chain
 0 s:CN = mydomain.com
   i:C = US, O = Let's Encrypt, CN = R3
   a:PKEY: rsaEncryption, 2048 (bit); sigalg: RSA-SHA256
   v:NotBefore: Nov 11 12:13:08 2023 GMT; NotAfter: Feb  9 12:13:07 2024 GMT
-----BEGIN CERTIFICATE-----
..
-----END CERTIFICATE-----
 1 s:C = US, O = Let's Encrypt, CN = R3
   i:C = US, O = Internet Security Research Group, CN = ISRG Root X1
   a:PKEY: rsaEncryption, 2048 (bit); sigalg: RSA-SHA256
   v:NotBefore: Sep  4 00:00:00 2020 GMT; NotAfter: Sep 15 16:00:00 2025 GMT
-----BEGIN CERTIFICATE-----
...
-----END CERTIFICATE-----
---
Server certificate
subject=CN = mydomain.com
issuer=C = US, O = Let's Encrypt, CN = R3
---
Acceptable client certificate CA names
C = DE, ...., OU = Intermediate CA, CN = intermediateca.mydomain.com
Requested Signature Algorithms: ECDSA+SHA256:ECDSA+SHA384:ECDSA+SHA512:Ed25519:Ed448:RSA-PSS+SHA256:RSA-PSS+SHA384:RSA-PSS+SHA512:RSA-PSS+SHA256:RSA-PSS+SHA384:RSA-PSS+SHA512:RSA+SHA256:RSA+SHA384:RSA+SHA512:ECDSA+SHA224:ECDSA+SHA1:RSA+SHA224:RSA+SHA1
Shared Requested Signature Algorithms: ECDSA+SHA256:ECDSA+SHA384:ECDSA+SHA512:Ed25519:Ed448:RSA-PSS+SHA256:RSA-PSS+SHA384:RSA-PSS+SHA512:RSA-PSS+SHA256:RSA-PSS+SHA384:RSA-PSS+SHA512:RSA+SHA256:RSA+SHA384:RSA+SHA512
Peer signing digest: SHA256
Peer signature type: RSA-PSS
Server Temp Key: X25519, 253 bits
---
SSL handshake has read 3343 bytes and written 416 bytes
Verification: OK
---
New, TLSv1.3, Cipher is TLS_AES_128_GCM_SHA256
Server public key is 2048 bit
This TLS version forbids renegotiation.
Compression: NONE
Expansion: NONE
No ALPN negotiated
Early data was not sent
Verify return code: 0 (ok)
---
Clon1998 commented 7 months ago

Thanks, the cert looks fine. Can you provide me the log files of mobileraker? They are located at the very bottom of the App Setting page.

boecko commented 7 months ago

mobileraker_2024-02-08T13-31-21.log

Here you are. Maybe you have to load the client.p12 into the Dart3.2 security-context, because it's not using the system profiles? https://api.dart.dev/stable/3.2.6/dart-io/SecurityContext/usePrivateKey.html

Clon1998 commented 7 months ago

Hey, I had more time to review the logs. I assume you want to use client certificate authentication to authorize the app with your server (mTLS) and unfortunately, this use case is currently unsupported.

boecko commented 7 months ago

That was the purpose of this stunt ;) Never mind.

Clon1998 commented 7 months ago

That was the purpose of this stunt ;)

Never mind.

Haha gotcha. I did not get it initially. I ll have a look at the required changes to get this working. It's a little bit more than just using the security context as I am using dio as http client and the all uses different client's for local and remote connection.