フルマネージドなプロキシサービス Secure Web Proxy を試す
はじめまして。クラウドエース株式会社で Google Cloud 認定トレーナーをしている廣瀬 隆博です。弊社には廣瀬が複数名おりますので、絵文字がメロイックサイン(🤘)になっている人だと覚えていただけると幸いです。
さて、今回は Google Cloud において 2023 年 5 月 22 日に一般公開された Secure Web Proxy についてご紹介していきます。このサービスは文字通り Web Proxy であり、Web サイトへのアクセスを中継してくれます。同じような働きをするオープンソースソフトウェアでは Squid が有名ですね。
概要
そもそも、Web Proxy はどのような時に使用するのでしょうか。Web Proxy では、Web サイトへのアクセスを中継する際に許可・拒否を制御することができます。つまり、業務に必要な Web サイト のみアクセスを許可することや、業務に不要な Web サイトへのアクセスを拒否することができます。また、中継した情報をログに記録することができますので、いつ・誰が・どこへアクセスしたのか監査することができるようになります。
似たような仕組みとして、外部 IP アドレスを持たないサーバーインスタンス等がインターネットへアクセスする場合は Cloud NAT を用いることがあります。しかし、Cloud NAT では上記のようなアクセス制御はできません。つまり、インターネットへアクセスしたいだけなら Cloud NAT、アクセス制御を実装したければ Web Proxy といった使い分けになります。
今回ご紹介する Secure Web Proxy はフルマネージドサービスですので、冗長性の考慮やセキュリティパッチの適用といった煩雑な運用作業から解放されます。 管理者が本来注力したいアクセス制御やログの監査に集中することができますので、Web Proxy の運用に手間を感じている場合は是非とも導入を検討していただければと思います。
[公式ドキュメント] Secure Web Proxy overview
事前準備
それでは、Secure Web Proxy を動かすための事前準備から初めていきましょう。今回は新しいプロジェクトを用意して検証しています。
[Google Cloud Console] 新しいプロジェクト
権限付与
公式ドキュメントでは roles/compute.networkAdmin
と roles/certificatemanager.editor
を付与していますが、今回は検証用ですので roles/owner
で対応します。ちゃんと稼働させる環境を構築する際には、厳格な権限付与をお勧めします。
API 有効化
今回の検証では以下の API が必要となりましたので、始める前に有効化しておくとスムーズですね。今回の本題ではないので詳細は割愛しますが、対象のAPIを見つけて有効化してください。
- Compute Engine API
- Network Services API
- Certificate Manager API
- Network Security API
[Google Cloud Console] API ライブラリ
ネットワーク作成
プロジェクトを作成した際に自動生成される default
ネットワークは既定 Firewall ルールいくつかが動作しており、検証には不向きです。今回は新たに検証用ネットワーク secure-web-proxy-test
を作成します。その際に、プロキシをテストするための VM が稼働するサブネット vm-subnet
を asia-northeast1
に作成しておきます。
ネットワークの作成後は、Secure Web Proxy が動作するプロキシ サブネット proxy-subnet
を追加します。後から追加する理由は、VPC 作成画面ではサブネットの目的を指定することができないためです。また、サブネットのサイズは /23
以上が推奨されるようなので、今回は /16
としました。
ネットワーク作成手順の詳細は割愛しますが、必要に応じて以下の公式ドキュメントをご参照ください。
[公式ドキュメント] IPv4 サブネットのみを持つカスタムモードの VPC ネットワークを作成する
[Google Cloud Console] VPC ネットワーク
SSL 証明書の作成と登録
Secure Web Proxy の作成には、SSL 証明書が必要です。Google Cloud には Cloud Shell と呼ばれる コマンド操作用の Linux 環境があり、証明書を作成するために必要な OpenSSL が導入されています。コンソールの右上にある Cloud Shell のアクティブ化ボタンを押せばすぐにこの環境が起動し、1コマンドで自己証明書を作成することができます。
今回は以下の要件で自己証明書を作成しました。
- 秘密鍵名 : key.pem
- 証明書名 : cert.pem
- 有効期限 : 36500 日(およそ 100 年)
- ホスト名 : myswp.example.com
openssl req -x509 -newkey rsa:2048 \
-keyout ./key.pem \
-out ./cert.pem -days 36500 \
-subj '/CN=myswp.example.com' -nodes -addext \
"subjectAltName=DNS:myswp.example.com"
このコマンドによって Cloud Shell 上に秘密鍵と証明書が作成されました。これを Certificate Manager に登録する必要があります。現在は GUI で登録する機能が提供されていませんので、Cloud Shell から以下のコマンドで登録します。
gcloud certificate-manager certificates create secure-web-proxy-cert \
--certificate-file=./cert.pem \
--private-key-file=./key.pem \
--location=asia-northeast1
登録した結果は GUI から確認することができます。この証明書は、後ほど Secure Web Proxy を作成する際に指定します。
なお、今回は検証ということもあって自己証明書、いわゆるオレオレ証明書を使用しています。これによって発生する事象は後ほどご紹介いたします。
[Google Cloud Console] 証明書マネージャ
TLS インスペクション
昨今の Web 通信はほとんど暗号化されています。これは通信秘匿の観点からとても良いことですね。しかし、暗号化されていることによって Web Proxy から通信先の URL を確認することができず、より高度なアクセス制御はできません。ではどのように対策すれば良いでしょうか?一度通信を復号してしまえば良いですね。これは TLS インスペクションと呼ばれる仕組みですが、この仕組みについて解説すると長くなってしまうので詳細は割愛します。
Secure Web Proxy にも TLS インスペクション機能は存在するのですが、手順が少し煩雑なこともあり、今回は実装しません。TLS インスペクションを使わない場合、ドメイン名のみ制御することが可能です。後ほど Secure Web Proxy の動作を確認しますので、その際に TLS インスペクションの使いどころも確認しましょう。
[公式ドキュメント] TLS inspection overview
Web Proxy 構築
では、本番の Web Proxy 構築に入りましょう。しかし、いきなり Secure Web Proxy を作成することはできません。作成時に ポリシーを指定する必要があるので、まずはポリシーから作成します。
[Google Cloud Console] セキュア ウェブプロキシ
ポリシー作成
ポリシーの名前とリージョンを指定します。今回は swp-test-policy
という名称で東京リージョンに作成しました。この画面ではルールも指定できますが、現在は何も指定していません。
Secure Web Proxy 作成
さて、いよいよ Secure Web Proxy の作成ですね。これまでに準備してきたものを以下のように指定しました。
- 名前 : swp-test
- リージョン : asia-northeast1 (東京)
- ネットワーク : secure-web-proxy-test
- サブネットワーク : vm-subnet
- ウェブプロキシ IP アドレス : 10.0.0.2
- ポート : 3128
- 証明書 : secure-web-proxy-cert
- 関連ポリシー : swp-test-policy
注意点として、ここではサブネットワークに vm-subnet
を選択します。proxy-subnet
は Secure Web Proxy が動作するための内部的なネットワークのため、選択肢にも出てきません。また、ウェブプロキシの IP アドレスとポートは、Secure Web Proxy を使用する際に指定する情報です。後ほどテストで出てきますので、その際に確認しましょう。
無事に Secure Web Proxy が稼働しました🎉
テスト VM 作成
Secure Web Proxy が無事に稼働したので、動作を確認するための VM を作成しましょう。今回の本題ではないので、Cloud Shell からコマンドでサクッと作ってしまいます。注意点として、テスト VM は外部 IP アドレスを持たせてはいけません。これは、Secure Web Proxy を介さず外部 IP アドレスから直接インターネットへアクセスさせないためです。
gcloud compute instances create user-pc-01 \
--project=<プロジェクト名> \
--zone=asia-northeast1-a \
--machine-type=e2-medium \
--network-interface=private-network-ip=10.0.0.3,stack-type=IPV4_ONLY,subnet=vm-subnet,no-address \
--provisioning-model=SPOT \
--create-disk=auto-delete=yes,boot=yes,device-name=user-pc-01,image=projects/rocky-linux-cloud/global/images/rocky-linux-9-optimized-gcp-v20230615,mode=rw,size=20,type=projects/<プロジェクト名>/zones/asia-northeast1-a/diskTypes/pd-balanced \
また、IAP を用いて SSH 接続をしたいので、Firewall ルールを追加します。こちらもコマンドで作ってしまいましょう。IAP については弊社の別記事が参考になりますので、よろしければご覧ください。
IAP を使って外部 IP を持たない Compute Engine(WindowsVM)にリモートデスクトップ接続する方法
gcloud compute firewall-rules create allow-iap-ssh \
--project=<プロジェクト名> \
--direction=INGRESS \
--priority=1000 \
--network=secure-web-proxy-test \
--action=ALLOW \
--rules=tcp:22 \
--source-ranges=35.235.240.0/20 \
--target-service-accounts=<サービスアカウント名>
動作検証
動作検証の準備が整いましたので、適宜設定を変更しながら Secure Web Proxy の挙動を確認します。
テスト VM への SSH 接続
テスト VM へ SSH 接続するには、Cloud Shell
から gloud compute ssh
コマンドを使用します。
gcloud compute ssh user-pc-01 --zone=asia-northeast1-a
External IP address was not found; defaulting to using IAP tunneling.
(略)
[hirose_takahiro@user-pc-01 ~]$
ルール無しでの動作
まず初めに、テスト用 VM が直接インターネットへアクセスできないことを確認します。curl
コマンドに --max-time <秒数>
を指定すると、タイムアウトまでの秒数を指定することができるので活用しましょう。接続先は本ブログ https://zenn.dev
とします。
[hirose_takahiro@user-pc-01 ~]$ curl --max-time 2 https://zenn.dev
curl: (28) Connection timed out after 2001 milliseconds
[hirose_takahiro@user-pc-01 ~]$
上記のようにタイムアウトしました。次に、Secure Web Proxy を介してインターネットへアクセスしてみましょう。curl
コマンドに -x <Secure Web ProxyのIPアドレス:ポート番号>
を追加することで、Web Proxy を指定して curl
コマンドを実行することができます。
[hirose_takahiro@user-pc-01 ~]$ curl -x https://10.0.0.2:3128 https://zenn.dev
curl: (60) SSL certificate problem: self-signed certificate
More details here: https://curl.se/docs/sslcerts.html
curl failed to verify the legitimacy of the server and therefore could not
establish a secure connection to it. To learn more about this situation and
how to fix it, please visit the web page mentioned above.
[hirose_takahiro@user-pc-01 ~]$
エラーが発生しました。これは、「指定した Web Proxy はオレオレ証明書だから信頼できないよ」といった趣旨のエラーですね。今回は検証ということもあり、このエラーを無視するために --proxy-insecure
オプションを追加します。
[hirose_takahiro@user-pc-01 ~]$ curl -x https://10.0.0.2:3128 https://zenn.dev --proxy-insecure
curl: (56) Received HTTP code 403 from proxy after CONNECT
[hirose_takahiro@user-pc-01 ~]$
Secure Web Proxy が 403
を返しました。これは閲覧禁止を示すエラーコードですね。つまり、ルールに引っかからない場合はアクセスを拒否するという、いわゆる暗黙の拒否ルールが存在するようです。
接続許可ルールを追加
上記を裏付けるために、接続許可ルールを追加しましょう。セッションの一致欄に host() == 'zenn.dev'
と指定します。優先度は重複しても良いので、とりあえず 1000
としました。
ルールありでの動作
これで zenn.dev
への接続は許可されたはずなので試しましょう。なお、ここからは --head
オプションを用いることでヘッダのみ表示されるようにします。これは、アクセスが成功した場合に大量の文字が帰ってくることを防ぐ目的ですね。
[hirose_takahiro@user-pc-01 ~]$ curl -x https://10.0.0.2:3128 https://zenn.dev --proxy-insecure --head
HTTP/1.1 200 OK
(略)
遂に接続 OK の 200
が返ってきました。ルールに従ったアクセスは許可されることが確認できましたね。念のために、google.com
にはアクセスできないことを確認しておきましょう。
[hirose_takahiro@user-pc-01 ~]$ curl -x https://10.0.0.2:3128 https://google.com --proxy-insecure --head
HTTP/1.1 403 Forbidden
(略)
想定通り google.com
にはアクセスできないですね。これで、ホワイトリスト形式で動作させることができるようになりました。
ブラックリスト形式を試す
ホワイトリスト形式では接続を許可する対象が多すぎて使いづらい場合もあります。ここでは、暗黙の拒否ルールが効かないように優先度を最も低く設定した全通信許可ルールを追加します。演算子 .matches
を用いることで正規表現が使用できるので、host().matches('.*')
を許可することで実現できるはずですね。
では、さきほどは接続できなかった google.com
に再接続してみましょう。
[hirose_takahiro@user-pc-01 ~]$ curl -x https://10.0.0.2:3128 https://google.com --proxy-insecure --head
HTTP/1.1 200 OK
(略)
うまく繋がりました。これであらゆるサイトに接続できるようになったのですが、ブラックリスト形式として扱うために拒否の動作を確認しておきましょう。zenn.dev
へのアクセス許可設定を拒否に変更してみます。名前が allow
から始まるのに拒否ルールであることは違和感しかありませんが、後から名前を変えられないので今回は気にしないでいきましょう。
[hirose_takahiro@user-pc-01 ~]$ curl -x https://10.0.0.2:3128 https://zenn.dev --proxy-insecure --head
HTTP/1.1 403 Forbidden
(略)
無事に zenn.dev
への接続が拒否されました。これで、ホワイトリスト形式・ブラックリスト形式ともに実現可能ですね。
TLS インスペクションによって実現できること
今回の検証では、zenn.dev
や google.com
といったドメイン名に対するアクセスを制御しました。TLS インスペクションを用いると、ドメイン名だけではなく URL に対するアクセスが制御できるようになります。例えば zenn.dev/cloud_ace/
だけアクセスを許可するといった形ですね。もしそういった制御が必要となった場合は TLS インスペクションの導入を検討しましょう。
まとめ
今回は Secure Web Proxy の動作を試してみました。動かしてみるとシンプルで使いやすいですね。とはいえ、以下のようなハマりどころがあり、本記事を完成させるまでに意外と四苦八苦しました。
- VPC 作成時にプロキシ用サブネットを同時作成することはできない
- 先にポリシーを作成しておかないと Secure Web Proxy が作成できない
- 自己証明書では Secure Web Proxy 使用時にエラーが出る
特に自己証明書について、セキュリティの観点から本稼働させるシステムでは証明書に関するエラーを許容することはできません。一般的な端末に登録済みの認証局から証明書を発行してもらうか、もし自己証明書を使用する場合はルート証明書を利用者の環境へ登録する必要があります。他にも、今回は検証しなかった TLS インスペクションを使用したい場合は追加の考慮が必要となります。
このように書くと考慮点の多く使いづらい印象を与えるかもしれませんが、これらの多くは Secure Web Proxy 独自の考慮ではなく、Web Proxy で一般的に考慮すべき内容です。今回のように「まずは動かしてみる」ことで設計ポイントが理解できるようになりますので、本記事がこれから Secure Web Proxy を使い始める皆さまの助けとなれば幸いです。
クラウドエース株式会社 Google Cloud 認定トレーナーの廣瀬 隆博がお届けしました。
また次の記事でお会いしましょう。
Discussion