ここにある文章は「BSD magazine No.12」に掲載された記事を アスキー社編集部の許可を得て公開しています。
WEBで公開するため若干手を加えているので、表現や言葉使いに相違があります。


+ Netscape Navigator のための小技

生活するネットワークが一つに定まってない人にとって、
移動する度にアプリケーションの設定を書き換えるのは非常にわずらわしい。
Netscape Navigator(以下NN) も、そんなアプリケーションの一つだ。

本稿では、出来るだけNNを再起動することなく、
また再設定しなくてもいいような小技を紹介する。

- ネームサーバを切替える

NNは、起動時に一回しか /etc/resolv.conf を読み込まない。
res_init(3)を使う全てのアプリケーションに言える事だが、
再起動しない限り起動時に読み込んだネームサーバを使い続ける。

これは、会社にいる時は会社のネームサーバを使い、
自宅にいる時は契約先のプロバイダのネームサーバを使うといった、
今いる場所によってネームサーバを使い分けたい時にうまくない。

NNを再起動せずにネームサーバを切替えられるようにするには、
アドレスの解決を他のプロセスに任せてしまえばよい。
それには手元のノートPCにHTTPプロキシを動かして、
NNは常にそのプロキシを使うように設定する。

プロキシとしては、wwwoffle[注1]やtinyproxy[注2]等
色々あるので好きなものを使うとよい。
筆者は、ノートPCにHTTPサーバを動かしているので apache[注3]を使っている。
どのプロキシにせよ重要なのは、
手元のノートPCからの要求しか受けつけないようにする事だ。
[図1 /usr/local/etc/apache/httpd.confの一部]に apacheの設定のうち、
最小限のプロキシの設定を示す。
これ以外の設定に関しては、
Apache HTTP SERVER PROJECTの Apache module mod_proxy [注4] を参照して欲しい。

	[図1 /usr/local/etc/apache/httpd.confの一部]

	
	    ProxyRequests On
	    
		Order Deny,Allow
		Deny from all
		Allow from ::1
		Allow from 127.0.0.1
	    
	

NNでプロキシを使うための設定は、
メニューバーの編集から、編集 -> 設定 -> 詳細 -> プロキシとだどり
プロキシ設定画面[図2 プロキシ設定画面]を出す。
そこで "手動でプロキシを設定する" をチェックする。
次に "表示" をクリックすると、
プロキシサーバ設定画面[図3 プロキシサーバ設定画面]が出るので、
例えば、ポート番号 8888 でプロキシを起動しているならば、
IPアドレスに 127.0.0.1 と書き、ポート番号に 8888 と書く。

ネットワークを移動して、/etc/resolv.conf が書き換わったら
プロキシを再起動すればよい。apache の場合は、

	# apachectl restart

とする。

	[図2 プロキシ設定画面]
	
	[図3 プロキシサーバ設定画面]
	

- /etc/resolv.conf の書き変わりの検知

DHCPが動いているネットワークで、
dhclient(8)を使うと /etc/resolv.conf も自動的に書き変わる。
ネームサーバが変われば、プロキシも再起動しなければいけない。
dhclient(8) が正常終了した後に、コマンドを叩いて再起動してもよいのだが、
/etc/dhclient.conf を使えば簡単に自動化できる。
通常dhclient(8)は状態が変わる度に/sbin/dhclient-scriptを実行するが、
[図4 /etc/dhclient.conf]のように
別のスクリプト[図5 /usr/local/etc/dhclient.script]を呼び出し、
そのスクリプトの中で元の/sbin/dhclient-scriptを
呼び出すと共に自動化の処理をする。

	[図4 /etc/dhclient.conf]

	script "/usr/local/etc/dhclient.script";

	[図5 /usr/local/etc/dhclient.script]

	#!/bin/sh

	resolvfile=/etc/resolv.conf
	backupfile=/tmp/.resolv.conf.old
	apachectl=/usr/local/sbin/apachectl

	# 元のスクリプトを実行する
	/sbin/dhclient-script $*

	if [ -f $backupfile ] ; then
		cmp -s $resolvfile $backupfile
		if [ $? = 0 ] ; then
			# ドメインが変わっていなければ何もせずに抜ける
			exit 0
		fi
		# apacheを再起動する
		$apachectl restart
		logger -t dhclient "restart apache due to changing the name server."
	fi

	# 古い $resolvfile を保存する
	cp $resolvfile $backupfile

	exit 0

dhclient.conf を書き換えたら忘れずにdhclient(8)を再起動する。

