nginx
AWS
SSL
elb
SSL証明書

ELBをNLB(non SSL Termination)からNLB(on SSL Termination)にオンラインで変更したよ


対応にあたる経緯

以前の ELBをCLB(Classic Load Balancer)からNLB(Network Load Balancer)にオンラインで変更した時のメモ - Qiita の対応以後、SSL TerminationがEC2内で行われることから、その負荷に対応するためにインスタンスタイプを上げたり、EC2内でnginxへSSLの設定を加えたり、毎年なり2年おきなりにSSL証明書の更新作業が入って、運用コストがかかっていまして、、、

あー、、、ACMで自動更新できるようにならないかなー :sweat: ってずっと思ってたんですが、先日、AWSから下記のアップデートが :exclamation: :exclamation: :exclamation:

Network Load Balancer が TLS ターミネーションのサポートを開始

お、これは :exclamation: :eyes: ということで、軽く検証したところ、SSL証明書をACM化できちゃいました :thumbsup:

ということで早速、ちょうどSSL証明書の期限切れアラートがきているシステムがあるので、実際に本番へ反映しちゃいます


対応手順の前に取り急ぎ検証した手順 :star:

※今の本番URL(www.XXXXXXX.jp)とは別で(nlb.XXXXXXX.jp)にてアクセスできるようにAWS管理コンソールを色々触りますので注意


1. まずは下記のデモの手順にそって新しいNLBを作成します。


  • AWS Elastic Load Balancer Demos

  • NLB作成時にElastic IPが1つ以上必要なので、作成しました。(ケチって1つだけにしてます :grin:

  • NLBへセットするリスナーにて、新しいターゲットグループも作成しました。


2. 作成したNLBへ現在の本番のNLBに接続されているプロキシサーバをぶらさげます。


  • せっかくNLBにて SSL Termination してくれるのであれば、それ以降のバックエンドではHTTPでいいだろってことでポートも 80 にします。

  • ターゲットグループでステータスが healthy にならなくて少しハマりました。。。。 :sweat:


    • 原因は受け側にいるEC2 の SG(セキュリティグループ)にて、80ポートの解放を NLBを配置した subnetのCIDRからアクセスできるように設定する必要があった感じでした :boom:




3. また、EC2で動いている nginx でも 80 でアクセスして動作するような設定が必要ということで、取り急ぎ、 /etc/nginx/conf.d/XXXX-http.conf をコピーで作成して設定


/etc/nginx/conf.d/XXXXXXX-http.conf

server {

listen 80;
server_name nlb.XXXXXXX.jp;

<後はコピー元と同じ>



4. んで、nginx再起動でできあがりです :rocket:

$ sudo service nginx reload

本当にできてるのか?って思ったので、下記の資料の方法を使って、SSL通信でなくて、HTTPでアクセスされるのかをアクセスログを見て、チェックしました。

SSLじゃない場合は -[ハイフン] で出るんですね。勉強になります :notebook:


ってことで次は本番反映にトライ!

検証はできたので、次はじゃあどうやってオンラインで変更するか :exclamation: :question: ですよね

どうやってやろうかなーってことで、下記の前提条件がありながら、下記の手順を考えました :exclamation: :thinking:


前提条件と必要条件


  • 今のNLBのグローバルIPは変えたくない


    • 理由は外部からシステムへアクセスする方がVPNをはってアクセスしてくる際に、またルーティングの変更が必要になる。



  • NLBのリスナーは複数作成できそうだったので、試したが同じポートだと作成できない。。。やろうとしたらエラーになっちゃいました・・・ :sweat:


    • 現在:TCP:443

    • 作成トライしたやつ:TLS:443



  • せっかくNLBで Termination してくれるんだからバックエンドはもう http にしたい。

  • バックエンドのnginxはHTTPS、HTTPの両方で動く状態にしておく。具体的には下記。

server {

listen 80;
listen 443 ssl;
server_name clb.XXXXXXX.jp www.XXXXXXX.jp;

# ここはコメントアウトしてね
# ssl on;
ssl_certificate /etc/pki/tls/certs/XXXXXXX.pem;
ssl_certificate_key /etc/pki/tls/certs/XXXXXXX.key;
ssl_session_timeout 10m;
ssl_session_cache shared:SSL:10m;
ssl_protocols SSLv2 TLSv1.2;


対応手順


  1. まずは新しく、CLB(Classic Load Balancer)を作成。 ※これを選んだのは単純に使い慣れてるのと、コンソール上でわかりやすいからでしたw

  2. 作成できたら今のプロキシEC2をぶらさげて下記を対応


    • CLBへ今回反映しようとしているACMのSSL証明書を設定

    • SG(セキュリティグループ)は取り急ぎ社内LANからのHTTPSを解放

    • ぶらさげたEC2のSGへは社内LANからのHTTPSを解放したSGを送信元としたHTTPを解放するように設定


    • clb.XXXXXXX.jpで、このCLBのエンドポイントが名前解決されるようにRoute53へCNAMEレコード追加(Aレコードでもできた)


    • https://clb.XXXXXXX.jp でアクセスできるかチェック



  3. 今、NLBにぶらさがってるプロキシEC2のSGをCLBへも設定

  4. Route53でwww.XXXXXXX.jp の名前解決先をCLBへ変更


    • これで、アクセスの許可されたユーザが社外からの場合はVPNのルーティングが要変更だが、社内からのアクセスは可能となります



  5. NLBへのアクセスがなくなった時点で、NLBの設定変更に着手


    • リスナーにて、TCP:443からTLS:443へ設定を変更し、新しく作成したACMを設定。

    • ぶら下がってるEC2のSGにて、一時的にHTTPを全解放するように設定



  6. Route53でclb.XXXXXXX.jpにてNLBのエンドポイントに名前解決されるように設定し、アクセス確認

  7. 問題なければ、Route53にて、www.XXXXXXX.jpの名前解決先をNLBへ変更して、アクセスできれば完了!

  8. 一時的に解放したHTTPの全解放をクローズしてアクセス確認

  9. 問題なければ、Route53でclb.XXXXXXX.jpの削除

  10. 最初に作成したCLBの削除などでお片づけして終了 :heart:

これでちゃんと、Amazon発行の証明書になります!

そして、SSL証明書の年間費用は不要となりましたとさ :exclamation: めでたし、めでたし :smile:


参考資料