PACファイル(プロキシ自動設定ファイル)の記述方法完全版

Windows
記事内に広告が含まれています。

  1. 1.はじめに
  2. 2.ファイル名のルール
  3. 3.サーバーの設定
  4. 4.PACファイルの基本構造
  5. 5.PACファイルの記述例
    1. 例1:特定のドメインにはプロキシを使用せず、それ以外はプロキシを使用する。
    2. 例2:特定のIPアドレス範囲にはプロキシを使用せず、それ以外はプロキシを使用する。
    3. 例3:特定のURLパターンにはSOCKSサーバーを使用し、それ以外はプロキシを使用する。
    4. 例4:特定の曜日や時刻にはプロキシを使用せず、それ以外はプロキシを使用する。
    5. 例5:社内で運用しているWebサーバなどにある、ホスト名がNetBIOS名の場合(”.”を含まない)はプロキシを使用せず、それ以外はプロキシを使用する。
    6. 例6:ホスト名がNetBIOS名の場合(”.”を含まない)または社内のローカルドメインの場合はプロキシを使用せず、それ以外はプロキシを使用する。
    7. 例7:複数のプロキシを指定する
    8. パラメータについての説明
  6. 6.PACファイルのデバッグ方法
    1. 6-1.ブラウザのデバッグツールを使用
      1. Chromeの場合
      2. Firefoxの場合
      3. Edgeの場合
    2. 6-2. PACファイルのテストツールを使用する
      1. 例: PACファイルテストツール
    3. 6-3. ローカルでのテスト
      1. ローカルでPACファイルをホスト:
      2. Autoprox.exeを使用したPACファイルのテスト
        1. 1.Autoprox.exeをインストール
        2. 2.テスト対象のPACファイルを準備
        3. 3.Autoprox.exeをコマンドラインから実行
        4. 4.結果の確認
        5. 5.デバッグ情報の活用
    4. 6-4. シンプルな条件から始める
    5. 6-5.Node.js を使ったテスト
  7. 7. PACファイルの最適化
    1. 最適化のポイント
  8. 8. PACファイルのセキュリティ対策
    1. リスク
    2. 対策
  9. 9.WPAD(Web Proxy Auto-Discovery)との関係
    1. WPADの仕組み
    2. WPADのリスクと対策
  10. 10.まとめ
  11. 免責規定

1.はじめに

PACファイルとは、Proxy Auto-Configurationの略で、ブラウザのプロキシ設定を自動的に管理するためのファイルです。
PACファイルには、JavaScriptの関数が記述されており、ブラウザがアクセスするURLやホスト名に応じて、使用するプロキシを決定します。
本記事では、PACファイルの記述方法について、基本概念から応用例、デバッグ方法、最適化、セキュリティまで詳しく解説します。

2.ファイル名のルール

PACファイルは拡張子「.pac」でなければなりません。

3.サーバーの設定

PACファイルを配置するWebサーバー側でも設定が必要です。
PACファイルをダウンロードできるように、MIMEタイプに「.pac」拡張子を下記のように設定する必要があります。

application/x-ns-proxy-autoconfig

IISの場合は、IISマネージャでMIMEの種類を開き、追加で、ファイル名の拡張子に.pac、MIMEの種類にapplication/x-ns-proxy-autoconfigを設定します。

4.PACファイルの基本構造

  • PACファイルは、次のようなJavaScriptの関数を必ず含める必要があります。
function FindProxyForURL(url, host) {
     // プロキシ設定を返すコード 
}

