SSL通信を行ないたい

概要

x-Servlet自体はSSLでの通信をサポートしていません。
しかし、いくつかのサポートサービスを用いることでSSL通信を用いることが可能になります。
ここではx-ServletでSSL通信を行なう方法について記述します。

説明

端末とx-Servlet間でSSL通信を行う場合

x-ServletはHTTPを用いたリクエスト/レスポンスにのみ対応しています。

そのため端末とx-Servlet間でSSL通信を行う場合は端末とx-Servletの間でHTTPSをHTTPに変換してくれるサービスが必要です。

【図版 SSL復号化の仕組み】

SSL復号化サービスに求められる処理は以下のようになります。

  1. 端末からのHTTPSリクエストを受け付けます。
  2. SSL復号化サービスはHTTPSリクエストを復号化し、復号化したHTTPリクエストをx-Servletに転送します。
  3. x-Servletは受け付けたHTTPリクエストに従いコンテンツを取得・変換を行い、結果をSSL復号化サービスに返します。
  4. SSL復号化サービスは受け取ったHTTPリクエストを暗号化しHTTPSレスポンスとして端末に返します。

ここではこのようなサービスを実現してくれるものとして

Apache(1.3.27)+mod_ssl(2.8.12)+mod_proxy(Apacheに付属)+mod_rewrite(Apacheに付属)を用いて説明を行います。
同様のサービスが可能であるならば、他のサービスを使うことも可能です。
以下ではSSL復号化サービスをApache+mod_ssl+mod_proxy+mod_rewriteの443番ポートで立ち上げ、復号化されたHTTPリクエストをx-Servletの10443番ポートで受け付ける場合について説明します。
(ApacheはAPACHE_HOSTで動作し、x-ServletはX_SERVLET_HOSTで動作するものとします)

<SSL復号化サービスの設定>

443番ポートに送られてきたHTTPSリクエストを復号しx-Servletに送るように設定します。
Apacheにこのような動作を行わせるために以下の設定をApacheの設定ファイルであるhttpd.confに追加します。
(前提条件として、443番ポートでHTTPS通信ができるようになっていることを確認ください)
以下のようなSSLに関する設定がなされている部分が見つかると思います。("_default_"の部分は異なる可能性があります)

<VirtualHost _default_:443>
# このVertualHostに対する設定とSSLに関する記述が行われています

</VirtualHost>

ここに対して2行を追加し以下のようにします。

<VirtualHost _default_:443>
# このVertualHostに対する設定とSSLに関する記述が行われています
RewriteEngine on ←この部分を追加
RewriteRule ^/(.*)$ http://X_SERVLET_HOST:10443/$1 [P,L] ←この部分を追加
</VirtualHost>

この記述を行った後、Apacheを起動しなおすことで、Apacheの443番ポートに来たHTTPSリクエストは復号化されx-Servletの10443番ポートに送られるようになります。

(設定の詳細についてはApacheのドキュメントを参照ください)

<x-Servletに対する設定>

  1. 10443番ポートを待ち受けるように設定します
    xproxy.propertiesのxproxyPortに10443を追加します。
    "# 変換サーバが動作するIPアドレス,ポート番号を指定する"
    xproxyHost=X_SERVLET_HOST
    xproxyPort=80,10443 ←",10443"を追加
  2. HTTPSの元コンテンツを示すContentsRuleを設定します
    conf/contentsRule.xmlにHTTPS用の元コンテンツに関するContentsRule要素を記述します。

    <ContentsRule>

    <ConditionPort>10443</ConditionPort> ← 10443番ポートへのアクセスがHTTPS用のアクセスであることを示します

    <Host>HTTPS元コンテンツのサーバのサーバ名</Host>

    <Port>HTTPS元コンテンツサーバのポート番号</Port>

    <DefaultEncoding>Shift_JIS</DefaultEncoding>

    <Attribute name="fakeScheme">https</Attribute> ←HTTPS用の元コンテンツにアクセスする絶対URIリンクの"schemeを強制的に"https"にします"

    <Attribute name="fakeHost">APACHE_HOST</Attribute> ←HTTPS用の元コンテンツにアクセスする絶対URIリンクはAPACHE_HOSTを経由するように指示します

    <Attribute name="fakePort">443</Attribute> ←HTTPS用の元コンテンツにアクセスする絶対URIリンクはAPACHE_HOSTの443ポートを経由するように指示します

    </ContentsRule>

