使用HAProxy仅在端口443上为某些流量提供证书

时间:2019-07-28 06:38:15

标签: ssl haproxy

我已经购买了通配符证书(例如* .example.com)。

我想使用HAProxy服务,这没问题。但是,我不知道如何告诉HAProxy不为* .example.com作为主机的任何内容提供证书。

这些是由我希望将流量重定向到的另一项服务(使用“让我们加密”)提供的。

1 个答案:

答案 0 :(得分:1)

问题

我遇到的问题是我想让HAProxy处理某个域及其任何子域的SSL / TLS握手(我购买了通配符证书)。

任何与该域都不匹配的东西,我想使用Greenlock通过Let's Encrypt为它们生成SSL证书,并且我还需要Greenlock来处理SSL / TLS握手。

解决方案

在HAProxy中,我们绑定到端口80和443,以侦听这两个端口上的流量。

在端口80上,我们:

  • 如果请求不是SSL且请求路径不是以/.well-known/acme开头,则重定向到HTTPS协议
  • 如果请求标头中的主机与我们的通配符域不匹配,请使用greenlock后端
frontend http-in
    acl acme_challenge path_beg /.well-known/acme
        acl is_wildcard_domain hdr_end(Host) example.com
        bind *:80

        redirect scheme https if !{ ssl_fc } !acme_challenge
        use_backend greenlock_http if !is_wildcard_domain acme_challenge

对于端口443,我们:

  • 首先使用tcp模式,因为此时我们不想处理SSL握手
  • 设置日志记录,因此我们可以看到req.ssl_sni,其中通常包含 客户端尝试连接的主机的名称(即您的域)
  • 如果主机名与通配符域不匹配,请使用greenlock_https后端
  • 或使用https-backend后端作为后备(即,如果主机匹配通配符域,则使用此后端)
frontend https-in
        bind *:443
        mode tcp

        tcp-request inspect-delay 5s
        tcp-request content capture req.ssl_sni len 40
        log-format "%ci:%cp [%t] %ft %b/%s %Tw/%Tc/%Tt %B %ts %ac/%fc/%bc/%sc/%rc %sq/%bq ssl_sni: %[capture.req.hdr(0)]"

        tcp-request content accept if { req_ssl_hello_type 1 }
        acl is_wildcard_domain req.ssl_sni -m end "${WILDCARD_DOMAIN}"

        use_backend greenlock_https if !is_wildcard_domain
        default_backend https-back

有趣的地方是https-back后端:

  • 它只是将请求转发到此地址unix@/var/run/haproxy.sock
backend https-back
    mode tcp
    server https-front unix@/var/run/haproxy.sock send-proxy-v2

谁在监听那个地址?这是提供通配符证书的前端:

frontend https-front
    bind   unix@/var/run/haproxy.sock ssl crt /etc/haproxy/paid_certs/exapmle.com.crt accept-proxy
    mode   http
    option forwardfor
    reqdel X-Forwarded-Proto
    reqadd X-Forwarded-Proto:\ https if { ssl_fc }

    default_backend elb

出于完整性考虑,以下是所有前端和后端:

frontend http-in
frontend http-in
        acl acme_challenge path_beg /.well-known/acme
        acl is_wildcard_domain hdr_end(Host) example.com
        bind *:80

        redirect scheme https if !{ ssl_fc } !acme_challenge
        use_backend greenlock_http if !is_wildcard_domain acme_challenge

frontend https-in
        bind *:443
        mode tcp

        tcp-request inspect-delay 5s
        tcp-request content capture req.ssl_sni len 40
        log-format "%ci:%cp [%t] %ft %b/%s %Tw/%Tc/%Tt %B %ts %ac/%fc/%bc/%sc/%rc %sq/%bq ssl_sni: %[capture.req.hdr(0)]"

        tcp-request content accept if { req_ssl_hello_type 1 }
        acl is_wildcard_domain req.ssl_sni -m end example.com

        use_backend greenlock_https if !is_wildcard_domain
        default_backend https-back

backend greenlock_http
        server greenlock greenlock:80 
        cookie webserver insert indirect nocache

backend greenlock_https
        mode tcp
        server greenlock greenlock:443

backend https-back
        mode tcp
        server https-front unix@/var/run/haproxy.sock send-proxy-v2

frontend https-front
        bind   unix@/var/run/haproxy.sock ssl crt /etc/haproxy/certs/example.com accept-proxy
        mode   http
        option forwardfor
        reqdel X-Forwarded-Proto
        reqadd X-Forwarded-Proto:\ https if { ssl_fc }

        default_backend elb

backend elb
        mode http
        server elb ${ELB_HOST}
        balance roundrobin     #balance type
        option forwardfor
        cookie webserver insert indirect nocache