背景

HTTP サーバーに仮想ホストを導入する目的は、複数のドメイン名が 1 つの IP アドレスを再利用して IPv4 アドレスの供給を分散させることです。 サーバーは、クライアントリクエストに指定されたホストに応じて、リクエストを異なるドメイン名 (仮想ホスト) に割り当て、処理します。 IP アドレスが複数のドメイン名 (仮想ホスト) で共有されている HTTPS サーバーでは、ブラウザーが HTTPS サイトにアクセスすると、最初にサーバーとの SSL 接続が確立されます。 SSL 接続を確立するための最初の手順は、サーバーからの証明書をリクエストすることです。 サーバーはドメイン名に関係なく証明書を送信します。 これは、ブラウザーがアクセスしたドメイン名をサーバーが判別できないためです。

SNI (Server name indication) は、複数のドメイン名と証明書を使用して単一サーバーの問題を解決するために使用される SSL/TLS 拡張です。 サーバーが SSL 接続を確立するために接続される前に、アクセスされるサイトのドメイン名 (ホスト名) が最初に送信されるので、サーバーはドメイン名に基づいて適切な証明書を返します。

現在、ほとんどのオペレーティングシステムとブラウザーは SNI 拡張をサポートしています。 この機能は OpenSSL 0.9.8 に組み込まれており、新しいバージョンの Nginx も SNI をサポートしています。

現象

クライアントが SNI をサポートしていない場合、WAF にアクセスしたときに HTTPS アクセスが異常になることがあります。

SNI をサポートしていないブラウザーを使用して WAF を使用する Web サイトにアクセスすると、WAF はクライアントがリクエストしたドメイン名を知らないため、クライアントとやり取りするための対応する仮想ホスト証明書を取得できません。 Web Application Firewall は、埋め込みのデフォルト証明書のみを使用して、クライアントとのハンドシェイクを実行します。 この場合、クライアントのブラウザーには "証明書が信頼できません" というメッセージが表示されます。

クライアントが SNI をサポートしていない場合は、次の現象が発生する可能性があります。

  • モバイルアプリクライアントでは、iOS クライアントには通常アクセスできますが、Android クライアントは通常開くことができません。
  • Web ページを開くと、ブラウザーに証明書が信頼できないことを示すメッセージが表示されます。

解決策

クライアント上で SSL ハンドシェイクパケットをキャプチャして、クライアントが SNI をサポートしているかどうかを確認します。 Chrome ブラウザーを使用してAlibaba Cloud の公式 Web サイトにアクセスするとします。

次の図に示すように、SNI 拡張が Client Hello パケットに表示される場合、クライアントはSNI 拡張をサポートしています。

それ以外の場合、クライアントは SNI 拡張をサポートしていません。 SNI をサポートしていないクライアントの場合、

  • ブラウザーをアップグレードするか、Chrome や Firefox などの新しいバージョンのブラウザーを使用することを推奨します。
  • WeChat および Alipay からのサードパーティコールバックの場合、配信元 IP アドレスを使用して Web Application Firewall を迂回します。

SNI 互換性

SNI は TLS1.0 以降のバージョンと互換性がありますが、SSL ではサポートされていません。
  • SNI は以下のデスクトップブラウザーをサポートしています。
    • Chrome 5 以降のバージョン
    • Chrome 6 以降のバージョン (Windows XP)
    • Firefox 2 以降のバージョン
    • IE 7 以降のバージョン (Windows Vista / Server 2008 以降のバージョンで動作、Windows XP OSの IE のどのバージョンも SNI をサポートしていません )
    • Konqueror 4.7 以降のバージョン
    • Opera 8 以降のバージョン
    • Windows Vista / Server 2008 以降のバージョンまたは Mac OS X 10.5.6 以降のバージョンのSafari 3.0
  • SNI は以下のライブラリをサポートしています。
    • GNU TLS
    • Java 7 以降のバージョン (クライアントとしてのみ機能)
    • HTTP クライアント 4.3.2 以降のバージョン
    • libcurl 7.18.1 以降のバージョン
    • NSS 3.1.1 以降のバージョン
    • OpenSSL 0.9.8j 以降のバージョン
    • OpenSSL 0.9.8f 以降のバージョン (フラグを設定する必要があります)
    • QT 4.8 以降のバージョン
    • Python 3、Python 2.7.9 以降のバージョン
  • SNI は以下のモバイルブラウザーをサポートしています。
    • 3.0 Honeycomb 以降のバージョンの Android ブラウザー
    • iOS 4 以降のバージョンの iOS Safari
    • Windows Phone 7 以降のバージョン
  • SNI は以下のサーバーをサポートしています。
    • Apache 2.2.12 以降のバージョン
    • Apache Traffic Server 3.2.0 以降のバージョン
    • HAProxy 1.5 以降のバージョン
    • IIS 8.0 以降のバージョン
    • lighttpd 1.4.24 以降のバージョン
    • LiteSpeed 4.1 以降のバージョン
    • Nginx 0.5.32 以降のバージョン
  • SNI は以下のコマンドラインをサポートしています。
    • cURL 7.18.1 以降のバージョン
    • wget 1.14 以降のバージョン