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
> ```
>