端末とx-Servlet間でSSL通信を行う場合は上記の2つの設定を行うことで実現できます。

x-Servletと元コンテンツサーバ間でSSL通信を行う場合

x-Servletは元コンテンツを取得する際にHTTPによるリクエスト/レスポンスにのみ対応しています。

そのためx-Servletと元コンテンツサーバ間でSSL通信を行う場合は、x-Servletと元コンテンツサーバの間でHTTPをHTTPSに変換してくれるサービスが必要です。

【図版 SSL暗号化の仕組み】

SSL暗号化サービスに求められる処理は以下のようになります。

  1. x-Servletから絶対URLによるHTTPリクエスト(プロキシ接続用リクエスト)を受けつけます。
  2. SSL暗号化サービスは絶対URLによるHTTPリクエストを解釈し、絶対URLで記述されているHOST:PORTにHTTPSリクエストを転送します。
  3. 元コンテンツサーバは受け付けたHTTPSリクエストに従い、結果をSSL暗号化サービスに返します。
  4. SSL暗号化サービスは受け取ったHTTPSレスポンスの内容を復号化し、HTTPレスポンスとしてx-Servletに返します。

補足)通常のリクエストとプロキシ接続用のリクエスト

通常のHTTPリクエストは

"GET /demo/index.html HTTP/1.0"

のように、ルートドキュメントからのパスのみを指定してリクエストを行ないます。

これを受け取ったWebサーバはルートドキュメントから該当のファイルを探しそれを返します。

対して、プロキシ接続用のリクエストは

"GET http://webServerHost/demo/index.html HTTP/1.0"

のように、接続方法と接続先も含むような絶対URLによるリクエストを行ないます。

 

これを受け取ったプロキシサーバは絶対URLから接続方法と接続先を解析し、その接続先に対して

"GET /demo/index.html HTTP/1.0"

というリクエストを発行します。

 

ここではこのようなサービスを実現してくれるものとして、Apache(1.3.27) + mod_ssl(2.8.12) + mod_proxy + mod_rewriteを用いて説明を行います。

同様のサービスが可能であるならば、他のサービスを使うことも可能です。

 

以下ではSSL暗号化サービスをApache+mod_ssl+mod_proxy+mod_rewriteの10080番ポートで立ち上げることを考えます。

(ApacheはAPACHE_HOSTで動作するものとします)

 

<SSL暗号化サービスの設定>

10080番ポートに送られてきた絶対URLによるHTTPリクエストを

絶対URLで指定されたHOST:PORTにHTTPSで転送するように設定します。

Apacheにこのような動作を行わせるために以下の設定をApacheの設定ファイルであるhttpd.confに追加します。

Listen 10080 ←この部分を追加
<VirtualHost _default_:10080>←この部分を追加
RewriteEngine on←この部分を追加
RewriteRule ^/(.*)$ https://%{HTTP_HOST}/$1 [P,L]←この部分を追加
</VirtualHost>←この部分を追加

この記述を行った後、Apacheを起動しなおすことでApacheの10080番ポートに送られてきた絶対URLによるHTTPリクエストは絶対URLで指定されたHOST:PORTにHTTPSで転送されるようになります。(設定の詳細についてはApacheのドキュメントを参照ください)

