最近クラウドの利用がますます増えて、オンプレシステムをAWSやAzureなどのクラウドに移行するケースが増えています。
オンプレのWebアプリケーションをAWSに移行する際に、Webサーバーといっしょにロードバランサーも移行することも検討されると思いますが、AWSのマーケットプレイスに利用しているロードバランサーがあるとも限りません。また昨今ではAWSの機能を利用してシステムを組み直すこともできます。
AWSにはApplication Load Balancer(以下、ALB)があり、オンプレで利用していたロードバランサーの代わりにALBを利用することができます。
このALBにはロードバランサーとして動作するのはもちろん、HTTPSで受信したものを復号してバックエンド (ターゲット)のWebサーバーにHTTPとしてデータを渡すことができるSSLオフロードの機能があり、Webサーバーで復号処理が不要となりWebサーバー自体の負荷を軽減させることが可能です。
そこで、Soliton OneGate(以下、OneGate)から発行したサーバー証明書を利用してALBでSSLオフロードを実現する方法を紹介します。
ALBを利用するには、VPCにそれぞれ異なるアベイラビリティゾーンのサブネットが2つ以上必要になります。それぞれのアベイラビリティゾーンのサブネットにAmazon Linux 2023でWebサーバーを構築して、これをALBでHTTPS化するようにします。
通常であればWebサーバーはメンテナンス用の作業用マシンを作成し、そのマシンからのみSSH接続を許可する構成を取ることが多いと思いますが、今回は割愛させていただき、社内(宅内)ネットワークから直接SSH接続する構成にしております。
今回は新規でVPCの作成から行い、最終的にALBでロードバランシングしつつ、SSLオフロードする方法を紹介します。
大まかな流れは次の通りです。
なお、新規でVPCやインターネットゲートウェイ、サブネット、EC2インスタンスを作成しておりますが、既にVPCや異なるアベイラビリティゾーンのサブネットが2つ以上ある場合はそちらを利用していただいても問題ございません。
今回利用しているAWS上に色々と検証環境があり、それらと区別するために名前タグの命名規則を「NetAtest-<リソース名>」としています。実際に構築する場合には、自社内のAWS利用規則に従って命名規則やVPCのIPアドレスレンジなどを設定してください。

| 項目 | 値 |
| 作成するリソース | VPCのみ |
| 名前タグ-オプション | NetAttest-vpc |
| IPv4 CIDRブロック | IPv4 CIDRの手動入力 |
| IPv4 CIDR | 適当なアドレス範囲 例)192.168.0.0/16 |
| IPv6 CIDRブロック | IPv6 CIDRブロックなし |



既にインターネットゲートウェイがある場合には、作成せずにそちらをご利用になられても問題ございません。




先に説明した通り、ALBを利用するにはアベイラビリティゾーンが異なるサブネットが2つ以上必要になります。今回は東京リージョンのap-northeast-1aとap-northeast-1cの2つのアベイラビリティゾーンに所属するサブネットを作成します。
こちらに関しても既にVPCに異なるアベイラビリティゾーンのサブネットがあれば新規に作成しないでも大丈夫です。

| 項目 | 値 |
| VPC ID | 作成したVPC 例)NetAttest-vpc |
| サブネット名 | ap-northeast-1a所属がわかるような名前 例)NetAttest-1a-sub |
| アベイラビリティゾーン | アジアパシフィック(東京)/ap-northeast-1a |
| IPv4 VPC CIDRブロック | NetAttest-vpcのCIDRブロック 例)192.168.0.0/16 |
| IPv4サブネット CIDRブロック | 適当なサブネット 例)192.168.1.0/24 |

| 項目 | 値 |
| サブネット名 | ap-northeast-1c所属がわかるような名前 例)NetAttest-1c-sub |
| アベイラビリティゾーン | アジアパシフィック(東京)/ap-northeast-1c |
| IPv4 VPC CIDRブロック | NetAttest-vpcのCIDRブロック |
| IPv4 サブネットCIDRブロック | 192.168.2.0/24 |

サブネットからインターネットに出れるようにルートテーブルを作成します。
こちらについても既に作成済みのサブネットに紐づいているルートテーブルがあれば新規に作成しなくても大丈夫です。

| 項目 | 値 |
| 名前 | NetAttest-rt |
| VPC | 作成済みのVPC 例)NetAttest-vpc |





| 項目 | 値 |
| 送信先 | 0.0.0.0/0 |
| ターゲット | インターネットゲートウェイ NetAttest-ig |

