OpenResty Edge で SNI プロキシを設定するには、SNI Proxy タイプの Stream アプリケーションを作成し、バックエンドごとにアップストリームを追加し、SNI サーバー名変数にマッチするページルールを書いて、各 TLS 接続を復号せずに適切なバックエンドへルーティングします。その後、SNI Proxy ポートをゲートウェイパーティションに追加してリリースします。本チュートリアルではポート 4003 をリッスンし、www.google.comwww.ebay.com を異なるアップストリームへルーティングして、curl とブラウザで結果を検証します。

以下の手順では、Admin Web コンソールでのセットアップ全体を解説します:SNI Proxy アプリケーションの作成、アップストリームと SNI サーバー名ページルールの定義、ポート 4003 の開放、ルーティングのテストです。

OpenResty Edge の SNI プロキシがポート 4003 をリッスンし、SNI 名に基づいて TLS 接続を異なるバックエンドにルーティングする構成図

SNI Proxy タイプの Stream アプリケーションを作成する

まずは OpenResty Edge の Admin Web コンソールにアクセスしましょう。これはコンソールのサンプルデプロイメントです。各ユーザーは独自のローカルデプロイメントを持っています。

OpenResty Edge Admin Web コンソールのホーム画面

Stream タイプのアプリケーションを作成します。

Stream アプリケーションリストページを選択します。

OpenResty Edge コンソールの Stream アプリケーション一覧ページ

新しいアプリケーションを作成します。

OpenResty Edge で新しい Stream アプリケーションを作成

Stream アプリケーションには SNI Proxy と TCP の2種類があることがわかります。

SNI Proxy と TCP の Stream アプリケーションタイプを選択

デフォルトで選択されているのは SNI Proxy タイプで、これが本日のテーマです。

デフォルトで選択された SNI Proxy アプリケーションタイプ

TCP アプリケーションは別のチュートリアルで紹介されています。

TCP Stream アプリケーションタイプの選択肢

ドメイン名として “www.google.com” を入力します。

SNI プロキシのドメインとして www.google.com を入力

この例では、異なる SNI 名を持つリクエストを処理する必要があります。そのため、複数のドメイン名が必要です。

このボタンをクリックして、2 つ目のドメイン名 www.ebay.com を追加します。

SNI プロキシアプリケーションに 2 つ目のドメイン www.ebay.com を追加

www.google.com と www.ebay.com のドメインを持つ SNI プロキシアプリケーション

このアプリケーションを作成します。

SNI Proxy Stream アプリケーションを作成

アップストリームと SNI サーバー名のページルールを作成する

これはOpenResty Edge で基本的なリバースプロキシとロードバランサーを構築するのと同じアップストリームとページルールの流れですが、ここではルーティングの判断を SNI ホスト名に基づいて行います。

アップストリームページに移動します。

SNI プロキシアプリケーションのアップストリームページ

新しいアップストリームを作成します。

新しいアップストリームを作成

このアップストリームに名前を付けます。例えば、“google” とします。

1 つ目のアップストリームを google と命名

ここで Google のホスト名を入力します。

アップストリームに google のホスト名を入力

ポート番号 443 を入力します。

google バックエンド用にアップストリームのポート 443 を設定

このアップストリームを保存します。

google アップストリームを保存

次に 2 つ目のアップストリームを作成します。

2 つ目のアップストリームを作成

このアップストリームを “eBay” と名付けます。

2 つ目のアップストリームを eBay と命名

ここに eBay のホスト名を入力します。

アップストリームに eBay のホスト名を入力

ポート番号 443 を入力します。

eBay バックエンド用にアップストリームのポート 443 を設定

このアップストリームを保存します。

eBay アップストリームを保存

アップストリームリストページに「google」と「eBay」が表示されています。

google と eBay の 2 つのアップストリームを示す一覧

次に、これらのアップストリームを使用するページルールを作成します。

SNI プロキシアプリケーションのページルールページ

最初のページルールを作成します。

1 つ目のページルールを作成

このページルールには条件を指定する必要があります。

ページルールに条件を追加

