【OCI_25】ロード・バランサのフロントエンドでHTTPSを一度終端し、バックエンドで再暗号化(HTTPS)する
今回の検証は、ロード・バランサのフロントエンドでHTTPSを一度終端し、バックエンドで再暗号化(HTTPS)したいと思います。
図示すると以下のようなイメージです。ロード・バランサで一度HTTPSが終端して、あらたに再暗号化(HTTPS)となるので矢印の色を分けて表示しています。

証明書は自己署名証明書を利用しています。
自己署名証明書について少し詳細に触れていますので、以下の記事を参考にしてください。
検証の流れとしては以下となります。
証明書を作成
環境構築(VCN、サブネットなど)
インタンス(WEBサーバ)の作成と設定
Webサーバへの接続確認
ロード・バランサの作成と設定
ロード・バランサへの接続確認
当検証は、有償アカウントで検証しています。無償アカウントと挙動が異なる場合がありますのでご了承ください。
※記事内では、ロード・バランサ = FLB という意味で記載しています。後から多数の表記揺れがあることに気付きましたが修正しておりません。読みにくいですがご了承ください。
目次
opensslモジュールの確認
証明書や秘密鍵を作成するために、opensslモジュールがインストールされていることを確認します。
インストールされてない場合は、インストールしてください。証明書や秘密鍵は、どのサーバで作成しても問題ありません。
dnf list installed | grep openssl

証明書の作成
CAの証明書とFLB用サーバ証明書、WEBサーバ用サーバ証明書を作成します。
CAの証明書とFLB用サーバ証明書、WEBサーバ用サーバ証明書をすべて自己署名証明書で作成します。
1つ目はクライアント→FLB用、2つ目はFLB→WEBサーバ用となります。
・CA(認証局)
CA証明書 CN = testca.com
・クライアント → FLB
https://www.2026testsite.com
サーバ証明書 CN/SAN = www.2026testsite.com
・FLB → Web サーバ
https://backend.internal.local
サーバ証明書 CN/SAN = backend.internal.local
CA証明書(testca.com)を作成
自己署名証明書でも「クライアントがその発行元(CA)を信頼している」状態にすれば、ブラウザの警告は表示されません。
■CA証明書のCNについて
・CA証明書の CN と、サーバ証明書の CN/SAN は一致する必要はない
・一致が必要なのは「署名の検証関係」であって「名前」ではない
■CA証明書とサーバ証明書の役割の違い
・CA証明書(ca.crt)
CA証明書の CN は、「この証明書を発行した“組織・認証局の名前”」を表すラベル。
・サーバ証明書(backend.crt)
サーバ証明書の CN / SAN は、「この証明書を提示するサーバは誰か」を表す。
CA秘密鍵作成
以下コマンドを実行します。
openssl genrsa -out ca.key 4096

CA公開証明書(自己署名CA)
以下コマンドを実行します。(行頭に全角スペースがあるので半角スペースで実行してください)
CA証明書 CN = testca.com
openssl req -x509 -new -nodes \
-key ca.key \
-sha256 \
-days 3650 \
-out ca.crt

以下のファイルが作成されました。
ca.key(CA秘密鍵)
ca.crt(CA公開証明書:FLB・クライアント端末で使用)

FLB用サーバ証明書を作成
サーバ証明書 CN/SAN = www.2026testsite.com
秘密鍵作成
以下コマンドを実行します。
openssl genrsa -out flb.key 2048

SANの作成
以下の内容でファイル(flb.cnf)を新規作成します。
[ req ]
default_bits = 2048
prompt = no
default_md = sha256
distinguished_name = dn
req_extensions = req_ext
[ dn ]
CN = www.2026testsite.com
[ req_ext ]
subjectAltName = @alt_names
[ alt_names ]
DNS.1 = www.2026testsite.com

CSRの作成
先ほど作成したSAN(flb.cnf)を含んだCSRを作成します。
openssl req -new -key flb.key -out flb.csr -config flb.cnf

CAで署名したFLBサーバ証明書を作成
以下コマンドを実行します。(行頭に全角スペースがあるので半角スペースで実行してください)
openssl x509 -req \
-in flb.csr \
-CA ca.crt \
-CAkey ca.key \
-CAcreateserial \
-out flb.crt \
-days 825 \
-sha256 \
-extfile flb.cnf \
-extensions req_ext

