Setup vagrant vm
vagrant box add precise64 http://files.vagrantup.com/precise64.box
vagrant init precise64
sed -i 's/# config.vm.network :hostonly/config.vm.network :hostonly/' Vagrantfile
vagrant up
vagrant ssh
Install base software and apache (to have something to proxy)
sudo apt-get update
sudo apt-get install -y curl build-essential libpcre3-dev libssl-dev apache2
Install haproxy
export HAPROXY_VERSION=haproxy-1.5-dev18
curl -O http://haproxy.1wt.eu/download/1.5/src/devel/$HAPROXY_VERSION.tar.gz
tar zxf $HAPROXY_VERSION.tar.gz
cd $HAPROXY_VERSION
make PREFIX=/usr/local \
IGNOREGIT=true \
MANDIR=/usr/local/share/man \
DOCDIR=/usr/local/share/doc/haproxy \
TARGET=linux2628 \
CPU=native \
USE_PCRE=1 \
USE_STATIC_PCRE=1 \
USE_OPENSSL=1 \
USE_ZLIB=1
sudo make install
Setup Ubuntu's official haproxy init.d script for 12.04
curl -O http://bazaar.launchpad.net/~ubuntu-branches/ubuntu/precise/haproxy/precise/download/head:/haproxy.init-20090727115323-3c2mw7iu0du8tdiw-208/haproxy.init
sed -i 's/PATH=/PATH=\/usr\/local\/sbin:/' haproxy.init
sed -i 's/HAPROXY=\/usr\/sbin\/haproxy/HAPROXY=\/usr\/local\/sbin\/haproxy/' haproxy.init
sudo mv haproxy.init /etc/init.d/haproxy
sudo chmod +x /etc/init.d/haproxy
Setup chroot and haproxy configuration
sudo addgroup --system haproxy
sudo adduser --system --no-create-home --ingroup haproxy haproxy
sudo mkdir /opt/haproxy
sudo chown haproxy:haproxy /opt/haproxy/
sudo chmod a-w /opt/haproxy/
sudo mkdir /etc/haproxy
echo "ENABLED=1" | sudo tee /etc/default/haproxy
echo 'global
daemon
maxconn 256
user haproxy
group haproxy
chroot /opt/haproxy
defaults
timeout connect 5000ms
timeout client 50000ms
timeout server 50000ms
option http-server-close
frontend http-in
mode http
bind *:443 ssl crt /etc/haproxy/server.pem ca-file /etc/haproxy/ca.crt verify required
default_backend servers
reqadd X-Forwarded-Proto:\ https if { ssl_fc }
option forwardfor
backend servers
mode http
server server1 localhost:80 maxconn 32' | sudo tee /etc/haproxy/haproxy.cfg
CA, server and client certificate setup. This is a slightly tweaked form of https://github.com/exceliance/haproxy/blob/master/blog/ssl_client_certificate_management_at_application_level/ca.sh
for only the valid client certificate, which also makes use of the -subj
commandline option to avoid re-typing those values.
export SUBJECT='/C=US/ST=California/L=San Francisco/[email protected]'
# certificate authority creation
openssl genrsa -out ca.key 4096
openssl req -new -x509 -days 365 -key ca.key -out ca.crt -subj "$SUBJECT"
# server certificate creation
openssl genrsa -out server.key 1024
openssl req -new -key server.key -out server.csr -subj "$SUBJECT"
openssl x509 -req -days 365 -in server.csr -CA ca.crt -CAkey ca.key -set_serial 01 -out server.crt
# client certificate creation
openssl genrsa -out client.key 1024
openssl req -new -key client.key -out client.csr -subj "$SUBJECT"
openssl x509 -req -days 365 -in client.csr -CA ca.crt -CAkey ca.key -set_serial 02 -out client.crt
cat server.crt server.key > server.pem
sudo cp server.pem /etc/haproxy/server.pem
sudo cp ca.crt /etc/haproxy/ca.crt
Start haproxy and test it:
sudo /etc/init.d/haproxy start
openssl s_client -connect localhost:443 -cert client.crt -key client.key
This gives me:
CONNECTED(00000003)
depth=0 C = US, ST = California, L = San Francisco, CN = [email protected]
verify error:num=18:self signed certificate
verify return:1
depth=0 C = US, ST = California, L = San Francisco, CN = [email protected]
verify return:1
139701807867552:error:14094418:SSL routines:SSL3_READ_BYTES:tlsv1 alert unknown ca:s3_pkt.c:1256:SSL alert number 48
139701807867552:error:140790E5:SSL routines:SSL23_WRITE:ssl handshake failure:s23_lib.c:177:
---
Certificate chain
0 s:/C=US/ST=California/L=San Francisco/[email protected]
i:/C=US/ST=California/L=San Francisco/[email protected]
---
Server certificate
-----BEGIN CERTIFICATE-----
MIIDmjCCAYICAQEwDQYJKoZIhvcNAQEFBQAwVTELMAkGA1UEBhMCVVMxEzARBgNV
BAgMCkNhbGlmb3JuaWExFjAUBgNVBAcMDVNhbiBGcmFuY2lzY28xGTAXBgNVBAMM
EHRlc3RAZXhhbXBsZS5jb20wHhcNMTMwNDA4MTgyMTQ1WhcNMTQwNDA4MTgyMTQ1
WjBVMQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwN
U2FuIEZyYW5jaXNjbzEZMBcGA1UEAwwQdGVzdEBleGFtcGxlLmNvbTCBnzANBgkq
hkiG9w0BAQEFAAOBjQAwgYkCgYEA672DeWWtseWeQnRa32Zhh9untI6F/gxRTvkv
vNZZgZqP1fgi/2+t6lmmZV5yM31A2wq54Qf00z+5uWwbOoxCeoyLiXQ7PDtWYdhP
zW+jyLWRzY4ndpI+dlA2HfLD9lbcoTMrcPJTab0TvhWSEaXSMCQWNIvhYPBsZ/HT
yy5WQNUCAwEAATANBgkqhkiG9w0BAQUFAAOCAgEA8EWe7WgcBthvFI+9d15jkCX+
SuVn0rSTzKNcU3IAyktm8vVaamhfWqdeV/21ocwUMdQcGSPYJ2DEN8X5YaiCLGup
IT/3CHg1fmDLYrB732vZ0u1Vqz4O0rS3JpPRTQOryjvgDAHyR9V0oe0dP65oDtSA
TqAuaJC79YTB36XEWWgxZIfQCvKqpLYgP9cnlhdy8UOWW7e8a2mic9tw8JYro57/
d3q4l/WoOZ5UkYo4o3y7GviGUldW834nue0Tsdrb8csl0bqR+vqpCU2f6joh1VlF
pMOyrmWm6M4LeqFPTAY6U/S7LjUnYcC/AYvOUyIntNpf8kLRFsmbQapqG5q7jDjW
oWIqdhAzQIG1wS8TevQVHtg8MXKJcNPhcR4lT/xEqtcdiY6F3IFg95STnb41aQXm
7Trnw9j1gTa6cfuQcuTNh4Y9GPQdYhMeJiUUhpZOxOZx86VE5cfSxbY7awYZ+EO2
4NYUajdvyAvwV5WGfTbyJ3+qU5eoOfMKvntHhSYHeHU4jiQ/6q3p1u27b1LoQnr9
k8+CF04AK+V/qhGkeMjg7zcwA6zLdChGpP0sizV3kwcTk4SjNrfepLHgXoOvMQsK
uX00ZsEgZ7EMJqI1NX+Ma4WHUcNMA7eHsb+TuRYudsG2YGLLCsrwNK4Mni1swqKU
vneURb2jEpRn8t6kTv4=
-----END CERTIFICATE-----
subject=/C=US/ST=California/L=San Francisco/[email protected]
issuer=/C=US/ST=California/L=San Francisco/[email protected]
---
Acceptable client certificate CA names
/C=US/ST=California/L=San Francisco/[email protected]
---
SSL handshake has read 1335 bytes and written 1230 bytes
---
New, TLSv1/SSLv3, Cipher is ECDHE-RSA-AES256-SHA
Server public key is 1024 bit
Secure Renegotiation IS supported
Compression: NONE
Expansion: NONE
SSL-Session:
Protocol : TLSv1.1
Cipher : ECDHE-RSA-AES256-SHA
Session-ID:
Session-ID-ctx:
Master-Key: 14DAE59074B21C9AEB0ADB6B77D0833D8BF5FD9B03FF5E5F92EB697483313BFAAB0E028A56925ECBE4FF3AFE001201FA
Key-Arg : None
PSK identity: None
PSK identity hint: None
SRP username: None
Start Time: 1365446671
Timeout : 300 (sec)
Verify return code: 18 (self signed certificate)
---
Note the two error lines:
139701807867552:error:14094418:SSL routines:SSL3_READ_BYTES:tlsv1 alert unknown ca:s3_pkt.c:1256:SSL alert number 48
139701807867552:error:140790E5:SSL routines:SSL23_WRITE:ssl handshake failure:s23_lib.c:177:
This
curl -vk --key client.key --cert client.crt https://localhost
gives me a similar error:
* About to connect() to localhost port 443 (#0)
* Trying 127.0.0.1... connected
* successfully set certificate verify locations:
* CAfile: none
CApath: /etc/ssl/certs
* SSLv3, TLS handshake, Client hello (1):
* SSLv3, TLS alert, Client hello (1):
* SSLv3, TLS handshake, Server hello (2):
* SSLv3, TLS handshake, CERT (11):
* SSLv3, TLS handshake, Server key exchange (12):
* SSLv3, TLS handshake, Request CERT (13):
* SSLv3, TLS handshake, Server finished (14):
* SSLv3, TLS handshake, CERT (11):
* SSLv3, TLS handshake, Client key exchange (16):
* SSLv3, TLS handshake, CERT verify (15):
* SSLv3, TLS change cipher, Client hello (1):
* SSLv3, TLS handshake, Finished (20):
* SSLv3, TLS alert, Server hello (2):
* error:14094418:SSL routines:SSL3_READ_BYTES:tlsv1 alert unknown ca
* Closing connection #0
curl: (35) error:14094418:SSL routines:SSL3_READ_BYTES:tlsv1 alert unknown ca
Browsers generally want a
.p12
file, so we should generate one as well: