Почему Chrome 79 не примет мой HTTPS-ответ, отправленный с помощью SslStream (C#)? err_response_headers_truncated - PullRequest
0 голосов
/ 09 января 2020

Я пытаюсь создать простой веб-сервер 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();
    }
}

1 Ответ

0 голосов
/ 12 января 2020

Хорошо, так что проблема оказалась в конце строки. Chrome хочет два \ r \ n в конце ответа. Я нашел эту статью на support.google.com об этом. Таким образом, строка должна выглядеть как

"HTTP/1.1 301 Moved Permanently\r\nCache-Control: no-store\r\nLocation: https://google.com/ \r\n\r\n";

вместо

"HTTP/1.1 301 Moved Permanently\r\nCache-Control: no-store\r\nLocation: https://google.com/ \r\n"

...