Hey Donovan,

I never used client certificates in haproxy, but have you tried the
setup with a regular HTTP backend instead of the stats socket? That is
something that should work and you could use to verify that your certs
are working correctly...

Cheers,
Conrad

On 07/24/2014 09:36 PM, Meyers, Donovan wrote:
> 
> Any ideas why "verify required" is allowing connections with no client
> cert?
> 
> Could this be an haproxy bug?
> 
> I hate to even ask that, because it's so presumptuous and this software is
> so well-written. It's one thousand times more likely that I'm doing
> something wrong.
> 
> But from where I sit it seems simple:
> - I used "verify require" which should require a client cert
> - I can connect without specifying a client cert
> 
> 
> 
> So, am I
> 
> 
>  - misusing/misunderstanding "verify require"?
>  - screwing up some other piece of haproxy config?
>  - using the wrong socat/openssl syntax to send (or not) the client cert?
>  - thinking a client cert is valid with tcp when it isn't?
> 
> I'm not sure what else to try, without spending money on a real client
> cert, which doesn't seem like it should matter. Hopefully someone can tell
> me what I'm doing wrong!
> 
> 
> Also, sorry about the HTML email for my original post.
> 
> Best,
> Donovan
> 
> 
> From:  <Meyers>, Donovan Meyers <donovan_mey...@playstation.sony.com>
> Date:  Tuesday, July 22, 2014 3:33 PM
> To:  "haproxy@formilux.org" <haproxy@formilux.org>
> Subject:  Client certs on tcp and securing stats socket
> 
> 
> Hi all,
> 
> First of all, thanks again and always for the great work and an excellent
> product.
> 
> I'm looking for a secure way to communicate with the haproxy stats socket
> for remote management of haproxy (without ssh), preferably without running
> some extra API service or anything.
> 
> I love that 1.5 can now listen on a socket instead of a file. My concern
> is securing it.
> 
> My current best idea is to have the stats socket on 127.0.0.1:7828, and to
> have haproxy handle authentication before forwarding remote connections to
> it. The only authentication I could think of would be client SSL
> certificates.
> 
> Having the socket on 127.0.0.1:7828 works great -- you can connect from
> locally on the box but not from elsewhere. Having a TCP-mode proxy
> listening and forwarding to there works great too, even with SSL. Haproxy
> is proxying connections to its own stats
>  socket!
> 
> Where I'm running into trouble is requiring a client cert -- even with
> "verify required" on my frontend (or listen) bind line, I can connect with
> no client cert.
> 
> My intention is to use an ACL to check for specific information in the
> client cert (using ssl_c_s_dn, ssl_c_serial, and/or ssl_c_sha1). I also
> ran into trouble matching against that information, but then I discovered
> that I wasn't even requiring a client
>  cert.
> 
> I'm using all self-signed certs. Maybe there's an issue with the way I'm
> generating certs that's causing this? Here's how I generated them:
> 
> FILENAME=haproxy-server
> openssl genrsa -out $FILENAME.key 1024
> openssl req -new -key $FILENAME.key -x509 -days 3653 -out $FILENAME.crt
> cat $FILENAME.key $FILENAME.crt >$FILENAME.pem
> 
> FILENAME=haproxy-client
> openssl genrsa -out $FILENAME.key 1024
> openssl req -new -key $FILENAME.key -x509 -days 3653 -out $FILENAME.crt
> cat $FILENAME.key $FILENAME.crt >$FILENAME.pem
> 
> At first I didn't enter any info for the certs (just pressed Enter on each
> line), but then I recreated the client cert with some valid info.
> 
> Here's my config:
> 
> global
>   daemon
>   pidfile  /var/run/haproxy.pid
>   stats socket ipv4@127.0.0.1:7828
>   log 127.0.0.1 local0 debug
> 
> defaults
>   log  global
>   option  redispatch
>   retries  3
>   timeout  http-request 10s
>   timeout  queue 1m
>   timeout  connect 10s
>   timeout  client 1m
>   timeout  server 1m
>   timeout  check 10s
> 
> listen default_stats
>   bind 0.0.0.0:10800
>   mode  http
>   stats  enable
> 
> listen main-service
>   bind 0.0.0.0:80
>   mode  http
> 
> frontend stats-socket
>   bind 10.108.0.166:7828 ssl crt /root/haproxy-ssl/haproxy-server.pem
> verify required ca-file /root/haproxy-ssl/haproxy-client.crt
>   mode tcp
>   log-format %ci:%cp\ [%t]\ %ft\ %b/%s\ %Tw/%Tc/%Tt\ %B\ %ts\
> %ac/%fc/%bc/%sc/%rc\ %sq/%bq\ %{+Q}[ssl_c_s_dn]
>   default_backend local_socket
> 
> backend local_socket
>   server localhost 127.0.0.1:7828
> 
> Here's my haproxy version and deets:
> 
> HA-Proxy version 1.5.2 2014/07/12
> Copyright 2000-2014 Willy Tarreau <w...@1wt.eu>
> 
> Build options :
>   TARGET  = linux2628
>   CPU     = generic
>   CC      = gcc
>   CFLAGS  = -O2 -g -fno-strict-aliasing
>   OPTIONS = USE_ZLIB=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.3
> Compression algorithms supported : identity, deflate, gzip
> Built with OpenSSL version : OpenSSL 1.0.1e-fips 11 Feb 2013
> Running on OpenSSL version : OpenSSL 1.0.1e-fips 11 Feb 2013
> OpenSSL library supports TLS extensions : yes
> OpenSSL library supports SNI : yes
> OpenSSL library supports prefer-server-ciphers : yes
> Built with PCRE version : 7.8 2008-09-05
> 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.
> 
> Here's how I'm connecting with a client cert:
> 
> socat stdio 
> openssl-connect:domeyers-haproxy-socket-test.gha.usw1.cld.scea.com:7828,cer
> t=/root/haproxy-ssl/haproxy-client.pem,cafile=/root/haproxy-ssl/haproxy-ser
> ver.crt
> OR (less often - I tried openssl in case there was a problem with my socat)
> openssl s_client -connect
> domeyers-haproxy-socket-test.gha.usw1.cld.scea.com:7828 -cert
> ./haproxy-client.crt -key ./haproxy-client.key
> 
> And without:
> 
> socat stdio 
> openssl-connect:domeyers-haproxy-socket-test.gha.usw1.cld.scea.com:7828,caf
> ile=/root/haproxy-ssl/haproxy-server.crt
> openssl s_client -connect
> domeyers-haproxy-socket-test.gha.usw1.cld.scea.com:7828
> 
> Here is it allowing my connection, without a client cert, despite the
> config above:
> 
> [root@domeyers-haproxy-socket-test haproxy-ssl]# socat stdio
> openssl-connect:domeyers-haproxy-socket-test.gha.usw1.cld.scea.com:7828,caf
> ile=/root/haproxy-ssl/haproxy-server.crt
> show stat
> # 
> pxname,svname,qcur,qmax,scur,smax,slim,stot,bin,bout,dreq,dresp,ereq,econ,e
> resp,wretr,wredis,status,weight,act,bck,chkfail,chkdown,lastchg,downtime,ql
> imit,pid,iid,sid,throttle,lbtot,tracked,type,rate,rate_lim,rate_max,check_s
> tatus,check_code,check_duration,hrsp_1xx,hrsp_2xx,hrsp_3xx,hrsp_4xx,hrsp_5x
> x,hrsp_other,hanafail,req_rate,req_rate_max,req_tot,cli_abrt,srv_abrt,comp_
> in,comp_out,comp_byp,comp_rsp,lastsess,last_chk,last_agt,qtime,ctime,rtime,
> ttime,
> default_stats,FRONTEND,,,0,0,2000,0,0,0,0,0,0,,,,,OPEN,,,,,,,,,1,2,0,,,,0,0
> ,0,0,,,,0,0,0,0,0,0,,0,0,0,,,0,0,0,0,,,,,,,,
> default_stats,BACKEND,0,0,0,0,200,0,0,0,0,0,,0,0,0,0,UP,0,0,0,,0,6304,0,,1,
> 2,0,,0,,1,0,,0,,,,0,0,0,0,0,0,,,,,0,0,0,0,0,0,-1,,,0,0,0,0,
> main-service,FRONTEND,,,0,0,2000,0,0,0,0,0,0,,,,,OPEN,,,,,,,,,1,3,0,,,,0,0,
> 0,0,,,,0,0,0,0,0,0,,0,0,0,,,0,0,0,0,,,,,,,,
> main-service,BACKEND,0,0,0,0,200,0,0,0,0,0,,0,0,0,0,UP,0,0,0,,0,6304,0,,1,3
> ,0,,0,,1,0,,0,,,,0,0,0,0,0,0,,,,,0,0,0,0,0,0,-1,,,0,0,0,0,
> stats-socket,FRONTEND,,,1,1,2000,10,91,12588,0,0,0,,,,,OPEN,,,,,,,,,1,4,0,,
> ,,0,0,0,1,,,,,,,,,,,0,0,0,,,0,0,0,0,,,,,,,,
> local_socket,localhost,0,0,1,1,,10,91,12588,,0,,0,0,0,0,no
> check,1,1,0,,,,,,1,5,1,,10,,2,0,,1,,,,,,,,,,0,,,,0,0,,,,,3,,,1,1,0,59,
> local_socket,BACKEND,0,0,1,1,200,10,91,12588,0,0,,0,0,0,0,UP,1,1,0,,0,6304,
> 0,,1,5,0,,10,,1,0,,1,,,,,,,,,,,,,,0,0,0,0,0,0,3,,,1,1,0,59,
> 
> Log line:
> 2014-07-22T15:03:10-07:00 localhost haproxy[21598]: 10.108.0.166:60116
> [22/Jul/2014:15:03:06.419] stats-socket~ local_socket/localhost 5/1/3890
> 1352 -- 0/0/0/0/0 0/0 ""
> 
> I've never seen anything logged as ssl_c_s_dn (the last field) -- it's
> always empty. At first I thought I wasn't using the client cert the right
> way for haproxy to receive it, because I was having trouble matching ACLs
> against it. But then I found that
>  I didn't even need a client cert to connect, so now I'm troubleshooting
> that.
> 
> Any help would be appreciated, including alternate options for securing
> this traffic.
> 
> For the record, here are some of the config lines I was trying to use to
> validate fields in the client cert:
> 
>   tcp-request inspect-delay 30s
>   acl client_cert_cn_ok ssl_c_s_dn(CN) -m str my.host.name.com
>   tcp-request content accept if client_cert_cn_ok
>   tcp-request content reject
> 
> 
> Thanks!
> Donovan
> 
> 

-- 
Conrad Hoffmann
Traffic Engineer

SoundCloud Ltd. | Rheinsberger Str. 76/77, 10115 Berlin, Germany

Managing Director: Alexander Ljung | Incorporated in England & Wales
with Company No. 6343600 | Local Branch Office | AG Charlottenburg |
HRB 110657B

Reply via email to