いますぐ実践! Linuxシステム管理

[バックナンバーのトップへ] [Linux システム管理のトップへ]


いますぐ実践! Linux システム管理 / Vol.147 / 読者数:1282名

こんばんは、うすだです。

ご無沙汰いたしております。1ヶ月も間が空いてしまいました。

お休みをいただいて、ライブマーケットなるものに出店しておりました。

予想に反して、一部のお客さまおよび出店者の方々にウケまして、 濃ゆい栗仲間ができました。
(その反面、売上げに関しては、まだ心の中で折り合いがついてません。)

さらに、名古屋栄のセントラルギャラリーで、クリエーターズマーケットの展示に、 なぜか紛れ込ませてもらっています。今回出店しないのに…。
(ちなみに、11/5 まで展示されています。お近くのかたは是非。)

クリエーターズ・ショーケース
http://usupi.seesaa.net/article/108748645.html

これからも、行動しないより行動して後悔するようにしたいと思った次第です。 また、その心がけを、仕事でも実践せねばと思っております。
(仕事では、後悔はしないほうがよいかしれませんが。)

それでは現実に戻って、今回も、はりきってまいりましょう!

今回のお題 - Apache でバーチャルホストを試してみる

1ヶ月空いた分、しっかり充電したのかと思いきや、 また Apache ネタで申し訳ございません。

でも、Apache を使ったネタは、なぜか心がうきうきしてしまうのです。
特に、何かへんちくりんなことを思いついたときほど、 テンションが上昇してしまいます。

今回はバーチャルホストですので、特にひねったことはしていません。
ですが、バーチャルホストは、Apache を扱う上で避けて通れない道だと思いますので、 ご存じない方は、目を通していただけますと幸いです。

おっと、基本的には、前回と前々回の続きになります。
設定などは、すでになされているという前提で、突き進んでいきます。

Vol.145 - いまさらだけど Apache を動かしてみる
http://www.usupi.org/sysad/145.html
Vol.146 - もうちょっと Apache を動かしてみる
http://www.usupi.org/sysad/146.html


さて、バーチャルホストを実現するには、IPベースと名前ベースという、 2つの方法のうちいずれかを使用します。(併用も可能ではあります。)

IPベース(IP-based)は、各サイト毎に異なるIPアドレスを割り当てる方法です。 待ち受けるIPアドレスが異なりますので、サイトを確実に区別することができますが、 サイトの数だけIPアドレスが必要となります。

名前ベース(Name-based)は、各サイトをホスト名で区別する方法です。
IPアドレスは1つだけで済みますが、 ブラウザがHTTP/1.1に対応している必要があります。 (今はたいてい対応しているはずですが…)

それでは、それぞれの設定方法を、簡単にご紹介します。


まずは、IPベースの設定方法をご紹介します。

ここでは、もともと使用している 192.168.1.225 の他に、 192.168.1.226 というIPアドレスを使用してみたいと思います。
さしあたって、自前のマシンが 192.168.1.226 というアドレスを使えるように、 以下を実行してください。(これには root の権限が必要です。)

  # ifconfig eth0:0 192.168.1.226 up

そして、httpd.conf に以下を追加してください。
以下では、仮に www.example.com というサイトを追加しています。

  Listen 192.168.1.226:65080
  <VirtualHost 192.168.1.226:65080>
    ServerAdmin usu@example.com
    DocumentRoot "/home/usu/httpd/html2"
    ServerName www.example.com
    ErrorLog logs/error2_log
    CustomLog logs/access2_log combined
  </VirtualHost>

ちなみに、最初の行の Listen の設定は、すでに

  Listen 65080

という行があるのでしたら、必要ありません。
(そうではなく、Listen 192.168.1.225:65080 などでしたら必要です。)

上記では、ドキュメントルートを、/home/usu/httpd/html2 としていますので、 以下のように、/home/usu/httpd/html2 以下を作成します。

  $ mkdir ~/httpd/html2
  $ cat > ~/httpd/html2/index.html << E-O-F
  <html><body><p>Hello www.example.com World!</p></body></html>
  E-O-F

作成したら、Apache を再起動して、実際にアクセスしてみましょう。

  $ httpd -f ~/httpd/conf/httpd.conf -k stop
  $ httpd -f ~/httpd/conf/httpd.conf -k start

http://192.168.1.226:65080/ と、IPアドレスで直接アクセスしてもよいですし、 /etc/hosts に以下を追加して、

  192.168.1.226   www.example.com

