>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