AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / server / 问题 / 662662
Accepted
mohrphium
mohrphium
Asked: 2015-01-28 03:51:25 +0800 CST2015-01-28 03:51:25 +0800 CST 2015-01-28 03:51:25 +0800 CST

具有 SNI 和不同 SSL 设置的 HAProxy

  • 772

我的两个站点都有 HAProxy,其中一个是公共的,一个是私有的。

www.mysite.com private.mysite.com

Atm,我正在使用这样的 haproxy:

frontend mysite_https
  bind *.443 ssl crt /etc/mycert.pem ca-file /etc/myca.pem verify optional no-sslv3
  mode http
  acl domain_www     hdr_beg(host) -i www.
  acl domain_private hdr_beg(host) -i private.
  acl path_ghost     path_beg         /ghost/
  acl clientcert     ssl_c_used

  redirect location https://www.example.com if path_ghost !clientcert
  redirect location https://www.example.com if !domain_www !clientcert

  use_backend bknd_private if domain_private
  use_backend bknd_www     if domain_www

  default_backend bknd_www

这应该做的是要求客户证书(可选)并继续。如果域不是 www.example.com 且访问者无法提供正确的证书或路径为 /ghost/ 且访问者无法提供正确的证书,则应重定向到https://www.example.com

到目前为止,这工作正常。但是,Mac 用户使用 Safari 浏览我的网站时抱怨说,他们在浏览https://www.example.com/时不断被要求提供证书,而例如 Firefox 仅在浏览https://private.example时询问.com/或https://www.example.com/ghost/。

显然这就是 Safari 的工作方式,所以我无法解决这个问题。我的想法是使用 SNI 来划分不同的前端

frontend mysite_https
  bind *.443 ssl crt /etc/mycert.pem no-sslv3

frontend private_https
  bind *.443 ssl crt /etc/mycert.pem ca-file /etc/myca.pem verify optional no-sslv3

当然这不起作用,因为

一个。我不能让两个前端监听端口 443,而只有一个公共 IP b。我还没有找到一种方法来说“use_frontend if domain_www”或类似的东西。(仅 use_backend 或 use-server)

我也试过用三个 haproxy 服务器来做

frontend haproxy-sni
bind *:443 ssl crt /etc/mycert.pem no-sslv3
mode tcp

tcp-request inspect-delay 5s
tcp-request content accept if { req.ssl_hello_type 1 }

acl domain_www ssl_fc_sni_end -i www.example.com

use-server server1 haproxy-private.lan  if !domain_www
use-server server2 haproxy-public.lan   if domain_www

这行得通,但是这里的问题是 haproxy-private 请求客户端证书,但请求没有到达浏览器。不知何故,haproxy-sni 放弃了请求。

此外,我现在有三个不可取的 haproxy 服务器(尽管如果我找不到更好的解决方案,这是一个可能的选择)。

最好我想要这样的东西(编造..不知道真正的选择)

frontend mysite_https
  bind *.443 ssl crt /etc/mycert.pem no-sslv3
  mode http

  acl domain_www     hdr_beg(host) -i www.
  acl domain_private hdr_beg(host) -i private.
  acl path_ghost     path_beg         /ghost/

  ssl_options ca-file /etc/myca.pem verify optional if !www_domain          # made up!
  ssl_options ca-file /etc/myca.pem verify optional if !path_ghost          # made up!

  acl clientcert     ssl_c_used

  redirect location https://www.example.com if path_ghost !clientcert
  redirect location https://www.example.com if !domain_www !clientcert
  ...

我希望有人可以帮助我解决这个问题...

ssl
  • 2 2 个回答
  • 21069 Views