以下のファイルが作成されました。
flb.key(FLB用秘密鍵)
flb.crt(FLB用サーバ証明書)
flb.csr(FLB用CSR)
flb.cnf(FLB用SAN)

バックエンド用サーバ証明書
バックエンドのWEBサーバ用サーバ証明書 CN / SAN = backend.internal.local
秘密鍵作成
以下コマンドを実行します。
openssl genrsa -out backend.key 2048

SANの作成
以下の内容でファイル(backend.cnf)を新規作成します。
[ req ]
default_bits = 2048
prompt = no
default_md = sha256
distinguished_name = dn
req_extensions = req_ext
[ dn ]
CN = backend.internal.local
[ req_ext ]
subjectAltName = @alt_names
[ alt_names ]
DNS.1 = backend.internal.local

CSRの作成
先ほど作成したSAN(backend.cnf)を含んだCSRを作成します。
openssl req -new -key backend.key -out backend.csr -config backend.cnf

CAで署名したBackendサーバ証明書の作成
以下コマンドを実行します。(行頭に全角スペースがあるので半角スペースで実行してください)
openssl x509 -req \
-in backend.csr \
-CA ca.crt \
-CAkey ca.key \
-CAcreateserial \
-out backend.crt \
-days 825 \
-sha256 \
-extfile backend.cnf \
-extensions req_ext

以下のファイルが作成されました。
backend.key(バックエンドのWEBサーバ用秘密鍵)
backend.crt(バックエンドのWEBサーバ証明書)
backend.csr(バックエンドのWEBサーバ用CSR)
backend.cnf(バックエンドのWEBサーバ用SAN)

証明書内容の確認
FLB証明書の内容確認
CN、SANともに「www.2026testsite.com」であることを確認します。
以下コマンドを実行します。
openssl x509 -in flb.crt -noout -subject -ext subjectAltName

Backend証明書の内容確認
CN、SANともに「backend.internall.local」であることを確認します。
以下コマンドを実行します。
openssl x509 -in backend.crt -noout -subject -ext subjectAltName

証明書などダウンロード
作成した各種ファイルをWinSCPなどでクライアント端末にダウンロードします。

VCN、サブネット(パブリック)、インターネットゲートウェイ、ルート・ルール、セキュリティ・リスト、インスタンスの作成
事前準備としてVCN、サブネット、セキュリティ・リスト、サービスゲートウェイを作成します。
事前準備の手順については、ここでは細かくふれておりませんのでご了承ください。
VCNの作成
次のVCN(dnslabel-on)を作成しました。

インターネットゲートウェイを作成
インターネット・ゲートウェイ(igw2)を作成しました。(※右下のルート表のプルダウンの関連付けは、不要 [失敗します])


ルート表(Default Route Table for dnslabel-on)にインターネットゲートウェイのルート・ルールを追加します。


サブネットの作成
インスタンスを配置するパブリック・サブネットとFLBを配置するパブリック・サブネットを作成します。
インスタンスを配置するパブリック・サブネット
(別の検証ですでに作成済みのため手順は割愛させていただきます。)

FLBを配置するパブリック・サブネット
サブネットを作成する際にセキュリティ・リスト、ルート表を選択する必要があるので事前に作成してからFLB用パブリック・サブネットを作成します。
FLB用セキュリティ・リストの作成
FLB用セキュリティ・リスト(LB_Security_List)を作成し、80番ポート、443番ポート、ICMPをとおすように設定しています。
※本番環境では十分考慮のうえポートを開放してください


ロード・バランサ用ルート表の作成
ロード・バランサ用ルート表(LB_route)を作成し、インターネット・ゲートウェイへのルートを定義します。

ロード・バランサを配置するパブリック・サブネットの作成
ロード・バランサを配置するパブリック・サブネット(subnet-LB)を作成しました。

インスタンスの作成
作成したパブリック・サブネットにWEBサーバとなるインスタンスを2台作成します。

