Hi,

what you observe is actually documented in relayd.conf(8):

     The with tls directive enables client-side TLS mode to connect to
     the remote host.  Verification of server certificates can be
     enabled by setting the ca file option in the protocol section.

I admit this could be a bit more obvious.

We could also change the default and add a way to disable verification.

Thanks for the report.

/Benno


Nick([email protected]) on 2020.02.10 23:38:34 +0000:
> >Synopsis:    relayd doesn't verify backend TLS by default
> >Category:    system
> >Environment:
>       System      : OpenBSD 6.6
>       Details     : OpenBSD 6.6 (GENERIC.MP) #372: Sat Oct 12 10:56:27 MDT 
> 2019
>                        
> [email protected]:/usr/src/sys/arch/amd64/compile/GENERIC.MP
> 
>       Architecture: OpenBSD.amd64
>       Machine     : amd64
> 
> >Description:
>               
>       In the spirit of secure by default and principle of least surprise I 
> think relayd
>       should always verify backend TLS connections. It certainly confused me 
> when I
>       realized I'd managed to (easily!) set `with tls` up without actual 
> security.
> 
>       I think `tls ca file "/etc/ssl/cert.pem"` should be the default.
> 
> >How-To-Repeat:
>               
>       To be fair, this is documented in the relayd(8) manpage:
>       
>       >     The with tls directive enables client-side TLS mode to connect to
>       >     the remote host.  Verification of server certificates can be
>       >     enabled by setting the ca file option in the protocol section.
> 
>       but my eyes skipped that second sentence multiple times.
> 
>       You can demonstrate the behaviour with a self-signed cert:
>       
>       ```
>       $ mkdir relayd-verify; cd relayd-verify
>       $ openssl req -x509 -newkey rsa:4096 -subj '/CN='"localhost" -nodes 
> -keyout localhost.key -out localhost.pem -days 3
>       $ mkdir -p site
>       $ mkdir -p logs # httpd insists on this
>       $ echo "Static Site" > site/index.html
>       $ cat > httpd.conf <<EOF                                                
>                   
>       chroot "."
>       
>       server "site" {
>               listen on localhost tls port 8443
>               tls {
>                   certificate "localhost.pem"
>                   key "localhost.key"
>               }
>               root "site"
>               directory auto index
>       }
>       EOF
>       $ doas httpd -f httpd.conf
>       $ curl --cacert localhost.pem https://localhost:8443 # test httpd came 
> up right
>       Static Site
>       $ cat > relayd.conf <<EOF                                               
>                                                           
>       table <web> { "127.0.0.1" }
>       table <app> { "127.0.0.1" }
>       
>       http protocol web {
>               # Return HTTP/HTML error pages to the client
>               return error
>       }
>       
>       relay https_proxy { 
>               listen on 0.0.0.0 port 80
>       
>               protocol web
>               forward with tls to <web> port 8443
>       }
>       EOF
>       $ doas relayd -f relayd.conf
>       ```
>       
>       Now the moment of truth: I would expect this to fail, because the 
> backend is using a
>       self-signed cert that relayd doesn't know about, and yet it passes:
>       
>       ```
>       $ curl http://localhost
>       Static Site
>       ```
>       
>       I would *expect* `tls ca file "localhost.pem"` to be necessary to make 
> this pass.
> 
> >Fix:
>       
>       Add `tls ca file "/etc/ssl/cert.pem"` to each `protocol` section. Then
> 
>       ```
>       $ curl http://localhost/     
>       curl: (52) Empty reply from server
>       ```
> 

Reply via email to