SNIとさまざまなSSL設定を備えたHAProxy


9

私は2つのサイト用にHAProxyを持っています。1つはパブリック、もう1つはプライベートです。

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にリダイレクトする必要があります。

これまでのところ、これは正常に動作します。しかし、私は、彼らが上であっ参照時に証明書を求め得続けることのSafariで、私のサイトを閲覧するMacユーザーで不満を持っhttps://www.example.com/ときブラウジング例えばFirefoxが唯一尋ね一方//private.example:HTTPS .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

もちろんそれはうまくいきません

a。パブリックIPが1つしかないポート443で2つのフロントエンドをリッスンすることはできません。「use_frontend if domain_www」またはそのようなものを言う方法をまだ見つけていません。(use_backendまたはuse-serverのみ)

3台の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はリクエストを破棄します。

また、私は現在、3つの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
  ...

誰かがこれを手伝ってくれることを願っています...

回答:


13

追加のサーバーやサービスを必要としない、この問題の解決策を見つけました。これが新しい問題を引き起こさないかどうか私は完全にはわかりません。私にとっては、今はうまくいくようです。

私がやった方法は、異なる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がオプションではないのかと思います。多分それは何らかの理由でやるべきではないことだからです。


良いアイデア。このセットアップに関するドキュメントも見つかりませんでした。このHAProxyループとパフォーマンスは似ていますか?
JB。モニカと。

申し訳ありませんが、パフォーマンスがどの程度かはわかりません。A:(ソースIPフィルターのため)長期間使用しなかったため、B:パフォーマンスの最適化がより興味深いトラフィック量の多いサイトがないためです...
mohrphium

私はapache2をhaproxyの前に置いただけです。これは機能しますが、hapoxyクラスターの前の単一障害点と(私が思うに)パフォーマンスのボトルネック(hapはap2よりも速いと思うので、実際のデータがありません)
それでも

3

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

セキュリティに関する注意:ssl_fc_sniHTTPホスト名ではなく、常に(機密)ホスト名をSNI と照合します。そうでない場合、攻撃者はTLS SNIを送信することでクライアント証明書認証をバイパスする可能性がありますwww.example.orgが、HTTPホスト名をprivate.example.org


OPは両方に同じ証明書を使用しています。問題は、さまざまなca-file設定に関するものでした。
gre_gor
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.