Squid Reverse Proxy with Domain Based Virtual Hosting for HTTP

IPv4のアドレス枯渇が叫ばれている昨今、企業も行政も外部公開用サーバに割り当て可能なグローバルIPアドレス(IPv4)には限りがあります。
多くの場合は8-IPまたは16-IPをISPから割り当てて貰って運用している、といったところでしょうか。
実際はネットワークアドレス、ブロードキャストアドレス、デフォルトゲートウェイ(インターネット接続用ルータ、またはファイアウォール
)で3-IP消費するので、サーバに割り当て可能なのは5-IPまたは13-IPが正確なところでしょう。
県庁クラスの大きな行政ともなると、様々なWebサーバ(またはWebアプリケーションサーバ)を公開しており、これらと1対1で紐付けしてはIPアドレスが圧倒的に不足します。
で、これを解決するのが今回の題目でもあるリバースプロキシ(Reverse Proxy)なのです。

今回主に参考にした情報は本家であるsquid-cache wiki Reverse Proxy with HTTP/1.1 Domain Based Virtual Host Support
当然のことながら全て英語です。
また検証した環境は以下の通り。

サーバのH/W: 秘密(ASUSのOEMでメモリが128MBの非力なノートPCとだけ言っておく)
OS: CentOS 5.9 i386
Squid: squid-2.6.STABLE21-6.el5.i386
IPアドレス(公開ドメイン名):

Squid Proxy: 192.168.1.1
sv-1: 192.168.1.2 (first.example.com)
sv-2: 192.168.1.3 (second.example.com)
sv-3: 192.168.1.4 (third.example.com)
DefaultGateway: 192.168.1.254

DNS情報

first.example.com. A x.y.z.10
second.example.com. A x.y.z.10
third.example.com. A x.y.z.10

NAT設定(ルーターまたはファイアウォールに機能依存)

グローバルIPアドレス(IPv4) x.y.z.10 Port 80
↓↑
プライベートIPアドレス(IPv4) 192.168.1.1 Port 80

以下が実際の設定方法になります。

1. 設定ファイル(/etc/squid/squid.conf)のオープン

# vi /etc/squid/squid.conf

viエディタで設定ファイルをオープンします。

2. ホスト名の設定

visble_hostname CentOS4

DNSでIPアドレスからホスト名を逆引きない場合、squidはエラーで起動しないので、手動でホスト名を設定する必要があります。
エラー画面の表示などで使用されるので、正式なホスト名でなくともOKです。

3. 待ち受けIPアドレスとポートの設定

http_port 192.168.1.1:80 accel vhost

IPアドレスが1つしか割り当てられていない場合はポート番号のみでもOKです。
複数のIPアドレスがある場合、指定しないと全てのIPアドレスのポートで待ち受けするようになります。

4. ヴァーチャルドメイン名とIPアドレスの紐付けの設定

# first.example.com -> 192.168.1.2(port 80)
acl site-1 dstdomain first.example.com
http_access allow site-1
cache_peer 192.168.1.2 parent 80 0 no-query originserver name=sv-1
cache_peer_access sv-1 allow site-1
cache_peer_access sv-1 deny all

URIが"first.example.com/*"のアクセスをIPアドレス 192.168.1.2のport 80へ転送します。
2行目のaclでドメイン名を設定
3行目で2行目のaclで設定したドメインへのアクセスを許可
4行目でreverse proxyの設定(実サーバのIPアドレスとポート番号を指定。ここではIPアドレスを用いていますが、DNSで名前解決が可能な環境ならばFQDNで記述することも可能。ただし、DNSの応答性が悪いとレスポンスに影響を及ぼすし、DNSがダウンすれば正常機能しなくなります)
5行目でaclのドメイン名と実サーバの紐付け(多くのサイトではcache_peer_domainを用いてますが、ここでは敢えて本家の設定例に倣っています)
6行目で5行目に該当しないアクセスを拒否

# second.example.com -> 192.168.1.3(port 80)
acl site-2 dstdomain second.example.com
http_access allow site-2
cache_peer 192.168.1.3 parent 80 0 no-query originserver name=sv-2
cache_peer_access sv-2 allow site-2
cache_peer_access sv-2 deny all

URIが"second.example.com/*"のアクセスをIPアドレス 192.168.1.3のport 80へ転送します。
詳細は"first.example.com"と同じなので割愛

# third.example.com -> 192.168.1.4(port 80)
acl site-3 dstdomain third.example.com
http_access allow site-3
cache_peer 192.168.1.4 parent 80 0 no-query originserver name=sv-3
cache_peer_access sv-3 allow site-3
cache_peer_access sv-3 deny all

URIが"third.example.com/*"のアクセスをIPアドレス 192.168.1.4のport 80へ転送します。
詳細は"first.example.com"と同じなので割愛

転送したいサーバの分だけ、この設定を繰り返します。
1つの実サーバで複数のドメインを運用している場合(Name-based Virtual Host)、2行目のaclに対象となるドメインを複数記述します。

# third.example.com -> 192.168.1.4(port 80)
# fourth.example.com -> 192.168.1.4(port 80)
acl site-3 dstdomain third.example.com fourth.example.com
cache_peer 192.168.1.4 parent 80 0 no-query originserver name=sv-3
cache_peer_access sv-3 allow site-3
cache_peer_access sv-3 deny all

論理的には動作するはずですが、未検証ですので...動かなかったら御免なさい。

5. おまけ(おなじない?)

acl no_cache urlpath_regex .*\/cgi-bin\/.*
acl no_cache urlpath_regex .*\.php$
acl no_cache urlpath_regex .*\.php\?.*
cache deny no_cache

動的コンテンツ(CGIスクリプトやPHPスクリプト)はキャッシュ対象外とします。

#cache_dir ufs /var/spool/squid 100 16 256 
cache_dir coss /var/spool/squid/coss 300 block-size=2048 max-size=500000
cache_swap_log /var/spool/squid/%s

ディスクキャッシュ方式をufsではなくcossへ変更。
メリット・デメリットはわかりません(笑)

6. 変更の保存

:wq

上記コマンドで保存してviエディタを終了します。

7. Squidの起動または再起動

起動する場合
# service squid start

再起動する場合
# service squid restart

設定に問題がなければsquidが起動します。
起動しない場合は設定ファイルを見直して修正します。

これで一つのグローバルIPアドレス(IPv4)で複数のWebサーバ(プライベートIPアドレス)を外部に公開して運用することが可能になります。
まぁ、これは基本中の基本設定なので、応用設定については各自勉強してみて下さい。