haproxy/tests/test-srv-verify.cfg
Willy Tarreau 2ab88675ec MINOR: ssl: compare server certificate names to the SNI on outgoing connections
When support for passing SNI to the server was added in 1.6-dev3, there
was no way to validate that the certificate presented by the server would
really match the name requested in the SNI, which is quite a problem as
it allows other (valid) certificates to be presented instead (when hitting
the wrong server or due to a man in the middle).

This patch adds the missing check against the value passed in the SNI.
The "verifyhost" value keeps precedence if set. If no SNI is used and
no verifyhost directive is specified, then the certificate name is not
checked (this is unchanged).

In order to extract the SNI value, it was necessary to make use of
SSL_SESSION_get0_hostname(), which appeared in openssl 1.1.0. This is
a trivial function which returns the value of s->tlsext_hostname, so
it was provided in the compat layer for older versions. After some
refinements from Emmanuel, it now builds with openssl 1.0.2, openssl
1.1.0 and boringssl. A test file was provided to ease testing all cases.

After some careful observation period it may make sense to backport
this to 1.7 and 1.6 as some users rightfully consider this limitation
as a bug.

Cc: Emmanuel Hocdet <manu@gandi.net>
Signed-off-by: Willy Tarreau <w@1wt.eu>
2017-07-06 15:15:28 +02:00

58 lines
1.8 KiB
INI

global
maxconn 490
stats socket /tmp/sock1 mode 666 level admin
stats timeout 10m
ssl-server-verify none
tune.ssl.default-dh-param 1024
log /dev/log local0 debug info
defaults
mode http
log global
option httplog
option dontlognull
timeout connect 5s
timeout http-keep-alive 15s
timeout http-request 15s
timeout queue 30s
timeout tarpit 1m
timeout tunnel 300s
timeout client 30s
timeout server 60s
listen 1
bind :8001
# passes checks and traffic (no hostname check)
# server ssl 127.0.0.1:8443 ssl verify required check inter 500 ca-file rsa2048.pem
# passes checks and traffic (localhost is what the server presents)
# server ssl 127.0.0.1:8443 ssl verify required check inter 500 ca-file rsa2048.pem verifyhost localhost
# fails checks and traffic (foo not matched on the server)
# server ssl 127.0.0.1:8443 ssl verify required check inter 500 ca-file rsa2048.pem verifyhost foo
# passes checks and traffic (verify none ignores the host)
# server ssl 127.0.0.1:8443 ssl verify none check inter 500 ca-file rsa2048.pem verifyhost foo
# passes checks and traffic (localhost is fine)
# server ssl 127.0.0.1:8443 ssl verify required check inter 500 ca-file rsa2048.pem sni str(localhost) verifyhost localhost
# passes checks and traffic (verifyhost overrides sni)
# server ssl 127.0.0.1:8443 ssl verify required check inter 500 ca-file rsa2048.pem sni str(foo) verifyhost localhost
# passes checks and traffic (localhost always valid)
# server ssl 127.0.0.1:8443 ssl verify required check inter 500 ca-file rsa2048.pem sni str(localhost)
# passes checks, and traffic without host or with "host: localhost" and fails other hosts.
server ssl 127.0.0.1:8443 ssl verify required check inter 500 ca-file rsa2048.pem sni req.hdr(host)
# just for tests
#server clear 127.0.0.1:8480
listen 2
bind :8480
bind :8443 ssl crt rsa2048.pem
stats uri /