如何使用阻塞套接字进行超时持久/保持活动 SSL 连接?

发布于 2024-11-19 15:55:57 字数 2320 浏览 5 评论 0原文

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

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

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

但是,不能保证客户端会发送其应发送的内容。因此,使用阻塞套接字的服务器似乎可以无限期地挂在 SSL_read() 上,同时等待永远不会到达的其他请求。 (SSL_CTX_set_timeout() 似乎不会导致后续的 SSL_read() 提前退出,因此不清楚如何执行超时连接,如 此维基百科页面(如果套接字被阻塞)。)

显然,服务器可以通过返回一个来表明它不会保持活动状态“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() 必须为 true到达SSL_read(),是不是SSL_read()永远不会挂起等待第一个请求?

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

A previous question asked if changing one line of code implemented persistent SSL connections. After seeing that question's responses, and checking the dearth of SSL documentation, the following appear true:

  • for the server, a persistent connection is simply doing repeated requests/responses between SSL_accept() and SSL_set_shutdown().

  • according to this page, the client has to indicate how many requests there will be by sending the appropriate "Content-length:" header or using an agreed-upon terminating request.

However, there's no guarantee the client will send what it's supposed to. Therefore, it would seem a server using blocking sockets can hang indefinitely on a SSL_read() while waiting for additional requests that never arrive. (SSL_CTX_set_timeout() doesn't appear to cause a subsequent SSL_read() to exit early, so it's not clear how to do timed-out connections as described at this Wikipedia page if sockets are blocking.)

Apparently, a server can indicate it won't do keep-alive by returning a "Connection: Close" header with a response, so I've ended up with the following code, which at least should always correctly do a single request/response per connection:

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

Two questions:

(1) Since SSL_accept() must be true to reach SSL_read(), is it true SSL_read() can never hang waiting for the first request?

(2) How should this code be modified to do timed-out persistent/keep alive SSL connections with blocking sockets (if that's even possible)?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

野味少女 2024-11-26 15:55:57

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

To quote this letter, "The only way to ensure that indefinite blocking is avoided is to use nonblocking I/O." So, I guess I'll give up trying to timeout blocked SSL_read()s.

黎歌 2024-11-26 15:55:57

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

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

(1) if the client connects but does not send a request (DoS attack, for instance), then SSL_read() would hang.

(2) try calling setsockopt(SO_RCVTIMEO) on the accepted SOCKET to set a reading timeout on it.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文