図解でわかる プロキシサーバ入門シリーズ ~第3回 PACファイルの書き方を図解で解説 FindProxyForURL 基本構文と実例集~

PACファイルとプロキシの概念図(クライアント→PAC→プロキシ/直接) ネットワーク
PACでアクセス先ごとに「プロキシか直接か」を自動判定する仕組み。

1. プロキシサーバ及びPACとは(第1・2回の復習)

本節では第1回で扱ったプロキシの概要及び第2回で解説したプロキシサーバをどのように利用するか(PACファイルの利用)について、短く復習した上で、本題であるPACファイルの書き方について解説したいと思います。

1-1_プロキシサーバの概要

まず、おさらいですがプロキシサーバとは「クライアントの代わりに外部と通信する中継役」です。 技術的にはクライアント(PC等)からのリクエストを受け取り、代わりに外部サイト(サーバ)へ接続して応答を返すソフトウェア/ハードウェアを指します。通信を仲介することで、プロキシサーバは単なる中継地ではなくページのキャッシュやフィルタなどの様々な機能を提供することが可能になります。

プロキシサーバの機能を示す図(中継・キャッシュ・フィルタ)
図解1_プロキシはクライアントの代わりに外部と通信し、キャッシュやフィルタ機能を提供する。

1-2 PACの役割とメリット

PAC(Proxy Auto-Config)ファイルは、クライアント機器(PC等)がアクセス先ごとに「 プロキシを使うか/直接接続するか」を自動判定するためのJavaScript形式の設定ファイルです。
PACは端末側でアクセス先ごとの接続先を動的に決定できるため、管理者が一括でルールを更新すれば全端末に反映されます。手動設定と比べて運用負荷が低く、特定サービスだけ別プロキシに振るなど柔軟な運用が可能です。

PAC取得及び取得後のDIRECTかPROXYへ振り分けられるフロー図
図解2_端末がPACを取得し、アクセス先ごとに直接接続またはプロキシ経由を選択する。
∞-CPU
∞-CPU

それでは実際のPACファイルの中身についてみていきましょう

2_PACファイルの構成要素

PACファイルの主な構成は、下記になります.

  • 基本構文(例:FindProxyForURL)      
  • 引数(例:url / host) 
  • 条件構文(例:If)
  • 判定関数(例 dnsDomainIs, shExpMatch, isInNet, dnsResolve)
  • 返却値(例 DIRECT / PROXY等)
FindProxyForURL・引数・判定関数・返却値を示す図
図解3_FindProxyForURL・引数(url, host)・判定関数・返却値の関係を図示。

2-1_基本構文【=前提となる関数FindProxyForURL】

FindProxyForURLPAC ファイルの中心となる関数で、ブラウザが各種Webサイト等にアクセスする際に必ず呼び出す 入口”です。少し分かりにくければ「 プロキシ経由の通信か直接通信のどちらにするかどうかの判定する処理に入りますよー」宣言していると思ってください。
構文の全体概要として、FindProxyForURL は アクセス先のurlhost を受け取り、内部で必要に応じて判定関数(dnsDomainIs など)を呼び出し、urlやhostを各条件と照合し、最終的な接続方法を返します。

FindProxyForURL の役割
図解4_FindProxyForURL は url と host を受け取り、判定関数で条件を評価して接続方法を返す

2-2_引数(url, host)

ここでの引数とは、関数「FindProxyForURL」に引き渡される情報のことを指します。引き渡されるのはurlhost情報になり、それぞれの説明は下記のとおりとなります。

例)アクセス先が「https://simple-viz.com/proxy-server-intro/

url = スキーム(https:)+ホスト(example.com)+パス(path)を含む完全なアクセス先 →上記例であれば、「https://simple-viz.com/proxy-server-intro/」が引数「url」に該当

host = ホスト名のみを指す。
→上記例であれば「simple-viz.com」が引数「host」に該当

URL(スキーム+ホスト+パス)と host(ホスト名のみ)の比較図
図解5_url と hostを比較。

引数は、関数「FindProxyForURL」の中で、更に判定関数と呼ばれる関数で利用され、条件に合致するかどうか照合に利用されます。判定は通常 host を使うのが簡潔で高速です

2-3_条件構文(if)

if は FindProxyForURL の中で「どの条件に当てはまるか」を判断するための基本的な条件構文です。urlやhostが特定の値に一致するか、 判定関数(dnsDomainIs や shExpMatch など)の結果が真かどうかを確認し、その条件に応じて接続方法 ①DIRECT(=直接通信) や ②PROXY(=指定したプロキシを経由した通信) などの接続方法を返します。
PAC の動作を決める中心的な仕組みで、複数の条件を順番に評価しながら最適な接続方法を選びます

条件構文の役割(IF)を示した図
図解6_条件構文の役割(IF)を示した図

2-4_判定関数

FindProxyForURL の中では、アクセス先がどの条件に当てはまるかを判断するためにdnsDomainIsshExpMatchisInNet などの判定関数を利用します。これらは引数として渡された「url」や「host」が特定のドメイン名・パターン・IP 範囲に一致するかを調べるための補助機能です。判定関数の結果(true / false)に応じて 条件構文(if) が評価され、最終的に DIRECT(=直接通信) や PROXY(=指定したプロキシを経由した通信)などの接続方法を返す仕組みになっています。
よく使用するものは、以下になりますのでそれぞれ見ていきましょう。

  • dnsDomainIs
  • shExpMatch
  • isInNet

2-4-1_ dnsDomainIs(特定のドメイン名に一致するかどうか)