2 个回答

  • Voted
  1. Best Answer
    mohrphium
    2015-02-01T02:29:31+08:002015-02-01T02:29:31+08:00

    我找到了解决这个问题的方法,不需要额外的服务器或服务。我不完全确定这是否不会产生新问题。对我来说,它现在似乎有效。

    我这样做的方式是为需要不同 ssl 设置的每个域创建一个前端。然后我将这些前端的绑定选项设置为高端口(公共无法访问这些端口!)。

    我创建了另一个在端口:443 上侦听的前端,以根据 SNI 划分流量,并将后端服务器设置为 127.0.0.1:high-port。

    这样,我在 haproxy 中创建了一个循环

    [incoming]->[haproxy:443]->[haproxy:7000]->[www.intern.lan]
    [incoming]->[haproxy:443]->[haproxy:8000]->[private.intern.lan]
    

    这是配置部分。

    frontend frnd_snipt                                             # Frontend_SNI-PassThrough (snipt)
      bind *:443                                                    # Do not use bind *:8443 ssl crt etc....!
      option tcplog
      mode tcp 
    
      tcp-request inspect-delay 5s
      tcp-request content accept if { req_ssl_hello_type 1 } 
    
      acl subdomain_is_www   req_ssl_sni -i www.example.com
      acl subdomain_is_www   req_ssl_sni -i example.com
      acl subdomain_is_private req_ssl_sni -i private.example.com
    
      use_backend bknd_snipt_private if subdomain_is_private
      use_backend bknd_snipt_www  if subdomain_is_www
    
    backend bknd_snipt_www
      mode tcp                                              # tcp mode must match the frontend mode - already set as default in [global]
      server snipt-www 127.0.0.1:7000                       # run without "check", otherwise haproxy checks itself all the time!
    
    backend bknd_snipt_private
      mode tcp     
      server snipt-private 127.0.0.1:8000                   # also, don't add "ssl" when in tcp mode. "ssl" is an http mode option (result in "NO-SRV" when set in tcp)
    
    ##### NORMAL HAPROXY PART #####
    frontend www_example_com                                # this frontend can be in tcp or http mode...
      bind *:7000 ssl crt /etc/mycert.pem no-sslv3          # www. frontend with normal https
      mode http
      option httplog
    
    
    frontend private_example_com
      bind *:8000 ssl crt /etc/mycert.pem ca-file /etc/myca.pem verify optional no-sslv3        # private. frontend with client certificate request.
      mode http
      option httplog
      ... # whatever you have in your frontend
    

    如果有人对此有想法,或者知道为什么这可能是个坏主意,请告诉我。它有效,但我想知道为什么 use_frontend 不是一个选项。也许是因为无论出于何种原因,这是不应该做的事情。

    • 13
  2. freaker
    2019-05-05T04:59:24+08:002019-05-05T04:59:24+08:00

    最新版本的 haproxy 支持一个名为的设置crt-list,允许您根据匹配的证书指定不同的 TLS 设置

    你可以像这样使用它:

    haproxy.conf:

    frontend https
        mode http
        bind *:443 ssl crt-list /etc/haproxy/crt-list.conf ca-file ca.pem
    
        use_backend test if { ssl_fc_sni -i test.area.example.org }
        use_backend private if { ssl_fc_sni -i private.example.org }
        default_backend www
    

    crt-list.conf:

    www.pem [verify none]
    www.pem [verify required] *.area.example.org
    private.pem [verify required]
    

    更多信息:https ://cbonte.github.io/haproxy-dconv/1.9/configuration.html#5.1-crt-list

    关于安全性的注意事项:始终将您的(敏感)主机名与 SNI 匹配ssl_fc_sni,而不是 HTTP 主机名。否则,攻击者可能会通过发送 TLS SNI 来绕过您的客户端证书身份验证,www.example.org但将 HTTP 主机名设置为private.example.org!

    • 4

相关问题

  • 如何使用 Tomcat 5.5 更新 SSL 证书

  • 为 IIS6 自行生成 SSL 证书?

  • plesk 上的域和子域 ssl 访问

  • 如何设置 SSL 邮件服务器?

  • 如何通过 SVN 命令行接受 SSL 证书?

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    新安装后 postgres 的默认超级用户用户名/密码是什么?

    • 5 个回答
  • Marko Smith

    SFTP 使用什么端口?

    • 6 个回答
  • Marko Smith

    命令行列出 Windows Active Directory 组中的用户?

    • 9 个回答
  • Marko Smith

    什么是 Pem 文件,它与其他 OpenSSL 生成的密钥文件格式有何不同?

    • 3 个回答
  • Marko Smith

    如何确定bash变量是否为空?

    • 15 个回答
  • Martin Hope
    Tom Feiner 如何按大小对 du -h 输出进行排序 2009-02-26 05:42:42 +0800 CST
  • Martin Hope
    Noah Goodrich 什么是 Pem 文件,它与其他 OpenSSL 生成的密钥文件格式有何不同? 2009-05-19 18:24:42 +0800 CST
  • Martin Hope
    Brent 如何确定bash变量是否为空? 2009-05-13 09:54:48 +0800 CST
  • Martin Hope
    cletus 您如何找到在 Windows 中打开文件的进程? 2009-05-01 16:47:16 +0800 CST

热门标签

linux nginx windows networking ubuntu domain-name-system amazon-web-services active-directory apache-2.4 ssh

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve