Secure Web Proxy を紹介します

Google Cloud Secure Web Proxyの紹介 (DevOps・セキュリティ Advent Calendar 2023 12/1記事)
2023.12.01

年末恒例のアドベントカレンダーの時期がやってまいりました。

私が所属するアライアンス事業部エンジニアグループでは、DevOps・セキュリティ・Google Cloudチームがリレー方式でDevOps・セキュリティをテーマとした技術ブログを発信していきます!

トップバッターはGoogle Cloudエンジニア 村田が務めます。今回はGoogle Cloudのネットワークセキュリティサービスの一つであるSecure Web Proxyについて紹介していきたいと思います。


本記事はクラスメソッド DevOps・セキュリティ Advent Calendar 2023 の12/1記事になります!


Secure Web Proxy について

Secure Web Proxyはクラウド上のワークロードからインターネットへのトラフィックをプロキシするフォワードプロキシのマネージドサービスで、2023/5にGAとなりました。

Secure Web Proxyは以下の機能と特徴があります。

  • 明示的プロキシサーバとして動作
  • ConnectメソッドのサポートによるTLSエンドツーエンド暗号化
  • 以下のアクセスポリシーに基づくアクセス制御とCloud Loggingへのログ出力
     - タグ、サービスアカウント、IPアドレス等の送信元
     - URL、ホスト名などの宛先
     - メソッド、ヘッダー、URLなどのリクエスト
     ※URLはワイルドカードを指定可能。
  • TLSインスペクション機能
  • 完全なマネージドサービス


これらの機能によって以下のようなメリットがあります。

  • 信頼できる宛先へのHTTP/HTTPSアクセスと送信元の秘匿
  • 柔軟なポリシーによるアクセス制限とアクセスログの管理
  • VMの設定と構成やソフトウェアの更新が不要


Secure Web Proxyによって、VM上に構成したSquidやSaaSプロキシサービスなどサードパーティ製品を利用することによるインフラ構成管理の煩雑さを回避し、Google Cloud上のコンソールで一元管理できることが魅力的であるといえます。

アーキテクチャ

特定のサブネットにSecure Web Proxyインスタンスとして起動します。Secure Web Proxyを起動すると Cloud NAT が自動生成されゲートウェイとして動作します。Cloud NATの自動生成に伴い、Cloud Routerも自動生成されます。Cloud RouterはNATによるトラフィック転送のためのコントロールプレーンとしてCloud NATから参照され、データプレーンとしては利用されません。
なお、Secure Web Proxy と Cloud NAT の通信のために、プロキシ専用サブネットの構成が必要となります。

Secure Web Proxy にはアクセス制御のためにポリシーをアタッチできます。
ポリシーは複数のルールで構成され、ルールには優先度、条件、アクションを指定します。
優先度順にトラフィックの照会し、条件にマッチしたトラフィックに対してアクション(拒否/許可)を行います。
また、合わせてCloud Loggingと連携し、アクセス制御のログ出力を行います。

利用の注意

利用にあたっては以下注意点があります。(特に費用は注意!)

  • 透過型プロキシは構成できない
  • 費用単価がCompute Engine等の他リソースと比較して高単価に設定されている

費用については以下のように設定されています。

項目 料金
処理するトラフィックでかかる費用 0.018 米ドル/GB
インスタンス起動でかかる費用 1.25 米ドル/時間

インスタンスを起動しておくだけで1時間あたり 1.25米ドル かかります。 ブログ執筆時点(2023/11)においてはインスタンスに対して停止/起動するためのAPI提供が無く、料金計上されないようにするには削除するしかありません。 利用を検討される際は費用について十分に検討のうえで導入されることをお勧めします。

詳細は以下をご参照ください。

実際に動かしてみる

検証構成

以下の構成を実際に構築してみます。 URLリストを作成し、許可したURLへの通信のみ外部アクセスできるアクセス制御を構成します。

構築はCloud Shellにて行います。 参考にしたドキュメントは以下です。

IAMロールの適用

Secure Web Proxyの構成には以下ロールの適用が必要です。

Computeネットワーク管理者:roles/compute.networkAdmin
→ポリシーの構成とSecure Web Proxy インスタンスのプロビジョニングに必要
Certificate Manager 編集者:roles/certificatemanager.editor
→TLS証明書を明示的にアップロードするために必要

