envoyの
HTTPアップグレード機能は、WebSocketとHTTP CONNECTメソッドをサポートしています。
CONNECTを使うとTCP通信をトンネルできます。
また、SNIに対応したクライアントであれば、単一のenvoyで複数TCPサービスをホストするプロキシを構築できます。
設定
configサンプルの通り、HttpConnectionManager
の設定によりCONNECTメソッドを有効にできます。
- name: envoy.filters.network.http_connection_manager
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
stat_prefix: ingress_http
route_config:
name: local_route
virtual_hosts:
- name: local_service
domains: ["*"]
routes:
- match:
connect_matcher: {}
route:
cluster: backend_tcp
upgrade_configs:
- upgrade_type: CONNECT
connect_config: {}
http_filters:
- name: envoy.filters.http.router
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router
http_protocol_options: {}
http2_protocol_options:
allow_connect: true
upgrade_configs:
- upgrade_type: CONNECT
upgrade_configs
やroute.upgrade_configs
などをセットで指定する必要があります。
http_protocol_options: {}
などところどころで空のオブジェクトを指定していますが、これはデフォルト値が設定されるため効いています。
バックエンドクラスタの設定には、特殊な点はありません。
確認していませんが、
Basic認証なども追加できるでしょう。
Proxy Protocol
アップストリームにProxy Protocolを送りたい場合は、connect_config
の設定を変更します。
route:
upgrade_configs:
- upgrade_type: CONNECT
connect_config:
proxy_protocol_config:
version: V1
フロントエンドの対応も必要
HTTP CONNECTメソッドはGET/POSTのように一般的なメソッドではないため、フロントエンドのプロキシが対応していないケースがあるため注意が必要です。
GCPの例では、HTTPSロードバランサ(従来)はCONNECTに対してダイレクトにHTTP405
エラーを返します。TCPロードバランサであればenvoyが直接受信するため動作します。
クライアントの例
CONNECTメソッドを用いてトンネルするクライアントはいくつか実装があります。
proxytunnelはSSLやSNIをサポートし、verbose
オプションが比較的詳細にレポートします。
sshのconfig設定例は以下のようになります。
Host ssh.example.com
User someone
Port 443
ProxyCommand proxytunnel -E -p ssh.example.com:443 -d %h:%p
なお、envoyのconnect_matcher
がポートをルーティングに用いているため、httpsのデフォルトポートであっても443
は省略しない方が無難でしょう。
Chuma Takahiro