<x-Servletに対する設定>

  1. httpsプロキシの設定を行います
    HTTPSで取得する元コンテンツがある場合はhttpsプロキシの設定を行う必要があります。
    この設定を行うと、元コンテンツをHTTPSで取得する必要がある場合には
    指定されたHOST:PORTに絶対URLのHTTPリクエスト(プロキシ接続用のリクエスト)を出力するようになります。

    xproxy.propertiesのhttpsProxyHostとhttpsProxyPortを設定します。
    ※セキュリティ設定オンのCookieを送信するためには下記の設定が両方行われている必要があります。
    httpsProxyHost=APACHE_HOST  (SSL暗号化をするホスト名)
    httpsProxyPort=10080 (SSL暗号化をするホスト名のポート番号)
  2. HTTPSの元コンテンツを示すContentsRuleを設定します
    conf/contentsRule.xmlにHTTPS用の元コンテンツに関するContentsRule要素を記述します。
    ※セキュリティ設定オンのCookieを送信するためには下記の設定(メソッドがhttpsであることに注意)が全て行われている必要が有ります。
    <ContentsRule>
    <Scheme>https</Scheme>← HTTPS用の元コンテンツであることを指定します
    <Host>HTTPS元コンテンツのサーバのサーバ名</Host>
    <Port>HTTPS元コンテンツサーバのポート番号</Port>
    <DefaultEncoding>Shift_JIS</DefaultEncoding>
    </ContentsRule>

    x-Servletと元コンテンツサーバ間でSSL通信を行う場合は上記の2つの設定を行うことで実現できます。

SSL設定例1

端末とx-Servletの間はSSL通信を行い、元コンテンツサーバとの間は通常のHTTP接続を行うが、このような環境を想定した場合、SSL復号化サービスの構成は以下のように想定されます。

このような構成の場合、x-Servlet以外に

・SSL復号化サービス

を設置する必要があります。

  1. 「端末とx-Servlet間でSSL通信を行う場合」を参考に「decryptHost:443」へのHTTPSリクエストを「xServletHost:10443」にHTTPで転送するようにSSL復号化サービスを設置してください。
  2. x-Servletの設定を行います。
  3. 80番ポートと10443番ポートを待ち受けるように設定します
    xproxy.propertiesに
    xproxyHost=xServletHost
    xproxyPort=80,10443

    を設定します。

  4. ContentsRuleを設定します
    • 通常のコンテンツについての設定は以下のようになります。

      <ContentsRule>

      <Host>WebHost</Host>

      <Port>80</Port>

      <DefaultEncoding>Shift_JIS</DefaultEncoding>

      <ContentsRule>

    • SSL復号化サービスからのリクエストに対する設定は以下のようになります。
      (ルールの適用順序の関係からこちらの設定がcontentsRule.xml内では前に来るように記述してください)

      <ContentsRule>

      <ConditionPort>10443</ConditionPort>

      <Host>WebHost</Host>

      <Port>81</Port>

      <DefaultEncoding>Shift_JIS</DefaultEncoding>

      <Attribute name="fakeScheme">https</Attribute>

      <Attribute name="fakeHost">decryptHost</Attribute>

      <Attribute name="fakePort">443</Attribute>

      </ConditionRule>

結果としてcontentsRule.xmlは以下のようになります。

<?xml version="1.0" encoding="Shift_JIS"?>

<!DOCTYPE ContentsRuleList SYSTEM "contentsRule.dtd">

<ContentsRuleList>

<ContentsRule>

<ConditionPort>10443</ConditionPort>

<Host>WebHost</Host>

<Port>81</Port>

<DefaultEncoding>Shift_JIS</DefaultEncoding>

<Attribute name="fakeScheme">https</Attribute>

<Attribute name="fakeHost">decryptHost</Attribute>

<Attribute name="fakePort">443</Attribute>

</ConditionRule>

<ContentsRule>

<Host>WebHost</Host>

<Port>80</Port>

<DefaultEncoding>Shift_JIS</DefaultEncoding>

</ContentsRule>

</ContentsRuleList>

上記の設定により、想定した環境でコンテンツの配信が可能です。

補足)
このような環境を構築した場合、HTTPのコンテンツからHTTPSのコンテンツに移行する際には
"http://WebHost:81/dir/file"('https'ではなく'http'になります)のように81番ポートで接続するようなリンクを元コンテンツ中に記述してください。
HTTPSのコンテンツからHTTPのコンテンツに移行する際には
"http://WebHost/dir/file"のように80番ポートで接続するようなリンクを元コンテンツに記述してください。
(端末とx-Servlet間でSSLを使うかどうかを元コンテンツ中の接続ポート番号で指定するイメージになります)

