Hi again, This is definitively not possible with HAProxy, unless I missed something! Better use 2 different domain names pointing to 2 IPs hosted by 2 frontends, one asking for a client cert, the other one not.
Baptiste On Wed, Jan 8, 2014 at 9:04 PM, Remy van Elst <[email protected]> wrote: > Lukas Tribus schreef op 08/01/14 19:37: > >> Hi, >> >>> Thank you. I've read the blog post. However, with the verify optional >>> bind line, if the client has a certificate in their browser, they will >>> get asked every time they visit the website. I only want them to be >>> asked for a certificate on a specific path. Possibly something like: >>> >>> if { path_beg /admin }ca-file ./ca.crt verify required >> >> (the proposal from Baptiste is basically the same as mine, we just >> overlapped in time) >> >> I'm afraid this is not possible at all (not even with Apache). Its for >> the same reason you cannot use the "Host:" header to select the correct >> server certificate (and need SNI instead): >> You are relying on a information available only after the SSL/TLS >> handshake >> to influence the actual handshake. This information about the URI is not >> known when you are doing the SSL/TLS handshake. >> >> This is how it looks like when I connect to a server which ask me (the >> client) for a certificate: >> openssl s_client -state -quiet -connect 10.0.0.55:443 >> SSL_connect:before/connect initialization >> SSL_connect:unknown state >> SSL_connect:SSLv3 read server hello A >> depth=0 C = IT, ST = bogus ST, L = Sin City, O = sin-org, CN = >> ubuntuvm.sin-org >> verify error:num=18:self signed certificate >> verify return:1 >> depth=0 C = IT, ST = bogus ST, L = Sin City, O = sin-org, CN = >> ubuntuvm.sin-org >> verify return:1 >> SSL_connect:SSLv3 read server certificate A >> SSL_connect:SSLv3 read server key exchange A >> SSL_connect:SSLv3 read server certificate request A <-- [1] >> SSL_connect:SSLv3 read server done A >> SSL_connect:SSLv3 write client certificate A >> SSL_connect:SSLv3 write client key exchange A >> SSL_connect:SSLv3 write change cipher spec A >> SSL_connect:SSLv3 write finished A >> SSL_connect:SSLv3 flush data >> SSL_connect:SSLv3 read server session ticket A >> SSL_connect:SSLv3 read finished A >> GET / HTTP/1.0 <-- [2] >> >> HTTP/1.1 200 OK >> Date: Wed, 08 Jan 2014 18:13:35 GMT >> [...] >> >> >> As you can see, the certificate request [1] happens before the HTTP >> request >> [2], so what you are saying is not possible. >> >> In case Apache really does the certificate request after the server done >> message, then I believe its a violation of the SSL/TLS specs [3]. >> >> >> Can you run >> openssl s_client -state -quiet -connect <hostname>:443 >> >> against your working apache server and paste: >> GET /admin/ HTTP/1.0 >> >> (with 2 newlines/enters after HTTP/1.0) >> >> so we can see the behavior of your working apache setup? >> >> >> >> Regards, >> >> Lukas >> >> >> [3] http://tools.ietf.org/html/rfc5746 > > > > Thank you all for the great and clear explanations. I'll explain the > situation a bit more. > The web app currently runs on 2 Apache servers set up by a former admin. > I've had to bolt on cluster functionality, now using Pacemaker and Corosync > HA. However, they're migrating all the apps from off a Big IP F5 > loadbalancer (which does not do SSL offloading) to a haproxy setup (SSL > offloading on haproxy, again, with pacemaker/corosync clustering). > > In the testing phase (now), some clients have issues with the app (because > they have a certificate in their browser). On Apache/F5 they are not asked > for a certificate in using the app, only admins are. > > The current haproxy setup does ask for a certificate to "regular users", > whereas the previous setup did not. Therefore, my understanding was that it > was a valid setup, however now it appears to be a "violation of the SSL/TLS > specs". > > Here is the requested data, both for a non-admin url and for the admin url. > > > The client side certificate requesting URL: > > $ openssl s_client -state -quiet -connect xx.xx.xx.xx:443 > > SSL_connect:before/connect initialization > SSL_connect:SSLv2/v3 write client hello A > SSL_connect:SSLv3 read server hello A > depth=4 /C=NL/O=xxx/CN=xxx > verify error:num=19:self signed certificate in certificate chain > verify return:0 > > SSL_connect:SSLv3 read server certificate A > SSL_connect:SSLv3 read server key exchange A > SSL_connect:SSLv3 read server done A > SSL_connect:SSLv3 write client key exchange A > SSL_connect:SSLv3 write change cipher spec A > SSL_connect:SSLv3 write finished A > SSL_connect:SSLv3 flush data > SSL_connect:SSLv3 read finished A > GET /admin/ HTTP/1.0 > > SSL_connect:SSL renegotiate ciphers > SSL_connect:SSLv3 write client hello A > SSL_connect:SSLv3 read server hello A > depth=4 /C=NL/O=xxx/CN=xxx > verify error:num=19:self signed certificate in certificate chain > verify return:0 > > SSL_connect:SSLv3 read server certificate A > SSL_connect:SSLv3 read server key exchange A > SSL_connect:SSLv3 read server certificate request A > SSL_connect:SSLv3 read server done A > SSL_connect:SSLv3 write client certificate A > SSL_connect:SSLv3 write client key exchange A > SSL_connect:SSLv3 write change cipher spec A > SSL_connect:SSLv3 write finished A > SSL_connect:SSLv3 flush data > SSL3 alert read:fatal:handshake failure > SSL_connect:failed in SSLv3 read finished A > 38843:error:14094410:SSL routines:SSL3_READ_BYTES:sslv3 alert handshake > failure:/SourceCache/OpenSSL098/OpenSSL098-50/src/ssl/s3_pkt.c:1106:SSL > alert number 40 > 38843:error:140940E5:SSL routines:SSL3_READ_BYTES:ssl handshake > failure:/SourceCache/OpenSSL098/OpenSSL098-50/src/ssl/s3_pkt.c:1010: > > The non client side certificate response: > > $ openssl s_client -state -quiet -connect xx.xx.xx.xx:443 > > SSL_connect:before/connect initialization > SSL_connect:SSLv2/v3 write client hello A > SSL_connect:SSLv3 read server hello A > depth=4 /C=NL/O=xxx/CN=xxx > verify error:num=19:self signed certificate in certificate chain > verify return:0 > > SSL_connect:SSLv3 read server certificate A > SSL_connect:SSLv3 read server key exchange A > SSL_connect:SSLv3 read server done A > SSL_connect:SSLv3 write client key exchange A > SSL_connect:SSLv3 write change cipher spec A > SSL_connect:SSLv3 write finished A > SSL_connect:SSLv3 flush data > SSL_connect:SSLv3 read finished A > GET / HTTP/1.0 > > HTTP/1.1 200 OK > Date: Wed, 08 Jan 2014 19:53:33 GMT > Server: Apache > X-Frame-Options: SAMEORIGIN > X-XSS-Protection: 1; mode=block > X-Content-Type-Options: nosniff > X-UA-Compatible: chrome=1 > Cache-Control: no-cache > X-Request-Id: 0978a920-5722-4acd-9a19-8bca6b49f8c3 > X-Runtime: 0.009102 > Set-Cookie: request_method=GET; path=/ > Status: 200 > Content-Length: 95 > Connection: close > Content-Type: text/html; charset=utf-8 > Strict-Transport-Security: max-age=31536000; includeSubDomains > > SSL3 alert read:warning:close notify > SSL3 alert write:warning:close notify > > > If it is not possible to do this with haproxy (because it is invalid > according to the spec) then I'll probably suggest they move the admin > interface out of the user-facing part of the app. >

