!!!Proxyサーバをスクリプトで自動設定 {{category Network,nolink}}JavaScriptを使ったProxyサーバの自動設定手段が、Internet ExplorerやNetscape CommunicatorなどのWebブラウザには用意されている。 自動設定のJavaScriptファイル作成し、イントラネット内のWebサーバに配置して、ブラウザのプロキシサーバの自動設定にそのURLを設定すればよい。 MIMEタイプ「application/x-ns-proxy-autoconfig」で、「.pac」という拡張子を指定する。 function FindProxyForURL(url,host){ if(isPlainHostName(host)||dnsDomainIs(host, ".mydomain.com")|| isInNet(host,"192.168.0.0","255.255.0.0")){ return "DIRECT"; } return "PROXY 192.168.0.254:8080; SOCKS 192.168.0.254:1080"; } この自動設定ファイルを使うと、例えば、イントラネットとインターネット接続でProxyサーバを切り替えたり、利用時間帯や所属ドメインなどに基づいて複数のProxyサーバを使い分けるなどという複雑な制御も行える。 *WebブラウザのProxy設定を行うための4つの方法 (@IT:Windows TIPS) **http://www.atmarkit.co.jp/fwin2k/win2ktips/031autoproxy/autoproxy.html !!IEの自動設定での“DIRECT”の意味 自動設定ファイルを使用していて "DIRECT" が返されるとき、本来「インターネット ゾーン」となるべきサイトも「イントラネット ゾーン」となってしまう。 これは、IEの'''仕様'''らしい。自動設定ファイルには、そのプロキシサーバを利用するかを決めるためのもので、インターネットとイントラネットといったゾーン定義がない。 そのため、「企業などでは、インターネットとイントラネットは、明確にファイアウォールなどで分離されている。そのため、インターネットにアクセスするためには、必ずプロキシサーバを経由する必要がある。」と言う前提の基に、「自動設定ファイルを使用した際のプロキシサーバを使用せず、直接通信するホストはイントラネットと見なす」ようになっている。 DIRECTをイントラネットゾーンとしないようにするためには、ステータス・バーのゾーン名をダブルクリックするか、[ツール]メニューから[インターネット オプション]を選択し、[セキュリティ]タブを選択する。そして[イントラネット]アイコンを選択して、その下にある[サイト]ボタンをクリックする。イントラネットゾーンに含めるサイトの設定で「プロキシ サーバーを使用しないサイトをすべて含める」のチェックを外すことで、自動設定ファイルの返す値でゾーン判定を行わなくなる。デフォルトではオンになっているので各ユーザごとに設定する必要がある。 自動設定ファイルを使用する場合の話で、手動やActive Directoryのグループ・ポリシーなどでプロキシサーバを設定している場合は、これには該当しない。 *IEの自動Proxy設定とセキュリティ・ゾーン (@IT) **http://www.atmarkit.co.jp/fwin2k/experiments/ieproxy/ieproxy_01.html !!!Proxy Autoconfig の JavaScript関数 !!メイン関数 !FindProxyForURL(url, host) Proxy Autoconfig で呼び出される関数。プロキシサーバの選択ルールを記述しその結果を返す。 :url :アクセスするサーバのURI(protocol://host:port/path?search) :host :アクセスするサーバのホスト名(URIのhost部のみ) :戻り値 :使用するプロキシサーバの文字列 プロキシサーバの文字列は以下のような値を返す。 ::direct :::Proxyサーバを使用せず、直接接続する ::proxy host:port :::指定されたproxyサーバが使用する ::socks host:port :::指定されたsocksサーバが使用する また、「proxy proxy1.example.com; proxy proxy2.example.com」の様に「;」で複数のプロキシサーバを指定できる。複数設定されている場合は、前から順番に接続を試みて確立するサーバに接続する。 前回応答がなかったプロキシサーバには、30分毎に再接続を試みる。 すべてのサーバから応答がない場合で、"DIRECT"も設定されていない場合は、直接接続を試みるかどうかをユーザに尋ねる。これは、20分毎に繰り返される。 !!ホスト名ベースの関数 ホスト名または IP アドレスを使用して、プロキシを使用するかを判断することができます。 !dnsDomainIs(host, domain) ホスト名が指定したドメインに一致するかを判断する。 :host :URLから得られるホスト名 :domain :評価するドメイン名 :戻り値 :ドメイン名が一致する場合に真を返す dnsDomainIs("www", ".yok.com") // = FALSE dnsDomainIs("www.example.com", ".example.com") // = TRUE dnsDomainIs("www.example.net", ".example.com") // = FALSE !localHostOrDomainIs(host, hostdom) ホスト名が指定したFQDNと一致するか、ホスト名のみでFQDNのホスト名と一致するかを判断する。 :host :URLから得られるホスト名 :hostdom:評価する完全修飾ホスト名 :戻り値 :ドメイン名が一致する場合に真を返す !isPlainHostName(host) ホスト名がドメインなどを含まないか(ホスト名のみか)を判断する。 :host :URLから得られるホスト名 :戻り値 :ホスト名のみの場合に真を返す isPlainHostName("www") // = TRUE isPlainHostName("www.example.com") // = FALSE !isResolvable(host) ホスト名がDNSで名前解決できるかを判断する。 :host :URLから得られるホスト名(ポート番号は除く) :戻り値 :DNSで名前解決できる場合に真を返す !isInNet(host, pattern, mask) ホスト名のIPアドレスが指定したサブネットに属しているかを判断する。渡されるホスト名がIPアドレスでない場合は、正引きを行いIPアドレスを取得する。 :host :URLから得られるホスト名 :pattern:IPアドレスパターン :mask :IPアドレスパターンマスク :戻り値 :サブネットに属している場合に真を返す isInNet(198.168.0.1, "198.168.0.1", "255.255.255.255") // = TRUE isInNet(198.168.0.*, "198.168.0.1", "255.255.255.0") // = TRUE !!ユーティリティー関数 ドメインレベル、ブラウザが実行されているホスト、あるいはホストの IP アドレスを検出することができます。 !dnsResolve(host) ホスト名のIPアドレスを取得する。 :host :URLから得られるホスト名 :戻り値 :ホスト名のIPアドレス dnsResolve("www.example.com") // = "192.0.2.1" !myIpAddress() ブラウザが実行されているホストのIPアドレスを取得する。 :戻り値 :ホストのIPアドレス myIpAddress() // = "198.168.0.1" !dnsDomainLevels(host) ホスト名の中の DNS レベルの数(ドットの数) を取得する。 :host :URLから得られるホスト名 :戻り値 :ドメインレベルの数 dnsDomainLevels("www") // = 0 dnsDomainLevels("www.example.com") // = 2 !!URL/ホスト名ベースの条件 負荷分散やルーティングを行うために、ホスト名または URL をマッチングすることができます。 !shExpMatch(str, shexp) 文字列が指定したシェル表現(正規表現ではない)にマッチするかを判断する。 :str :比較対象の文字列 :shexp :比較するシェル表現 :戻り値 :マッチする場合に真を返す shExpMatch("http://home.example.com/people/index.html", "*/people/*") // = TRUE shExpMatch("http://home.example.com/people/index.html", "*/mypage/*") // = FALSE !!時間ベースの条件 日付、時間、または曜日によって、FindProxyForURL 関数が異なる動作をするように設定できます。 !weekdayRange(wd1, wd2, gmt) 特定の曜日または曜日の範囲を検出する。 :wd :曜日を表す文字列 (SUN MON TUE WED THU FRI SAT) :gmt :GMT(グリニッジ標準時)か、空白(ローカル時間帯) :戻り値 :マッチする場合に真を返す weekdayRange("sat") // 現地時間で土曜日なら真 weekdayRange("sun", "gmt") // 標準時間で日曜日なら真 weekdayRange("mon", "fri") // 現地時間で月曜日から金曜日までは真 weekdayRange("fri", "mon", "gmt") // 標準時間で金曜日から翌週月曜日までは真 !dateRange(day1, month1, year1, day2, month2, year2, gmt) 特定の日付や日付範囲を検出する。 :day :月の日付を表す 1 〜 31 までの整数 :month :月を表す文字列 (JAN FEB MAR APR MAY JUN JUL AUG SEP OCT NOV DEC) :year :西暦を表す 4桁の整数 :gmt :GMT(グリニッジ標準時)か、空白(ローカル時間帯) :戻り値 :マッチする場合に真を返す dateRange(24) // 24日は真 dateRange(24, "dec") // 12月24日は真 dateRange(24, "dec", 1996) // 1996年12月24日は真 dateRange(1, 15) // 1日〜15日は真 dateRange(1, "jun", 15, "aug") // 6月1日〜8月15日は真 dateRange(1, "jun", 1996, 15, "aug", 1998) // 1996年6月1日〜1998年8月15日は真 dateRange("jan") // 6月は真 dateRange("jan", "aug") // 6月〜8月は真 dateRange("jan", 1996, "aug", 1998) // 1996年6月〜1998年8月は真 dateRange(1996) // 1996年は真 dateRange(1996, 1998) // 1996年〜1998年は真 !timeRange(hour1, min1, sec1, hour2, min2, sec2, gmt) 特定の時間や時間範囲を検出する。 :hour :時間を表す 0 〜 23 までの整数 :min :分を表す 0 〜 59 までの整数 :sec :秒を表す0 〜 59 までの整数 :gmt :GMT(グリニッジ標準時)か、空白(ローカル時間帯) :戻り値 :マッチする場合に真を返す timeRange(12) // 12:00:00〜12:59:59は真 timeRange(12, 13) // 12:00:00〜13:59:59は真 timeRange(12, 15, 13, 45) // 12:15:00〜13:45:59は真 timeRange(12, 15, 30, 13, 45, 30) // 12:15:30〜13:45:30は真