SSL設定例2

端末とx-Servletの間でSSL通信を行い、元コンテンツサーバとの間でもSSL通信を行うが、このような環境を想定した場合、SSL復号化サービス、SSL暗号化サービスの構成は以下のように想定されます。

このような構成の場合、x-Servlet以外に

・SSL復号化サービス

・SSL暗号化サービス

を設置する必要があります。

  1. 「端末とx-Servlet間でSSL通信を行う場合」を参考にして「decryptHost:443」へのHTTPSリクエストを「xServletHost:10443」にHTTPで転送するようにSSL復号化サービスを設置してください。
  2. 「x-Servletと元コンテンツサーバ間でSSL通信を行う場合」を参考にして「encryptHost:10080」へのHTTPリクエストを「WebHost:443」にHTTPSで転送するようにSSL暗号化サービスを設置してください。
  3. x-Servletの設定を行います。
  4. 80番ポートと10443番ポートを待ち受けるように設定します
    xproxy.propertiesに
    xproxyHost=xServletHost
    xproxyPort=80,10443

    を設定します。

  5. httpsプロキシの設定を行います
    xproxy.propertiesに
    httpsProxyHost=encryptHost
    httpsProxyPort=10080

    を設定します。

  6. ContentsRuleを設定します
    • 通常のコンテンツについての設定は以下のようになります。

      <ContentsRule>

      <Host>WebHost</Host>

      <Port>80</Port>

      <DefaultEncoding>Shift_JIS</DefaultEncoding>

      <ContentsRule>

    • SSL復号化サービスからのリクエストに対する設定は以下のようになります。
      (ルールの適用順序の関係からこちらの設定がcontentsRule.xml内では前に来るように記述してください)

      <ContentsRule>

      <ConditionPort>10443</ConditionPort>

      <Scheme>https</Scheme>

      <Host>WebHost</Host>

      <Port>443</Port>

      <DefaultEncoding>Shift_JIS</DefaultEncoding>

      <Attribute name="fakeScheme">https</Attribute>

      <Attribute name="fakeHost">decryptHost</Attribute>

      <Attribute name="fakePort">443</Attribute>

      </ConditionRule>

結果としてcontentsRule.xmlは以下のようになります。

<?xml version="1.0" encoding="Shift_JIS"?>

<!DOCTYPE ContentsRuleList SYSTEM "contentsRule.dtd"><ContentsRuleList>

<ContentsRule>

<ConditionPort>10443</ConditionPort>

<Scheme>https</Scheme>

<Host>WebHost</Host>

<Port>443</Port>

<DefaultEncoding>Shift_JIS</DefaultEncoding>

<Attribute name="fakeScheme">https</Attribute>

<Attribute name="fakeHost">decryptHost</Attribute>

<Attribute name="fakePort">443</Attribute>

</ConditionRule>

<ContentsRule>

<Host>WebHost</Host>

<Port>80</Port>

<DefaultEncoding>Shift_JIS</DefaultEncoding>

</ContentsRule>

</ContentsRuleList>

上記の設定により「xServletHost:10443」に投げられたリクエストは「encryptHost:10080」に対して

GET http://WebHost:443/~ HTTP/1.0

というHTTPリクエストが発行されます。

補足)

このような環境を構築した場合、HTTPのコンテンツからHTTPSのコンテンツに移行する際には"https://WebHost/dir/file"のようにHTTPSで接続するようなリンクを元コンテンツ中に記述してください。

HTTPSのコンテンツからHTTPのコンテンツに移行する際には"http://WebHost/dir/file"のようにHTTPで接続するようなリンクを元コンテンツに記述してください。

(端末とx-Servlet間でSSLを使うかどうかを元コンテンツ中のSchemeで指定するイメージになります)

TOP