2016-06-21 3 views
2

Im пытается создать собственный HTTPS-прокси-сервер. По какой-то причине я получил исключение, когда пытаюсь читать из sslstream-объекта. Вот это:C# SSLStream Функция чтения Throws IOException

Необработанное исключение типа «System.IO.IOException» произошло в System.dll

Дополнительная информация: Не удается прочитать данные из транспортного соединения: Попытка подключения не удалась, поскольку связанная сторона не ответила должным образом после определенного периода времени, или установленное соединение не удалось, так как подключенный хост не смог ответить.

Вот мой код:

public Server() 
    { 
     m_portnumber = 4434; 
     m_tcplistener = new TcpListener(IPAddress.Any, m_portnumber); 
     m_cert = createCertificate(); 
    } 
    public void start() 
    { 
     m_tcplistener.Start(); 
     while (true) 
     { 
      TcpClient client = m_tcplistener.AcceptTcpClient(); 
      ClientHandler(client); 
     } 
    } 

    private void ClientHandler(TcpClient client) 
    { 
     // A client has connected. Create the 
     // SslStream using the client's network stream. 
     SslStream sslStream = new SslStream(
      client.GetStream(), false); 
     // Authenticate the server but don't require the client to authenticate. 
     try 
     { 
      sslStream.AuthenticateAsServer(m_cert, 
       false, SslProtocols.Tls, true); 
      // Display the properties and settings for the authenticated stream. 
      DisplaySecurityLevel(sslStream); 
      DisplaySecurityServices(sslStream); 
      DisplayCertificateInformation(sslStream); 
      DisplayStreamProperties(sslStream); 

      // Set timeouts for the read and write to 5 seconds. 
      sslStream.ReadTimeout = 5000; 
      sslStream.WriteTimeout = 5000; 
      // Read a message from the client. 
      Console.WriteLine("Waiting for client message..."); 
      string messageData = ReadMessage(sslStream); 
      Console.WriteLine("Received: {0}", messageData); 
     } 
     catch (AuthenticationException e) 
     { 
      Console.WriteLine("Exception: {0}", e.Message); 
      if (e.InnerException != null) 
      { 
       Console.WriteLine("Inner exception: {0}", e.InnerException.Message); 
      } 
      Console.WriteLine("Authentication failed - closing the connection."); 
      sslStream.Close(); 
      client.Close(); 
      return; 
     } 
     finally 
     { 
      // The client stream will be closed with the sslStream 
      // because we specified this behavior when creating 
      // the sslStream. 
      sslStream.Close(); 
      client.Close(); 
     } 
    } 
    static string ReadMessage(SslStream sslStream) 
    { 
     // Read the message sent by the server. 
     // The end of the message is signaled using the 
     // "<EOF>" marker. 
     byte[] buffer = new byte[2048]; 
     StringBuilder messageData = new StringBuilder(); 
     int bytes = -1; 
     do 
     { 
      bytes = sslStream.Read(buffer, 0, buffer.Length); 

      // Use Decoder class to convert from bytes to UTF8 
      // in case a character spans two buffers. 
      Decoder decoder = Encoding.UTF8.GetDecoder(); 
      char[] chars = new char[decoder.GetCharCount(buffer, 0, bytes)]; 
      decoder.GetChars(buffer, 0, bytes, chars, 0); 
      messageData.Append(chars); 
      // Check for EOF. 
      if (messageData.ToString().IndexOf("<EOF>") != -1) 
      { 
       break; 
      } 
     } while (bytes != 0); 

     return messageData.ToString(); 
    } 
    static void DisplaySecurityLevel(SslStream stream) 
    { 
     Console.WriteLine("Cipher: {0} strength {1}", stream.CipherAlgorithm, stream.CipherStrength); 
     Console.WriteLine("Hash: {0} strength {1}", stream.HashAlgorithm, stream.HashStrength); 
     Console.WriteLine("Key exchange: {0} strength {1}", stream.KeyExchangeAlgorithm, stream.KeyExchangeStrength); 
     Console.WriteLine("Protocol: {0}", stream.SslProtocol); 
    } 
    static void DisplaySecurityServices(SslStream stream) 
    { 
     Console.WriteLine("Is authenticated: {0} as server? {1}", stream.IsAuthenticated, stream.IsServer); 
     Console.WriteLine("IsSigned: {0}", stream.IsSigned); 
     Console.WriteLine("Is Encrypted: {0}", stream.IsEncrypted); 
    } 
    static void DisplayStreamProperties(SslStream stream) 
    { 
     Console.WriteLine("Can read: {0}, write {1}", stream.CanRead, stream.CanWrite); 
     Console.WriteLine("Can timeout: {0}", stream.CanTimeout); 
    } 
    static void DisplayCertificateInformation(SslStream stream) 
    { 
     Console.WriteLine("Certificate revocation list checked: {0}", stream.CheckCertRevocationStatus); 

     X509Certificate localCertificate = stream.LocalCertificate; 
     if (stream.LocalCertificate != null) 
     { 
      Console.WriteLine("Local cert was issued to {0} and is valid from {1} until {2}.", 
       localCertificate.Subject, 
       localCertificate.GetEffectiveDateString(), 
       localCertificate.GetExpirationDateString()); 
     } 
     else 
     { 
      Console.WriteLine("Local certificate is null."); 
     } 
     // Display the properties of the client's certificate. 
     X509Certificate remoteCertificate = stream.RemoteCertificate; 
     if (stream.RemoteCertificate != null) 
     { 
      Console.WriteLine("Remote cert was issued to {0} and is valid from {1} until {2}.", 
       remoteCertificate.Subject, 
       remoteCertificate.GetEffectiveDateString(), 
       remoteCertificate.GetExpirationDateString()); 
     } 
     else 
     { 
      Console.WriteLine("Remote certificate is null."); 
     } 
    } 
    private static void DisplayUsage() 
    { 
     Console.WriteLine("To start the server specify:"); 
     Console.WriteLine("serverSync certificateFile.cer"); 
     Environment.Exit(1); 
    } 

    private X509Certificate createCertificate() 
    { 
     byte[] c = Certificate.CreateSelfSignCertificatePfx(
        "CN=localhost", //host name 
        DateTime.Parse("2015-01-01"), //not valid before 
        DateTime.Parse("2020-01-01"), //not valid after 
        "sslpass"); //password to encrypt key file 
     using (BinaryWriter binWriter = new BinaryWriter(File.Open(@"cert.pfx", FileMode.Create))) 
     { 
      binWriter.Write(c); 
     } 
     return new X509Certificate2(@"cert.pfx", "sslpass"); 
    } 
} 
+0

