kazokmr's Blog

試したこと、読んだこと、見たこと、聴いたことを書きたくなったら書くブログ

mkcertで生成した証明書をHAProxyにインポートしローカルでSSLオフロードする

前回、ローカル環境でHAProxyを使った分散環境が用意できたので、HTTPS接続にも対応させてみる

kazokmr.hatenablog.com

mkcert で自己証明書を生成する

mkcert というツールを使い、ローカルCA証明書を作成・インポートして、サーバー証明書を作成します。 手順は、mkcert のGitHubページに従って進めます。

GitHub - FiloSottile/mkcert: A simple zero-config tool to make locally trusted development certificates with any names you'd like.

mkcert のインストール

brewでインストールします。nssはFireforx からアクセスする場合に必要です。

brew install mkcert
brew install nss

ローカル CA 証明書を作り 端末にインポートする

まずは自己認証局(CA)を作るため、mkcert -installを実行します。途中でrootパスワードを求められたら、端末の管理者パスワードを入力します。

mkcert -install
Created a new local CA 💥
Sudo password:
The local CA is now installed in the system trust store! ⚡️
The local CA is now installed in the Firefox trust store (requires browser restart)! 🦊
The local CA is now installed in Java's trust store! ☕️

ローカルのCA証明書が作成されMacにインポートされているか確認します。 mkcert -CAROOT で表示されるディレクトリに CAのルート証明書秘密鍵が作成されます。インポートは 「Keychain Access」を開き左側のメニューで「System」を選び、「Certificates」タブを選ぶと、"mkcert ....." というルートCA証明書がインポートされていることが確認できます。

サーバー証明書を生成する

mkcertで作成したCAを利用してサーバー証明書を作成します。今回は localhost ドメインに対する証明書を作成してみます。mkcert localhost とコマンド実行すると、localhost.pem と localhost-key.pem が生成されます。

mkcert localhost

Created a new certificate valid for the following names 📜
 - "localhost"

The certificate is at "./localhost.pem" and the key at "./localhost-key.pem" ✅

It will expire on 23 April 2023 🗓

ドメインとしては、他にもワイルドカード (*.example.com) や ループバックアドレス (127.0.0.1) などでも作成できる。

HAProxyにSSLオフロード設定を行う

サーバー証明書をHAProxyにインポートする

HAProxyにインポートする証明書ファイル(.pem)は、1つのファイルにまとめる必要があるため、先程作成したキーペアを1つにまとめておきます。

HAProxy version 2.3.19 - Configuration Manual

cat localhost.pem localhost-key.pem > cert.localhost.pem

作成したPemファイルをDockerコンテナで利用するようにDockerfileを修正します

FROM haproxy:2.3
COPY haproxy.cfg /usr/local/etc/haproxy/haproxy.cfg
COPY cert.localhost.pem /usr/local/etc/haproxy/cert.localhost.pem

設定ファイルを編集する

haproxy.cfg に 証明書のパス、httpヘッダーへのx-forwardedの追加、httpからhttpsへのリダイレクトを追加します。

...
frontend http-in
    bind *:80
    default_backend servers

    # サーバー証明書のパスを指定
    bind :443 ssl crt /usr/local/etc/haproxy/cert.localhost.pem

    # x-forwarded-for を有効にし、プロトコルとポートもheader にセットする
    option forwardfor
    http-request set-header x-forwarded-proto https
    http-request set-header x-forwarded-port 443

    # httpからのアクセスをhttpsにリダイレクトする
    redirect scheme https if !{ ssl_fc }
...

最後にHAProxyのコンテナイメージを再ビルドして実行します。 またホスト側から443ポートでアクセスできるようにすること。

...
services:
  haproxy:
    build: ./haproxy
    depends_on:
      - app01
      - app02
      - app03
    ports:
      - 80:80
      - 443:443
...

動作確認

ブラウザから https でアクセスできました。httpでアクセスした場合もhttpsにリダイレクトします。 またSpringBootアプリのセッション管理も正常でした。

httpsでアクセス

ローカルでSSLやLBの動作確認できるの便利。 今日の設定内容は証明書を除いてGitHubリポジトリにあります。

github.com

参考記事

多機能なロードバランサとして使える多機能プロクシサーバー「HAProxy」入門 | さくらのナレッジ

多機能プロクシサーバー「HAProxy」のさまざまな設定例 | さくらのナレッジ

HAProxy version 2.3.19 - Configuration Manual