本検証では外部通信用のワークロードとしてCompute EngineによるVMインスタンスを起動するため以下ロールの適用も行います。
Compute 管理者:roles/compute.admin
→Compute Engineの管理に必要
サービス アカウント ユーザー: roles/iam.serviceAccountUser
→他のGoogle CloudリソースにアクセスするためのサービスアカウントをCompute Engineに関連付けるために必要

APIの有効化

以下APIを有効化します。

Network Security API:Secure Web Proxyポリシー作成に必要
Certificate Manager API:Secure Web Proxyインスタンス作成に必要
(その他、VMインスタンス起動のためCompute Engine APIも有効化します)

検証のためのネットワーク/コンピューティングリソースを準備

Secure Web Gatewayからのインターネットアクセスを検証するための環境として、VPC/サブネット/ファイアウォールルール/Compute Engineを設定します。

Cloud Shellを起動し、以下コマンドを実行します。

  • VPC my-network の作成
    gcloud compute networks create my-network \
    --subnet-mode=custom

  • サブネット vm-subnet の作成

    gcloud compute networks subnets create vm-subnet \
    --network=my-network \
    --range=10.0.1.0/24 \
    --region=us-west1

  • ファイアウォールルール vm-subnet の作成
    ※後ほどSSHでVMにアクセスするために穴あけします。

    gcloud compute firewall-rules create my-network-allow-ssh \
    --network=my-network \
    --action=ALLOW \
    --direction=INGRESS \
    --rules=tcp:22 \
    --source-ranges=0.0.0.0/0
    --priority=1000

  • Compute Engine swp-test-vm の作成

    gcloud compute instances create swp-test-vm \
    --subnet=vm-subnet \
    --zone=us-west1-a \
    --image-project=debian-cloud \
    --image-family=debian-11

プロキシ専用サブネットを作成

Secure Web Proxyインスタンスの外向きトラフィックに一意のIPアドレスを割り振り、Cloud NATなどとやり取りを行うための専用のサブネットを用意します。

gcloud compute networks subnets create swp-subnet \
--purpose=REGIONAL_MANAGED_PROXY \
    --role=ACTIVE \
    --region=us-west1 \
    --network=my-network \
    --range=10.0.2.0/24

プロキシ専用サブネットとするには--purpose=REGIONAL_MANAGED_PROXYをオプションで指定する必要があります。
※Cloud Consoleで設定する場合はサブネット作成画面で[目的]→[リージョンのマネージド プロキシ]にチェックを入れます。

Cloud Consoleでプロキシ専用サブネットが構成されていることが確認できます。

Secure Web Proxy ポリシーを作成

アクセス制御のためのポリシーmyswppolicyを作成します。この時点ではルールは作成せず、空のポリシーを作成しておきます。なお、空のポリシーをSecure Web Proxyインスタンスにアタッチすると、すべてのトラフィックを拒否する動作となります。

policy.yamlを作成する。

vim policy.yaml

policy.yamlを以下のように記述する。(PROJECT IDは書き換えてください)

policy.yaml

description: basic Secure Web Proxy policy
name: projects/PROJECT ID/locations/us-west1/gatewaySecurityPolicies/myswppolicy

Secure Web Proxy ポリシーを作成する。

gcloud network-security gateway-security-policies import myswppolicy \
--source=policy.yaml \
--location=us-west1

SSLサーバ証明書を作成

HTTPSのプロキシを行うため、SSLサーバ証明書を作成します。検証のため、今回は自己署名証明書をOpenSSLで作成します。

OpenSSLでSSLサーバ証明書と秘密鍵を作成する。
※Secure Web Proxyのホスト名をmyswp.example.comとしています。

openssl req -x509 -newkey rsa:2048 \
-keyout ~/key.pem \
-out ~/cert.pem -days 365 \
-subj '/CN=myswp.example.com' -nodes -addext \
"subjectAltName=DNS:myswp.example.com"

SSLサーバ証明書と秘密鍵をCertificate Managerにmycertとしてアップロードする。
※Certificate ManagerはGoogle Cloudで証明書を管理するサービスです。

gcloud certificate-manager certificates create mycert \
--certificate-file=cert.pem \
--private-key-file=key.pem \
--location=us-west1

Cloud Consoleより[セキュリティ]→[Certificate Manager]にてアップロードされたことが確認できます。

