【问题标题】:Why won't Chrome 79 accept my HTTPS response sent with SslStream (C#)? err_response_headers_truncated为什么 Chrome 79 不接受我使用 SslStream (C#) 发送的 HTTPS 响应? err_response_headers_truncated
【发布时间】:2020-01-09 08:08:37
【问题描述】:

我正在尝试用 C# 构建一个在 localhost 上运行的简单 TLS Web 服务器。在这种情况下,我希望服务器做的就是发出重定向。为此,我使用 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。我可以在调试时读取 chrome 的 GET 请求,但 chrome 显然不能或不会读取我的响应。

我已成功使用完全相同的代码重定向边缘(http 和 https),所以这似乎是特定于 chrome 的

在服务器发送响应之前,快速的wireshark 调查显示没有任何异常。举例说明:标准 tcp syn/ack 握手,tls 握手,然后是客户端应用程序。数据(GET)服务器应用程序数据(301)。在服务器发送 301 之后,有 3 个 FIN/ACK,一个保持活动状态,一个密码更改,然后是一堆 RST。鉴于这些信息,似乎 chrome 并没有给我们任何东西,但同时也不指望我们抛弃它们,并开始拼命恳求重新连接。奇怪的是,如果我调试,它会重新连接。但随后它抛出异常,因为服务器在读取时超时;我们给了 Chrome 第二次机会,但 Chrome 不愿意为已经破裂的关系恢复任何东西,并留下了伤痕。

差不多了,我在问我在做什么 Chrome 显然没有预料到,我该如何纠正它以便它在 Chrome 上运行?我是在做其他浏览器正在补偿的明显错误,还是 SslStream 有问题?

我的 TLS 代码基本上取自 Microsoft doc for SslStream,http 设计遵循相同的模式:接受、读取、写入、刷新、流关闭、tcp 关闭。如果要复制,则创建的证书与 X509Certificate.CreateFromCertFile(string) 一起使用。 TcpListener 使用了IPAddress.Loopback。为了生成我的证书,我关注了this tutorial,并使用openssl pkcs12 导出了我的localhost.crtlocalhost.key

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();
    }
}

【问题讨论】:

    标签: c# google-chrome https wireshark tls1.2


    【解决方案1】:

    好的,所以问题原来是行尾。 Chrome 希望在响应结束时有两个 \r\n 。我在 support.google.com 上找到了 this 关于它的文章。 所以字符串应该看起来像

    "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"

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-11-22
      • 2021-08-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-06-10
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多