この関数は、引数としてURLとホスト名を受け取り、プロキシ設定を表す文字列を返します。

  • プロキシ設定を返すコード“に入るプロキシ設定の文字列は、次のような書式に従います。
    • DIRECT :プロキシを使用せずに直接接続する
    • PROXY host:port :指定されたプロキシサーバー:ポートを使用する
    • SOCKS host:port :指定されたSOCKSサーバー:ポートを使用する
    • HTTP host:port :指定されたHTTPプロキシサーバー:ポートを使用する(Firefoxのみ対応
    • HTTPS host:port :指定されたHTTPSプロキシサーバー:ポートを使用する(Firefoxのみ対応
    • SOCKS4 host:port, SOCKS5 host:port :指定されたSOCKSサーバー:ポートを(指定されたSOCKSバージョンで)使用する(Firefoxのみ対応
  • 指定するプロキシサーバーの文字列は、セミコロン(;)で区切って複数指定することができます。
    その場合、最も左にある有効な設定が優先されます。(「例7:複数のプロキシを指定する」を参照)
  • PACファイルで使用できる関数と変数
    • PACファイルでは、JavaScriptの標準的な関数や変数に加えて、次のような特殊な関数や変数が使用できます。
      • ホスト名に基づく条件
        • isPlainHostName(host):ホスト名にドットが含まれない場合にtrueを返す
        • dnsDomainIs(host, domain):ホスト名が指定されたドメインと一致する場合にtrueを返す
        • localHostOrDomainIs(host, hostdom):ホスト名が指定されたホスト名またはドメインと一致する場合にtrueを返す
        • isResolvable(host):ホスト名がDNSで解決できる場合にtrueを返す
        • isInNet(host, pattern, mask):ホスト名が指定されたパターンとマスクに一致するIPアドレスを持つ場合にtrueを返す
      • 関連するユーティリティ関数
        • dnsResolve(host):ホスト名からIPアドレスを取得する
        • convert_addr(ipaddr):IPアドレスから整数値に変換する
        • myIpAddress():自分自身のIPアドレスを取得する
        • dnsDomainLevels(host):ホスト名に含まれるドットの数を取得する
      • URL/ホスト名に基づく条件
        • shExpMatch(str, shexp):文字列が指定されたシェル式に一致する場合にtrueを返す
      • 時刻に基づく条件
        • weekdayRange(wd1, wd2, gmt):現在の曜日が指定された範囲内にある場合にtrueを返す
        • dateRange(day1, month1, year1, day2, month2, year2, gmt):現在の日付が指定された範囲内にある場合にtrueを返す
        • timeRange(hour1, min1, sec1, hour2, min2, sec2, gmt):現在の時刻が指定された範囲内にある場合にtrueを返す
      • ログ用ユーティリティ
        • alert(message):メッセージをログに出力する
      • 定義済みの連想配列(非推奨)
        • ProxyConfig.bindings:プロキシ設定の値をキーとして持つオブジェクト

5.PACファイルの記述例

ここでは、PACファイルの記述方法をいくつかの例で紹介します。

例1:特定のドメインにはプロキシを使用せず、それ以外はプロキシを使用する。

function FindProxyForURL(url, host) {
  if (dnsDomainIs(host, ".example.com")) {
    return "DIRECT";
  } else {
    return "PROXY 192.168.100.20:8080";
  }
}

説明:もしURLが”.example.com”ドメインの場合はプロキシを使用しないで直接接続する。
それ以外は、プロキシ192.168.100.20:8080を使用する。

例2:特定のIPアドレス範囲にはプロキシを使用せず、それ以外はプロキシを使用する。

function FindProxyForURL(url, host) {
  if (
    isInNet(host, "10.0.0.0", "255.0.0.0") ||
    isInNet(host, "172.16.0.0", "255.240.0.0") ||
    isInNet(host, "192.168.0.0", "255.255.0.0")
  ) {
    return "DIRECT";
  } else {
    return "PROXY 192.168.100.20:8080";
  }
}

説明:もしIPアドレスが、10.0.0.0/8、172.16.0.0/12、192.168.0.0/16の範囲に含まれる場合はプロキシを使用しないで直接接続する。
それ以外はプロキシ192.168.100.20:8080を使用する。

例3:特定のURLパターンにはSOCKSサーバーを使用し、それ以外はプロキシを使用する。

function FindProxyForURL(url, host) {
  if (shExpMatch(url, "://.example.com/*")) {
    return "SOCKS socks.example.com:1080";
  } else {
    return "PROXY 192.168.100.20:8080";
  }
}

説明:もしURLが”.example.com”ドメインの場合はSOCKSサーバーsocks.example.com:1080を使用し、それ以外はプロキシ192.168.100.20:8080を使用する。

例4:特定の曜日や時刻にはプロキシを使用せず、それ以外はプロキシを使用する。

function FindProxyForURL(url, host) {
  if (weekdayRange("SAT", "SUN") || timeRange(18, 0, 0, 9, 0, 0)) {
    return "DIRECT";
  } else {
    return "PROXY 192.168.100.20:8080";
  }
}

説明:土曜日と日曜日の場合または、18:00~09:00まではプロキシを使用しないで直接接続する。
それ以外はプロキシ192.168.100.20:8080を使用する。

例5:社内で運用しているWebサーバなどにある、ホスト名がNetBIOS名の場合(”.”を含まない)はプロキシを使用せず、それ以外はプロキシを使用する。

function FindProxyForURL(url, host) {
  if (isPlainHostName(host)){
    return "DIRECT";
  } else {
    return "PROXY 192.168.100.20:8080";
  }
}

説明:アクセスするURLが”http://example/”、”https://intrasite/”などホスト名が”.”を含まない場合はプロキシを使用しないで直接接続する。
それ以外はプロキシ192.168.100.20:8080を使用する。

例6:ホスト名がNetBIOS名の場合(”.”を含まない)または社内のローカルドメインの場合はプロキシを使用せず、それ以外はプロキシを使用する。

function FindProxyForURL(url, host) {
  if (
        isPlainHostName(host) ||
        shExpMatch(host, "*.intra1.local") ||
        shExpMatch(host, "*.intra2.local") ||
        shExpMatch(host, "*.intra3.local")
    ){
    return "DIRECT";
  } else {
    return "PROXY 192.168.100.20:8080";
  }
}

説明:アクセスするURLが”http://example/”、”https://intrasite/”などホスト名が”.”を含まない場合、またはホスト名が”*.intra1.local”、”*.intra2.local”、”*.intra3.local”のパターンに一致する場合はプロキシを使用しないで直接接続する。
それ以外はプロキシ192.168.100.20:8080を使用する。

例7:複数のプロキシを指定する

function FindProxyForURL(url, host) {
  if (dnsDomainIs(host, ".example.com")) {
    return "DIRECT";
  } else {
    return "PROXY 192.168.1.1:8080; PROXY 192.168.1.2:8080";
  }
}

説明:もしURLが”.example.com”ドメインの場合はプロキシを使用しないで直接接続する。
それ以外は、プロキシ192.168.1.1:8080またはプロキシ192.168.1.2:8080を使用する。

パラメータについての説明

  • urlパラメータ
    アクセスするURLです。
    例:http://www.example.com/
  • hostパラメータ
    URLから抽出したホスト名です。
    例:www.example.com
  • urlパラメータに渡される値のHTTPプロトコルとHTTPSプロトコルでの違い
    FindProxyForURL(url, host)関数では、urlパラメータにはアクセスするURLが渡されます。
    ただし、HTTPとHTTPSでこのurlパラメータの内容に違いがあります。
    • HTTPの場合urlパラメータには完全なURL(パスとクエリを含む)が渡されます。
    • HTTPSの場合urlパラメータには、パスとクエリの部分が削除されたURLが渡されます。

以下の表にまとめてみました。

アクセスするURLurlに渡される値hostに渡される値
HTTPの場合http://www.example.com/site/sample/index.htmlhttp://www.example.com/site/sample/index.htmlwww.example.com
HTTPSの場合https://www.example.com/site/sample/index.htmlhttps://www.example.com/www.example.com

これは、HTTPS通信の内容が暗号化されており、PACファイル(特にJavaScriptコード)がHTTPSリクエストの詳細(パスやクエリパラメータなど)を見ることができないためです。

ただし、この挙動はブラウザによります。
例えば、現在のEdgeやChromeではこの設定を無効にすることはできませんが、Firefoxでは、この設定はnetwork.proxy.autoconfig_url.include_pathで制御できます。

したがって、PACファイルを使用する際は、これらの違いを理解し、必要に応じて適切に対応することが重要です。

6.PACファイルのデバッグ方法

6-1.ブラウザのデバッグツールを使用

現代のブラウザ(Chrome、Firefox、Edgeなど)には、PACファイルのデバッグを手助けするための開発者ツールが組み込まれています。
これを利用することで、PACファイルがどのように動作しているのかを確認できます。

Chromeの場合

  1. プロキシ設定の確認:
    • 「設定」 → 「詳細設定」 → 「システム」 → 「プロキシ設定を開く」 → 「インターネット プロパティ」で、設定しているPACファイルのURLを確認。
  2. PACファイルのログ出力:
    • PACファイル内で alert() 関数を使用して、特定の条件がマッチした場合に通知を表示することができます。
      これにより、PACファイルのどの部分が実行されているかを確認できます。
function FindProxyForURL(url, host) {
alert("Checking URL: " + url);
if (dnsDomainIs(host, ".example.com")) {
return "DIRECT";
}
return "PROXY 192.168.1.1:8080";
}

Firefoxの場合

  1. network.proxy.autoconfig_url.include_path 設定:
    • Firefoxでは、PACファイルのデバッグに関して細かい制御が可能です。
      network.proxy.autoconfig_url.include_path を有効にすると、HTTPSリクエストでもパスを含めてデバッグできます。
    • アドレスバーに about:config と入力して、設定を変更します。
  2. Webコンソールでのログ確認:
    • Firefoxでは、console.log() を使用してログを表示し、PACファイルの動作を追跡することができます。
function FindProxyForURL(url, host) {
console.log("Evaluating URL: " + url);
if (shExpMatch(url, "http://*.example.com/*")) {
return "DIRECT";
}
return "PROXY 192.168.1.1:8080";
}

Edgeの場合

  • EdgeでもChromeと同様に、PACファイルをデバッグするために開発者ツールを使用できます。PACファイルの挙動を追跡するために alert()console.log() を使って、条件にマッチするかどうかを確認します。

6-2. PACファイルのテストツールを使用する

オンラインのPACファイルテストツールや、特定のツールを使うことで、PACファイルの動作をシミュレートして、どのようにプロキシ設定が適用されるかを確認することができます。

例: PACファイルテストツール

  • PACファイルテストサービス: いくつかのウェブサービスでは、PACファイルのURLを入力して、ファイル内のロジックをシミュレートし、どのようなプロキシ設定が適用されるかを確認できます。

6-3. ローカルでのテスト

実際にPACファイルをサーバーにアップロードする前に、ローカル環境でテストすることができます。例えば、手元でPACファイルをホストし、ブラウザのプロキシ設定をそのローカルホストに向けることで、すぐに結果を確認することができます。

ローカルでPACファイルをホスト:

例えば、IISやApacheやNginxなどのウェブサーバーを使って、http://localhost/proxy.pac のようにPACファイルをローカルでホストします。

サーバーが動作しているか、ブラウザの設定をローカルに合わせて、テストします。

Autoprox.exeを使用したPACファイルのテスト

Autoprox.exeは、PACファイルのテストやデバッグを行うためのコマンドラインツールです。
このツールを使うと、PACファイルがどのようにプロキシ設定を決定するかを確認することができます。

Autoprox.exeの使用手順:

Autoprox.exeの実行結果には、どの条件が評価されたかや、どのプロキシ設定が選ばれたのかなど、詳細なデバッグ情報が含まれることがあります。
これにより、PACファイル内のロジックに誤りがないか、意図した通りに動作しているかを確認できます。

1.Autoprox.exeをインストール

Autoprox.exeはWindows環境で動作するツールで、PACファイルの解析を行うために使用します。
インターネットからAutoprox.exeをダウンロードして、インストールします。
こちらのMicrosoftのサイトにダウンロードリンクがあります。

2.テスト対象のPACファイルを準備

使用するPACファイル(例:proxy.pac)を準備します。
内容にはFindProxyForURL()関数が含まれ、URLやホスト名に基づくプロキシ設定のルールを記述しています。

3.Autoprox.exeをコマンドラインから実行

以下のようにコマンドラインでAutoprox.exeを実行します。


Autoprox.exe -p "C:\pacfile\proxy.pac" "http://www.example.com" 

ここで、-pオプションを使用してPACファイルのパスを指定し、テストしたいURL(この例ではhttp://www.example.com)を指定します。

4.結果の確認

Autoprox.exeは、指定したURLに基づいてPACファイルがどのプロキシを使用するかを出力します。
たとえば、プロキシが設定されている場合は、次のような出力が表示されることがあります。

"PROXY 192.168.100.20:8080"

逆に、プロキシなしで直接接続する設定であれば、次のような結果が表示されることになります。

"DIRECT"
5.デバッグ情報の活用

Autoprox.exeの実行結果には、どの条件が評価されたかや、どのプロキシ設定が選ばれたのかなど、詳細なデバッグ情報が含まれることがあります。
これにより、PACファイル内のロジックに誤りがないか、意図した通りに動作しているかを確認できます。

6-4. シンプルな条件から始める

デバッグ時に複雑な条件を一度にテストするのは難しいことがあるため、まずはシンプルな条件から始めるのが良い方法です。たとえば、以下のように一つの条件に絞ってテストします。

javascriptコピーする編集するfunction FindProxyForURL(url, host) {
  if (host == "www.example.com") {
    return "DIRECT";
  }
  return "PROXY 192.168.100.20:8080";
}

上記のように、最も基本的な条件をチェックして、機能が動作していることを確認してから、次に進むと良いでしょう。

6-5.Node.js を使ったテスト

開発者の方はNode.jsを使ってテストをすることが可能です。

const pac = require('pac-resolver');
const fs = require('fs');
fs.readFile('proxy.pac', 'utf8', async (err, script) => {
    if (err) throw err;
    const FindProxyForURL = pac(script);
    console.log(await FindProxyForURL("<http://example.com>", "example.com"));
});


7. PACファイルの最適化

最適化のポイント

デバッグの際、PACファイルが複雑になり過ぎるとパフォーマンスに悪影響を与えることがあります。複雑な条件を使用する場合でも、必要最小限の処理で済ませるよう心がけましょう。
具体的には、以下の点を意識して最適化します。

  1. ホスト名のチェックを最適化
    • 頻繁にアクセスするドメインを先に評価する。
      上から順番に条件を判定していくので、頻繁にアクセスするドメインを上の方に入れると早く処理が終わります。
  2. DNSルックアップを最小限に
    • dnsResolve(host) などの使用を極力避ける。
      DNSサーバーとの通信が発生するためパフォーマンスに影響があります。
  3. 条件をシンプルにする
function FindProxyForURL(url, host) {
    if (shExpMatch(host, "*.trusted.local")) return "DIRECT";
    return "PROXY 192.168.1.1:8080";
}

8. PACファイルのセキュリティ対策

リスク

考えられるリスクとして下記があります。

  • 改ざんされたPACファイル
  • 悪意のあるリダイレクト

対策

上記リスクの対策として下記があります。

  • HTTPS で配信する
  • 変更検知を行う(MD5/SHA チェック)
  • 社内ネットワーク限定で提供

9.WPAD(Web Proxy Auto-Discovery)との関係

WPAD を使うと PACファイルを自動配信できます。

WPADの仕組み

クライアントは、DNSまたはDHCPを使ってWPADの設定を取得し、WPADファイをダウンロードします。
例)

  • クライアントが http://wpad/wpad.dat にアクセス
  • DHCP のオプションから PAC のURLを取得

WPADのリスクと対策

  • WPADハイジャック攻撃 → 社内 DNS でのみ提供
  • 不正なPACファイル配信 → HTTPS で保護

10.まとめ

  • PACファイルでは、JavaScriptの関数と変数を使って、プロキシ設定のロジックを記述します。
  • PACファイルは、ブラウザのプロキシ設定を自動的に管理するためのファイルです。
  • PACファイルの記述方法は、様々な条件や目的に応じてカスタマイズできます。
  • パフォーマンス最適化で処理を軽量化
  • セキュリティ対策として HTTPS で配信し、改ざん防止を徹底
  • WPAD を活用する場合はハイジャック攻撃に注意

PACファイルを適切に管理し、効率的なプロキシ設定を実現しましょう!

免責規定

この記事で提供される情報は、一般的なガイダンスを目的としており、すべての環境やシステムでの動作を保証するものではありません。
OSのバージョンやリリースによっては、記載されている事が実行できない、または異なる結果をもたらす可能性があります。
また、会社所有のパソコン、スマホ、タブレットなどでは、ポリシーや権限によって実行できない場合があります。
この記事の情報を使用することによって生じる問題や結果について、筆者およびサイト管理者は責任を負いません。
すべての操作は自己責任で行ってください。

最後までお読みいただきありがとうございました。
またお会いしましょう!

コメント

  1. Anoymos より:

    助かりました!ありがとうございます。

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