http://www.example.com:65080/ でアクセスしても構いません。

いずれにしましても、Hello www.example.com World! と言われたら成功です。 言われなかったら、エラーログなどをご確認ください。

 

もし、諸般の事情により、192.168.1.226 など、別のアドレスが使えない場合は、 代わりに localhost を使う方法もあります。

  <VirtualHost 127.0.0.1:65080>
    ServerAdmin usu@localhost
    DocumentRoot "/home/usu/httpd/html2"
    ServerName localhost.usupi.org
    ErrorLog logs/error_local_log
    CustomLog logs/access_local_log combined
  </VirtualHost>

あるいは、ポート番号を変える手もあります。
以下は、65081番を新たに使用する場合の設定です。
(これをバーチャルホストと呼んでいいのかどうか、わかりませんが…。)

  Listen 65081
  <VirtualHost *:65081>
    ServerAdmin usu@usupi.org
    DocumentRoot "/home/usu/httpd/html2"
    ServerName www.usupi.org
    ErrorLog logs/error_65081_log
    CustomLog logs/access_65081_log combined
  </VirtualHost>

さて、お次は、名前ベースの設定方法です。

まず、NameVirtualHost というディレクティブを使用して、 名前ベースのバーチャルホストに使用するIPアドレスを指定します。

  NameVirtualHost 192.168.1.225

そして、www.example.org と www.example.net というサイトを、 以下のように追加してみましょう。

  <VirtualHost 192.168.1.225>
    ServerAdmin usu@example.org
    DocumentRoot "/home/usu/httpd/html3"
    ServerName www.example.org
    ErrorLog logs/error3_log
    CustomLog logs/access3_log combined
  </VirtualHost>
  <VirtualHost 192.168.1.225>
    ServerAdmin usu@example.net
    DocumentRoot "/home/usu/httpd/html4"
    ServerName www.example.net
    ErrorLog logs/error4_log
    CustomLog logs/access4_log combined
  </VirtualHost>

次に、それぞれのドキュメントルートを作成します。

  $ mkdir ~/httpd/html3
  $ cat > ~/httpd/html3/index.html << E-O-F
  <html><body><p>Hello www.example.org World!</p></body></html>
  E-O-F
  $ mkdir ~/httpd/html4
  $ cat > ~/httpd/html4/index.html << E-O-F
  <html><body><p>Hello www.example.net World!</p></body></html>
  E-O-F

作成したら、Apache を再起動して、確認を行います。

  $ httpd -f ~/httpd/conf/httpd.conf -k stop
  $ httpd -f ~/httpd/conf/httpd.conf -k start

ただし、名前ベースですと、IPアドレスで直接確認できません。
ですので、/etc/hosts に以下を追加して、アクセスしてください。

  192.168.1.225   www.example.org www.example.net

 

ちなみに、NameVirtualHost で指定したIPアドレスは、 すべて名前ベースだとみなされますので、 もとのメインの設定が無視されてしまいます。
ですが、Listen 65080 と設定している場合は、 http://localhost:65080/ でアクセスすると、メインのページを参照できます。
(localhost(127.0.0.1) は、 NameVirtualHost で指定したIPアドレスとは異なるためです。)


さて、IPベースや名前ベースとはまた別の、たくさんのサイトを扱う方法もあります。 簡単ではありますが、ご紹介させていただきます。

まず、今回追加した設定を、全部コメントアウトするか削除して、 以下を追加してください。

  VirtualDocumentRoot "/home/usu/httpd/vhosts/%0/html"
  VirtualScriptAlias  "/home/usu/httpd/vhosts/%0/cgi"

そして、ここではお試しで、www.example.org と www.example.net 用のコンテンツを、 以下のように新たに作成します。

  $ mkdir ~/httpd/vhosts
  $ cd ~/httpd/vhosts
  $ mkdir -p www.example.org/html www.example.org/cgi \
  www.example.net/html www.example.net/cgi
  $ cp -p ../html3/index.html www.example.org/html/
  $ cat > www.example.org/cgi/test << E-O-F
  #!/bin/sh
  echo "Content-Type: text/plain"
  echo ""
  echo "www.example.org!"
  E-O-F
  $ cp -p ../html4/index.html www.example.net/html/
  $ cat > www.example.net/cgi/test << E-O-F
  #!/bin/sh
  echo "Content-Type: text/plain"
  echo ""
  echo "www.example.net!"
  E-O-F
  $ chmod 555 www.example.org/cgi/test www.example.net/cgi/test

