クラウドHA-WAFパターン:SOPHOS UTM9 on Amazon VPCで高可用性のWAFを構築

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

aws-sophos

そろそろマニアック過ぎて、誰もついて来ていない気がしていますw 10ブクマいったら拍手喝采。

今回のエントリーは、下記の2つのエントリーが伏線となっています。まだお読みでない方は、先に下記エントリをご覧下さい。

お気づきでしょうか、UTM9もEC2インスタンスに乗っているコンポーネントであるため、前回ご紹介した「単純にUTM9を配置する構成」の場合、UTMサーバがSPOF(単一障害点)となってしまいます。そこで今回は、SOPHOS UTM9を高可用性(HA)の構成にしてみようと思います。前回のUTM9の構成は、簡略化のために非VPC構成で構築しました。が、今回はより本格的に、VPC上に組み立てていこうと思います。

システム概要

ha-sophos

図をご覧下さい。以上。

としたいところですが、一応解説。

このシステムはELBを2段で噛ましてます。ユーザは1つ目(上: ha-lbext)のELBにアクセスし、複数AZにまたがった「UTMサーバ」にアクセスを振り分けます。UTM9の「本サーバ」には、2つ目(下: ha-lbint)のELBを設定しておき、リクエストが転送されます。この2つ目のELBは「内部ロードバランサ」と呼ばれ、グローバルIPアドレスを持たない、VPC内で利用するロードバランサです。この内部ロードバランサを介して「Webコンテンツサーバ」にリクエストが到達します。2つ目の「内部LB」に対して、1つ目のELBのことは、本エントリーでは「外部LB」と呼ぶことにします。

以上がメインとなる経路です。あとはNATや踏み台サーバを置くか置かないか等によって構成が変わってきます。

上側2つのサブネットには外部LBを配置するため、public-subnetとなるのは確定です。更なる堅牢性を要求するのであれば、外部LBとUTMサーバのサブネットを分けてもいいかもしれません。

下側2つについては、httpd等のインストールのためにyumを使うタイミングがあります。これらを、より堅牢な構成としてprotected-subnet(private-subnate w/NAT)とする場合は、public-subnet側にNATを配置する必要があります。UTMを配置するほどの要件であれば、protected-subnetとすべきでしょう。

ただ、今回はチュートリアル目的であるため、全てのサブネットをpublic-subnetとして構築することにします。

先のエントリーで指摘している通り、UTMサーバは一定のメモリが必要なためm1.smallで立ち上げます。Webコンテンツサーバはt1.microでいきましょう。

システム構築

さて、上記構成を作っていきましょう。そこそこ複雑な構成であるため、先に全体の流れを把握しておきましょう。下記8ステップの作業になります。

  1. VPCの作成
  2. Subnetの作成
  3. Security Groupの作成
  4. Webコンテンツサーバの構築
  5. 内部LBの構築
  6. UTMサーバの起動
  7. 外部LBの構築
  8. UTMサーバの設定

1及び2については、「Amazon VPCを使ったミニマム構成のサーバ環境を構築する」を参考にして構築してください。VPC Wizardを利用しても構いません。全てのsubnetに同じRouteTable(public-subnetのため、InternetGatewayが設定されている)を割り当てればOKですね。

has-vpc-1

以下では、3以降を解説します。

3. Security Groupの作成

全体像としてはこんな感じです。もしSecurity Groupの設定に自身がなければ、VPC内同士の通信許可としてdefaultグループを使っても良いでしょう。

has-secg-5-all

  • secg-lbext : 外部LB用。全IPからtcp/80にアクセスできる。has-secg-2-lbext
  • secg-utm : UTMサーバ用。secg-lbextからtcp/80にアクセスできる。全IPからtcp/4444にアクセスできる。has-secg-3-utm
  • secg-lbint : 内部LB用。secg-utmからtcp/80にアクセスできる。has-secg-4-lbint
  • secg-web : Webコンテンツサーバ用。secg-lbintからtcp/80にアクセスできる。全IPからtcp/22にアクセスできる。
    (スクリーンショット撮り忘れましたw
    「80(HTTP) -> sg-6e******」
    「22(SSH) -> 0.0.0.0/0」
    となります。)

4. Webコンテンツサーバの構築

普通に、Amazon Linux 64bitの最新版を、下側の2つのサブネットに各1つ作成し、それぞれ ha-web-leftとha-web-rightと名付けます。起動先のサブネットを分ける必要があるので、一気に2台作成することはできません。Secutiry Groupはどちらものsecg-webを割り当てましょう。これらのインスタンスには一時的にEIPを振り、SSHでログインします。httpdをインストール&起動し、index.htmlにそれぞれのサーバが認識できるような内容を書き込みます。念のためcurlでアクセスしてみると、index.htmlの内容が取れるはずです。

$ sudo yum -y install httpd
$ sudo service httpd start
$ sudo sh -c 'echo "<html><body>ha-web-left</body></html>" >>/var/www/html/index.html'
$ curl http://localhost
<html><body>ha-web-left</body></html>

HTMLの内容について、2台目はleftではなくrightにしましょうね。慣れている方は、わざわざSSHでログインせずに、User Dataにシェルスクリプトを組み込んでしまえば良いと思います。(ただし、EIPは後の検証のために必須です。)

参考: Amazon EC2のUser Dataにシバンを指定してスクリプトを実行する

5. 内部LBの構築

EC2のManagement Consoleの左側メニューから「Load Balancers」を選択し、Create Load Balancerボタンをクリックします。

2013-03-01_1715-has-lbint-1

ELBの名前として「ha-lbint」を設定し、先ほど作成したVPCを指定します。また「Create an internal load balancer」のチェックボックスをONにするのを忘れないでください。その他はデフォルトで構いません。

