relayd doesn't verify backend TLS by default

classic Classic list List threaded Threaded
2 messages Options
Reply | Threaded
Open this post in threaded view
|

relayd doesn't verify backend TLS by default

Nick Guenther-2
>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
                         [hidden email]:/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 | Threaded
Open this post in threaded view
|

Re: relayd doesn't verify backend TLS by default

Sebastian Benoit-3
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([hidden email]) 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
> [hidden email]:/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
> ```
>