ここで条件の変数名を選択できます。

条件の変数名を選択

リクエストの SNI 名に基づいてプロキシするアップストリームを選択するので、変数名は SNI サーバー名にする必要があります。

SNI を検索します。

SNI サーバー名変数を検索

SNI サーバー名を選択します。

SNI サーバー名の条件変数を選択

演算子はデフォルトの String= のままにしておきます。

SNI 条件の演算子を String= のまま維持

値の型は String にする必要があります。

条件の値の型を String に設定

値として “www.google.com” を入力します。

SNI サーバー名の値として www.google.com を入力

プロキシターゲットを追加します。

ページルールにプロキシターゲットを追加

先ほど作成した最初のアップストリームを選択します。

プロキシターゲットとして google アップストリームを選択

プロキシターゲットに選択された google アップストリーム

ここにはいくつかのバランシング戦略が選択可能です。

プロキシターゲットのバランシング戦略の選択肢

アップストリームにはサーバーが1つしかないため、どのバランシング戦略を選んでも重要ではありません。

単一サーバーのアップストリーム向けラウンドロビン戦略

デフォルトのラウンドロビン戦略のままで構いません。

デフォルトのラウンドロビン戦略を維持

公共ネットワークを介してこのアップストリームにアクセスするため、ここですべてのタイムアウト時間を 60 秒に設定します。

google アップストリームのすべてのタイムアウトを 60 秒に設定

このページルールを作成します。

www.google.com のページルールを作成

次に、もう1つのページルールを作成します。

2 つ目のページルールを作成

このルールにも条件を指定します。

2 つ目のページルールに条件を追加

条件の変数名は引き続き SNI サーバー名です。

2 つ目のページルール条件に SNI サーバー名を選択

eBay ページルールの SNI サーバー名条件変数

eBay ページルールの条件を設定

値として “www.ebay.com” を入力します。

SNI サーバー名の値として www.ebay.com を入力

プロキシターゲットを追加します。

eBay ページルールにプロキシターゲットを追加

先ほど作成した 2 つ目のアップストリームを選択します。

プロキシターゲットとして eBay アップストリームを選択

プロキシターゲットに選択された eBay アップストリーム

すべてのタイムアウト時間を 60 秒に変更します。

eBay プロキシターゲットのタイムアウトを 60 秒に設定

このページルールを作成します。

www.ebay.com のページルールを作成

プロキシページルールがページルールリストページに表示されていることがわかります。

google と eBay の SNI ルーティングルールを示すページルール一覧

最後のステップは、新しい設定をリリースすることです。先ほどの変更をすべてのゲートウェイサーバーにプッシュします。

新しい設定リリースの準備ができた保留中の変更

このボタンをクリックして新しいリリースを行います。

新しい設定リリースを実行

リリースします。

設定リリースを確定

変更がすべてのゲートウェイサーバーに同期されました。このサンプルデプロイメントでは、ゲートウェイネットワークに14台のサーバーがあることがわかります。

14 台のゲートウェイサーバーに同期された設定

ネットワーク全体で増分的な設定同期を行っています。

ゲートウェイネットワーク全体での増分的な設定同期(フレーム 1)

ゲートウェイネットワーク全体での増分的な設定同期(フレーム 2)

ゲートウェイネットワーク全体での増分的な設定同期(フレーム 3)

リクエスト単位でリアルタイムに設定を更新しています。アプリケーションレベルの設定変更はすべて、サーバーのリロード、再起動、またはバイナリアップグレードを必要としません。そのため、多くの異なるユーザーが頻繁にリリースを行っても、スケーラビリティが高くなっています。

サーバーのリロードや再起動なしのリクエスト単位のリアルタイム設定更新

ゲートウェイパーティションに SNI Proxy ポートを追加する

図に示すように、リッスンポートとして 4003 を使用します。まず、このポートをアプリケーションのパーティションに追加します。

OpenResty Edge の SNI プロキシがポート 4003 をリッスンし、SNI 名に基づいて TLS 接続を異なるバックエンドにルーティングする構成図

ゲートウェイパーティションページに移動します。

