2016-08-08 71 views
3

Ich habe einen kleinen Webserver unter Linux mit der Mono HTTPListener-Klasse geschrieben. Es funktioniert gut für HTTP-Anfragen. . Es ist jedoch ein un-abfangbare Ausnahme, wenn ich ein selbst signiertes SSL-Zertifikat (erstellt mit OpenSSL und installiert mit httpcfg) verwenden, sobald die Anfrage werfen forom ein Browser kommtMono HTTPListener löst Ausnahme aus, wenn selbstsigniertes SSL-Zertifikat verwendet wird

Die Ausnahme ist:

Hier
Unhandled Exception: 
System.IO.IOException: The authentication or decryption has failed. ---> Mono.Security.Protocol.Tls.TlsException: The client stopped the handshake. 
at Mono.Security.Protocol.Tls.SslServerStream.EndNegotiateHandshake (IAsyncResult asyncResult) <0xb4b079c8 + 0x001cf> in <filename unknown>:0 
at Mono.Security.Protocol.Tls.SslStreamBase.AsyncHandshakeCallback (IAsyncResult asyncResult) <0xb4b07428 + 0x0005f> in <filename unknown>:0 

ist der vollständige Code:

using System; 
using System.Net; 
using System.IO; 
using System.Text; 
using System.Threading; 

namespace SSLTest 
{ 
    class MainClass 
    { 
     static void Main() 
     { 
      try 
      { 
       HttpListener l = new HttpListener(); 
       l.Prefixes.Add ("https://*:8443/"); 
       l.Start(); 

       Console.WriteLine("Server is running."); 
       while (l.IsListening) 
       { 
        //create the worker thread 
        HttpListenerContext ctx = l.GetContext(); //.GetContext() blocks until something comes in 
        if(ctx != null) 
        { 
         if(ctx.Request.RemoteEndPoint != null) 
         { 
          Thread workerThread = new Thread(() => RunWorker(ctx)); 
          workerThread.Start(); 
         } 
        } 
       } 
       Console.WriteLine("Server is stopped."); 
      } 
      catch(Exception ex) 
      { 
       Console.WriteLine ("Exception in Main: " + ex); 
      } 
     } 


     static void RunWorker(HttpListenerContext ctx) 
     { 
      try 
      { 
       if(ctx.Request != null) 
       { 
        if(ctx.Request.RemoteEndPoint != null) 
        { 
         Console.WriteLine ("Got request from " + ctx.Request.RemoteEndPoint.ToString()); 
         string rstr = "Test Website!\n" + DateTime.Now.ToString(); 
         byte[] buf = Encoding.UTF8.GetBytes(rstr); 
         if(buf!=null) 
         { 
          ctx.Response.ContentLength64 = buf.Length; 
          ctx.Response.OutputStream.Write(buf, 0, buf.Length); 
         } 
        } 
       } 
      } 
      catch(Exception ex) 
      { 
       Console.WriteLine ("@Exception in RunWorker: " + ex.Message); 
      } 
     } 

    } 
} 

Dies ist der Fall, wenn ich einen Browser zum ersten Mal verwenden. Der Browser zeigt etwas wie "Unsicheres Zertifikat! Möchten Sie fortfahren (nicht empfohlen)?". Wenn ich auf "Ja" klicke und die abgestürzte Server-App neu starte, funktioniert sie ab diesem Moment.

Wie kann ich das beheben?

Auch ich bin nicht in der Lage, diese Ausnahme mit einem try-Block zu fangen. Es wird immer meine Bewerbung beenden. Wie kann ich das verhindern?

+0

Ich habe definitiv ein ähnliches Problem hier, obwohl mit einem CA signierten Zertifikat, nicht selbst signiert: http://StackOverflow.com/Questions/39604945/How-to-i-Catch-ssl-Exceptions-in -a-mono-httplistener-server –

Antwort

0

Sollte durch einen unveröffentlichten Bugfix behoben werden https://bugzilla.xamarin.com/show_bug.cgi?id=52675 ... obwohl ich keine Chance hatte zu testen.

Ich habe das auch gesehen und bin gerade dabei, einen Weg zu finden, mit der Ausnahme umzugehen. Dies scheint ein Fehler in Mono zu sein.

Es tritt auf, wenn die Überprüfung des Zertifikats in keiner Weise fehlschlägt.

Ich habe ein CA-signiertes Zertifikat erhalten, das das Problem behoben hat, solange der allgemeine Name des Zertifikats (DNS) mit dem DNS übereinstimmt, das in der URL verwendet wird, an die ich eine get-Anfrage senden möchte. Wenn ich stattdessen die öffentliche IP-Adresse in der URL (in der das Zertifikat nicht registriert ist) angeben, stürzt die Mono-App mit einer unbehandelten Ausnahme ab.

Eine Option, die wir in Erwägung ziehen, ist die Implementierung eines TCP-basierten Webservers, der anstelle des schweren HttpListeners einen TcpListener verwendet, der andere Probleme behebt, die mono-httplistener-Präfixe nicht korrekt funktionieren, wenn sie an die interne IP gebunden sind hinter einem NAT. Dies würde bedeuten, dass das Zertifikat auch grammatikalisch gebunden werden könnte, es braucht nur mehr Arbeit.

+0

Ich habe den tcp-basierten Webserver implementiert und das SSL-Zertifikat programmgesteuert gebunden. Der Bug, den ich oben gepostet habe, würde das Problem beheben, aber dieser Bug wurde in 4.8 von Mono gefunden und wurde seitdem in Revision nicht implementiert. Nicht sicher, warum es keine Motivation gibt, es umzusetzen. Ich schlage vor, den Weg des Erstellens Ihres eigenen TCP-Listeners zu nehmen, der http/https analysiert, es dauert einige Arbeit, aber ist es am Ende wert. Sie können auch die Mono-Quelle herunterziehen, den Bugfix über sich selbst implementieren und Ihre eigene Kopie erstellen ... –