Poundを使ってDynamicDNSでも複数台のWebサーバを公開する

今のところ自宅サーバはDELLマシン一台ですが今後サーバ台数を増やせるようにしました。

DynamicDNSで自宅サーバを構築する場合にはインターネット側から来るアクセスをポート・フォワーディングやDMZなどのルータの設定である特定のPCに向けることが多いと思います。この特定のPCというのかつまり自宅サーバマシンなわけですが、この方法だと困ったことに外側からくるアクセスを1台のPCでしか受けることができません。つまり用途ごとにサーバをわけたり負荷分散するために複数台のWebサーバーを公開することができません。

これを解決するためには、サーバごとに固定IPを割り振る。サーバごとに振り分けるポートを変える。といった方法があります。

最初前者の方法を考えたのですが、固定IPを一つとるのに月1000円くらい取られたりします。

参考:http://flatray.com/ip/

.comのドメインが年間で980円でとれることを考えるとやっぱり高いと思います。しかもサーバを追加するたびにこの料金がかかるとすると、、用途によって携帯電話を何台も持つような感じの無駄遣いなように思えました。決して払えない金額ではないですが、自宅サーバは余ったPCとDynamicDNSでお金を使わずに公開できるのが魅力なわけなので基本はお金を使わない方針で行きたい。というわけでこの方法はなしです。(8IPで年間1000円くらいなら考えますが)

後者のポートで振り分けるというのは、ルータの設定でポート80はPC-Aに、ポート8080はPC-Bにというように振り分ける方法です。この方法でWebサーバを複数台たてるとなると、ポート80以外で待ち受けるサーバにアクセスするには

URLに http://example.com:8080/ みたいにサイトを見る人にポートを指定してもらわないといけなくなります。個人や知り合いだけで使うなら良いかもしれませんが、世の中に公開するURLで8080ってつけてもらうのはちょっと格好悪いです。またすでに公開しているURLの場合はリダイレクトなども考えないといけなくなって面倒です。

で、それ以外の方法を考えていたところそういえば、ソフトウェアでロードバランサーみたいなことができるのを聞いたことがあったなぁと思い調べたところPoundというソフトウェアを見つけました。

Poundはリバースプロキシとも呼ばれたりしますが、受け取ったリクエスト内の宛先のhost名やHTTPヘッダを読んで別のマシンで処理させることができます。つまり宛先が、example.comならPC-Aに処理させる、example.netならPC-Bに処理させるということが可能です。またロードバランサとしても使えて、exmple.comをPC-A,PC-C,PC-Dの3台のいずれかに処理させるということもできます。

とりあえず今回は
PC-Aで http://example.com/ を公開
PC-Bで http://example.net/ を公開
PC-Cで http://example.org/ を公開
というのを例にしてセットアップしてみます。

poundをインストールするのはPC-Aです。poundだけ動かすだけだともったいないのでPC-AでもWebサーバを公開します。図にすると下記のようになります。

network_pound(example)_20080106.jpg

まずインターネットからのアクセスをPC-Aで受けます。DMZでPC-Aにふるか、ポートフォワーディングでport 80をPC-Aにルータを設定しておきます。PC-Aでpoundがport 80で待ち受けます。宛先のホストに応じてPC-A,PC-B,PC-Cに振り分けます。PC-Aではport 80をpoundが使うのでapacheはport 80以外(ここでは8080)でlistenさせます。

今回はDebian GNU/Linuxでやるのでapt-getでインストールします。(PC-Aでセットアップします)

apt-get install libssl-dev pound

startup=1 にします。

vi /etc/default/pound

pound.cfgを編集します。今回は簡単に宛先ごとにIPを割り当てます。192.168.1.100(PC-A)だけはport 8080に振ります。その他の設定についてはman poundで調べてみてください。

ListenHTTP
        Address 192.168.1.100
        Port    80
        ## allow PUT and DELETE also (by default only GET, POST and HEAD)?:
        xHTTP           1
        Service
                HeadRequire "Host: .*example.com.*"
                BackEnd
                        Address 192.168.1.100
                        Port    8080
                End
        End
        Service
                HeadRequire "Host: .*example.net.*"
                BackEnd
                        Address 192.168.1.101
                        Port    80
                End
        End
        Service
                HeadRequire "Host: .*example.org.*"
                BackEnd
                        Address 192.168.1.102
                        Port    80
                End
        End
End

apacheのportを8080に変更してpoundを起動します。

vi /etc/apache2/ports.conf
/etc/init.d/apache2 restart
/etc/init.d/pound start

これでokです。固定IPなし、DynamicDNSで3台のWebサーバを公開(?)できました。ただこれだけではまだ問題があります。PC-Aがリバースプロキシになっているのでこの3台のWebサーバからみるとアクセス元がPC-A(192.168.1.100)になってしまい、アクセスログのアクセス元も192.168.1.100になってしまう他、ローカルサイトをローカルアドレスで制限している場合、外からアクセスでもローカル内でのアクセスと判断されるのでローカルサイトが見放題になってしまいます。

mod_rpafを使うとログの件は解決できるのですが、アクセス制限はスルーされてしまうようです。ログとアクセス制限を両方解決するにはmod_extract_forwarded2があります(apache 1.xならmod_extract_forwarded)。Debianのパッケージにはmod_extract_forwarded2は見あたらないようなのでソースからインストールします。なおmod_extract_forwarded2はpoundを実行しているサーバではなくpoundからリクエストをもらうサーバでインストールする必要があります。今回の場合はPC-A、PC-B、PC-Cの3台です。

最新バージョンは下記サイトを見て適宜置き換えてください。
Module mod_extract_forwarded for Apache 2.0.x

今回は2.0.1をダウンロードしてコンパイルします。

wget http://www.cotds.org/mod_extract_forwarded2/mod_extract_forwarded2-0.1.tar.gz
tar zxf mod_extract_forwarded2-0.1.tar.gz
cd mod_extract_forwarded2-0.1
apxs2 -c -i -a mod_extract_forwarded2.c

面倒なので上記のように素でコンパイルとすると、Debianではapache2の設定が /etc/apache2/httpd.conf にはまるで書いていないので設定ファイルの更新でエラーになります。

apxs:Error: Activation failed for custom /etc/apache2/httpd.conf file..
apxs:Error: At least one `LoadModule' directive already has to exist..

Debianのapache2の設定ファイルの書き方は特殊なのですが、今回はそのやり方を踏襲します。

# /etc/apache2/mods-available/extract_forwarded.load
LoadModule extract_forwarded_module /usr/lib/apache2/modules/mod_extract_forwarded2.so
# /etc/apache2/mods-available/extract_forwarded.conf
AddAcceptForwarder 192.168.1.100

最後に上記設定ファイルを有効にします。

a2enmod extract_forwarded

これでアクセスログやアクセス制限がpoundを実行しているサーバじゃなくちゃんと、ページを見ているPCのもので動作していればokです。

うまく動かない場合アクセス制限は以下のようにして使うことも可能です。

<IfModule mod_setenvif.c>
    SetEnvIf X-Forwarded-For "^192\.168\.1\.[0-9]+" internal
</IfModule>
<Directory /path/to/document>
    Order deny,allow
    Deny from all
    allow from env=internal
</Directory>

poundはクライアントから来たhttpヘッダに加えてX-Forwarded-Forにクライアントのリクエスト元を追加してくれるので、これを使って何らかの処理をすることが可能になります。

poundはただリクエストを振り分けるだけでなくPriorityをつけてロードバランスさせたりSSLのやりとりする機能もあるそうです。また必要になったら調べてみたいと思います。