I’m kind of at wit’s end attempting to figure out what I’m doing wrong, but damned if I can figure it out.
First, my config file:
global
log /dev/log local0
log /dev/log local1 notice
chroot /var/lib/haproxy
stats socket /run/haproxy/admin.sock mode 660 level admin
stats timeout 30s
user haproxy
group haproxy
daemon
ca-base /etc/ssl/certs
crt-base /etc/haproxy/ssl
ssl-default-bind-ciphers ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256
ssl-default-bind-options no-sslv3 no-tlsv10 no-tlsv11
ssl-dh-param-file /etc/haproxy/ssl/dhparam.pem
defaults
log global
mode tcp
option tcpka
option dontlognull
option http-server-close
timeout connect 5000
timeout client 50000
timeout server 50000
errorfile 400 /etc/haproxy/errors/400.http
errorfile 403 /etc/haproxy/errors/403.http
errorfile 408 /etc/haproxy/errors/408.http
errorfile 500 /etc/haproxy/errors/500.http
errorfile 502 /etc/haproxy/errors/502.http
errorfile 503 /etc/haproxy/errors/503.http
errorfile 504 /etc/haproxy/errors/504.http
frontend redirect
mode http
bind :::80 v4v6
acl letsencryptrequest path_beg -i /.well-known/acme-challenge/
acl http ssl_fc,not
http-request redirect scheme https if http
use_backend letsencrypt if letsencryptrequest
default_backend dummy
frontend liquidfront
mode tcp
bind :::443 v4v6 ssl crt (redacted long list of certificates and hosts) ecdhe secp384r1 alpn h2,http/1.1
default_backend tovarnish
backend tovarnish
mode tcp
server local 127.0.0.1:6081 send-proxy-v2
backend letsencrypt
mode http
server letsencrypt 127.0.0.1:54321
backend dummy
mode http
server local 127.0.0.1:9999
Stack:
HAProxy 1.7.5 <-> Varnish 5.1 <-> Nginx 1.13.0
The reason there are multiple front-ends is for HTTP/2 support. The way I understood the documentation between HAPropxy and Varnish, I need to use TCP mode on my Varnish backend stanza in order to use the proxy protocol; Varnish then can extract the protocol and route to the appropriate nginx listening port.
I have to separate the frontends until HAProxy support http/2 in HTTP mode—at least, that’s how I understand it.
Problem behavior:
I use LetsEncrypt, and I use HAProxy to watch for incoming ACME challenges by using the same method that’s all over the web: matching to an ACL based on path_beg -i /.well-known/acme-challenge/
, and then kicking all matching traffic to a LetsEncrypt backend that points to 127.0.0.1:54321, where the local certbot is listening.
However, the ACL doesn’t appear to be matching anymore. Instead of the requests going to the LE backend, they go to the tovarnish
backend, which is where everything except LE traffic should be going. I can watch the varnishncsa
logs and see the LE requests hitting Varnish:
66.133.109.36 - - [10/Jun/2017:20:09:17 -0400] GET http://myhost.redacted.com/.well-known/acme-challenge/7euurczH9HL4Q6_DV_Yn1eG7LSFpqYsvXQm8vvcv3UY HTTP/1.1 403 162 http://myhost.redacted.com/.well-known/acme-challenge/7euurczH9HL4Q6_DV_Yn1eG7LSFpqYsvXQm8vvcv3UY Mozilla/5.0 (compatible; Let's Encrypt validation server; +https://www.letsencrypt.org)
66.133.109.36 - - [10/Jun/2017:20:12:18 -0400] GET http://myhost.redacted.com/.well-known/acme-challenge/MJI1xHqUO8VpgNKLzhfJddYw1iz2IVuZUAXAGBiWLBs HTTP/1.1 403 162 http://myhost.redacted.com/.well-known/acme-challenge/MJI1xHqUO8VpgNKLzhfJddYw1iz2IVuZUAXAGBiWLBs Mozilla/5.0 (compatible; Let's Encrypt validation server; +https://www.letsencrypt.org)
66.133.109.36 - - [10/Jun/2017:20:12:43 -0400] GET http://myhost.redacted.com/.well-known/acme-challenge/vpatZfBKKygczculNMVksQEeko1T8wuYaDdJk9riEL4 HTTP/1.1 403 162 http://myhost.redacted.com/.well-known/acme-challenge/vpatZfBKKygczculNMVksQEeko1T8wuYaDdJk9riEL4 Mozilla/5.0 (compatible; Let's Encrypt validation server; +https://www.letsencrypt.org)
66.133.109.36 - - [10/Jun/2017:20:15:21 -0400] GET http://myhost.redacted.com/.well-known/acme-challenge/VJI1Y-OyKoe9KmJOOlZ3_RxvLfDDlHv7Xzqz0Xy7hO4 HTTP/1.1 403 162 http://myhost.redacted.com/.well-known/acme-challenge/VJI1Y-OyKoe9KmJOOlZ3_RxvLfDDlHv7Xzqz0Xy7hO4 Mozilla/5.0 (compatible; Let's Encrypt validation server; +https://www.letsencrypt.org)
66.133.109.36 - - [10/Jun/2017:20:16:38 -0400] GET http://myhost.redacted.com/.well-known/acme-challenge/HT4lhg0ixP981CTTPP95A6wPD2ddbj0jAEPMuoksmCQ HTTP/1.1 403 162 http://myhost.redacted.com/.well-known/acme-challenge/HT4lhg0ixP981CTTPP95A6wPD2ddbj0jAEPMuoksmCQ Mozilla/5.0 (compatible; Let's Encrypt validation server; +https://www.letsencrypt.org)
66.133.109.36 - - [10/Jun/2017:20:17:58 -0400] GET http://myhost.redacted.com/.well-known/acme-challenge/l5UAdVGTwLJalvi7U9uSi4B-riJP4bEg33mhEt34Zhk HTTP/1.1 403 162 http://myhost.redacted.com/.well-known/acme-challenge/l5UAdVGTwLJalvi7U9uSi4B-riJP4bEg33mhEt34Zhk Mozilla/5.0 (compatible; Let's Encrypt validation server; +https://www.letsencrypt.org)
66.133.109.36 - - [10/Jun/2017:20:21:04 -0400] GET http://myhost.redacted.com/.well-known/acme-challenge/yxB_gxKWooknSgjCCkTJNk0ac1SMHqGUQiu3lSQY5bY HTTP/1.1 403 162 http://myhost.redacted.com/.well-known/acme-challenge/yxB_gxKWooknSgjCCkTJNk0ac1SMHqGUQiu3lSQY5bY Mozilla/5.0 (compatible; Let's Encrypt validation server; +https://www.letsencrypt.org)
(hostname redacted, obviously)
I don’t know exactly when the problem behavior started, and I’ve been going over HAProxy’s docs for a few hours now without figuring out my problem. I’ve tried using hdr_beg(host)
and matching hostname, so that the ACL looks like this instead:
acl letsencryptrequest hdr_beg(host) -i myhost.redacted.com
…and it still doesn’t match, even when definitely using the correct hostname.
I’m completely baffled. What on earth am I doing wrong? Any help would be greatly appreciated.