haproxy

HAProxyで複数のSSL証明書に対応する

More than 1 year has passed since last update.

HAProxyで複数のSSL証明書に対応する方法をググったけどあんまり情報が無かったのでメモ。

HAProxyでSSL接続を終端させるときは

haproxy.cfg
frontend app
 bind *:443 ssl crt /etc/haproxy/ssl/hoge.pem

みたいな感じで、SSL接続に使いたいpemファイルのパスを書いておく。

複数のSSL証明書に対応する場合は

haproxy.cfg
frontend app
 bind *:443 ssl crt /etc/haproxy/ssl/hoge.pem crt /etc/haproxy/ssl/hoge2.pem

と、単純にpemファイルのパスを並べていく感じの例をよく見るけど、これだとSSL証明書の数が多くなってきたときに可読性があまりにも悪い。
なんか方法ないかなーと思っていたら、普通に公式ドキュメントに書いてあった。

If a directory name is used instead of a PEM file, then all files found in
that directory will be loaded in alphabetic order unless their name ends with
'.issuer', '.ocsp' or '.sctl' (reserved extensions). This directive may be
specified multiple times in order to load certificates from multiple files or
directories. The certificates will be presented to clients who provide a
valid TLS Server Name Indication field matching one of their CN or alt
subjects. Wildcards are supported, where a wildcard character '*' is used
instead of the first hostname component (eg: *.example.org matches
www.example.org but not www.sub.example.org).

要はpemファイルのパスじゃなくて、pemファイルがあるディレクトリのパスを指定すればいいっぽい。

haproxy.cfg
frontend app
 bind *:443 ssl crt /etc/haproxy/ssl

こんな感じでディレクトリを指定すると、末尾が「.issuer」「.ocsp」「.sctl」以外のファイルをアルファベット順にロードしていって、対応するSSL証明書を使ってくれるとの事。
注意点としては、 「.issuer」「.ocsp」「.sctl」以外のファイルは全部ロードしてしまうので、ディレクトリの中に関係ないファイルが混ざっているとhaproxyが起動に失敗する。

後、クライアントやSSLのライブラリがSNIに対応していない場合には

If no SNI is provided by the client or if the SSL library does not support
TLS extensions, or if the client provides an SNI hostname which does not
match any certificate, then the first loaded certificate will be presented.
This means that when loading certificates from a directory, it is highly
recommended to load the default one first as a file or to ensure that it will
always be the first one in the directory.

との事。
この場合は最初にロードしたSSL証明書が使われてしまうので、デフォルトとして使いたいSSL証明書はディレクトリではなくファイルパスを明示的に指定する、またはその証明書が最初にロードされるようにしておく(アルファベット順に並べたときに先頭になるようなファイル名にする)。

まあ、ファイル名に気を付けて運用するのはめんどくさいので、ファイルパスを指定しておくのが正解だと思います。

haproxy.cfg
frontend app
 bind *:443 ssl crt /etc/haproxy/ssl/hoge.pem crt /etc/haproxy/ssl/

こんな感じかな?