自宅のプロキシサーバーでのPACファイルによるアクセス制御の検証手順

## はじめに
PAC（Proxy Auto-Configuration）ファイルの存在は知っていましたが、具体的な理解が不十分だったため、自宅の検証環境でテストを行いました。
過去に「特定の通信のみ社内のプロキシを経由せず、直接インターネットにアクセスする」という案件があり、その際に苦戦した経験を基に、この記事を記録として残すことにしました。

PACファイルやWPADの仕組みを理解することで、端末のアクセス制御を柔軟に行えるようになります。
また、それをGPO（グループポリシー）などを通じてクライアント端末に一斉に配布できるため、今後役立つスキルだと思いました。

今回は自宅のプロキシサーバーにNGINXを導入し、WebサーバーとしてPACファイルを配置し、アクセス制御を行うことをゴールとします。

## 前提条件
:::note info
前提条件としては、以下の環境で後続の検証を進めていきます。
**・VirtualBox上で稼働しているAlmaLinux（CentOSの後継）を採用**
**・VirtualBox上で稼働しているWindows 10端末（評価版）を使用**
**・プロキシのミドルウェアとしてSquidを使用**
**・Webサーバーの要件としてNGINXを採用**
:::

## 全体像および自宅検証環境
以前、[自宅にプロキシサーバーを構築してアクセスログを確認する方法](https://qiita.com/free-honda/items/27a201413787414b0108)というブログを書いていますので、プロキシに関する詳細はそちらをご参照ください。

今回はPACファイルの検証に焦点を当てて紹介していきます。

**自宅のVirtualBox環境**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3662571/37727888-dfb1-13f0-720f-290d69e65b6b.png)

:::note info
※検証で使用するのは「proxy」と「Windows 10」になります。
:::

**VirtualBox環境のネットワーク設計は以下の通りです。**

Windows 10端末は独自のNICを持たず、インターネットにアクセスする際には内部ネットワークを通り、プロキシサーバーを経由しないと外部に出ていけないように構成しています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3662571/cea5b0a6-ce47-ef49-b99f-b66f2afe0ea7.png)

**プロキシサーバー**
VirtualBox: AlmaLinux release 9.3 (Shamrock Pampas Cat)
ミドルウェア: Squid Cache Version 5.5
ミドルウェア: nginx/1.20.1

**Windows 10端末（評価版）**
エディション: Windows 10 Enterprise
バージョン: 22H2
OSビルド: 19045.2006

## 知識整理
PAC（Proxy Auto-Configuration）ファイルは、ブラウザや他のアプリケーションがどのプロキシサーバーを使用するかを決定するスクリプトファイルです。
PACファイルを使用することで、ネットワークトラフィックを動的に制御できます。

:::note warn
必要な知識については、詳しいサイトが多数ありますので、公式サイトと併せてご紹介します。

**プロキシサーバーについて**
詳細サイト: https://www.ntt.com/bizon/glossary/j-h/proxy-server.html

**PACファイルについて**
詳細サイト: https://jpdsi.github.io/blog/internet-explorer-microsoft-edge/pac/
詳細サイト: https://www.cisco.com/c/ja_jp/support/docs/security/web-security-appliance/118076-configure-wsa-00.html

**Squidについて**
詳細サイト: https://qiita.com/zabuton13/items/bbe5f540f7536fa95eae
公式サイト: https://www.squid-cache.org/

**NGINXについて**
詳細サイト: https://cn.teldevice.co.jp/column/38275/
公式サイト: https://nginx.org/en/
:::

## 構築の流れ
VirtualBoxの導入などのステップ1〜3は割愛しますが、上記の参考サイトなどをご参照し、ご自身の環境に合わせてセットアップを行ってください。