作成したら、Apache を再起動し、それぞれアクセスしてみてください。

  http://www.example.org:65080/
  http://www.example.org:65080/cgi-bin/test
  http://www.example.net:65080/
  http://www.example.net:65080/cgi-bin/test

ドキュメントルートは、~/httpd/vhosts/ホスト名/html に、 そして CGI のディレクトリは、~/httpd/vhosts/ホスト名/cgi になります。
VirtualDocumentRoot や VirtualScriptAlias ディレクティブで指定したパスの %0 の部分が、ホスト名に置き換わるわけですね。
(ちなみに、%0 が www.example.org の場合、%1 は www, %2 は example, %3 は org に置き換わります。)

ただし、UseCanonicalName を On にしていますと、 %0 が ServerName に置き換えられてしまい、意味がなくなってしまいます。
ですので、UseCanonicalName は Off に設定しておいてください。

また、ScriptAlias の設定がすでにありますと、 VirtualScriptAlias の設定がうまく機能してくれないようです。 CGI が動作せず、ScriptAlias の設定が残っている場合は、 試しにコメントアウトしてみてください。

この設定ですと、新たにサイトが増えた場合、 ~/httpd/vhosts/ホスト名以下を用意するだけで済みますので、 数十〜数百のサイトを扱う場合に、とても楽なのではないかと思います。

あと、蛇足ですが、VirtualDocumentRootIP や VirtualScriptAliasIP という、 IPアドレス版のディレクティブもあります。
(…が、説明は割愛させていただきます。ご了承くださいませ。)


以上、Apache のバーチャルホストに関する設定方法をご紹介しました。

Apache に関するネタはいくらでも出てきそうで、 当メルマガのタイトルを「いますぐ実践! Apache サーバ管理」に改名しようかと思ったくらいです。(も、もちろん、冗談です。そんなにネタはないと思います。)

またヘンなネタを思いついたら、嬉々としてご紹介したいと思いますが、 そうでなくても、Apache はいろいろ触りがいがありますので、 みなさんも是非いろいろ試してみてください。

宿題の答え

前回の宿題は、

  Basic 認証と Digest 認証のやりとりを、生で見てみましょう。

でした。

もっとわかりやすいツールがあると思いますが、 ここではあえて tcpdump でがんばってみたいと思います。

まずは、tcpdump で /tmp/http-basic.log にパケットを記録させます。

  # tcpdump -x -s 1500 -w /tmp/http-basic.log -i lo port 65080

上記を動かしておきながら、Basic 認証を必要とするページに、 ブラウザでアクセスします。

  http://192.168.1.225:65080/authtest/

エラーなどなく Hello Basic Authentication World! と出力されたら、 すみやかに tcpdump を強制終了させて、記録した内容を参照します。

  # tcpdump -x -r /tmp/http-basic.log
  ...省略...

…ああ、これはちょっと、敷居が高すぎますね。
tcpdump でがんばってみましょうと言いましたが、早くも撤回します。
やや長いですが、簡易的なスクリプトをご用意いたしました。

#!/usr/bin/perl
use strict;
my $line = 0;
my @data;
while(<>) {
    chomp;
    if(/^\s+0x([^:]+):\s+(\S.*)$/) {
        if(hex($1) == 0 && $line > 0) {
            parse_tcp(@data);
            @data = (); $line = 0;
        }
        foreach(split(' ', $2)) {
            $data[$line++] = hex($_);
        }
    }
}

sub parse_tcp {
    my @data = @_;
    my $len = $data[1]>>1;
    my $off = (($data[16]>>11) & 0x1f) + 10;
    return 0 if $off >= $len;
    for(my $i=$off; $i<$len; $i++) {
        for(my $j=0; $j<2; $j++) {
            print chr(($data[$i]>>(8-8*$j)) & 0xff);
        }
    }
    print "\n";
}

詳細は割愛しますが、前半の while 文で tcpdump の出力を読み取って、 後半の parse_tcp でデータ部分だけをそのまま出力します。
いろいろ決め打ちな箇所がありますが、ちょこっと試す分には実害はない…と思います。

さて、これを parsetcp.pl というファイル名で保存したら、 以下の手順で実行してみてください。

  $ chmod +x parsetcp.pl
  $ tcpdump -x -r /tmp/http-basic.log | ./parsetcp.pl

