『グローバルIP を持たない GCP VM への SSH 接続方法』で記載した IAP tunnel は、HTTPS トンネル内で TCP パケットを forward するための技術です。
この HTTPS トンネルは、ユーザと tunnel.cloudproxy.app
の間で確立される WebSocket です。
そのため、IAP tunnel を HTTP プロキシ環境下で利用する際には、以下の二つに注意する必要があります。
tunnel.cloudproxy.app
への通信を許可する。tunnel.cloudproxy.app
との WebSocket 接続が問題なく行える。tunnel.cloudproxy.app
への通信を許可こちらのページに記載のとおりです。HTTP プロキシサーバで通信の許可対象 whitelist を制御している場合は、whitelist に tunnel.cloudproxy.app
を含める必要があります。
tunnel.cloudproxy.app
との WebSocket 接続IAP tunnel は、Cloud IAM による認証が行われた後に作成される、ユーザと Cloud IAP の間の HTTPS トンネルです。
HTTPS トンネルによって、SSH や RDP といったアプリケーションのための TCP パケットを forward します。
公式のドキュメントに明記されている箇所はありませんが、この HTTPS は具体的には、ユーザと tunnel.cloudproxy.app
の間に作成される WebSocket 接続です。より正確には WebSocket over SSL/TLS です。URI スキームとしては ws:
ではなく wss:
です。
SSH/RDP
----------
TCP
----------
HTTP ->(upgrade)-> WebSocket
----------
SSL/TLS
----------
TCP
SSH from browser 機能を実行した際の WebSocket 接続
参考資料:
The IAP TCP forwarding tunnels that IAP Desktop uses to create SSH and RDP connections use WebSockets. Make sure that your proxy server permits WebSocket communication to the following domain: https://tunnel.cloudproxy.app
GoogleCloudPlatform / iap-desktop / Proxy Configuration
HTTP プロキシを通して GCP と通信する際には、
上記二つの観点から、以下の 4 つの場合が存在します。
User ----------- HTTP ------------ googleapis.com
User ---------- SSL/TLS ---------- googleapis.com
User --- TCP --- Proxy --- TCP --- googleapis.com
User --- HTTP -- Proxy --- HTTP -- googleapis.com
User - SSL/TLS - Proxy - SSL/TLS - googleapis.com
User --- TCP --- Proxy --- TCP --- googleapis.com
User ---------- SSH/RDP ---------- tunnel.cloudproxy.app
User ------------ TCP ------------ tunnel.cloudproxy.app
User --------- WebSocket --------- tunnel.cloudproxy.app
User ---------- SSL/TLS ---------- tunnel.cloudproxy.app
User --- TCP --- Proxy --- TCP --- tunnel.cloudproxy.app
User - SSH/RDP - Proxy - SSH/RDP - tunnel.cloudproxy.app
User --- TCP --- Proxy --- TCP --- tunnel.cloudproxy.app
User - WebSocket Proxy - WebSocket tunnel.cloudproxy.app
User - SSL/TLS - Proxy - SSL/TLS - tunnel.cloudproxy.app
User --- TCP --- Proxy --- TCP --- tunnel.cloudproxy.app
ここで問題になるのは 4 つ目のパターンです。多くの HTTP プロキシは 4 つ目のパターンをサポートしておらず、SSL Inspection を WebSocket と併用できません。その場合、SSL Inspection を用いる場合には tunnel.cloudproxy.app
に対して 3つ目のパターンになるように、プロキシを設定する必要があります。
参考資料:
Note: Squid (and possibly other proxy servers) does not allow WebSocket connections when configured to perform SSL inspection (bumping). To allow WebSocket communication, exclude tunnel.cloudproxy.app from SSL termination by letting Squid splice connections to this domain.
GoogleCloudPlatform / iap-desktop / Proxy Configuration
例えば、Google の Block access to consumer accounts 機能を利用する場合に、4つ目のパターンが発生します。
Squid における SSL Inspection は SSL bumping として実装されています。SSL bumping のバージョンは過去の経緯で大きく 3つ存在しています。
特定のバージョンの squid が必要な場合はソースコードからビルドします。
設定 directives のドキュメントは Squid configuration directives を参照します。バージョンによって設定方法が異なります。
SSL bumping における、接続先サーバのドメインが利用する証明書に相当する、偽の証明書は、後述の認証局秘密鍵を用いて動的に生成されます。
openssl コマンドで秘密鍵を発行します。
openssl genrsa -out my-private-key.pem 2048
CSR を自分の秘密鍵で署名します。
openssl req -sha256 -new -key my-private-key.pem -out csr.pem
openssl x509 -sha256 -req -days 36500 -in csr.pem -signkey my-private-key.pem -out my-certificate.crt
squid の仕様に従い、秘密鍵と証明書を一つのファイルにまとめます。
cat my-private-key.pem my-certificate.crt > squidCA.pem
それぞれのコマンドの意味については、こちらのページも参照します。
squid.conf
http_port 3128 ssl-bump generate-host-certificates=on dynamic_cert_mem_cache_size=4MB cert=/etc/squid/squidCA.pem
systemctl restart squid
systemctl status squid
を実行した後に以下のファイルのログを確認します。
/var/log/squid/cache.log
初回 SSL Bump 利用時は SSL DB が初期化されていない旨のエラーが確認できます。以下のコマンドで初期化します。
/usr/lib64/squid/ssl_crtd -c -s /var/lib/ssl_db
chown -R squid:squid /var/lib/ssl_db
参考:
[root@ip-172-31-13-150 squid]# rpm -qa | grep squid
squid-3.5.20-17.amzn2.6.1.x86_64
[root@ip-172-31-13-150 squid]# rpm -ql squid-3.5.20-17.amzn2.6.1.x86_64 | grep crtd
/usr/lib64/squid/ssl_crtd
acl wssConnection ssl::server_name .tunnel.cloudproxy.app
acl step1 at_step SslBump1
acl step2 at_step SslBump2
acl step3 at_step SslBump3
ssl_bump splice wssConnection
ssl_bump peek step1 all
ssl_bump stare step2 all
ssl_bump bump step3 all
以下のような記法になります。
acl broken_sites dstdomain .tunnel.cloudproxy.app
ssl_bump none broken_sites
ssl_bump server-first all
Windows を対象とする場合は、DER 形式に変換します。
openssl x509 -in my-certificate.crt -outform DER -out squid.der
Windows の場合は Internet Properties の Content を開いて Certificates をクリックします。
Import からルート証明書をインポートします。
確かに squid が発行した偽の証明書が使われていることが分かります。
tunnel.cloudproxy.app
は squid の splice 対象となっており、squid が SSL 終端になっていないことが分かります。
補足: ブラウザの SSL 証明書キャッシュをクリアしたい場合は「Clear SSL state」をクリックします。
SSH from browser が動作します。
tunnel.cloudproxy.app
を SSL 終端とすると、WebSocket 通信が失敗するため、以下のエラーとなります。
Cloud Shell ではなくローカル PC にインストールした gcloud で IAP tunnel を作成できるか検証します。
補足: Cloud Shell で接続される端末は、インターネット上の端末であり、ローカル PC が参照するプロキシを通らないため検証になりません。
gcloud compute ssh instance-2 --project myproject-20210411 --zone asia-northeast1-b --tunnel-through-iap --log-http
--tunnel-through-iap
は IAP tunnel による接続を強制するためのオプションです。--log-http
は検証時のデバッグ用途です。
Windows の場合はシステムの証明書設定を参照せず、gcloud と同封された python の証明書設定を参照します。そのため、Squid のルート証明書を信頼できておらず、通信がタイムアウトすることが確認できます。
これを回避する簡単な方法は、以下のオプションを指定することです。証明書をすべて信頼するようになります。curl の -k
と同じ働きです。
gcloud config set auth/disable_ssl_validation True
あるいは、以下のオプションで gcloud が信頼するルート証明書を指定することもできます。CER や DER ではなく PEM ファイルです。
gcloud config set core/custom_ca_certs_file C:\Users\Administrator\Downloads\roots.pem
注意: 信頼するルート証明書が追加されるのではなく、上書きされます。そのため、まずは roots.pem
を python のフォルダからコピーしてきて、squidCA.pem
の内容を追記します。
IAP tunnel の作成に成功すると、以下のようなウィンドウが起動します。