graygnuorg / pound

Light-weight reverse proxy, load balancer and HTTPS front-end for Web servers.
GNU General Public License v3.0
43 stars 13 forks source link

openssl 0A000438 error and Caddy servers #21

Closed beelze closed 11 months ago

beelze commented 11 months ago

I'm getting error for some Caddy server backends:

pound: BIO_do_handshake with xx.xx.xx.xx:443 failed: error:0A000438:SSL routines::tlsv1 alert internal error

backend configuration (inside https listener) is minimal:

       BackEnd              
           HTTPS            
           Address some.caddy.server
           Port 443         
       End                  

Playing with Disable TLSx or Ciphers options (like any other options) changed nothing. Tested with openssl 3.0.9 and 3.1.3 – same results.

Here's Qualys report on one of "problematic" sites. Also, this discussion on stackoverflow may be relevant to the issue

beelze commented 11 months ago

upd: Trying to directly request the Caddy server in question by wget, using IP address instead domain name, got same error:

# wget -Sv https://xx.xx.xx.xx/path -O -
--2023-10-21 16:08:12--  https://xx.xx.xx/path
Connecting to xx.xx.xx.xx:443... connected.
OpenSSL: error:0A000438:SSL routines::tlsv1 alert internal error
Unable to establish SSL connection.
graygnuorg commented 11 months ago

Apparently you don't have the corresponding root certificate or keychain. Use Cert keyword in the Backend section to supply the missing info.

beelze commented 11 months ago

Sorry if I missed something, but according to docs Cert "filename" is for specifying the certificate that pound will use as a client

The Caddy server in question is a public server and is can be successfully queried by wget (from the host the pound is running on) without providing client certificate:

# wget -Sv https:/some.caddy.server/path -O -
--2023-10-21 19:49:14--  https://some.caddy.server/path
Resolving some.caddy.server (some.caddy.server).. xx.xx.xx.xx
Connecting to some.caddy.server (some.caddy.server)|xx.xx.xx.xx|:443... connected.
HTTP request sent, awaiting response... 
  HTTP/1.1 200 OK
  Alt-Svc: h3=":443"; ma=2592000
  Content-Length: 8
  Content-Type: application/json
  Date: Sat, 21 Oct 2023 13:49:15 GMT
  Server: Caddy
  Server: restify
Length: 8 [application/json]
…

More, when I replaced some.caddy.server to my own test https server (lighttpd), pound processes backend request successfully.

graygnuorg commented 11 months ago

beelze @.***> ha escrit:

The Caddy server in question is a public server and is can be successfully queried by wget (from the host the pound is running on) without providing client certificate:

In your previous posting you said that:

Trying to directly request the Caddy server in question by wget, using IP address instead domain name, got same error:

Right? That seems to indicate that pound is accessing it by wrong name. If the remote server is using SNI (nowadays most servers do) it will fail the handshake if presented wrong name in the Host: header. That header, in turn, will contain the name client used to access the server pound lives on. In that case you will need to modify the Host: header before sending request to the backend.

Regards, Sergey

beelze commented 11 months ago

pound is accessing it by wrong name

my guess was the same, so I've tried to use SetHeader "Host: some.caddy.server" inside Service section, but it changed nothing (same error). Again, I've checked (on my test server) that this header was actually sent so I really do not know what exactly I'm doing wrong. `

beelze commented 11 months ago

Here's two real-world configs to reproduce the problem.

    Service                                  
        SetPath "/tyrian/site-logo.svg"      
        SetHeader "Host: assets.gentoo.org"  
        BackEnd                              
            HTTPS                            
            Disable TLSv1_1                  
            Address assets.gentoo.org        
            Port 443                         
        End                                  
    End     

this request processed successfully:

pound: xx.xx.xx.xx GET /rotate/akjhnv5m47zx HTTP/1.1 - HTTP/1.1 200 OK (assets.gentoo.org/- -> 185.76.9.19:443) 0.395 sec

But this config is not working:

   Service                                                      
       SetPath "/user_avatar/caddy.community/matt/24/8322_2.png"
       SetHeader "Host: caddy.community"                        
       BackEnd                                                  
           HTTPS                                                
           Disable TLSv1_1                                      
           Address caddy.community                              
           Port 443                                             
       End                                                      
   End                                                          

same error:

pound: BIO_do_handshake with 159.89.152.193:443 failed: error:0A000438:SSL routines::tlsv1 alert internal error
graygnuorg commented 11 months ago

Thanks for the additional info. Please, pull commit bcb10cbcf1a036b2d9a38cde91b7dfad7577347e. It introduces additional keyword ServerName for the Backend section. With this change, the following service definition works:

Service
    SetPath "/user_avatar/caddy.community/matt/24/8322_2.png"
    BackEnd
        HTTPS
        Disable TLSv1_2
        ServerName "caddy.community"
        Address caddy.community
        Port 443
    End
End

Observe the following:

  1. SetHeader is not needed, since ServerName implies it for that particular backend. This means that correct SNI and Host: header will be used in case of multiple backends as well.

  2. You can use IP address in the Address directive as well - it doesn't affect SNI.

  3. This particular host uses TLSv1_3, so the Disable statement has been changed accordingly.

Regards, Sergey

beelze commented 11 months ago

bcb10cb has fixed an issue. Thanks!