Cloudflare Zero TrustのGateway proxyを使ってWARPなしの状態でサイトのブロックをしてみた。

どうもさいちゃんです。本ブログはクラスメソッド DevOps・セキュリティ Advent Calendar 2023の23日目の記事です今回はWARPクライアントをインストールできないデバイスに対してHTTPポリシーを作成する方法についてご紹介します。
2023.10.31

PACファイルとは

PACファイルについて理解するためにはプロキシを理解する必要があるので簡単に説明します。プロキシとは、クライアントがサーバーにアクセスする際に間に入る「代理サーバー」のことを指します。このプロキシサーバーには大きく「フォワードプロキシ」と「リバースプロキシ」の2つがあり、目的によって使い分けられています。

Cloudflareの提供するApplicarionサービスやZero Trustサービスも基本的にはクライアントとサーバの間にCloudflareが入り、プロキシのような動きをすることで、高速かつ安全な通信や、負荷分散を可能にしています。

下記ブログにプロキシ化についての分かりやすい説明があるのでこちらも併せて読んでいただけると、Cloudflareがどのように動作するかが想像しやすいかと思います。

前置きが長くなりましたが、ここから本題のPACについてです。PACとはproxy auto-configの略で日本語ではプロキシ自動設定となります。
簡単にいうと、WEBブラウザのリクエストをどのプロキシサーバーを経由して送信するのかJavaScriptで記載された設定ファイルです。つまり、PACファイルがあれば、クライアントのリクエストは自動的に正しいプロキシサーバーを経由して、サーバーに送られます。

Cloudflare Zero Trustには、このPACファイルを使用して、デバイスにWARPクライアントをインストールできない場合でも、ブラウザレベルでHTTPポリシーを適用できるようになるGateway proxyという機能があります。 今回はこのGateway proxyの設定方法についてご紹介していきたいと思います。

やってみた

上記で説明したようにこちらの機能はエージェントレスでのHTTPポリシー適用を可能にするものなのでWARPクライアントのインストールは必要ありません。条件としては、CloudflareのルートCA証明書をデバイスにインストールしておく必要があります。こちらについてはプロキシ―サーバーのテストの項目で詳しく説明します。

Proxy endpointの作成

Proxy endpointはAPIで作成することも可能ですが、今回はダッシュボードから作成していきます。

ダッシュボードからGateway > Proxy Endpointへ進みます。

Create endpointを選択して新しいエンドポイントを作成していきます。

エンドポイントに任意の名前を付け、トラフィックをプロキシさせたいデバイスのパブリックIPアドレスを入力し、Save endpointで保存します。

出来上がったエンドポイント名を選択すると詳細が確認できるので、エンドポイントをメモしておきます。

プロキシサーバーのテスト

初めに、Cloudflare GatewayのHTTPポリシーでexample.comをブロックするポリシーを作成し、有効化しておきます。

通常だとWARPをインストールしていないデバイスではこの設定が反映することはないはずです。しかし、プロキシサーバーを経由する場合は設定したHTTPポリシーが適用されるため、example.comはブロックされます。 では、さっそく試してみます。

CloudflareのルートCA証明書を指定をしないとエラーが発生してしまうようなので、証明書の指定をしてアクセスします。

証明書のインストールがまだの場合は先にインストールしてください。

  • 証明書のインストール
    curl -O https://developers.cloudflare.com/cloudflare-one/static/documentation/connections/Cloudflare_CA.pem

証明書を指定してアクセスしてみます。(ここでもしエラーが出る場合は--insecureもしくは-kオプションを付けることで回避することが出来ます。)

