【问题标题】:WSS support for C# .exe to work over httpsWSS 支持 C# .exe 通过 https 工作
【发布时间】:2020-06-10 15:15:31
【问题描述】:

我有 .net .exe,它监听网络套接字。它在 http 上完美运行。 当我的发件人通过 https 转移到 WSS 时,我的 .exe 无法解密传入的请求。 我的客户端收到字节数组,但是当我尝试将其解密为 UTF 编码时,它无法通过 Encoding.GetEncoding("ISO-8859-1"); 正确解密

代码:

public void ReadCallback(IAsyncResult ar)
{
    try
    {
        // Retrieve the state object
        // and the handler socket
        // from the asynchronous state object.
        var state = (StateObject)ar.AsyncState;
        // Read data from the client socket. 
        var bytesRead = _socket.EndReceive(ar);

        // Below code doesn't decrypt correctly for wss
        // but works correctly for ws
        Utils.Encoding.GetString(state.Buffer, 0, bytesRead);

【问题讨论】:

  • 您使用的是什么网络套接字 API?它知道它正在使用 TLS 吗?等等 - 没有一些代码,这很难评论,但概括地说:“是的,如果配置正确,那应该可以工作”
  • ` public void ReadCallback(IAsyncResult ar) { try { // 从异步状态对象中检索状态对象 // 和处理程序套接字。 var state = (StateObject)ar.AsyncState; // 从客户端套接字读取数据。 var bytesRead = _socket.EndReceive(ar); ` ** 下面的代码无法正确解密 was,但适用于 ws** ` Utils.Encoding.GetString(state.Buffer, 0, bytesRead) `
  • Encoding.GetsString 没有解密我的流,这就是问题所在。
  • Encoding 从不 处理解密 - 这不是 Encoding 的工作 - 但是:您评论中的代码在这里真的很有帮助;我已将其编辑到问题中,因为它非常重要

标签: c# https wss


【解决方案1】:

在您现有的代码中,您在套接字层谈论原始字节,直接从Socket 到Encoding。这对于未加密的数据来说很好,因为数据字面上是相同的字节(虽然......只有握手的第一部分是文本;在 HTTP 标头之后,您应该处理帧解析器,理想情况下,这里靠近Encoding 有点危险;上下文:我也直接从Socket 层编写了一个成功的、高吞吐量的网络套接字服务器。

但是:当您在中间需要进行任何字节转换时,事情就没有那么简单了——这里就是 TLS(如果这也是压缩转换,您也会遇到同样的问题)。

很简单:需要有人来处理实际的 TLS 工作。如果您决心自己处理细节,那么您最好的选择可能是包装:

Socket NetworkStream SslStream (你的代码)

这意味着您将针对Stream API 进行编码,而不是Socket API(可能在初始化服务器流时使用AuthenticateAsServer())。为避免有两个代码库,您可以只使用:

Socket NetworkStream (你的代码)

对于ws 层。但是,坦率地说,IMO 最好让框架和库担心这一点 - 特别是如果您使用 .NET Core:您可以使用 Kestrel 设置支持 TLS 的 Web 服务器,您的代码基本上只是:

public void Configure(IApplicationBuilder app)
{
    app.UseWebSockets(new WebSocketOptions()
    {
        // set KeepAliveInterval / ReceiveBufferSize / etc
    });
    app.Run(ctx =>
    {
        if (ctx.WebSockets.IsWebSocketRequest)
        {
            return RunClientAsync(ctx);
        }
        else { /* whatever you want to do when not WS/WSS */ }
    });
}
private async Task RunClientAsync(HttpContext context)
{
    var socket = await context.WebSockets.AcceptWebSocketAsync();
    // TODO: all your read/write logic using the WebSocket API
}

这种方法在 .NET Core 3.1 上的扩展性比在 .NET Framework 上要好得多(检查我的状态页面);我目前在 9 个节点上运行约 518,000 个并发 Web 套接字连接(因为我恰好有 9 个节点可用),CPU 几乎为 0%,每个节点 5 个端口(以避免临时端口耗尽)每个端口每个端口约 11,500 个连接节点。我们迁移了我们的自定义 Socket 级别代码以将 WebSocket API 与 .NET Core 3.1 一起使用,因为这些改进意味着我们不再需要维护自己的代码来处理web-socket 协议的细微差别。

【讨论】:

  • 感谢您的回答,我现在遇到的问题是,我有旧版服务器(控制台 .exe),它位于 .net 框架上而不是 .net 核心上。我目前无法将其迁移到 .net 核心。我正在寻找的是,当我通过“ws”收到请求时,它会正确解密,然后我向其添加握手,但我的客户端尝试通过“wss”连接它,它无法解密,因此我不能与我的客户握手。客户端部署在安装证书的 ISS 上。我已经使用私钥在服务器(.exe)上安装了相同的证书,但我现有的代码没有运气。
  • @TusharMali 如果您直接与Socket 交谈:您可能没有托管在 IIS 中;当然,IIS 可能在同一个盒子上并且有证书,但我认为它不涉及这个自定义服务器,所以:它是无关紧要的。在您的场景中,我想知道是否更实用的选择是使用负载均衡器/反向代理作为网关,并在负载均衡器处终止 TLS:所以从外部客户端的角度来看,它们'正在谈论 TLS,但从负载均衡器到您的服务的流量:未加密。我过去曾使用 haproxy 来执行此操作
  • 是的,代理是解决方案之一。
猜你喜欢
  • 1970-01-01
  • 2016-11-22
  • 2022-11-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多