今度は、HTTP のやりとりがずらっと出てきたのではないかと思います。 これまた詳細は割愛しますが、以下のようなやりとりが行われています。

  1. GET で、/authtest/ を素直に要求。
  2. 以下のヘッダとともに、404 Authorization Required と言われ、拒否される。
      WWW-Authenticate: Basic realm="basic-auth-test"
    
  3. GET で、以下のヘッダを追加して再度要求。
      Authorization: Basic YXV0aHVzZXI6YXV0aHVzZXIx
    
  4. 今度は、/authtest/index.html をいただけた。

Authorization: で呪文を渡していますが、これは、 ユーザ名:パスワードという文字列を、base64 でエンコードしただけのものです。

  $ echo -n authuser:authuser1 | mmencode
  YXV0aHVzZXI6YXV0aHVzZXIx

ですので、同様の手順で再度確認しても、 Authorization: で渡す呪文は毎回同じです。
…これでは、ユーザ名とパスワードを生で送信しているのと、 さして違いはありませんよね。

 

さて、Digest 認証ではどうでしょうか。
同様に、以下のような手順で確認してみましょう。

  # tcpdump -x -s 1500 -w /tmp/http-digest.log -i lo port 65080
  (この間に http://192.168.1.225:65080/authtest2/ を参照する。
   Hello Digest Authentication World! と言われたら Ctrl-c で停止)
  $ tcpdump -x -r /tmp/http-digest.log | ./parsetcp.pl

すると、以下のようなやりとりが行われていることがわかります。

  1. GET で、/authtest2/ を素直に要求。
  2. 以下のヘッダとともに、404 Authorization Required と言われ、拒否される。
      WWW-Authenticate: Digest realm="digest-auth-test", \
      nonce="uKpu...略", algorithm=MD5, qop="auth"
    
  3. GET で、以下のヘッダを追加して再度要求。
      Authorization: Digest username="authuser", realm="digest-auth-test", \
      nonce="uKpu...略", uri="/authtest2/", algorithm=MD5, \
      response="d7ab...略", qop=auth, nc=00000001, cnonce="e320...略"
    
  4. 今度は、/authtest2/index.html をいただけた。

…うわああ、ややこしいですね…。
2. の nonce は、ランダムな文字列です。いわゆる、 チャレンジコードというやつです。
3. では、詳細はまたまた割愛しますが、nonce を含めた文字列の MD5 値を計算して、 response として返します。

試しに、もう一度同じことをさせてみますと、以下のようになりました。

  1. 以下とともに GET で /authtest2/ を要求。
      Authorization: Digest username="authuser", realm="digest-auth-test", \
      nonce="uKpu...略", uri="/authtest2/", algorithm=MD5, \
      response="725e...略", qop=auth, nc=00000002, cnonce="67ce...略"
    
  2. 以下のヘッダとともに、404 Authorization Required に。
      WWW-Authenticate: Digest realm="digest-auth-test", \
      nonce="hJEs...略", algorithm=MD5, stale=true, qop="auth"
    
  3. 以下とともに GET で再度要求。
      Authorization: Digest username="authuser", realm="digest-auth-test", \
      nonce="hJEs...略", uri="/authtest2/", algorithm=MD5, \
      response="8180...略", qop=auth, nc=00000001, cnonce="a83d...略"
    
  4. 今度は、/authtest2/index.html をいただけた。

別の nonce を使えと言われますので、 response も先ほどとは異なる値になっています。
これですと、毎回異なる文字列を渡すことになり、Basic 認証に比べて、 安心感が増しますね。

 

なんだか見にくくわかりにくくて、申し訳ありません。
実際にやってみると、それほどややこしくはありませんので、時間のあるときにでも、 トライしてみてくださいまし。

今回の宿題

今回の宿題は、

  telnet コマンドを用いて、名前ベースのバーチャルホストの動作確認
  をしてみましょう。

です。

つまり、名前ベースのバーチャルホストの設定が正しいかどうか、 telnet コマンド上で、HTTP/1.1 でやりとりして確認してみてください。

telnet コマンドは各種クライアントになってくれますので、 ブラウザでアクセスできない状況の際に、重宝すると思います。

…な、なんじゃそりゃあ? と思われた貴兄は、以下をご覧くださいませ。

Vol.019 - telnet を活用する
http://www.usupi.ort/sysad/019.html
Vol.020 - telnet でメールのチェックをする
http://www.usupi.ort/sysad/020.html

あとがき

DNSキャッシュポイズニングの問題が、ここのところホットな話題です。
そろそろ、BIND 一辺倒な環境を見直すときなのかもしれませんね。

というわけで、Unbound というキャッシュサーバを試してみました。
発端は、下記の @IT の記事です。