dnsDomainIs は、FindProxyForURL の中で「 特定のドメイン名に一致するかどうか」を判定するための関数です。dnsDomainIs(host, “.example.com”) のように使い、host が指定したドメインで終わっていれば true を返します。社内システムや特定サービスを DIRECT にしたい場合など、最もよく使われる基本的な判定方法です。処理が軽く誤判定も少ないため、PAC ではまず最初に検討すべき判定関数といえます

2-4-2_shExpMatch(文字列が特定のパターンに一致するかを判定

shExpMatch は、 文字列が特定のパターンに一致するかを判定するための関数です。shExpMatch(host, “*.example.com”) のように使い、ワイルドカード(* や ?)を含む柔軟なパターン指定ができます。ドメイン名だけでなく、URL 全体を対象にした判定にも利用できますが、ブラウザによって url の扱いに差があるため、基本的には host を対象に使うのが安全です。細かいパターン判定を行いたい場合に便利な関数です。

2-4-3_ isInNet(指定の IP アドレスが特定のネットワーク範囲に含まれるかを判定)

isInNet は、指定した IPアドレスが特定のネットワーク範囲に含まれるかを判定するための関数です。isInNet(host, “10.0.0.0”, “255.0.0.0”) のように使い、社内ネットワークや特定のセグメントを DIRECT にしたい場合に利用します。上記事例では、アクセスURLのホスト名にIPが含まれる場合に有効です。実際には、ホストを名前解決し、解決後のIPアドレスで照合するような場面で便利ですが、dnsResolve を併用すると名前解決が発生し処理が重くなるため、必要最小限に使うことが推奨されます。

2-5_返却値(DIRECT / PROXY)

FindProxyForURLの処理結果として返す値は、ブラウザが実際にどの経路で通信するかを判断するための「返却文字列」です。代表的な形式は 「DIRECT(プロキシを使わず直接通信)」と、「PROXY ホスト名 or IP:ポート番号(指定したプロキシ経由で通信)」の2種類です。また、PROXY を複数並べて通信の宛先ごとに異なるプロキシを使い分けたりすることも可能です。

3. 実践テンプレ集(コピペで使える)

ここでは「すぐ使える」テンプレを2種類用意します。
用途別にコメント付きで解説し、テンプレはそのままコピーして試せる形式で用意していますので、是非ご活用ください。

3-1 テンプレA:社内優先→特定外部→デフォルトプロキシ

1)社内サービスを優先的にDIRECTにし、2)特定の外部サービスは専用プロキシへ、3)それ以外は共通プロキシへ送る基本テンプレです。導入が簡単で多くの企業環境に適合します。

function FindProxyForURL(url, host) {
  // 1) 社内ドメインは直接接続
  if (dnsDomainIs(host, "corp.local") |
 shExpMatch(host, "*.intra.corp.local")) {
    return "DIRECT";
  }

  // 2) 特定外部サービスは専用プロキシへ
  if (shExpMatch(host, "*.example.com")) {
    return "PROXY 192.168.10.20:8080";
  }

  // 3) それ以外は共通プロキシ(フォールバックあり)
  return "PROXY 192.168.10.10:8080; PROXY 192.168.10.11:8080; DIRECT";
}

3-2 テンプレB:用途別プロキシ振り分け(負荷分散/専用)

複数プロキシを用途別に振り分けるテンプレ。動画配信は専用プロキシ①、APIは専用プロキシ②社内は直接通信など用途に応じた振り分け例を示します。

function FindProxyForURL(url, host) {
  // 動画配信は専用プロキシ①
  if (shExpMatch(host, "*.cdn.video.example") ||
 shExpMatch(url, "*video*")) {
    return "PROXY 10.10.1.10:8080";
  }

  // APIは専用プロキシ②(認証やログ分離)
  if (shExpMatch(host, "api.example.com") || 
shExpMatch(host, "*.api.example")) {
    return "PROXY 10.10.2.20:8080";
  }

  // 社内は直接
  if (dnsDomainIs(host, "corp.local")) {
    return "DIRECT";
  }

  // デフォルトプロキシ
  return "PROXY 10.10.0.10:8080; DIRECT";
}

4_まとめ

本稿はプロキシとPACの役割を復習し、FindProxyForURLの構造(url/host引数、if判定、dnsDomainIs/shExpMatch/isInNet等)と返却値(DIRECT/PROXY)を解説の上、テンプレA/Bを提示しました。次回はPACのテストとデバッグ手順を実例で紹介する予定です。

(参考)よくある問い合わせ

Q1
PACファイルとは何ですか?
A1

PAC(Proxy Auto-Config)ファイルは、クライアントがアクセス先ごとに「プロキシを使うか/直接接続するか」を自動判定するためのJavaScript形式の設定ファイルです。端末側で接続先を動的に決定でき、管理者がルールを更新すれば全端末に反映されます。

Q2
FindProxyForURL に渡される引数 url と host の違いは何ですか?
A2

url はスキーム+ホスト+パスを含む完全なアクセス先(例: https://example.com/path)で、host はホスト名のみ(例: example.com)です。判定は通常 host を使う方が簡潔で高速です

Q3
PACでよく使う判定関数と返却値の形式は?
A3

よく使う判定関数は dnsDomainIs、shExpMatch、isInNet などで、条件に応じて返す値は DIRECT(直接接続) や PROXY ホスト:ポート です。複数のプロキシを並べてフォールバックを指定することも可能です。

コメント

タイトルとURLをコピーしました