web-dev-qa-db-ja.com

自己署名SSLと自己ホストを備えたSignalR

研究で運試しをしましたが、今のところ喜びはありません。

SignalR javascriptクライアントを、自己署名SSL証明書にバインドする自己ホスト型SignalRWindowsサービスに接続したいと思います。

私のアプリケーションはhttp上で非常にうまく機能しますが、Owin WebApplicationがhttpsの使用を開始すると、クライアントは繰り返し切断されます。

これが、SSLを使用してSignalRを構成するために行ったことです。

  1. IISを使用して自己署名証明書を作成しました
  2. Mmcの信頼されたルート証明機関に証明書をインポートしました(それが役に立ったかどうかはわかりません)
  3. NETSHコマンドを実行してSSLをポート8080にバインドしました

    netsh http add sslcert ipport=0.0.0.0:8080 certhash=123456f6790a35f4b017b55d09e28f7ebe001bd appid={12345678-db90-4b66-8b01-88f7af2e36bf}
    
  4. セルフホストのHubConnectionインスタンスに、このようにエクスポートされたSSLを追加するコードを追加しました(ただし、接続できないのはクライアントであるため、これは問題ではありません)。

    if (File.Exists("MyCert.cer") 
        && Settings.GetSetting(Settings.Setting.SrProtocol).Equals("https", StringComparison.InvariantCultureIgnoreCase))
            connection.AddClientCertificate(X509Certificate.CreateFromCertFile("MyCert.cer"));
    
  5. Httpsを使用してOwinWebApplicationを起動します(これにより、http.sysにバインディングが作成されます)

    string registerUrl = string.Format("{0}://SOME.WHERE.COM:{1}", Service.Server.SrProtocol, Service.Server.SrPort);
    WebApp.Start<StartUp>(registerUrl);
    

SignalR 2.0のドキュメントには、次のように記載されています。

Webサーバーを起動するには、WebApplication.Start(endpoint)を呼び出します。これで、ブラウザでエンドポイント/シグナル/ハブに移動できるようになります。

URLを参照すると http://SOME.WHERE.COM:8080/signalr/hubs SignalRを駆動するJavaScriptを正常に受信しています。

URLを参照すると https://SOME.WHERE.COM:8080/signalr/hubs 失敗し、FFを使用して「サーバーへの接続がリセットされました」というメッセージが表示されます。

私が考慮したいくつかの追加のポイント:

  • NETSH SHOWは、URLが登録されていることを示します

    URL group ID: E300000240000022
    State: Active
    Request queue name: Request queue is unnamed.
    Properties:
        Max bandwidth: inherited
        Max connections: inherited
        Timeouts:
            Timeout values inherited
        Number of registered URLs: 1
        Registered URLs: HTTPS://SOME.WHERE.COM:8080/
    
  • NETSH SHOWは、SSL証明書が8080にバインドされていることを示します。

    IP:port                 : 0.0.0.0:8080 
    Certificate Hash        : 123456f6790a35f4b017b55d09e28f7ebe001bd
    Application ID          : {12345678-db90-4b66-8b01-88f7af2e36bf} 
    Certificate Store Name  : (null) 
    Verify Client Certificate Revocation    : Enabled
    Verify Revocation Using Cached Client Certificate Only    : Disabled
    Usage Check    : Enabled
    Revocation Freshness Time : 0 
    URL Retrieval Timeout   : 0 
    Ctl Identifier          : (null) 
    Ctl Store Name          : (null) 
    DS Mapper Usage    : Disabled
    Negotiate Client Certificate    : Disabled
    

どんな助けでも大歓迎です!

22
ISZ

私はそれがすべて私のために今働いていると信じています。これは私が物事を流すために取ったステップの要約です:

SSLノート