curl -4 -p --insecure https://example.com/ --proxy https://moa31kmjso.proxy.cloudflare-gateway.com -v --cacert Cloudflare_CA.pem
*   Trying 162.159.193.21:443...
* Connected to moa31kmjso.proxy.cloudflare-gateway.com (162.159.193.21) port 443 (#0)
* schannel: disabled automatic use of client certificate
* ALPN: offers http/1.1
* ALPN: server accepted http/1.1
* allocate connect buffer
* Establish HTTP proxy tunnel to example.com:443
> CONNECT example.com:443 HTTP/1.1
> Host: example.com:443
> User-Agent: curl/8.0.1
> Proxy-Connection: Keep-Alive
>
< HTTP/1.1 200 OK
< Cf-Team: 1c0ccf5a5c0000fcf11ddd6400000001
< Date: Thu, 26 Oct 2023 08:59:59 GMT
<
* CONNECT phase completed
* CONNECT tunnel established, response 200
* schannel: disabled automatic use of client certificate
* ALPN: offers http/1.1
* ALPN: server accepted http/1.1
* using HTTP/1.1
> GET / HTTP/1.1
> Host: example.com
> User-Agent: curl/8.0.1
> Accept: */*
>
< HTTP/1.1 302 Found
< Location: https://blocked.teams.cloudflare.com/?account_id=172411ba14a3cd8e6dce641de0152c07&user_id=&rule_id=e14cc886-1c36-4a35-a660-01ef694eaac5&url=https%3A%2F%2Fexample.com%2F&source_ip=60.89.164.18%3A60302&device_id=
< Cf-Team: 1c0ccf65560000fcf11de03400000001
< Content-Length: 0
< Date: Thu, 26 Oct 2023 09:00:02 GMT
<
* Connection #0 to host moa31kmjso.proxy.cloudflare-gateway.com left intact

うまくいけば上記のように、example.comの中身は表示されず、CloudflareのBlockページが返ってきます。 Cloudflare側のログも確認してみましょう。

HTTPログを確認すると、exampl.comがブロックされています。
Request IDがレスポンスヘッダCf-Team: 1c0ccf5a5c0000fcf11ddd6400000001と一致していることも確認できます。

PACファイルの作成

次にPACファイルを作成して行きます。今回のPACファイルの中身は以下の通りです。
プライベートアドレス(RFC 1918)以外のアドレスからの通信はすべてProxy Endpoint経由でProxyされるような設定になっています。

proxy.pac

function FindProxyForURL(url, host) {
  // No proxy for private (RFC 1918) IP addresses (intranet sites)
  if (
    isInNet(dnsResolve(host), "10.0.0.0", "255.0.0.0") ||
    isInNet(dnsResolve(host), "172.16.0.0", "255.240.0.0") ||
    isInNet(dnsResolve(host), "192.168.0.0", "255.255.0.0")
  ) {
    return "DIRECT";
  }

  // No proxy for localhost
  if (isInNet(dnsResolve(host), "127.0.0.0", "255.0.0.0")) {
    return "DIRECT";
  }

  // Proxy all
  return "HTTPS moa31kmjso.proxy.cloudflare-gateway.com:443";
}

PACファイルはブラウザーがアクセスできる場所であればどこにおいても問題ないのですが、今回は公開設定にしたS3バケットに置きます。

こちらのファイルを格納するS3バケットを作成していきます。

バケットを今回は公開設定にしておきたいので「パブリックアクセスをすべてブロック」の項目はチェックを外しておきます。

他はデフォルトの設定で問題ないのでそのままバケットを作成します。 S3バケットのバケットポリシーはデフォルトが許否設定になっているため、バケットを公開するためにバケットポリシーを下記のものに変更します。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "PublicRead",
            "Effect": "Allow",
            "Principal": "*",
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::バケットの名前/*"
        }
    ]
}

S3バケットのアクセス許可を確認して設定を確認しましょう。

バケットポリシーに問題がなければ、これでバケットは公開の状態になっているはずです。

こちらのバケットにPACファイルをアップロードします。

この時PACファイルのオブジェクトURLをメモしておきましょう。

 

S3のPACファイルにアクセスできるかをcurlで確認します。

curl https://proxy-sample-bucket.s3.ap-northeast-1.amazonaws.com/proxy.pac
function FindProxyForURL(url, host) {
  // No proxy for private (RFC 1918) IP addresses (intranet sites)
  if (
    isInNet(dnsResolve(host), "10.0.0.0", "255.0.0.0") ||
    isInNet(dnsResolve(host), "172.16.0.0", "255.240.0.0") ||
    isInNet(dnsResolve(host), "192.168.0.0", "255.255.0.0")
  ) {
    return "DIRECT";
  }

  // No proxy for localhost
  if (isInNet(dnsResolve(host), "127.0.0.0", "255.0.0.0")) {
    return "DIRECT";
  }

  // Proxy all
  return "HTTPS moa31kmjso.proxy.cloudflare-gateway.com:443";
}

このように、S3にアップロードしたファイルの中身が返ってくれば問題なくS3バケットにアクセスできている状態です。

ブラウザの設定

ではブラウザ側の設定をしていきます。今回はFirefoxを使用していきます。

初めにまだプロキシ設定を行っていない状態でexample.comへアクセスをしてみます。

この状態だと問題なくexample.comへアクセスできています。 ではFirefoxでプロキシ設定を行っていきます。 Firefoxブラウザの右上にある三線アイコンをクリックし、設定を選択します。

一般オプションの一番下にネットワーク設定の項目があるので、そこまでスクロールし、接続設定を選択します。

自動プロキシ設定スクリプト URLにチェックをいれ、先ほどメモしておいたPACファイルのオブジェクトURLを入力します。 OKを選択して保存します。

確認

これですべての設定が終わったので、実際に動作確認を行っていきます。

example.comへアクセスしてみます。

WARPがオンになっていない状態でもサイトがブロックされています。 念のためログの確認もしておきます。

example.comがポリシーによってブロックされていることが確認できました。

まとめ

今回はPACファイルを使用して、WARPがない状態でもHTTPフィルタリングを行う方法についてご紹介しました。
こちらの機能を使うことで、WARPのインストールに対応していないOSタイプでもサイトのブロックが可能になります。PACファイルの用意をしておけば、後はブラウザを設定するだけで、簡単にフィルタリングを行うことが出来ました。WARPのインストールができないOSを使用しているが、不審なサイトのブロックをしたいという場合にはこちらの機能を試してみてください。