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