【问题标题】:How do you do timed-out persistent/keep alive SSL connections with blocking sockets?您如何使用阻塞套接字进行超时持久/保持活动 SSL 连接?
【发布时间】:2011-08-14 06:27:52
【问题描述】:

previous question 询问更改一行代码是否实现了持久 SSL 连接。在看到该问题的回答并检查 SSL 文档的缺乏后,以下情况似乎是正确的:

  • 对于服务器而言,持久连接只是在 SSL_accept() 和 SSL_set_shutdown() 之间重复请求/响应。

  • 根据this page,客户端必须通过发送适当的“Content-length:”标头或使用商定的终止请求来指示将有多少请求。

但是,不能保证客户端会发送它应该发送的内容。因此,使用阻塞套接字的服务器似乎可以在 SSL_read() 上无限期地挂起,同时等待永远不会到达的其他请求。 (SSL_CTX_set_timeout() 似乎不会导致后续 SSL_read() 提前退出,因此如果套接字阻塞,不清楚如何按照this Wikipedia page 中的描述进行超时连接。)

显然,服务器可以通过返回带有响应的“Connection: Close”标头来指示它不会保持活动状态,所以我最终得到了以下代码,至少应该始终正确地执行一次每个连接的请求/响应:

while TRUE do
  begin  // wait for incoming TCP connection
  if notzero(listen(listen_socket, 100)) then continue; // listen failed
  client_len := SizeOf(sa_cli);
  sock := accept(listen_socket, @sa_cli, @client_len); // create socket for connection
  if sock = INVALID_SOCKET then continue; // accept failed
  ssl := SSL_new(ctx); // TCP connection ready, create ssl structure
  if assigned(ssl) then
    begin
    SSL_set_fd(ssl, sock); // assign socket to ssl structure
    if SSL_accept(ssl) = 1 then // handshake worked
      begin
      request := '';
      repeat // gather request
        bytesin := SSL_read(ssl, buffer, sizeof(buffer)-1);
        if bytesin > 0 then
          begin
          buffer[bytesin] := #0;
          request := request + buffer;
          end;
      until SSL_pending(ssl) <= 0;
      if notempty(request) then
        begin // decide on response, avoid keep-alive
        response := 'HTTP/1.0 200 OK'#13#10'Connection: Close'#13#10 + etc;
        SSL_write(ssl, pchar(response)^, length(response));
        end; // else read empty or failed
      end; // else handshake failed
    SSL_set_shutdown(ssl, SSL_SENT_SHUTDOWN or SSL_RECEIVED_SHUTDOWN);
    CloseSocket(sock);
    SSL_free(ssl);
    end; // else ssl creation failed
  end; // infinite while

两个问题:

(1) 既然 SSL_accept() 必须为真才能到达 SSL_read(),那么真的 SSL_read() 永远不会挂起等待第一个请求吗?

(2) 应如何修改此代码以使用阻塞套接字执行超时持久/保持活动 SSL 连接(如果可能的话)?

【问题讨论】:

    标签: https openssl winsock keep-alive


    【解决方案1】:

    引用this letter,“确保避免无限阻塞的唯一方法是使用非阻塞 I/O。”所以,我想我会放弃尝试使阻塞的 SSL_read()s 超时。

    【讨论】:

      【解决方案2】:

      (1) 如果客户端连接但不发送请求(例如 DoS 攻击),则 SSL_read() 将挂起。

      (2) 尝试在已接受的SOCKET 上调用setsockopt(SO_RCVTIMEO) 以设置读取超时。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-12-20
        • 2020-02-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-01-04
        • 2013-04-04
        相关资源
        最近更新 更多