web-dev-qa-db-ja.com

HAProxyをルーティングする方法TCP SNIに基づいて(openssl s_clientを使用してテスト))

HAProxyを使用して、TLSで暗号化されたTCP接続を終了し、暗号化されていないTCPトラフィックを、開始に使用されたサーバー名表示に基づいてさまざまなバックエンドに渡したいTLS接続。

バックエンドサーバーで3つのサービスを実行しており、それぞれが異なるポート(5001、5002、5003)で実行されています。 HAProxyはポート5000にバインドします。最初の2つのサービスに名前で接続するか、一致しない場合は3番目のサービスにルーティングします。 openssl s_clientを使用してHAProxyへの接続を開始しています。ただし、ログでは、接続がデフォルトサーバーにしかルーティングされないことがわかります。つまり、SNIは無視されているようです。

DNS:

A record     demo.sni.example.com     1.2.3.4
CNAME        1.sni.example.com        pointing to demo.sni.example.com   
CNAME        2.sni.example.com        pointing to demo.sni.example.com   

つまり、次のルーティングを実行したいのですが。

SNI = 1.sni.example.com:5000 -> 1.2.3.4:5001
SNI = 2.sni.example.com:5000 -> 1.2.3.4:5002
anything else on port 5000 -> 1.2.3.4:5003

haproxy.cfg:

global
  log stdout  format raw  local0 info

defaults
  timeout client 30s
  timeout server 30s
  timeout connect 5s
  option tcplog

frontend tcp-proxy
  bind :5000 ssl crt combined-cert-key.pem
  mode tcp
  log global
  tcp-request inspect-delay 5s
  tcp-request content accept if { req_ssl_hello_type 1 }

  use_backend bk_sni_1 if { req.ssl_sni -i 1.sni.example.com }
  use_backend bk_sni_2 if { req.ssl_sni -i 2.sni.example.com }
  default_backend bk_default

backend bk_sni_1
  mode tcp
  log global
  balance roundrobin
  server server1 1.2.3.4:5001 check

backend bk_sni_2
  mode tcp
  log global
  balance roundrobin
  server server1 1.2.3.4:5002 check

backend bk_default
  mode tcp
  log global
  balance roundrobin
  server server1 1.2.3.4:5003 check

combined-cert-key.pemは、自己署名証明書ファイルとキーです。ここで、CNはサーバーのIP(1.2.3.4)であり、すべてのDNS値とIPのSANがあります。

openssl s_clientを使用して開始された接続:

DNS経由で接続してみました(AおよびCNAMEレコードとIP):

echo test | openssl s_client -connect demo.sni.example.com:5000 -servername 1.sni.example.com
echo test | openssl s_client -connect 1.sni.example.com:5000 -servername 1.sni.example.com
echo test | openssl s_client -connect 1.2.3.4:5000 -servername 1.sni.example.com

ただし、すべての接続はデフォルトのバックエンドbk_defaultにルーティングされます。

HAProxyがSNIサーバー名を認識しない原因は何ですか? (私は最新のHAProxy Dockerイメージを使用しています: https://hub.docker.com/_/haproxy

1
John

答えは、req.ssl_sniではなく ssl_fc_sni を使用することです。前者はSSLで終了するセッション用であり、後者はTCPが直接渡されるセッション用です。

2
John