使用 HAProxy 设置 HTTPs 正向代理

Posted

技术标签:

【中文标题】使用 HAProxy 设置 HTTPs 正向代理【英文标题】:Setup HTTPs Forward Proxy with HAProxy 【发布时间】:2018-09-01 04:07:15 【问题描述】:

在 HAProxy 中,我使用 option http-proxy 使其像转发代理一样工作。这似乎工作正常,但对于 HTTPS 流量来说这是不可能的。

那么,HAProxy 配置中是否有任何选项可以像 Squid 一样代理 HTTPS 流量?

我认为问题在于 option https_proxy 不可用。

此配置非常适用于 HTTP 协议:

frontend http_proxy
   bind :3128
   option http_proxy
   default_backend proxy_server

backend proxy_server
   option http_proxy

注意 - 我已经使用了带有“ssl crt”的证书以及绑定选项,但它似乎没有通过 HTTPS 协议代理

【问题讨论】:

【参考方案1】:

这是我的 Haproxy 文件配置,它适用于 HTTP 和 HTTPS 协议。

代码如下:

#-----------------------------------------------------------------------------
# global
#-----------------------------------------------------------------------------

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

    # Default SSL material locations
    ca-base /etc/ssl/certs
    crt-base /etc/ssl/private

    # Default ciphers to use on SSL-enabled listening sockets.
    # For more information, see ciphers(1SSL). This list is from:
    #  https://hynek.me/articles/hardening-your-web-servers-ssl-ciphers/
    # An alternative list with additional directives can be obtained from
    #  https://mozilla.github.io/server-side-tls/ssl-config-generator/?server=haproxy
    ssl-default-bind-ciphers ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:RSA+AESGCM:RSA+AES:!aNULL:!MD5:!DSS
    ssl-default-bind-options no-sslv3

    # Tuning if required/needed
    # tune.ssl.default-dh-param 2048

#-----------------------------------------------------------------------------
# defaults
#-----------------------------------------------------------------------------

defaults
    log global
    mode    http
    option  httplog
    option  dontlognull
    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

#-----------------------------------------------------------------------------
# http frontend
#-----------------------------------------------------------------------------

frontend http-in
    bind *:80
    # Domain redirect, force the 'www' prefix
    redirect prefix https://www.domain1.net code 301 if  hdr_beg(host) -i domain1.net 
    redirect prefix https://www.domain2.net code 301 if  hdr_beg(host) -i domain2.net 
    # Define hosts
    acl is-domain1-site hdr(host) -i www.domain1.net
    acl is-domain1-blog hdr(host) -i blog.domain1.net
    acl is-domain1-wiki hdr(host) -i wiki.domain1.net
    acl is-domain2-site hdr(host) -i www.domain2.net
    acl is-domain2-blog hdr(host) -i blog.domain2.net
    acl is-domain2-wiki hdr(host) -i wiki.domain2.net
    # Force https for domain1
    redirect scheme https if is-domain1-site ! ssl_fc 
    redirect scheme https if is-domain1-blog ! ssl_fc 
    redirect scheme https if is-domain1-wiki ! ssl_fc 
    # Force https for domain2
    redirect scheme https if is-domain2-site ! ssl_fc 
    redirect scheme https if is-domain2-blog ! ssl_fc 
    redirect scheme https if is-domain2-wiki ! ssl_fc 
    # Default backend (parking)
    default_backend bk-ct100

#-----------------------------------------------------------------------------
# https frontend
#-----------------------------------------------------------------------------

frontend https-in
    bind *:443 ssl crt /etc/ssl/private/
    # Domain redirect force www
    redirect prefix https://www.domain1.net code 301 if  hdr_beg(host) -i domain1.net 
    redirect prefix https://www.domain2.net code 301 if  hdr_beg(host) -i domain2.net 
    # Define hosts for domain1
    acl is-domain1-site hdr(host) -i www.domain1.net
    acl is-domain1-blog hdr(host) -i blog.domain1.net
    acl is-domain1-wiki hdr(host) -i wiki.domain1.net
    # Define hosts for domain2
    acl is-domain2-site hdr(host) -i www.domain2.net
    acl is-domain2-blog hdr(host) -i blog.domain2.net
    acl is-domain2-wiki hdr(host) -i wiki.domain2.net
    # Figure out which backend to use for domain1
    use_backend bk-ct101 if is-domain1-site
    use_backend bk-ct101 if is-domain1-blog
    use_backend bk-ct101 if is-domain1-wiki
    # Figure out which backend to use for domain2
    use_backend bk-ct102 if is-domain2-site
    use_backend bk-ct102 if is-domain2-blog
    use_backend bk-ct102 if is-domain2-wiki
    # Default backend (parking)
    default_backend bk-ct100

#-----------------------------------------------------------------------------
# ct100 backend - parking
#-----------------------------------------------------------------------------

backend bk-ct100
    mode   http
    option forwardfor
    server ct100 192.168.100.100:80 check

#-----------------------------------------------------------------------------
# ct101 backend - domain1
#-----------------------------------------------------------------------------

backend bk-ct101
    mode   http
    option forwardfor
    server ct101 192.168.100.101:80 check

#-----------------------------------------------------------------------------
# ct102 backend - domain2
#-----------------------------------------------------------------------------

backend bk-ct102
    mode   http
    option forwardfor
    server ct102 192.168.100.102:80 check

#-----------------------------------------------------------------------------
# End-Of-File
#-----------------------------------------------------------------------------

在此配置中,我选择将所有流量从 HTTP 重定向到 HTTPS。我所有的证书都存储在 /etc/ssl/private 目录中。我使用 CertBot 生成它们。

您可以根据需要调整此文件,但它应该可以工作:)

【讨论】:

感谢您的帮助,不胜感激。此配置(重定向)对我不起作用。因为,我想要实现的是使用 haproxy 设置转发代理。正如这里所解释的:***.com/a/366212/2770176 我确实设法仅使用 http 协议完成了转发代理部分。从文档中,不清楚是否也支持 https 协议。使用 curl 我测试了 http 和 https 代理 curl -x <HAProxy-IP>:3128 http://<remote-server>:80/home/page1/ -vvvcurl -x <HAProxy-IP>:443 https://<remote-server>:80/home/page1/ -vvv 我相信最好不要将 HAProxy 与 option http_proxy 一起使用,因为我发现 HAProxy 返回 503 Service Unavailable No server is available to handle this request. 时会出现一些奇怪的行为(有时会这样做,并不总是)

以上是关于使用 HAProxy 设置 HTTPs 正向代理的主要内容,如果未能解决你的问题,请参考以下文章

nginx实现正向代理和反向代理

正反向代理

Nginx 能正向代理 https get 请求吗

nginx实战 正向代理支持https

反向代理之HAProxy的简单应用

nginx正反向代理配置详解