WEBサーバの設定
Apache HTTPサーバーをインストールします。「Complete!」が表示されればインストールは完了しています。
sudo yum -y install httpd
サービスを起動して、OSを再起動してもサービスが自動起動するよう設定します。
sudo systemctl start httpd
sudo systemctl enable httpd
firewalldでポート番号を指定して、80番ポート(http)と443番(https)ポートをオープンします。「success」が表示されれば成功しています。
sudo firewall-cmd --permanent --add-port=80/tcp
sudo firewall-cmd --permanent --add-port=443/tcp
firewalldをリロードして設定を反映します。
sudo firewall-cmd –reload
index.html ファイルを作成し、「WEBサーバ1号機」、「WEBサーバ2号機」とそれぞれ表示されるようにします。
クライアント端末からブラウザでアクセス(http://WEBサーバのIPアドレス)してWEBページが表示されることを確認します。

証明書の設定
今回はクライアント→FLBでhttpsを終端後、FLB→WEBサーバであらたにhttpsで暗号化します。
ここでは先にWEBサーバ側の設定をして、確認のためクライアント→WEBサーバでhttps通信できているか確認します。
SSL設定ファイル(/etc/httpd/conf.d/ssl.conf)を編集します。
存在しない場合は、Apache(httpd) のSSL用設定(mod_ssl)が入っていない/有効になっていない可能性が高いです。
パッケージマネージャでmod_sslがインストールされているか確認します。
dnf list installed | grep mod_ssl

mod_sslがインストールされていないのでインストールします。「Complete!」が表示されればインストール成功です。
dnf -y install mod_ssl
もう一度パッケージマネージャで確認すると、mod_sslがインストールされていることが確認できました。
dnf list installed | grep mod_ssl
/etc/httpd/conf.d/ ディレクトリ配下にssl.confファイルが生成されました。

/etc/httpd/conf.d/ssl.conf の一番下へ以下SSLの設定を追記します。ServerName、SSLCertificateFile(サーバ証明書)、SSLCertificateKeyFile(秘密鍵)の各名称はご自身の環境に読み替えてください。
<VirtualHost *:443> と </VirtualHost> はもともとssl.confに記載されていると思います。重複するとエラーになるわけではないですが、検証以外では混乱を避けるため1つにまとめることを推奨します。今回は検証で重複して記載しますが・・・
<VirtualHost *:443>
ServerName backend.internal.local
DocumentRoot "/var/www/html"
SSLEngine on
SSLCertificateFile /etc/pki/tls/certs/backend.crt
SSLCertificateKeyFile /etc/pki/tls/private/backend.key
<Directory "/var/www/html">
Options -Indexes +FollowSymLinks
AllowOverride All
Require all granted
</Directory>
ErrorLog logs/ssl_error_log
TransferLog logs/ssl_access_log
LogLevel warn
</VirtualHost>

まだ、サーバ証明書や秘密鍵をアップロードしてないのでApacheは再起動しません。
この時点でApacheを再起動するとエラーとなり、Apacheが起動できなくなります。
WEBサーバへサーバ証明書と秘密鍵を配置
WEBサーバ用サーバ証明書と秘密鍵をWEBサーバ側へアップロードします。
私の環境では、Teratermへドラッグアンドドロップしてアップロードします。
※設定にもよりますがrootから一般ユーザー(opcなど)にユーザーを切り替えてからドラッグアンドドロップしてください。
最悪、設定ファイルが壊れてopcユーザーでもログインできなくなります。

Teratermへドラッグアンドドロップすると以下画面が表示されるので、そのまま「OK」をクリックします。

アップロードできました。

/etc/httpd/conf.d/ssl.conf で設定した場所にサーバ証明書と秘密鍵を配置します。
おそらく本番環境などではセキュリティのためにファイルの所有者や権限を変更しますが、検証なのでそのままにしています。
サーバ証明書:SSLCertificateFile /etc/pki/tls/certs/backend.crt
秘密鍵:SSLCertificateKeyFile /etc/pki/tls/private/backend.key
Apache(httpd)を再起動します。
/etc/httpd/conf.d/ssl.conf で設定した場所にサーバ証明書と秘密鍵を配置せずにサービスを再起動するとエラーでApacheが起動しないのでご注意ください。
systemctl restart httpd
念のため確認しておきます。
systemctl status httpd

クライアント側に CA 証明書をインストール
今のままでは、証明書エラーが表示されるので証明書エラーが表示されないようクライアント端末にCA証明書をインストールします。
これによりサーバ証明書を信頼することになり証明書エラーが表示されなくなります。
※今回の検証であれば「ca.crt」がCA証明書となります。

CA証明書「ca.crt」を右クリックし、「証明書のインストール」をクリックします。

以下画面で「ローカルコンピューター」を選択し、「次へ」をクリックします。

以下画面で「証明書をすべて次のストアに配置する」を選択、証明書ストアで「信頼されたルート証明機関」を参照して「次へ」をクリックします。

以下画面で「完了」をクリックします。

ポップアップ「正しくインポートされました」に対して「OK」をクリックします。

Windowsの検索バーで「cert」と入力すると「ユーザー証明書の管理」が表示されるのでクリックします。

左ペインの「信頼されたルート証明機関」の「証明書」を選択すると右側の発行先にCA証明書「testca.com」が表示されていることが確認できます。

クライアント端末のhostsファイルの編集と動作確認
WEBサーバのIPアドレスとFQDN「backend.internal.local」をhostsファイルに記載して、https通信で証明書エラーが表示されないことを確認します。
面倒ですがWEBサーバ1台ずつ確認します。
hostsファイルの場所
C:\Windows\System32\drivers\etc\hosts
WEBサーバ1号機

「https://backend.internal.local/」へアクセスし、証明書エラーなくWEBサーバ1号機のWEBページが表示されました。

次は、WEBサーバ2号機です。

「https://backend.internal.local/」へアクセスし、証明書エラーなくWEBサーバ2号機のWEBページが表示されました。

ひとまず、WEBサーバ側の証明書関連設定は完了しました。次は、ロード・バランサを作成し、証明書関連の設定をします。
ロード・バランサの作成
今回の検証においてロード・バランサを作成する過程でリスナーをhttpsで構成しようとすると最後のステップで何度も以下のエラーとなりました。
エラーメッセージ:Invalid SSL configuration: [Constraint listener:listener_lb_2026-0111-0615 violation: Invalid listener ssl configuration. * Constraint sslConfiguration violation: Certificate alias or certificateIds / trustedCertificateAuthorityIds required
エラーメッセージ(機械翻訳):無効なSSL構成: [制約 listener:listener_lb_2026-0111-0615 違反: リスナーSSL構成が無効です。 * 制約 sslConfiguration 違反: 証明書の別名または証明書ID/trustedCertificateAuthorityIdsが必要です]

結果的にロード・バランサを作成する際はリスナーをhttpで構成して、ロード・バランサの設定で証明書と秘密鍵を追加し、その後、リスナーを編集してhttpからhttpsへ変更することでうまくいきました。
ロード・バランサの作成
ロード・バランサを作成していきます。要所だけコメントを記載しています。
「ロード・バランサの作成」をクリックします。

ロード・バランサ名は、「lb」にしています。

ロード・バランサ用に作成したサブネットを選択して、帯域幅の最大帯域幅の選択を「50」に変更しています。

セキュリティの項目以下はデフォルトのまま「次」をクリックします。

バックエンドを構成します。
バックエンドは、FLB→WEBサーバの設定となります。
ロード・バランシング・ポリシーの設定は、デフォルトの「重み付けラウンド・ロビン」を選択します。

バックエンド・サーバの選択で事前に作成したWEBサーバ2台を選択します。今回は、FLB→WEBサーバもhttps通信にするのでポートは「443」を選択します。

ヘルス・チェック・ポリシーのポートも「443」に設定します。その他はデフォルト値で設定します。

「SSLの使用」を有効化します。
FLB→WEBサーバのhttps通信は、WEBサーバでサーバ証明書、秘密鍵を保持し、FLBはクライアント側となります。
そのため、WEBサーバの自己署名証明書を信頼するためにFLBへCA証明書を設定します。
SSL証明書の指定は何も指定しません。

CA証明書の指定でCA証明書「ca.crt」を指定します。

秘密キーの指定は、機能をOFFのままとし、何も指定しません。

バックエンド・セットを選択します。

セキュリティ・リストの選択設定はデフォルトのままにします。
ロード・バランサとインスタンスの間で必要となる通信をセキュリティ・リストへ自動で追加してくれます。(自動追加されなければ自身で追加すればよいくらいの認識で大丈夫です)
エグレス・セキュリティ・リストは、ロード・バランサからインスタンスへ出ていく80番ポートの通信を開けてくれます。
イングレス・セキュリティ・リストは、インスタンスへ入ってくる80番ポートの通信を開けてくれます。

セッション永続性移行は、デフォルトのまま「次」をクリックします。

リスナーを構成します。
本セクションの冒頭にも記載していますが、結果的にロード・バランサを作成する際はリスナーをhttpで構成して、ロード・バランサの設定で証明書と秘密鍵を追加し、その後、リスナーを編集してhttpからhttpsへ変更することでうまくいきました。

ロギングを構成します。
検証のため、エラーログ、アクセスログはOFFにしています。「次」をクリックします。

設定内容を確認し、「送信」をクリックします。

ロード・バランサが作成されました。
今の構成は、以下の状態になります。バックエンド・セットのヘルスが「OK」となっていて、全体的なヘルスも「OK」となっているので FLB→WEBサーバはhttps通信できていると推測されます。
リスナー:80番ポートの待ち受け
バックエンド・セット:443番ポートの通信

FLB用証明書の追加
ロード・バランサの「証明書と暗号」へFLB用サーバ証明書と秘密鍵を追加します。
「証明書と暗号」タブを選択します。

「ロード・バランサ管理対象証明書」の「証明書の追加」をクリックします。

証明書の追加画面で以下を入力、選択します。
証明書名:任意の証明書名
SSL証明書:事前に作成したFLB用サーバ証明書(flb.crt)
CA証明書は、バックエンドの構成で設定しているのでここでは不要です。

秘密鍵を設定して右下の「証明書の追加」をクリックします。
秘密キーの指定:ON
秘密キー:事前に作成したFLB用秘密鍵(flb.key)

少し待つと作業リクエストの結果が「成功」になりました。

ロード・バランサ管理対象証明書にも追加されました。

リスナーを編集
ロード・バランサ作成時に設定したリスナーのhttp:80番ポートをhttps:443番ポートへ変更し、証明書を追加します。
ロード・バランサの「リスナー」タブを選択します。

リスナーの編集画面で以下を変更、追加し、右下の「変更の保存」をクリックします。
プロトコル:HTTPS
ポート:443
証明書リソース:ロード・バランサ管理対象証明書
証明書名:事前にロード・バランサへ追加した「flb-cert-2026」を選択

その他の設定はデフォルトのままで「変更の保存」をクリックします。

少し待つと作業リクエストの結果が「成功」になりました。

リスナーの構成をhttpsに変更できました。

ロード・バランサの詳細タブで、全体的なヘルス、バックエンド・セットのヘルスがともに「OK」となっているのでリスナーの構成に問題はないと推測されます。

クライアント端末のhostsファイルの編集と動作確認
ロード・バランサのIPアドレスとFQDN「www.2026testsite.com」をhostsファイルに記載します。
hostsファイルの場所
C:\Windows\System32\drivers\etc\hosts

クライアント端末のブラウザで「https://www.2026testsite.com」へアクセスし、WEBサーバのWEBページが表示され、https通信で証明書エラーが表示されないことを確認します。
ブラウザをF5更新するとWEBサーバ1号機、WEBサーバ2号機へ負荷分散されることが確認できます。
クライアント端末には、WEBサーバとのhttps通信を確認する際にCA証明書(ca.crt)を取り込んでいるので、ここであらためて取り込む必要はありません。
補足:
Google Chrome の仕様のようですが、実際に接続している URL は https://www.2026testsite.com/ ですが、画像のとおり表示上だけ www. が省略されています。
テキストなどにコピーすると https://www.2026testsite.com/は表示されます。


まとめ
長くなりましたが、ロード・バランサのフロントエンドでHTTPSを一度終端し、バックエンドで再暗号化(HTTPS)を検証することができました。
CA証明書の仕組みについて、あらためて理解を深めることができました。
以下、他の記事をまとめた一覧です。OCI以外にAWSもまとめています。