さて、DHCPが動いていないネットワークでは別の方法が必要である。
適切なネームサーバを自動設定するには、
今いるネットワークがどこなのかを自動検知する必要がある。
ネットワークインターフェイスをモニタして、流れているパケットに応じて
今いるネットワークを自動判定するようなプロセスを書いてもいいのだが、
プライベートアドレスを使っているネットワークでは区別がつかない。

結局知恵をしぼるよりコマンドで場所を指定してがやるのが簡単だ。
[図6 /usr/local/sbin/chdom]に例を示す。
このスクリプトを使う場合、例えば家に帰ったら以下のように叩く。

	# chdom home

すると [図7 chdomの設定ファイル]の $dn{'home'}の設定が
/etc/resolv.conf に反映する。
そして、プロキシが再起動される。

	[図6 /usr/local/sbin/chdom]

	#!/usr/bin/perl

	# 設定ファイルへのパス
	require '/usr/local/etc/chdom.conf';

	$apachectl = '/usr/local/sbin/apachectl';
	$resfile = '/etc/resolv.conf';

	# 引数なしか -h が指定された時はusageを表示する
	if (!$ARGV[0] || $ARGV[0] eq '-h') {
		print "Usage: chdom (domain)\n";
		print "       chdom tmp (nameserver) (options) ... \n";
		exit 1;
	}

	$domain = shift(@ARGV);

	# 設定ファイルにあるドメイン名か?
	if ($domain ne 'tmp' && !defined $dn{$domain}) {
		print "ERROR: no definition for \"$domain\" found.\n";
		exit 1;
	}

	open(OUT, "> $resfile") || die;
	if ($domain eq 'tmp') {
		# 第1引数が tmp の時は、第2引数を nameserver
		# 第3引数以降を options として処理する
		if (@ARGV) {
			printf OUT "nameserver %s\n", shift @ARGV;
			foreach $i (@ARGV) {
				print OUT "options $i\n";
			}
		}
	} else {
		# 設定ファイルを反映する
		foreach (@{$dn{$domain}}) {
			printf OUT "%s\n", $_;
		}
	}
	close(OUT);

	# apacheを再起動する
	system("$apachectl restart");

	exit 0;

	[図7 chdomの設定ファイル /usr/local/etc/chdom.conf]

	$dn{'home'}[0]	= 'nameserver 3ffe:501:4819::1';
	$dn{'foo'}[0]	= 'nameserver 10.21.0.1';
	$dn{'foo'}[1]	= 'nameserver 10.21.0.2';
	$dn{'bar'}[0]	= 'nameserver 3ffe:501:4819::fe5f:4061';
	$dn{'bar'}[1]	= 'nameserver 3ffe:501:4819::feda:cfc7';
	$dn{'local'}[0]	= 'nameserver 127.0.0.1';
	$dn{'local'}[1] = 'nameserver ::1';

- IPv6だけのネットワークで生活する

 IPv6しか使えないネットワークでNNを使うときについて考える。NNはIPv6アドレスを扱
えないので、IPv6 HTTPサーバーに接続するには、IPv6に対応したプロキシを経由する。
手元のプロキシがIPv6対応しているとこの目的にも使えるので、この意味でも手元のノー
トPCでプロキシを起動しておくと便利だ。
 さて、IPv4アドレスしか持っていないHTTPサーバーに接続するときは、IPv6のHTTPリク
エストをIPv4に変換するトランスレータと呼ばれるシステムを経由しなければならない。[図8 IPv6だけのネットワークでのHTTP接続]
詳しくは割愛するが、トランスレータを経由させる一つの方法としてDNSが利用できる。
この場合、ネームサーバの設定によって使用するトランスレータが決まる。一つのネーム
サーバを使い続けると、ネットワークを移動しても同じトランスレータを使う事になる。
極端な例だが、普段日本に置かれたトランスレータを使っている人が、韓国へ出張したと
しよう。ネームサーバを切替えなければ、韓国のIPv6ネットワークから韓国のIPv4 HTTP
サーバに繋ぐには、韓国、日本、韓国と経由しなくてはならない。これでは非効率なので
、ネットワーク的に一番近いトランスレータを使いたい。そのためにも今いる場所に応じ
てネームサーバを切替える必要がある。[図6 /usr/local/sbin/chdom]のスクリプトは、この目的にも使える。

	[図8 IPv6だけのネットワークでのHTTP接続]
	

- IPv6/IPv4が混在したネットワークで生活する