これから構築するWebサーバーに対して社内からのみSSHとHTTPアクセスを許可するセキュリティグループを作成します。
WebサーバーにSSH接続する際のキーペアを作成します。既存で作成済みのキーペアを利用する場合には、この操作は不要です。
EC2ダッシュボードにて「ネットワーク&セキュリティ」→「キーペア」を開き「キーペアを作成」をクリックします。 
下記を設定して「キーペアを作成」をクリックします。
| 項目 | 値 |
| 名前 | NetAttest-Key |
| キーペアのタイプ | ED25519 |
| プライベートキーファイル形式 | SSH接続にTeraTermを利用する場合には「.pem」を選択 |
Amazon Linux 2023を使ってWebサーバーを構築します。Webサーバーはnginxを使用します。

| 項目 | 値 |
| 名前 | NetAttet-1a-web |

| 項目 | 値 |
| Amazonマシンイメージ(AMI) | Amazon Linux 2023 AMI |
| アーキテクチャ | 64ビット(x86) |

| 項目 | 値 |
| インスタンスタイプ | t2.micro |

| 項目 | 値 |
| キーペア名 | NetAttest-key |

| 項目 | 値 |
| VPC | NetAttest-vpc |
| サブネット | NetAttest-1a-sub |
| パブリックIPの自動割り当て | 有効化 ※Webサーバー構築後に「無効化」にします |
| ファイアウォール(セキュリティグループ) | 既存のセキュリティグループを選択する |
| 共通のセキュリティグループ | NetAttest-WebSrv-nsg |



$ sudo timedatectl set-timezone Asia/Tokyo$ sudo dnf -y install nginx
$ sudo systemctl start nginx
$ sudo systemctl enable nginx
Created symlink /etc/systemd/system/multi-user.target.wants/nginx.service → /usr/lib/systemd/system/nginx.service.
$ systemctl is-enabled nginx
enabled$ sudo rm -r /usr/share/nginx/html/index.html
$ sudo vi /usr/share/nginx/html/index.html<html>
<head>
<meta charset="UTF-8">
<style type="text/css">
body {background-color: green}
h1,p {color: white}
</style>
<title>Webサーバー1へようこそ</title>
</head>
<body>
<h1>Webサーバー1へようこそ</h1>
<p>このサーバーはap-northeast-1aで動作しています。</p>
</body>
</html>
※アクセスできない場合には、EC2ダッシュボードにてインスタンスを開いてセキュリティタブに表示されているインバウンドルールが間違っていないかを確認してください。NetAttest-1a-subに構築したWebサーバーと同等のものをNetAttest-1c-subに構築します。

| 項目 | 値 |
| 名前 | NetAttet-1c-web |

| 項目 | 値 |
| Amazonマシンイメージ(AMI) | Amazon Linux 2023 AMI |
| アーキテクチャ | 64ビット(x86) |

| 項目 | 値 |
| インスタンスタイプ | t2.micro |

| 項目 | 値 |
| キーペア名 | NetAttest-key |

| 項目 | 値 |
| VPC | NetAttest-vpc |
| サブネット | NetAttest-1c-sub |
| パブリックIPの自動割り当て | 有効化 ※Webサーバー構築後に「無効化」にします |
| ファイアウォール(セキュリティグループ) | 既存のセキュリティグループを選択する |
| 共通のセキュリティグループ | NetAttest-WebSrv-nsg |



$ sudo timedatectl set-timezone Asia/Tokyo
$ sudo dnf -y install nginx
$ sudo systemctl start nginx
$ sudo systemctl enable nginx
Created symlink /etc/systemd/system/multi-user.target.wants/nginx.service → /usr/lib/systemd/system/nginx.service.
$ systemctl is-enabled nginx
enabled
$ sudo rm -r /usr/share/nginx/html/index.html
$ sudo vi /usr/share/nginx/html/index.html<html>
<head>
<meta charset="UTF-8">
<style type="text/css">
body {background-color: blue;}
h1,p {color: white}
</style>
<title>Webサーバー2へようこそ</title>
</head>
<body>
<h1>Webサーバー2へようこそ</h1>
<p>このサーバーはap-northeast-1cで動作しています。</p>
</body>
</html>
※アクセスできない場合には、EC2ダッシュボードにてインスタンスを開いてセキュリティタブに表示されているインバウンドルールが間違っていないかを確認してください。構築した2つのWebサーバーへのHTTPアクセスをALBでロードバランシングさせます。
ALB経由でWebサーバーにHTTP及びHTTPSでアクセスできるように、ALBに対してHTTPとHTTPS通信を許可するセキュリティグループを作成します。
Webサーバー用のセキュリティグループでは社内のIPからHTTPで通信ができるようになっていますが、これを廃止してALBのセキュリティグループからHTTPの通信ができるようにします。

| タイプ | ソース |
| SSH | マイIP |
| HTTP | カスタム セキュリティグループ NetAttest-alb-nsg |
| HTTPS | カスタム セキュリティグループ NetAttest-alb-nsg |

ALBでの振り分け先を設定します。