ゲートウェイパーティションページへ移動

ゲートウェイパーティションページを開きます。現在はパーティションリストページにいます。多くのパーティションが既に存在していることがわかります。

ゲートウェイパーティション一覧ページ

「default」パーティションに SNI Proxy タイプのポートを追加します。

ポートを追加するため default ゲートウェイパーティションを開く

このボタンをクリックします。

default パーティションにポートを追加

ポートを追加します。

パーティション設定のポート追加ボタン

リストの一番上に新しい行が表示されていることがわかります。

パーティションに追加された新しいポート行

ポート番号として 4003 を入力します。

SNI プロキシのポート番号として 4003 を入力

タイプとして SNI Proxy を選択します。

ポートタイプとして SNI Proxy を選択

保存をクリックします。

SNI Proxy ポートを保存

新しいポートがデフォルトパーティションに正常に追加されたことがわかります。

default ゲートウェイパーティションに追加されたポート 4003

このパネルを閉じます。

パーティション設定パネルを閉じる

curl とブラウザで SNI プロキシをテストする

次に、ゲートウェイクラスターページに移動し、テスト用の Edge サーバーを1つ選択しましょう。

Edge テストサーバーを選択するゲートウェイクラスターページ

米国にあるノードを選択します。IP アドレスが .84 で終わるものに注目してください。

IP が .84 で終わる米国の Edge サーバーをテスト用に選択

このサーバーを使用して、先ほど追加したページルールをテストします。

SNI 名 www.google.com を使用して、curl リクエストを送信します。

curl -I --resolve www.google.com:4003:3.131.85.84 https://www.google.com:4003

SNI 名 www.google.com でポート 4003 に送信した curl リクエスト

サーバーが確かに Google であることがわかります。これは、先ほど追加したページルールが機能していることを意味します。SNI 名が “www.google.com” のリクエストが正しいアップストリームにプロキシされました。

google バックエンドが SNI リクエストに応答したことを示す curl レスポンス

次に、SNI 名が “www.ebay.com” の別の curl リクエストを送信します。

curl -I --resolve www.ebay.com:4003:3.131.85.84 https://www.ebay.com:4003

SNI 名 www.ebay.com でポート 4003 に送信した curl リクエスト

サーバーが eBay であることがわかります。2 つ目のページルールも機能しています。

eBay バックエンドが SNI リクエストに応答したことを示す curl レスポンス

次に、ブラウザを使用してテストを行います。まず、マシンの Host バインディングを確認しましょう。

cat /etc/hosts

ブラウザテスト用の Host バインディングを示す cat /etc/hosts

Host バインディングが正しいことがわかります。

www.google.com と www.ebay.com の /etc/hosts バインディングを確認

次に、ブラウザで Google にアクセスします。

SNI プロキシ経由でブラウザが Google を読み込む

eBay にアクセスします。

SNI プロキシ経由でブラウザが eBay を読み込む

よくある質問

SNI プロキシはどのように復号せずに TLS トラフィックをルーティングするのですか?

SNI プロキシは、TLS ハンドシェイクの暗号化されていない ClientHello から SNI ホスト名を読み取ってバックエンドを選択し、暗号化されたストリームをそのまま転送します。OpenResty Edge では、ページルールで SNI サーバー名変数にマッチさせることで、ゲートウェイは TLS を終端も復号もせずに各接続を正しいアップストリームへルーティングします。

OpenResty Edge で異なる SNI ホスト名を異なるバックエンドにルーティングするには?

バックエンドごとにアップストリームを 1 つ作成し、ホスト名ごとにページルールを追加します。条件で SNI サーバー名変数をそのホスト名(例:www.google.comwww.ebay.com)に設定し、プロキシターゲットを対応するアップストリームにします。リクエストが到着すると、ゲートウェイはその SNI 名をルールと照合し、該当するアップストリームへプロキシします。

SNI プロキシはどのポートをリッスンしますか?

ポートは、ゲートウェイパーティションに SNI Proxy タイプのポートとして追加したものです。本チュートリアルではポート 4003 を追加するので、Edge サーバーは 4003 でリッスンし、受信 TLS 接続を SNI 名でルーティングします。空いているポートであれば任意に選べます。