IPv6/IPv4が混在したネットワークで生活する場合を考える前に、
NNの Automatic Proxy Configuration(以下PAC)を説明しておこう。

これは、接続するURLや現在時刻に応じて自動的にプロキシを
切替える仕組みである。
NNは指定されたサーバへHTTP接続する前に関数 FindProxyForURL()を呼び出す。
その評価結果として、プロキシに接続したり、直接接続する事ができる。
評価式は JavaScriptで記述できるので複雑な設定ができる。
詳しくは、Netscapeのホームページにある
Navigator Proxy Auto-Config File Format [注5]を参照されたい。

この仕組みを使うためには、NNのプロキシ設定画面[図2 プロキシ設定画面]で
"自動プロキシ設定" を選ぶ。
設定ファイルの場所には、FindProxyForURL() が書かれたファイルのURLを書く。
多くの組織では、このURLに1つのサーバにおかれたファイルを指定させているようだ。
これにより組織は、ユーザにプロキシ経由のHTTP接続を強制している。

さて、IPv6/IPv4が混在したネットワークで生活する場合にも、この仕組みは使える。
手元のプロキシは IPv6 HTTPサーバへ接続するためだけに使い、
IPv4 HTTPサーバへ接続する時は直接接続か、指定されているプロキシに
接続したい時だ。[図9 IPv6/IPv4が混在したネットワークでのHTTP接続]

	[図9 IPv6/IPv4が混在したネットワークでのHTTP接続]
	
 
この時のFindProxyForURL()の例を[図10 FindProxyForURL()の例]に示す。
この例では、URLのホスト部が IPv4アドレスだったら、または、
IPv4 アドレス解決が成功したら直接接続する。
また、URLの中に文字列 .xxx.co.jp があればプロキシ proxy.xxx.co.jpへ
接続する。
どれにも当てはまらなければ、手元のノートPCのプロキシへ接続する。

	[図10 FindProxyForURL()の例]

	function FindProxyForURL(url, host)
	{
		if (host.match("[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+")) {
			// URLのホスト部が IPv4アドレスだったら直接接続
			return "DIRECT; PROXY 127.0.0.1:80;";
		} else if (isResolvable(host)) {
			// IPv4 アドレス解決が成功したら直接接続
			// URLの中に文字列 .xxx.co.jp があれば
			return "DIRECT; PROXY 127.0.0.1:80;";
		} else if (shExpMatch(url, "*.xxx.co.jp/*")) {
			// プロキシサーバ proxy.xxx.co.jpへ接続
			return "PROXY proxy.xxx.co.jp:80";
		}

		// どれにも当てはまらなければ手元のノートPCのプロキシサーバへ接続
		return "PROXY 127.0.0.1:80";
	}

FindProxyForURL()では、JavaScriptの拡張関数として
自システムのIPv4アドレスを返す関数 myIpAddress()がある。
これが正常に動くノートPCならば、インターフェイスについたアドレスに
従ってプロキシを切替えられるので、もっと複雑な事ができる。
筆者のノートPCでは常に127.0.0.1が帰ってくるので、残念だがこの関数は使えない。

- おわりに

 手もとのノートPC上でHTTPプロキシを動かすことにより、
NNを再起動せずにネームサーバーを切り替える方法を示した。
この方法はNNに限らずさまざまなアプリケーションでも応用できる。
ネームサーバの切替えに関してはtotd(8)のようなDNSプロキシに
任せる方法もあるが本稿では触れてない。
また、PACを使ったIPv6/IPv4が混在したネットワークにおけるプロキシの
切り替え方法を示した。
PACはNNに限らず、Mozilla//ky06でも使えるので同様のことが実現できるかもしれない。
MozillaはIPv6アドレスを扱えるので、IPv6ネットワークで生活するには、
Mozilla のほうが適しているかもしれない。
しかし、Mozilla は実行に相当なCPUパワーを使うので、
貧弱なノートPCでは使いものにならない。
筆者のようにNNを使い続けている人は多いと思う。
今回示した方法がNNを使って快適に過ごすためのヒントになってくれれば幸いである。

- 参照
[注1] http://www.gedanken.demon.co.uk/wwwoffle/
[注2] http://tinyproxy.sourceforge.net/
[注3] http://www.apache.org/
[注4] http://httpd.apache.org/docs/mod/mod_proxy.html
[注5] http://home.netscape.com/eng/mozilla/2.0/relnotes/demo/proxy-live.html
[注5] http://www.mozilla.org/
[注6] http://www.vermicelli.pasta.cs.uit.no/ipv6/software.html