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 <[email protected]>
Date:  Tuesday, July 22, 2014 3:33 PM
To:  "[email protected]" <[email protected]>
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 [email protected]: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 <[email protected]>

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


Reply via email to