Я пытаюсь создать простой веб-сервер TLS, работающий на локальном хосте, в C#. В этом случае все, что я хочу от сервера - это выполнить перенаправление. Для этого я использую Microsoft SslStream
класс. Это кажется достаточно простым в использовании. Проблема, с которой я сталкиваюсь, заключается в том, что chrome определенно не нравится моему HTTPS. (Код внизу)
Ответ довольно прост: "HTTP/1.1 301 Moved Permanently\r\nCache-Control: no-store\r\nLocation: https://google.com/"
При использовании реализации HTTP страница перенаправляется, как ожидается, на клиенте не возникает ошибок или исключений (Chrome) или сервер.
Однако при использовании моей реализации HTTPS я получаю нечто подобное от chrome:
Этот сайт недоступен
Веб-страница на .....
ERR_RESPONSE_HEADERS_TRUNCATED
Я не уверен, чего еще он от меня хочет. Я бы сказал, что заголовок ответа очень не урезан, но я не chrome. Я могу прочитать GET-запрос chrome во время отладки, но chrome явно не может или не будет читать мой ответ.
Я успешно использовал тот же самый код для перенаправления края (http и https), так что, похоже, это chrome конкретный c
Быстрое исследование Wireshark не показывает ничего необычного до тех пор, пока сервер не отправит ответ. Для иллюстрации: стандартное рукопожатие tcp syn / ack, рукопожатие tls, затем клиентское приложение. data (GET,) серверное приложение data (301.) После того, как сервер отправил 301, есть 3 FIN / ACK, keep-alive, изменение шифра и затем набор RST. Учитывая эту информацию, кажется, что chrome ничего нам не дал, но в то же время не ожидал, что мы их выбросим, и начинает отчаянно умолять восстановить связь. Любопытно, что, если я отлаживаю, он переподключается. Но затем он выдает исключение, потому что время ожидания сервера для чтения истекло; мы дали Chrome второй шанс, но Chrome не хотел возвращать что-то обратно в эти и без того разрушенные отношения, и это оставило шрам.
Так много, я спрашиваю, что я делаю, что Chrome явно не ожидает и как я могу исправить это так, чтобы он работал на Chrome? Я делаю что-то явно неправильное, что другие браузеры компенсируют, или это что-то не так с SslStream?
Мой код TLS был в основном взят из Microsoft do c для SslStream
и дизайн http следует той же схеме: принять, прочитать, записать, flu sh, закрыть поток, закрыть tcp. Если вы хотите воспроизвести, созданный сертификат был использован с X509Certificate.CreateFromCertFile (string). TcpListener
используется IPAddress.Loopback
. Чтобы сгенерировать свой сертификат, я следовал этому руководству и экспортировал мои localhost.crt
и localhost.key
с openssl pkcs12
private string response = "HTTP/1.1 301 Moved Permanently\r\nCache-Control: no-store\r\nLocation: https://google.com/ \r\n";
private void listen() {
while (true) {
TcpClient client = listener.AcceptTcpClient();
NetworkStream stream = client.GetStream();
stream.Read(new Byte[1024], 0, 1024);
stream.Write(Encoding.UTF8.GetBytes(response), 0, response.Length);
stream.Flush();
stream.Close();
client.Close();
}
}
private void listenSSL() {
TcpClient client;
while (true) {
client = listener.AcceptTcpClient();
SslStream sslStream = new SslStream(client.GetStream(), false);
sslStream.AuthenticateAsServer(certificate, clientCertificateRequired: false, SslProtocols.Tls12, checkCertificateRevocation: true);
sslStream.ReadTimeout = timeout;
sslStream.WriteTimeout = timeout;
string message = readMessage(sslStream);
sslStream.Write(Encoding.UTF8.GetBytes(response), 0, response.Length);
sslStream.Flush();
sslStream.Close();
client.Close();
}
}