サーバーがロードバランサー配下にある場合の対処法

#

久しぶりのブログ投稿するカツです。

concrete5 を本番公開した瞬間に下記のようなエラーに直面して頻繁にログアウトされてしまうことはありませんか?

Session Invalidated. Session IP "XXX.XXX.XXX.XXX" did not match provided IP "XXX.XXX.XXX.XXX".

concrete5 の前に AWS の ELB のようなロードバランサーを配置する場合、config で trusted_proxies を設定する必要があります。

以前の記事「ロードバランサーを通してconcrete5のセッションを維持する」や「Cloud9 で concrete5 開発環境を作る」では invalidate_on_ip_mismatch を false にしたり、$_SERVER['REMOTE_ADDR'] を trusted_proxies として設定しています。本番環境ではNGなやり方です。正規なやり方として、ロードバランサーの IP アドレスのみを trusted_proxies として登録してください。

 

設定サンプル /application/config/concrete.php

設定ファイルにロードバランサーの IP アドレスを、IP アドレスや CIDR 形式で登録してください。

複数 IP アドレスがある場合は複数行で登録できます。

 
<?php
return [
    'security' => [
        'trusted_proxies' => [
            'ips' => [
                '【ロードバランサーのIPアドレス】',
            ],
        ]
    ]
];

ファイルアップロード後、concrete5 のキャッシュをクリアすることも忘れずに。

 

AWS の ELB (Elastic Load Balancer) の場合

AWS では VPC の設定を参照し、EC2 が存在する VPC の CIDR ブロックを設定します。これは CLB (Classic Load Balancer) でも ALB (Application Load Balancer) でも同じです。

 

ELB にどのようなIPアドレスが振り分けられるのか・・・、 AWS の公式ドキュメントによると

ロードバランサーが正しくスケーリングできるように、ロードバランサー毎に各サブネットの CIDR ブロックを、最低でも /27 ビットマスク (例: 10.0.0.0/27) にし、少なくとも 8 個の空き IP アドレスを用意してください。ロードバランサーはこれらの IP アドレスを使用して、インスタンスとの接続を確立します。

各 Subnet に 30個以上の IP アドレスの空きを作ってほしいということ。そして VPC の Subnet に8個以上の IP が振り分けられると書いてあります。具体的にどの IP に振り分けられるとは書いていないので、VPC の CIDR ブロックを設定することになります。

※セキュリティグループを強固にするのも忘れずに。

 

例:自分の VPC の CIDR ブロックを見つける方法

VPC の CIDR ブロックの範囲が下記の AWS Management Console で使用しているEC2インスタンスの VPC を見つけます。

そこの「IPv4 CIDR」の項目を探しましょう。

vpc.png

 

/application/config/concrete.php 内の設定は下記のようになります。

<?php
return [
    'security' => [
        'trusted_proxies' => [
            'ips' => [
                '10.0.0.0/16',
            ],
        ]
    ]
];

 

この設定を concrete5 サイトにアップロードしてください。

ファイルアップロード後、concrete5 のキャッシュをクリアすることも忘れずに。

 

頻繁にログアウトが起きてしまう原因と詳しい対策の内容

ちょっと専門的になってしまうので、読み飛ばしていただいても結構です。

concrete5 がベースとして使用している PHP フレームワーク Symfony のセキュリティ機能の仕様によるものです。

concrete5 では、ユーザーのアクセス元 IP アドレスが変わると、強制ログアウトするというセキュリティ機能があります。

例えば、悪意ある人物が、何らかの方法で正しくログインしたユーザーのセッション情報を盗み取り、違う IP アドレスからアクセスするというケースがあるからです。

ロードバランサーを介すると、concrete5 から見えるアクセス元の IP アドレスはロードバランサーの IP アドレスになってしまいます。

ロードバランサーによっては複数台運営されている場合があります。同じユーザーがアクセスしていても別のロードバランサーを介してアクセスしてしまいます。つまり 違う IP アドレスからのアクセスになるので concrete5 でセキュリティ機能が働き、ログアウトされます。

ただ、ロードバランサーでは、通常 X-Forwarded-For というヘッダーを追加し、元々の IP アドレスを情報に追加しています。

concrete5 に、このIP アドレスのロードバランサーは、信頼できるプロキシーサーバー (trusted proxies) だから、X-Forwarded-For の情報を信用して良いよという設定情報を追加します。

こうすることで concrete5 は、ロードバランサーの IP アドレスではなく X-Forwarded-For のヘッダー情報に書かれている IP アドレスをユーザーの IP アドレスとして認識し、突然のログアウト現象が解決されます。

なぜこういう設定を追加する必要があるかと言うと X-Forwarded-For の IP アドレス情報は誰でも任意に追加できます。つまり改ざんが可能だからです。

 

以上


コメント欄を読み込み中