Secure Web Proxy インスタンスを作成

Secure Web Proxy インスタンスmyswpを作成します。

gateway.yamlを作成する。

vim gateway.yaml

gateway.yamlを以下のように記述する。(PROJECT IDは書き換えてください)

gateway.yaml

name: projects/PROJECT ID/locations/us-west1/gateways/myswp
type: SECURE_WEB_GATEWAY
ports: [443]
certificateUrls: ["projects/PROJECT ID/locations/us-west1/certificates/mycert"]
gatewaySecurityPolicy: projects/PROJECT ID/locations/us-west1/gatewaySecurityPolicies/myswppolicy
network: projects/PROJECT ID/global/networks/my-network
subnetwork: projects/PROJECT ID/regions/us-west1/subnetworks/vm-subnet

Secure Web Proxy インスタンスをデプロイする。

gcloud network-services gateways import myswp \
--source=gateway.yaml \
--location=us-west1

Cloud Consoleより[ネットワークセキュリティ]→[セキュア ウェブプロキシ]にてmyswpが作成されていることが確認できます。本検証ではゲートウェイのIPアドレスを指定していないためvm-subnetから10.0.1.2が自動でアサインされています。(指定も可能です)

また、Cloud Consoleより[ネットワークサービス]→[Cloud NAT]にてCloud NATとCloud Routerも自動生成されていることが確認できます。

URLリストを作成

アクセス制御のためのポリシーに設定するルールの条件として使用する「URLリスト」を作成します。
ここでは、.google.comwww.google.com といったドメインへのアクセスを許可するためのURLをワイルドカードを用いて指定し、URLリストmyurlとします。

myurl.yamlを作成する。

vim myurl.yaml

myurl.yamlを以下のように記述する。(PROJECT IDは書き換えてください)

myurl.yaml

name: projects/PROJECT ID/locations/us-west1/urlLists/myurl
values:
  - "*google.com"