設定変更にはゲートウェイの再起動が必要ですか?

いいえ。OpenResty Edge は増分的な設定同期を行い、リクエスト単位でリアルタイムに設定を更新します。アプリケーションレベルの変更にはサーバーのリロード、再起動、バイナリアップグレードは一切不要なので、多くのユーザーが頻繁にリリースしてもスケーラビリティは高いままです。

OpenResty Edge は SNI TLS 以外のプロトコルもプロキシできますか?

はい。SNI Proxy Stream アプリケーションのほか、Edge は TCP Stream アプリケーションと L7 プロキシもサポートします。例えば HTTP/2 ベースのバックエンドについてはOpenResty Edge で gRPC プロキシを設定する方法を参照してください。

SNI プロキシが機能しているかをテストするには?

特定の SNI 名を持つ TLS リクエストを送信し、どのバックエンドが応答するかを確認します。本チュートリアルでは curl -I --resolve www.google.com:4003:<edge-ip> https://www.google.com:4003www.ebay.com も同様)を使い、その後 /etc/hosts バインディングを使ってブラウザで再確認します。

OpenResty Edge について

OpenResty Edge は、マイクロサービスと分散トラフィックアーキテクチャ向けに設計された多機能ゲートウェイソフトウェアで、当社が独自に開発しました。トラフィック管理、プライベート CDN 構築、API ゲートウェイ、セキュリティ保護などの機能を統合し、現代のアプリケーションの構築、管理、保護を容易にします。OpenResty Edge は業界をリードする性能と拡張性を持ち、高同時接続・高負荷シナリオの厳しい要求を満たすことができます。K8s などのコンテナアプリケーショントラフィックのスケジューリングをサポートし、大量のドメイン名を管理できるため、大規模ウェブサイトや複雑なアプリケーションのニーズを容易に満たすことができます。

→ SNI プロキシはプラットフォームの L4 ツールの一つです。その他の機能は OpenResty Edge プラットフォームの全体像を、オープンソース版との比較もあわせてご参照ください。

→ 関連記事:ゲートウェイで TLS を終端する場合は、OpenResty Edge の ACME モジュールで SSL 証明書の発行・更新を自動化できます。

著者について

章亦春(Zhang Yichun)は、オープンソースの OpenResty® プロジェクトの創始者であり、OpenResty Inc. の CEO および創業者です。

章亦春(GitHub ID: agentzh)は中国江蘇省生まれで、現在は米国ベイエリアに在住しております。彼は中国における初期のオープンソース技術と文化の提唱者およびリーダーの一人であり、Cloudflare、Yahoo!、Alibaba など、国際的に有名なハイテク企業に勤務した経験があります。「エッジコンピューティング」、「動的トレーシング」、「機械プログラミング」 の先駆者であり、22 年以上のプログラミング経験と 16 年以上のオープンソース経験を持っております。世界中で 4000 万以上のドメイン名を持つユーザーを抱えるオープンソースプロジェクトのリーダーとして、彼は OpenResty® オープンソースプロジェクトをベースに、米国シリコンバレーの中心部にハイテク企業 OpenResty Inc. を設立いたしました。同社の主力製品である OpenResty XRay動的トレーシング技術を利用した非侵入型の障害分析およびトラブルシューティングツール)と OpenResty Edge(マイクロサービスおよび分散トラフィックに最適化された多機能ゲートウェイソフトウェア)は、世界中の多くの上場企業および大企業から高い評価を得ております。OpenResty 以外にも、章亦春は Linux カーネル、Nginx、LuaJITGDBSystemTapLLVM、Perl など、複数のオープンソースプロジェクトに累計 100 万行以上のコードを寄与し、60 以上のオープンソースソフトウェアライブラリを執筆しております。

翻訳

英文版の原文と日本語訳版(本文)をご用意しております。読者の皆様による他の言語への翻訳版も歓迎いたします。全文翻訳で省略がなければ、採用を検討させていただきます。心より感謝申し上げます!