@IT: DNSリゾルバのニューフェイス「Unbound」
http://www.atmarkit.co.jp/flinux/special/unbound/unbounda.html
Unbound (本家のページ)
http://unbound.net/
日本Unboundユーザ会
http://unbound.jp/

本家では、ソースコードのみ公開されていますが、日本Unboundユーザ会では、 主要なディストリビューションのパッケージを公開してくださっています。 非常にありがたいです。

安直なわたくしは、上記から SRPM を入手し、Vine に入れてみました。
rpm --rebuild するだけで、あっけなく RPM ができ、 インストールまで難なくこぎつけました。

とりあえず、素の設定のままでも、問題なく動作してくれます。
ただ、デフォルトでは localhost のみ listen しますので、 他のマシンから利用される場合は、 interface と access-control の設定を行う必要があります。

IPv4 だけの例:
  # 192.168.1.225 で listen (0.0.0.0 にするとすべて)
  interface 192.168.1.225
  # localhost と 192.168.1.* からの問合せに答える
  access-control: 0.0.0.0/0 refuse
  access-control: 127.0.0.0/8 allow
  access-control: 192.168.1.0/24 allow

いまのところ、まったく問題なく動作していますが、問題は、 BIND との違いがよくわからないことでしょうか。
違い(脆弱でなくなったこと)がはっきりわかるツールがあるとよいのですが… どこかにないでしょうか?

まあ、使いつづけて問題がなければ、 適用範囲を徐々に広げていこうかなと思っています。

というわけで、導入自体は簡単ですので、気になった貴兄は、お試し環境の上などで、 ぜひ試してみてください。

 

…ああ、とうとう500行を越えてしまいました。
次回以降は、もうちょっとコンパクトにまとめます。すみません!

 

今回も、ここまで読んでいただき、ありがとうございました。
それでは、次回は 11月16日(日) 頃に、お会いしましょう!

 

「いますぐ実践! Linux システム管理」の解除は、以下からできます。
http://www.usupi.org/sysad/ (まぐまぐ ID:149633)

バックナンバーは、こちらにほぼ全部そろっています。
http://www.usupi.org/sysad/backno.html

「栗日記」−このチャンスを最大限有効活用したい今日このごろです。
http://www.usupi.org/kuri/ (まぐまぐ ID:126454)
http://usupi.seesaa.net/ (栗日記ブログ)
http://usupi.org/k/ (モバイル栗日記)


[バックナンバーのトップへ] [Linux システム管理のトップへ]

トップ

バックナンバー
    [日付順] [目的別]

プロフィール

▼ リンク

独学Linux
Linuxデスクトップ環境に関する情報が満載です。 メルマガもありますよ。
Server World
CentOS 6をサーバとしたときの設定例が、これでもかというくらいたくさん載っています。 CentOS以外のディストリビューション(Fedora, Ubuntu)も充実しています。
LINUXで自宅サーバーを構築・導入(Fedora9)
Fedora9のインストールの仕方から管理方法まで、詳しく載っています。 SearchManには情報がもりだくさんです。
マロンくん.NET
〜サーバ管理者への道〜
Linuxをサーバとして使用するための、いろいろな設定方法が載っています。 マロンくんもかわいいです。 なんといっても、マロンくんという名前がいいですね!!
日経Linux
今や数少なくなってしまったLinuxの雑誌。ニュースやガイドもあります。
Linux Square − @IT
@ITが提供する、Linux の情報が満載。 載っていない設定方法はないんじゃないでしょうか。
gihyo.jp…技術評論社
Linuxに限らず様々な技術情報が満載のサイト。 SoftwareDesign誌も、 ソフトウェア技術者は必見です。
SourceForge.JP Magazine
Linux に限らず、オープンソース関連の記事が網羅されています。
ITmediaエンタープライズ:Linux Tips 一覧
Tips というより FAQ 集でしょうか。わからないことがあれば覗きましょう。
IBM developerWorks : Linux
開発者向けですが、勉強になりますよ。
Yahoo!ニュース - Linux
Yahoo!のLinuxに関するニュース一覧です。
栗日記
システム管理とかと全然関係ありませんが、毎日栗の絵を描いています。
システム管理につかれちゃったとき、癒されたいときに、ご覧ください。:-)
WEB RANKING - PC関連
ランキングに参加してみました。押してやってください。

▼ 作ってみました

Add to Google

▼ せんでん




▼ 最近読んだ本

▼ 気に入ってる本