下記のように設定して「次へ」をクリックします。
使用可能なインスタンスにてNetAttest-1a-webインスタンスとNetAttest-1c-webインスタンスにチェックををいれて「保留中として以下を含める」をクリックします。 


下記を設定して「ロードバランサーの作成」をクリックします。



ALBでHTTPのロードバランシングができましたので、これをHTTPS化します。
HTTPS化するには通常であればWebサーバーであるNginx側でSSL有効の設定をするのですが、今回はWebサーバー側はHTTPのままで、ALBでHTTPSをHTTP化して転送するようにします。
OneGateからロードバランサーに対してサーバー証明書を発行します。
今回はサーバー証明書のCNとサブジェクト代替名(SANs)のDNS名については、ALBのDNS名を記載するようにしますが、通常の運用ではALBへのアクセスをAWSが自動生成したDNS名ではなく、自社のDNSサーバーでCNAMEで別名を割り当て、そのCNAMEの値でアクセスすると思いますので、その際にはCNとSANsのDNS名についてはCNAMEの値で発行してください。
NetAttest D3でドメイン管理している場合のCNAMEの例
この場合はCN及びSANsのDNS名は「webapp.example.com」になる


| 項目 | 値 |
| 名前(CN) | ALBのDNS名(※) |
| 国(C) | 日本 |
| 都道府県名(S) | 任意 |
| 市区町村名(L) | 任意 |
| 組織名(O) | 任意 |
| 部署名(OU) | 任意 |
| Emailアドレス | 空欄 |
| DNS名 | ALBのDNS名(※) |
| 鍵長 | 4096 |
| 拡張キー使用方法 | TLS Webサーバー認証(1.3.6.1.5.5.7.3.1) |
| 証明書の有効期限 | 任意 |
| ダウンロードファイル形式 | PEM形式(秘密鍵+サーバー証明書) |
| パスフレーズ | 任意の文字列 |
※OneGateからサーバー証明書を発行する場合、CN及びSANsのDNS名は64文字以下にする必要があります。ALBのリソース名を長い文字列にすると生成されるDNS名が64文字以上になるとこともありますが、その場合にはOneGateでサーバー証明書が発行できなくなります。文字数に引っかかってサーバー証明書が発行できない場合にはCNとSANsのDNS名を「*.ap-northeast-1.elb.amazonaws.com」などワイルドカードを使用した値にしてください。$vi srv-enc.key
-----BEGIN ENCRYPTED PRIVATE KEY-----MIIJmjBMBgkqhkiG9w0BBQ0wPzAnBgkqhkiG9w0BBQwwGgQUVtfcNKOXgr334nGb<中略>kE5GnzNJ92yTuhJfsF4=-----END ENCRYPTED PRIVATE KEY-----$ openssl rsa -in srv-enc.key -out srv.keyEnter pass phrase for srv-enc.key:<サーバー証明書を発行したときのパスフレーズ>writing RSA key$ cat srv.key-----BEGIN PRIVATE KEY-----MIIJQgIBADANBgkqhkiG9w0BAQEFAASCCSwwggkoAgEAAoICAQCoUYcyFGm5ml5g<中略>il698UAW116MV//ggiWpzRMvNMfUUg==-----END PRIVATE KEY-----

$ rm srv.key$ rm srv-enc.keyALBにHTTPSを受信するリスナーを追加し、OneGateで発行したサーバー証明書を使ってHTTPS通信できるようにします。


Webサーバー自体にはサーバー証明書をインポートしておりませんが、ALBがサーバー証明書を使って通信の暗号を代行しています。
SSL通信できることが確認できたので、必要に応じてALBのリスナーからHTTPを削除します。(EC2ダッシュボードの「ロードバランシング」→「ロードバランサー」でNetAttest-albを開き、「リスナーとルール」タブで「HTTP:80」を選択して「リスナーの管理」→「リスナーの削除」で削除できます。) 
ALBを使ってHTTPS通信もできるようになったので「VPCダッシュボード」の「セキュリティ」→「セキュリティグループ」を開いて「NetAttest-alb-nsg」にインバウンドルールで
| タイプ | ソース |
| HTTPS | Anyware-IPv4 |
ただし、現時点ではセキュリティ設計を行っていない Amazon Linux 上に初期状態の Nginx を構成した環境であるため、このまま公開することは、セキュリティ上のリスクを伴う可能性があります。
公開にあたっては、AWS や Web サーバー構築に関する知見を有する専門家にご相談のうえ、慎重にご判断ください。
なお、ALBにもう一工夫加えてOneGateから発行したクライアント証明書を持った端末からのみアクセス可とする方法を取ることができ、よりセキュリティ的に強固なシステムに仕上げることが可能ですので、そちらの方法も紹介できればと考えております。