ステップ4、5については前回のブログで紹介しているので、そちらをご参照ください。
[自宅にプロキシサーバーを構築してアクセスログを確認する方法](https://qiita.com/free-honda/items/27a201413787414b0108)

:::note info
ここでは、Webサーバーの構築とPACファイルの作成パターンについて説明します。
~~**ステップ1：VirtualBoxの導入（ここでは割愛）**~~
~~**ステップ2：VirtualBoxにAlmaLinuxサーバーを1台構築（ここでは割愛）**~~
~~**ステップ3：VirtualBoxにWindows 10端末（評価版）を1台構築（ここでは割愛）**~~
~~**ステップ4：AlmaLinuxサーバーにSquidを導入・設定（ここでは割愛）**~~
~~**ステップ5：Windows 10端末のセットアップ（ここでは割愛）**~~
**ステップ6：AlmaLinuxサーバーにNGINXを導入・設定**
**ステップ7：PACファイルの作成及び配置**
**ステップ8：Windows 10端末の一部設定の変更**
:::

## ステップ6：AlmaLinuxサーバーにNGINXを導入・設定
まずはパッケージを最新の状態に更新します。
```
sudo yum update -y
```

AlmaLinux上でNGINXをインストールします。
```
sudo yum install nginx -y
```

NGINXを起動し、サーバーが再起動したときにも自動で起動するように設定します。
```
sudo systemctl start nginx
sudo systemctl enable nginx
```

## ステップ7：PACファイルの作成及び配置
NGINXのデフォルトのWebサーバーのルートディレクトリにPACファイルを作成します。
```
sudo vi /usr/share/nginx/html/test.pac
```

以下に、いくつかのPACファイルのパターンを示します。必要に応じてプロキシサーバーのIPアドレスを変更してください。

:::note info
ここでは、PACファイルのパターン⓵の記述を採用して後続の検証を実施しております。
:::

PACファイルのパターン⓵：Yahoo!のみプロキシを使用し、他はダイレクトアクセス
```javascript
function FindProxyForURL(url, host) {
    if (dnsDomainIs(host, "yahoo.co.jp") || dnsDomainIs(host, "www.yahoo.co.jp")) {
        return "PROXY 10.0.1.1:3128";  // Yahoo!にアクセスするときにプロキシを使用
    }
    return "DIRECT";  // それ以外はダイレクトアクセス
}
```

PACファイルのパターン⓶：Yahoo!にHTTPSでアクセスする際のみプロキシを使用
```javascript
function FindProxyForURL(url, host) {
    if (shExpMatch(url, "https://*.yahoo.co.jp/*")) {
        return "PROXY 10.0.1.1:3128";  // HTTPSのYahoo!にアクセスする際はプロキシを使用
    }
    return "DIRECT";  // それ以外はダイレクトアクセス
}
```

PACファイルのパターン⓷：Yahoo!以外のすべてのアクセスでプロキシを使用
```javascript
function FindProxyForURL(url, host) {
    if (dnsDomainIs(host, "yahoo.co.jp") || dnsDomainIs(host, "www.yahoo.co.jp")) {
        return "DIRECT";  // Yahoo!へのアクセスはダイレクト
    }
    return "PROXY 10.0.1.1:3128";  // 他のサイトはプロキシ経由
}
```

PACファイルのパターン⓸：Yahoo!にアクセスする際に異なるプロキシを使用
```javascript
function FindProxyForURL(url, host) {
    if (dnsDomainIs(host, "yahoo.co.jp") || dnsDomainIs(host, "www.yahoo.co.jp")) {
        return "PROXY 54.248.138.53:3128";  // Yahoo!へのアクセスのみ異なるプロキシを使用
    }
    return "PROXY 10.0.1.1:3128";  // 他のサイトは通常のプロキシを使用
}
```

PACファイルのパターン⓹：Yahoo!にアクセスする際のロードバランシングプロキシ
```javascript
function FindProxyForURL(url, host) {
    if (dnsDomainIs(host, "yahoo.co.jp") || dnsDomainIs(host, "www.yahoo.co.jp")) {
        var proxies = ["PROXY 10.0.1.1:3128", "PROXY 10.0.1.2:3128"];
        return proxies[Math.floor(Math.random() * proxies.length)];  // ランダムにプロキシを選択
    }
    return "DIRECT";  // それ以外はダイレクトアクセス
}
```

PACファイルのパターン⓺：Yahoo!へのアクセスのみ多段プロキシ
```javascript
function FindProxyForURL(url, host) {
    if (dnsDomainIs(host, "yahoo.co.jp") || dnsDomainIs(host, "www.yahoo.co.jp")) {
        // Yahoo!へのアクセスに対して、最初のプロキシを経由し、その後、次のプロキシを経由する
        return "PROXY 10.0.1.1:3128; PROXY 10.0.1.2:3128";
    }
    return "DIRECT";  // それ以外はダイレクトアクセス
}
```

## ステップ8：Windows 10端末の一部設定の変更

:::note info
**セットアップ手順は、以下の通りとなります。**
・スタートメニューから「設定」を開き、「ネットワークとインターネット」を選択。
・「プロキシ」をクリックし、「セットアップスクリプトを使う」をオンにします。
・「スクリプトのアドレス」にAlmaLinuxサーバーのIPアドレスとPACファイルのパスを指定します。
:::

**例：**
セットアップスクリプトを使う：オン
スクリプトのアドレス：http://192.168.1.10/〇〇〇.pac

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3662571/73d1a878-6fc9-e2ee-ae13-906cf4f622b8.png)