values:にURLを記述します。URLは複数行に渡って記述することができます。本検証では.google.com www.google.com を含むようにワイルドカードを利用して*google.comと指定しています。
なお、ワイルドカード(*)を使用する際は、引用符(")で囲む必要があるため注意ください。

myurlをSecure Web Proxy ポリシーから参照できるようにアップロードする。(PROJECT IDは書き換えてください)

gcloud network-security url-lists import myurl \
--location=us-west1 \
--project=PROJECT ID \
--source=myurl.yaml

Cloud Consoleより[ネットワークセキュリティ]→[セキュア ウェブプロキシ]→[URLリスト]にてmyurlがアップロードされていることが確認できます。

Secure Web Proxy ルールを作成

アクセス制御のためのポリシーに設定するルールmyruleを作成します。
条件にはmyurlを指定し、*google.comにマッチする宛先への通信を「許可」、それ以外の通信を「暗黙の拒否」するルールとします。

myrule.yamlを作成する。

vim myrule.yaml

myrule.yamlを以下のように記述する。(PROJECT IDは書き換えてください)

myrule.yaml

name: projects/PROJECT ID/locations/us-west1/gatewaySecurityPolicies/myswppolicy/rules/myrule
basicProfile: ALLOW
enabled: true
priority: 100
sessionMatcher: "inUrlList(host(), 'projects/murata-kazuhiro/locations/us-west1/urlLists/myurl')"

sessionMatcherでURLリストを用いたマッチ条件をCEL(Common Expression Language)形式で記述します。
CELの記述については以下のリファレンスを参照ください。

myruleをSecure Web Proxy ポリシー myswppolicy にアタッチする。(PROJECT IDは書き換えてください)

gcloud network-security gateway-security-policies rules import myrule \
--location=us-west1 \
--project=PROJECT ID \
--source=myrule.yaml \
--gateway-security-policy=myswppolicy

Cloud Consoleより[ネットワークセキュリティ]→[セキュア ウェブプロキシ]→[ポリシー]からmyswppolicyを選択します。myruleがアタッチされていることが確認できます。

Secure Web Proxyの構成はここまでで完了です。

プロキシ通信の確認

Secure Web Proxyによるプロキシ通信とURLによるアクセス制御の動作を確認します。
通信確認用のVMインスタンスswp-test-vmにSSHアクセスしログインします。Cloud Consoleより[Compute Engine]→[VMインスタンス]→swp-test-vmの[SSH]をクリックします。

curlコマンドを利用してプロキシ経由の通信を検証します。
-xで指定したプロキシを経由して通信を行います。指定するプロキシはSecure Web Proxyのゲートウェイに設定された10.0.1.2となります。また、本検証ではHTTPSのプロキシ通信のために自己署名証明書を利用しているため、証明書による検証を無視する--proxy-insecureオプションも付けます。

まずは、「許可」としたgoogle.comへのアクセス確認を行います。

$ curl -x https://10.0.1.2:443 https://google.com --proxy-insecure
<HTML><HEAD><meta http-equiv="content-type" content="text/html;charset=utf-8">
<TITLE>301 Moved</TITLE></HEAD><BODY>
<H1>301 Moved</H1>
The document has moved
<A HREF="https://www.google.com/">here</A>.
</BODY></HTML>

(301 Movedではありますが)HTTPSリクエストがSecure Web Proxyを経由してレスポンスが返ってくることが確認できます。

次に、許可していないexample.comへのアクセス確認を行います。

$ curl -x https://10.0.1.2:443 https://example.com --proxy-insecure
curl: (56) Received HTTP code 403 from proxy after CONNECT

CONNECTメソッドによるHTTPSリクエスト後にプロキシから403が返ってきたことが確認できます。

Secure Web Proxyのアクセス制御により拒否されたものであるか確認するために、Cloud loggingでログを確認してみます。

Cloud Consoleより[ロギング]→[ログエクスプローラー]から、クエリフィールドに以下のログクエリをコピーし[クエリを実行]します(PROJECT IDは書き換えてください)。

resource.type="networkservices.googleapis.com/Gateway"
resource.labels.gateway_type="SECURE_WEB_GATEWAY"
resource.labels.network_name="projects/PROJECT ID/global/networks/my-network"
resource.labels.gateway_name="myswp"
severity=WARNING

以下のようなログが確認できます。

{
  "insertId": "z8l61sedwurf",
  "jsonPayload": {
    "@type": "type.googleapis.com/google.cloud.loadbalancing.type.LoadBalancerLogEntry",
    "enforcedGatewaySecurityPolicy": {
      "matchedRules": [
        {
          "name": "default_denied",
          "action": "DENIED"
        }
      ],
      "hostname": "example.com:443"
    }
  },
  "httpRequest": {
    "requestMethod": "CONNECT",
    "requestSize": "114",
    "status": 403,
    "responseSize": "141",
    "userAgent": "curl/7.74.0",
    "remoteIp": "10.0.1.3:52028",
    "latency": "0.000151s",
    "protocol": "HTTP/1.1"
  },
...
}

example.com:443へのリクエストがdefault_denied(暗黙のdeny)によってDENIEDとなっていることが確認できます。

検証環境のクリーンアップ

Secure Web Proxyインスタンスは料金単価が高いため、検証の際は削除することを忘れないようにしましょう。(ひとまずSecure Web Proxyインスタンスが削除できれば課金されません。)

  • Secure Web Proxyインスタンス削除
    gcloud network-services gateways delete myswp \
    --location=us-west1

その他リソースは以下コマンドで削除できます。

  • ルール削除
    gcloud network-security gateway-security-policies rules delete myrule \
    --location=us-west1 \
    --gateway-security-policy=myswppolicy

  • ポリシー削除

    gcloud network-security gateway-security-policies delete myswppolicy \
    --location=us-west1

  • URLリスト削除

    gcloud network-security url-lists delete myurl \
    --location=us-west1

Secure Web Proxyインスタンスの作成に伴って自動作成されたCloud RouterとCloud NATも明示的に削除する必要があります。

  • Cloud Router削除(ROUTER_NAMEは書き換えてください)
    ※Cloud Routerを削除すると、紐づくCloud NATも削除されます。

    gcloud compute routers delete ROUTER_NAME --region=us-west1

Conpute Engineの削除コマンドも参考までに記載します。

  • Compute Engine削除
    gcloud compute instances delete swp-test-vm

おわりに

本ブログではSecure Web Proxyについて紹介しました。
柔軟なアクセス制御が容易に構成できるマネージドサービスであることがおわかりいただけたかと思います。お試しいただけるよう検証結果も記載しましたが、料金には十分気を付けて検証してください。