SSL&SignalR(Owin WebApplication)では、証明書をポートにバインドする必要があります。

  1. IISを使用して自己署名証明書を生成します。これにより、証明書がCERTMGRの[ローカルコンピューター]> [個人]> [証明書]フォルダーに配置されます。
  2. CERTMGRで、シフト+証明書をローカルコンピューター>信頼されたルート証明機関>証明書フォルダーにドラッグします。ここで証明書のコピーを作成する必要があります。
  3. 次のコマンドを実行して、SSL証明書を0.0.0.0:8080にバインドします

    netsh http add sslcert ipport=0.0.0.0:8080 certhash=123456f6790a35f4b017b55d09e28f7ebe001bd appid={12345678-db90-4b66-8b01-88f7af2e36bf} 
    netsh http show urlacl > D:\urlacl.txt
    

    出力:

    Reserved URL            : https://*:8080/ 
    User: SOMEWHERE\Administrator
    Listen: Yes
    Delegate: No
    SDDL: D:(A;;GX;;;S-1-5-21-138209071-46972887-2260295844-1106) 
    
  4. 次のNETSHコマンドを実行して、ポート8080のすべてのIPアドレスをマイサービスアプリケーションIDとサービスアカウントに予約します。

    netsh http add urlacl url=https://*:8080/ user=SOMEWHERE\Administrator listen=yes
    netsh http show sslcert > D:\sslcert.txt
    

    出力:

    IP:port                 : 0.0.0.0:8080 
    Certificate Hash        : 123456f6790a35f4b017b55d09e28f7ebe001bd
    Application ID          : {12345678-db90-4b66-8b01-88f7af2e36bf} 
    Certificate Store Name  : (null) 
    Verify Client Certificate Revocation    : Enabled
    Verify Revocation Using Cached Client Certificate Only    : Disabled
    Usage Check    : Enabled
    Revocation Freshness Time : 0 
    URL Retrieval Timeout   : 0 
    Ctl Identifier          : (null) 
    Ctl Store Name          : (null) 
    DS Mapper Usage    : Disabled
    Negotiate Client Certificate    : Disabled
    
  5. Httpsプロトコルを使用するようにMyServices.exe.configファイルを更新します(これらは、マイサービスの開始時にSignalRのプロトコルとポートを動的に設定するために使用されるappSettingキーです)

    <add key="SrProtocol" value="https" />
    <add key="SrPort" value="8080" />
    
  6. NETSTATSTARTコマンドを使用してマイサービスを開始します

  7. 次のNETSHコマンドを実行して、サービス状態が登録済みURLを占有していることを示します

    netsh http show servicestate > D:\servicestate.txt
    

    出力:

    Server session ID: C300000320000039
    Version: 2.0
    State: Active
    Properties:
        Max bandwidth: 4294967295
        Timeouts:
            Entity body timeout (secs): 120
            Drain entity body timeout (secs): 120
            Request queue timeout (secs): 120
            Idle connection timeout (secs): 120
            Header wait timeout (secs): 120
            Minimum send rate (bytes/sec): 150
    URL groups:
    URL group ID: C600000340000138
        State: Active
        Request queue name: Request queue is unnamed.
        Properties:
            Max bandwidth: inherited
            Max connections: inherited
            Timeouts:
                Timeout values inherited
            Number of registered URLs: 1
            Registered URLs:
                HTTPS://*:8080/
    

私のアプリケーションはIISに依存していませんが、IISを使用してSSL証明書へのポートバインディングを一時的に作成すると、アプリケーションが機能し始め、NETSHサービス状態を調べて確認することができました。どのようにIISそれを行います。それ以来、IISバインディングを削除し、セットアップノートを実行しましたが、それでも成功しています。

私のOwingスタートアップは次のように見えます。

private void configureMessaging()
{
    string registerUrl = string.Format("{0}://*:{1}", Service.Server.SrProtocol, Service.Server.SrPort);

    try
    {
#if DEBUG
        //System.Diagnostics.Debugger.Launch();
#endif
        //  Starts an owin web application to Host SignalR, using the protocol and port defined.
        WebApp.Start<StartUp>(registerUrl);
    }
    catch (Exception ex)
    {
        Logger.Logs.Log(string.Format("Failed to configure messaging.  Exception: {0}", ex.RecurseInnerException()), LogType.Error);            

        if (ex is HttpListenerException || ex.InnerException is HttpListenerException)
        {
            try
            {
                Process p = new Process();
                p.StartInfo.UseShellExecute = false;
                p.StartInfo.RedirectStandardOutput = true;
                p.StartInfo.FileName = "netsh.exe";
                p.StartInfo.Arguments = string.Format("netsh http delete urlacl url={0}"
                    , registerUrl
                    );
                p.Start();
                p.StandardOutput.ReadToEnd();
                p.WaitForExit();
            }
            catch (Exception exP)
            {
                Logger.Logs.Log(string.Format("Failed to delete urlacl {0}.  Exception: {1}"
                    , registerUrl
                    , exP.RecurseInnerException()
                    )
                    , LogType.Error
                    )
                    ;

                retries = 5;
            }
        }

    if (retries < 5)
    {
        retries++;

        Logger.Logs.Log(string.Format("Attempting to configure messaging again.  Attempt No. {0}", retries), LogType.Warn);

        Thread.Sleep(1000);

        configureMessaging();
    }
    else
        Logger.Logs.Log(string.Format("Exceeded total number of retries to configure messaging.", retries), LogType.Error);

    }

}

また、自己ホスト型のHubConnetionインスタンスは次のようになります。

    public IHubProxy MyHubProxy
    {
        get
        {
            if (this._MyHubProxy == null)
            {
                var connection = new HubConnection(string.Format("{0}://{1}:{2}/"
                    , Settings.GetSetting(Settings.Setting.SrProtocol)
                    , MyHub.GetLocalhostFqdn(null)
                    , Settings.GetSetting(Settings.Setting.SrPort)
                    )
                    )
                    ;
                this._MyHubProxy = connection.CreateHubProxy("MyHub");

                if (File.Exists("My.cer")
                    && Settings.GetSetting(Settings.Setting.SrProtocol).Equals("https", StringComparison.InvariantCultureIgnoreCase))
                    connection.AddClientCertificate(X509Certificate.CreateFromCertFile("My.cer"));

                connection.Start().Wait();
            }

            return this._MyHubProxy;
        }
    }

ここには関連するよりも少し多くのコードがありますが、うまくいけばそれが役立つかもしれません!

18
ISZ