2013-03-01_1716-has-lbint-2

この画面はデフォルトのままでも構いませんし、検証をやりやすくするため、Health Check Intervalを0.1秒に、Healthy Thresholdを2にしても構いません。

has-lbint-3

ELB配置先のサブネットは、10.0.20.0/24 と 10.0.21.0/24 を選択。

2013-03-01_1717-has-lbint-4

Security Groupとして、先ほど作成した secg-lbint を指定します。しかし、ここでsecg-lbintがデフォルトで自動選択されているのは、さりげなくManagement Consoleが凝っているところだと思いませんか? よく空気を読んでくれています。

has-lbint-5

内部LB配下に、2つのWebコンテンツサーバを編入します。

has-lbint-6

以上で内部LBの設定を完了させてください。完了してしばらくすると、ステータスが「2 of 2 instances in service」となるはずです。

2013-03-01_1800-has-lbint-status

6. UTMサーバの起動

引き続き、UTMサーバの構築に移ります。以下の作業も、ほぼ同じ作業を2回繰り返す必要があります。それぞれを ha-utm-leftとha-utm-rightと名付けます。起動先のサブネットを分ける必要があるので、一気に2台作成することはできません。

AWS MarketplaceにおけるUTM9のページより、UTMサーバを作成します。Continueボタンをクリックして次のページへ。前回は「1-Click Launch」で起動しましたが、今回はVPC内に起動しなければならないため、「Launch with EC2 Console」側のタブを選択し、適切なリージョン(本エントリの検証ではus-east-1を利用しています)の「Launch with EC2 Console」ボタンをクリックします。

2013-03-01_1740-has-utm-1

起動するAMIやアーキテクチャ等の確認。特に設定項目はありません。

2013-03-01_1741-has-utm-2

サブネットを適切に選択(1度目は10.0.10.0/24、2度目は10.0.11.0/24)し、インスタンスタイプを m1.small に設定します。

2013-03-01_1741-has-utm-3

扱いやすいように、IPアドレスを自動割り当てせず、明示的に指定しておきます。

2013-03-01_1742-has-utm-4

あとはKeyPairは適切に、SecurityGroupは secg-utm を指定し、起動します。これらの2台についても、メンテナンスのためEIPを振っておいてください。 https://(UTMサーバのEIP):4444/ でUTM9のコンソールにアクセスできます。(HTTPSであることに注意!)

ここまでの設定で、EC2インスタンスはこんな感じになっているはずです。

2013-03-01_1750-has-servers

7. 外部LBの構築

続いて、外部LBの構築を行います。先ほどの内部LBとほぼ同様です。ただし、「Create an internal load balancer」のチェックボックスはOFFにしておきます。

2013-03-01_1810-has-lbext-1

ELB配置先のサブネットは、10.0.10.0/24 と 10.0.11.0/24 を選択。

2013-03-01_1811-has-lbext-3

その他、SecurityGroupは ha-lbext を選択。ELB配下に編入するインスタンスは先ほど起動した2台のUTMサーバですね。

2013-03-01_1812-has-lbext-5

以上で、外部LBの構築は完了です。完了してしばらくすると、ステータスが「2 of 2 instances in service」となるはずです。

2013-03-01_1822-has-lbext-status

8. UTMサーバの設定

さああと一息。UTM9の設定を2台分。ほぼ同じ作業を ha-utm-left 及び ha-utm-right に対して行ってください。コンソールへURLは https://(UTMサーバのEIP):4444/ (HTTPSであることに注意!)でしたね。初回設定は以下の通り。Hostnameの所には、プライベートのIPアドレスを入れておきましょう。

2013-03-01_1752-has-utm-5

以下は、以前のエントリを参考にしてください。タイムゾーンや言語の設定もやってしまいましょう。

WAFの「本サーバ」として、内部LBのドメイン名を設定します。

2013-03-01_1801-has-utm-6

WAFの「仮想サーバ」として、外部LBのドメイン名を設定します。

2013-03-01_1833-has-utm-7

最後に、WAFを有効化して完了です。おつかれさまでした。書いてる方もちょっと疲れましたw

検証

まず、ブラウザで、外部LBにアクセスしてみてください。UTMサーバを介して、コンテンツサーバのレスポンスが表示されることを確認しましょう。リロードを繰り返すと、left と right それぞれが等確率で表示されるはずです。

2013-03-01_1834-has-success1

2013-03-01_1837-has-success2

次に、Webコンテンツサーバの模擬障害によるフェイルオーバーを試します。例えばha-web-rightにSSHログインし、httpdをstopしてみます。その上で外部LBを開いたブラウザをリロードすると、ha-web-leftのみが表示されるようになります。

2013-03-01_1839-has-failover-web

続いて、UTMサーバの模擬障害によるフェイルオーバーを試します。ha-utm-leftのWAF機能を、Disableボタンによって停止(左のブラウザが赤信号)させてみます。その上で外部LBを開いたブラウザにリロードを掛けても、サービスが継続していることが分かります。

2013-03-01_1844-has-failover-utm-1

そして、ha-utm-leftの模擬障害は一旦復旧させます。そして今度は ha-utm-right をDisableにしてみても、同様にサービスは継続しています。

2013-03-01_1845-has-failover-utm-2

最後に、起こってはならないことですが、両方のWAFが死んでしまった場合を一応確認しておきましょう。まぁ、想定通り、お亡くなりになりました。

2013-03-01_1847-has-doublefailure-utm

まとめ

さて、長くなってしまいましたが。AWSの本番運用には、Availability Zoneを活用したHA構成が必須です。WAF等の機構を導入する際は、コンテンツサーバだけでなく、そのWAF自体にもHAの構成が必要になってきます。今回は Sophos UTM9 を利用して、その実例を示してみました。