## 検証及び検証結果
今回は、以下のスクリプトのPACファイルを使用しました。想定では、Yahoo!のサイトのみアクセスが可能で、他の通信はダイレクト、つまりインターネットに直接接続されるように設定しています。

:::note alert
**※ただし、検証用のWindows 10端末はインターネットに直接接続できない構成の為、実際には他のサイトにはアクセスできないことを確認します。**
:::

**Windows 10端末**
Windows 10端末のIPアドレスは以下の通りです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3662571/2321c2aa-41a2-3d34-badb-6a19263363a3.png)

検証の結果、Yahoo!のサイトにのみ正常にアクセスできていることを確認しました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3662571/43bddbc9-5c8b-e96a-bc32-94648b4305d1.png)

一方、Amazonのサイトにアクセスした際には「このサイトにアクセスできません」と表示され、他のサイトにはアクセスできないことが確認できました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3662571/a8e5c51e-a217-8ef0-95d7-e3ae14018f48.png)

**プロキシサーバー側のアクセスログ**
以下のコマンドでリアルタイムにプロキシサーバーのログを確認し、「Yahoo!」に関するアクセスのみが記録されていることを確認しました。
```
tail -f /var/log/squid/access.log
```

プロキシサーバーのログにも、Windows 10端末のIPアドレス「**10.0.1.2**」によるアクセスが記録されていることを確認しました。

**実際のログ画面**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3662571/4d3268d0-e3d9-3de1-2922-b64949d3d4d3.png)

:::note warn
一方、Amazonなどのアクセスログは記録されておらず、これにより他のサイトへのダイレクト接続ができないことが確認できました。
:::

つまり、Yahoo!以外の通信はインターネットに出られない設定が正しく動作していることが証明されました。

```
1725702436.584  11661 10.0.1.2 TCP_TUNNEL/200 61351 CONNECT www.yahoo.co.jp:443 - HIER_DIRECT/183.79.219.252 -
1725704195.201   6798 10.0.1.2 TCP_TUNNEL/200 60545 CONNECT www.yahoo.co.jp:443 - HIER_DIRECT/182.22.31.252 -
1725704228.470   9699 10.0.1.2 TCP_TUNNEL/200 53866 CONNECT www.yahoo.co.jp:443 - HIER_DIRECT/182.22.31.252 -
1725704261.473   4192 10.0.1.2 TCP_TUNNEL/200 60508 CONNECT www.yahoo.co.jp:443 - HIER_DIRECT/182.22.31.124 -
1725704333.239    212 10.0.1.2 TCP_TUNNEL/200 626 CONNECT www.yahoo.co.jp:443 - HIER_DIRECT/183.79.219.124 -
1725704337.413   4389 10.0.1.2 TCP_TUNNEL/200 53128 CONNECT www.yahoo.co.jp:443 - HIER_DIRECT/183.79.219.124 -
1725704435.034  10431 10.0.1.2 TCP_TUNNEL/200 53227 CONNECT www.yahoo.co.jp:443 - HIER_DIRECT/183.79.217.124 -
1725704511.994   3011 10.0.1.2 TCP_TUNNEL/200 61581 CONNECT www.yahoo.co.jp:443 - HIER_DIRECT/182.22.16.123 -
```

## まとめ
この記事では、NGINXを使用したWebサーバーにPACファイルを配置し、アクセス制御を行う方法について解説しました。
VirtualBox上でAlmaLinuxサーバーとWindows 10端末を使用し、Squidプロキシを導入して検証を行いました。
PACファイルを活用することで、Yahoo!のみアクセスを許可し、他のサイトへのアクセスを制限する設定が可能であることを確認しました。

また、プロキシのログからも意図した動作が確認でき、PACファイルを用いたアクセス制御の基本を学ぶ良い機会となりました。

## 参考記事
https://note.com/peternwse/n/n61906f00ed37

https://www.bnote.net/windows/debug_pac.html

https://help.zscaler.com/ja/zia/best-practices-writing-pac-files

https://qiita.com/free-honda/items/5b686db48a7d9f1ff449