自鯖やってますか! 仮想化やってますか! サーバを公開してますか!
突然ですけど、最近、RedMineとか使い始めました。家の中で。でも、これが困ったことに、外でも使いたくなるんですよね。
しかし、まぁ、残念ながら我が家は Global IP が一つしかないので、Webサーバを既に 1台公開している状態では、他に立ててしまった WebサーバのRedMineを公開することができないのです。
まぁ、FireWallで、ポート番号を変えてアクセスさせれば、それはそれで対応できるんですが、Webサーバ毎にポートを割り当てるのはナンセンスですし、家の中からの場合と、外からの場合とでアクセスURLが変わってしまうのはちょっと残念です。
さて、どうすれば良いのか、とここ数日で達成しえた内容をレポートします。
目次
1.現状認識
まず、現状を認識しましょう。その上で、どのようにすべきかを考えます。
現在の状態も分からずに対処することほど、おこがましいことはありません。さぁ、我が家の Webサーバ周りはどうなっているでしょうか。
[I]Private IPアドレスは説明ように別のものを割り当てています
こんな感じです。
よくよく考えたら、munin や zabbixも別のサーバとして構成していたので、外からはアクセスできない状況でした。これはいかん。
仮想化が簡単に利用できるようになればなるほど、こうやって、サーバーノードは増えていく傾向にありますね。
現状の構成をまとめると、次のようになっています。
- FireWallにてNATをかけて、1台のApache Webサーバのみを公開している
- Apache では仮想ホスト(vhost)を利用している
- munin,zabbix,RedMineは異なるサーバで実行されている
- 外部向けGlobal IPアドレスは一つしか無い
2.なにを実現したいか
次、これらをどうしたいか。です。
要求事項を列挙してみましょう。
- 現状のApache Webサーバと同じように、munin、zabbix、RedMineへ仮想ホスト名を与えて、その仮想ホスト名で Internet(外側)からもアクセスしたい
- Internet/Intranet(My Home)いずれも、同じURLでアクセスしたい
単純明確です。
3.どのように実現するか
では、どのように実装すれば良いのでしょうか。
FireWall では Layer-4までの Filteringしかできないものを使っていますので、ここに頼ることはできません。
そのため、Webサーバの前に Reverse PROXYをおく方法が妥当と判断しました。これは、LVS などで LoadBalancer を置くことでも対処できるでしょう。
なぜ、今回 PROXYを採用したかというと、1)キャッシュ 2)アクセス制御、への対応が柔軟・簡単だと判断しました。PROXY は元々キャッシングのためにあるようなものですから、キャッシング機能は十分です。
アクセス制御機能に関しても、URL など Layer7での制御可能なものを考えると、PROXYサーバのほうが柔軟・お手軽ではないでしょうか。
とは言え、まずはキャッシュやアクセス制御のことも忘れて、Reverse PROXY にて実装する方向で考えます。
3-1.Reverse PROXY構成を考える
Reverse PROXYは”squid : Optimising Web Delivery“さんを採用します。
Apache の mod-proxy なども採用実績は高いですが、仮想ホストが沢山増えてきた場合に、いちいち構成しないといけなさそうだった mod-proxy がちょっとめんどうに見えたので、squid さんを採用することにしました。負荷分散や、外部の機能連携などもあり、認証機能との連携豊富さにも悶えましたし。
では、squid を挟んでみると、どのような構成になるでしょうか。
こうなりました。
各Webサーバは、Internetからのアクセスの際に、必ず squid を経由するルートを通るようにしました。
Transparent Proxy + Reverse と言う構成にもちょっと悶えたのですが、ネットワークセグメントの作り直しなどがめんどうだったので、同じセグメントにsquidを配置する方法としました。
セキュリティも考慮すると、squid を専用の DMZ(今時言わないか)のセグメントにおいて、他のサーバは、一段後ろへ持っていくことが常套でしょう。ゆくゆくはそうしていきたいです。
対応は大きく三つ
- squid:Reverse PROXYサーバを準備する
- Internet/Intranet(My Home)の端末とでは、同じドメイン名で異なるIPアドレスを返すようにする
- FireWall:NATの宛先をWebサーバから、squidへ変更する
3-2.squid:Reverse PROXY構成
squid での実現方法について説明します。
今回は、いつものように debian wheezy で、squid3 (squid 3.1.20) を利用します。
まずはsquidをインストールしましょう。aptitude にお任せです。
1 | # sudo aptitude install squid3 |
次に、/etc/squid3/squid.conf を修正します。今回の構成での変更点は次のようになります。
3-2-1. acl の設定
aclを追加しましょう。
各サーバへのドメイン名の定義になります。
1 2 3 4 | acl oshiire_server dstdomain oshiire.to acl redmine_server dstdomain redmine.oshiire.to xxxx.oshiire.to acl zabbix_server dstdomain zabbix.oshiire.to xxxx.oshiire.to acl munin_server dstdomain munin.oshiire.to xxxx.oshiire.to |
- oshiire_server
- 元々 apache webサーバとして、全体に公開していたものです。標準のドメイン名となる “oshiire.to” が与えられています。
- redmine_server
- redmineサーバのドメインを指定しています。一応、localで割り当てている個別のホスト名も追加して入れていますが、なくても平気のはずです。
※ xxxx は固有のホスト名になっています - zabbix_server
- 同じく zabbixサーバのドメインを指定しています。
- munin_server
- これも同じです。構成が同じであれば、特にここでの設定は、他のサーバと変わりはありません
3-2-2. Reverse PROXYの構成にする
アクセスされるポート番号と、Reverse PROXY である構成を実現します。
1 2 | http_access allow all http_port 80 accel vhost |
- http_access allow all
- http_access deny all の前に置くことが精神的にも良いとされています。
どこからのアクセスでも、許可する設定です。これがないと、Internet からのアクセスは全て denyされます。 - http_port 80 accel vhost
- Reverse PROXY であることなどを宣言するのが、この行です。
80 … tcp port:80 で起動することを宣言しています。NATをかけるので、80でなくても好きなもので良いのですが、今回、FireWall での宛先だけを変更して、ルールを追加せずに対応するために 80にしておきました。好きなポートを使ってください。
accel … アクセラレータモードをONです。vhost を利用するために必要です。
vhost … 仮想ホストを利用してアクセスさせることを宣言しています。背後の Apacheで仮想ホストを利用している場合には必須となります。
まだあります。
ホスト名とサーバの割当と、ドメイン名の割当です。
1 2 3 4 5 6 7 8 9 | cache_peer 172.16.10.14 parent 80 0 no-query originserver name=redmine_server login=PASS cache_peer 172.16.10.13 parent 80 0 no-query originserver name=zabbix_server login=PASS cache_peer 172.16.10.12 parent 80 0 no-query originserver name=munin_server login=PASS cache_peer 172.16.10.11 parent 80 0 no-query originserver name=oshiire_server login=PASS cache_peer_domain redmine_server redmine.oshiire.to xxxx.oshiire.to cache_peer_domain zabbix_server zabbix.oshiire.to xxxx.oshiire.to cache_peer_domain munin_server munin.oshiire.to xxxx.oshiire.to cache_peer_domain oshiire_server .oshiire.to |
- cache_peer hostname type http-port icp-port [options]
- 背後のサーバを指定します。
hostname … 対象となるサーバのアドレス(ホスト名)を指定します。
type … ‘parent’は、対象が「親」であることを示しています。宛先の役割を示します。主従関係を示すわけです。
http-port … 宛先のポート番号です。今回はすべてのWebサーバがポートを変えていないので、全て80です
icp-port … 宛先で ICPがサポートされていない場合は ‘0’ です。’0’=disable らしいです。おまじないだと思ってつけておいてください。
[options] … Reverse PROXYとして重要な成分が、ここに集約されています。今回設定しているものをご紹介します- no-query : ICPクエリを発行しないよ、と言う宣言です。これもおまじない扱いで良いです。
- originserver : これも Reverse PROXY構成ではおまじないですが、Parent 指定しているとき、相手先が Webサーバですよ、と言う宣言です。これぞ、Reverse PROXYの宣言
- name= : ここにaclを指定します。どのホストへの宛先か、と言うのをここで割り当てます
- login=PASS : Authorization ヘッダ利用時にはこれが必要です。認証情報をそのまま引き継ぐよという指定みたいですが、今回、RedMine ではiPhoneアプリからのアクセスをさせたく、その場合に REST APIを利用するのですが、その場合には、このオプションが必須です。これがないと、REST 使えません
※ 参考 : “Azure | myownwords“
- cache_peer_domain cache-host domain [domain …]
- 指定したドメインのアクセスを制御します
cache_peer と対になって利用する形になります。俄然、よく分かってません
cache-host … cache_peer で指定した相手先を指定するのですが、name=の先のaclを指定するようです。
domain … その相手先にアクセス可能なドメイン名を指定します。”.oshiire.to” とすると、サブドメインも全て含む、と言う設定になります。従って、redmine.oshiire.to=>redmine_server、munin.oshiire.to=>munin_server となり、その他の yyyy.oshiire.to や、zzzz.oshiire.to などは oshiire_server へと割り当てられるようです
3-2-3.Internet/Intranet(My Home)の端末とでは、同じドメイン名で異なるIPアドレスを返すようにする
例えばこのような感じにします。
今回、squid では宛先をIPアドレスで指定していますが、ホスト名にしておくと、もっと優雅に設定できそうです。
bind であれば、view
を利用すれば良いですし、nsd を使う場合は、外部用と内部用の 2つのサーバを動かす必要があります。
そもそも、このようなタイプではなく、”My Home”内のホスト名は、すべて squid宛として “172.16.10.10”を返すようにして、内部のアクセスも PROXY経由にすることができそうです。
今回は、外部のアクセスのみを squidのアクセスへ記録できるように、分離ができると考えてこのような構成にしています。
3-2-4.FireWall:NATの宛先をWebサーバから、squidへ変更する
最後に、FireWallの NAT宛先を squid宛へ変更したら完成です。
ここは各自でお持ちのマニュアルを参考にしましょう。
4.おまけ
Reverse PROXY化によって、影響のあるものへの対処をいくつか。
4-1.WordPress のIP取得
Reverse PROXY背後になるコトによって、各Webサーバの access.logでは、アクセス元が全て squidサーバのアドレスになります。
WordPress も例外ではなく、ここでなにもしないと、アクセス解析系が全滅です。
そこで、/etc/squid3/squid.conf と [wordpress directory]/wp-config.php に次の行を追加しましょう。
/etc/squid3/squid.conf
1 | follow_x_forwarded_for allow all |
[wordpress directory]/wp-config.php
1 2 | $_SERVER['HTTP_HOST'] = $_SERVER['HTTP_X_FORWARDED_HOST']; $_SERVER['REMOTE_ADDR'] = $_SERVER['HTTP_X_FORWARDED_FOR']; |
※ 参考 : “リバースプロキシ配下のWordPress » ねころくぶろぐ”
4-2.munin で監視する
squid もめでたく、munin 様で監視できます。
次のコマンドを実行しましょう。
1 | # sudo ln -s /usr/share/munin/plugins/squid_* /etc/munin/plugins/ |
次のような symbolic link ができてれば成功です。
1 2 3 4 5 | /etc/munin/plugins/squid_cache -> /usr/share/munin/plugins/squid_cache /etc/munin/plugins/squid_icp -> /usr/share/munin/plugins/squid_icp /etc/munin/plugins/squid_objectsize -> /usr/share/munin/plugins/squid_objectsize /etc/munin/plugins/squid_requests -> /usr/share/munin/plugins/squid_requests /etc/munin/plugins/squid_traffic -> /usr/share/munin/plugins/squid_traffic |
munin-node の構成ファイルの修正も必要になるかも知れません。
次のファイルに、以下の行を追加して、必要な項目のみ有効化しましょう。サンプルですので、今回の構成であれば、”env.squidport 80″ のみでいけます。
/etc/munin/plugin-conf.d/munin-node
1 2 3 4 5 6 7 8 9 | [squid_*] # squidhost - host (default "localhost") # squidport - port (default "3128") # squiduser - username (default "") # squidpasswd - password (default "") env.squidhost localhost env.squidport 80 env.squiduser admin env.squidpasswd p@ssw0rd |
4-3.muninに認証をつけよう
muninやzabbixなどが、外からアクセスできるようになってしまいますので、認証をつけておきましょう。
zabbixやredmineはユーザ認証機能を持っているので、そのままでもある意味問題ありませんが、munin は URLばれると、アクセスし放題です。見られ放題です。ドMならそのままで、多少なりとも恥じらいとセキュリティの意識があれば、少なくともBASIC認証程度はつけておきましょう。
muninの鯖で設定が必要です。
debian Wheezyの場合です。次のコマンドでパスワードを作りましょう。usernameはお好みで好きなものでどうぞ。
1 | # sudo htpasswd -c /etc/munin/munin-htpasswd username |
次は、apache の munin用設定ファイルの修正です。
/etc/apache2/conf.d/munin
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | <directory /var/cache/munin/www> Order allow,deny Allow from localhost xxx.xxx.xxx.0/24 Options None # This file can be used as a .htaccess file, or a part of your apache # config file. # # For the .htaccess file option to work the munin www directory # (/var/cache/munin/www) must have "AllowOverride all" or something # close to that set. # AuthUserFile /etc/munin/munin-htpasswd AuthName "Munin" AuthType Basic require valid-user # This next part requires mod_expires to be enabled. # # Set the default expiration time for files to 5 minutes 10 seconds from # their creation (modification) time. There are probably new files by # that time. # <ifModule mod_expires.c> ExpiresActive On ExpiresDefault M310 </ifModule> </directory> |
どこよ(‘A`)という感じなので、ココです。この 4行を有効化してください。
1 2 3 4 | AuthUserFile /etc/munin/munin-htpasswd AuthName "Munin" AuthType Basic require valid-user |
ついてる ‘#’ を外せってことですね。さぁ、あとは次のコマンドで、apache2 再起動でどうぞ。
1 | # sudo service apache2 restart |
[tmkm-amazon]1849513902[/tmkm-amazon]
References
↑I | Private IPアドレスは説明ように別のものを割り当てています |
---|
なんでVirtual Hostを使わないんですか?
内部では論理的に別のIPアドレスで、複数のWEBサーバを立ち上げているので、それらへ振り分けるためです。
1台の WEBサーバ上に、複数ドメインを共有するのであれば、VirtualHost も勿論使えますし、実際に我が家でも使っています。
ただ、今回は WEBサーバを分けざるをえない状況になったため、このような方式をとっています。