HAProxy community

Haproxy with Nginx can't use client certificate authentication

#1

Hi, all

I have one IP Adress and one port 443
At the end I have four web applications
I use two domain name (www.domainsample1.com, www.domainsample2.com) and two context root (context_root_1, context_root_2) to backend mapping
I have path: request https -> nginx -> haproxy -> http application
It works until I try to use client certificate authentication
When I add client certificate authentication I get error “1: SSL handshake failure” and client browser do not even try to ask questions about the use of the certificate.
When I test it without nginx (https -> haproxy -> http application ) I can authenticate with a client certificate but I get a 400 error when displaying the application page.
Any help or suggestions are appreciated.
Thanks! :slight_smile:

config haproxy:

global
# log 127.0.0.1 local1 notice
log localhost:514 local0
stats timeout 30s
user haproxy
group haproxy
daemon
tune.ssl.default-dh-param 2048
stats socket /var/run/haproxy.sock mode 666 level admin
stats timeout 2m
stats bind-process 1
nbproc 2
cpu-map 1 0
cpu-map 2 1

defaults
log global
option dontlognull
option httplog
balance leastconn
timeout client 60000
timeout server 60000
timeout connect 5000
retries 3
option redispatch

frontend demo
mode http
acl context_root_1 path_beg /context_root_1
acl context_root_2 path_beg /context_root_2
acl domainsample1 hdr(Host) www.domainsample1.com
acl domainsample2 hdr(Host) wwww.domainsample2.com
bind 172.16.10.1:443 ssl crt /etc/pki/tls/certs/domainsample1.pem crt /etc/pki/tls/certs/domainsample2.pem ca-file /etc/pki/tls/certs/CA.cer verify required
http-request set-header X-SSL %[ssl_fc]
http-request set-header X-SSL-Client-Cert %[ssl_fc_has_crt]
http-request set-header X-SSL-Client-Verify %[ssl_c_verify]
http-request set-header X-SSL-Client-SHA1 %{+Q}[ssl_c_sha1]
http-request set-header X-SSL-Client-DN %{+Q}[ssl_c_s_dn]
http-request set-header X-SSL-Client-CN %{+Q}[ssl_c_s_dn(cn)]
http-request set-header X-SSL-Issuer %{+Q}[ssl_c_i_dn]
http-request set-header X-SSL-Client-Not-Before %{+Q}[ssl_c_notbefore]
http-request set-header X-SSL-Client-Not-After %{+Q}[ssl_c_notafter]
use_backend bk_context_root_1_demo_domainsample1 if domainsample1 context_root_1
use_backend bk_context_root_1_demo_domainsample2 if domainsample2 context_root_1
use_backend bk_context_root_2_demo_domainsample1 if domainsample1 context_root_2
use_backend bk_context_root_2_demo_domainsample2 if domainsample2 context_root_2

backend bk_context_root_1_demo_domainsample1
mode http
server server1 172.16.10.2:5071 check
reqirep ^([^\ :])\ /context_root_1/(.) \1\ /\2

backend bk_context_root_1_demo_domainsample2
mode http
server server2 172.16.10.3:5071 check
reqirep ^([^\ :])\ /context_root_1/(.) \1\ /\2

backend bk_context_root_2_demo_domainsample1
mode http
server server1 172.16.10.2:5070 check
reqirep ^([^\ :])\ /context_root_2/(.) \1\ /\2

backend bk_context_root_2_demo_domainsample2
mode http
server server2 172.16.10.3:5070 check
reqirep ^([^\ :])\ /context_root_2/(.) \1\ /\2

haproxy -vv

HA-Proxy version 1.5.18 2016/05/10
Copyright 2000-2016 Willy Tarreau willy@haproxy.org

Build options :
TARGET = linux2628
CPU = generic
CC = gcc
CFLAGS = -O2 -g -fno-strict-aliasing -DTCP_USER_TIMEOUT=18
OPTIONS = USE_LINUX_TPROXY=1 USE_ZLIB=1 USE_REGPARM=1 USE_OPENSSL=1 USE_PCRE=1

Default settings :
maxconn = 2000, bufsize = 16384, maxrewrite = 8192, maxpollevents = 200

Encrypted password support via crypt(3): yes
Built with zlib version : 1.2.7
Compression algorithms supported : identity, deflate, gzip
Built with OpenSSL version : OpenSSL 1.0.2k-fips 26 Jan 2017
Running on OpenSSL version : OpenSSL 1.0.2k-fips 26 Jan 2017
OpenSSL library supports TLS extensions : yes
OpenSSL library supports SNI : yes
OpenSSL library supports prefer-server-ciphers : yes
Built with PCRE version : 8.32 2012-11-30
PCRE library supports JIT : no (USE_PCRE_JIT not set)
Built with transparent proxy support using: IP_TRANSPARENT IPV6_TRANSPARENT IP_FREEBIND

Available polling systems :
epoll : pref=300, test result OK
poll : pref=200, test result OK
select : pref=150, test result OK
Total: 3 (3 usable), will use epoll.

#2

On nginx I getting error:
2019/03/14 17:39:39 [error] 1090#0: *6254 SSL_do_handshake() failed (SSL: error:14094410:SSL routines:SSL3_READ_BYTES:sslv3
alert handshake failure:SSL alert number 40) while SSL handshaking to upstream,

#3

So what are you trying to solve? The 400 error without nginx or the SSL issue with nginx? How is nginx configured exactly and where those SSL termination/authentication occur exactly?