Проблема возникает в этой строке: bytes = sslStream.Read (buffer, 0, buffer.Length); –

+0

Конечно. Вы устанавливаете тайм-аут чтения, и MSDN говорит: «Если операция чтения не завершается в течение времени, указанного этим свойством, операция чтения генерирует исключение IOException». Чего вы ожидали? –

+0

(Если вы ожидали обнаружить EOF с помощью 'messageData.ToString(). IndexOf (" ")', это будет только ударить, если клиент буквально отправит вам байты ''. Ваш клиент делает это? Я подозреваю, что ваш клиент - веб-браузер, я сомневаюсь, что это так.) –

ответ

2

Это не ошибка SSL, но TCP один. Вы подключаетесь к паре ip/port, которая не прослушивается. Является активным отказом, поэтому не похоже на то, что вы достигаете IP-адреса и говорите, что нет порта. Является ли тайм-аут, который может означать недействительный IP-адрес, или брандмауэр цели игнорирует вас (намеренно).

Мое первое подозрение было бы на линии m_portnumber = 4434;. Это необычный номер порта. Вы уверены, что это не опечатка, и вам нужен обычный порт HTTPS (443)? Если вы действительно имеете в виду 4434, вам необходимо проверить подключение к сети. Убедитесь, что IP-адрес разрешен правильно, доступен целевой объект, и он активирует брандмауэр.

+0

Даже если я использую номер порта 443, я получаю такое же исключение –