Once a client connects to a SSL server over socket accept() the newly returned client socket `newsock` is wrapped in SSL context.
Since the new client `newsock` does not have a socket timeout set (i.e. None), the final returned SSL context socket is also assigned `None` socket timeout. Clients are then able to connect to such server and hold the connection indefinitely without sending any data to server (ghosting the server connections).
Problematic excerpt from Lib/ssl.py:
```
def accept(self):
"""Accepts a new connection from a remote client, and returns
a tuple containing that new connection wrapped with a server-side
SSL channel, and the address of the remote client."""
newsock, addr = super().accept()
newsock = self.context.wrap_socket(newsock,
do_handshake_on_connect=self.do_handshake_on_connect,
suppress_ragged_eofs=self.suppress_ragged_eofs,
server_side=True)
return newsock, addr
```
Attached minimal https.py server Python3 example producing the issue.
After the server is working run the bellow ghost client script to produce the issue:
```
# Script implements ghost client (that does not send anything to server but keeps connection active until server socket timeouts or forever if socket timeouts are not working)
# Usage - after https.py server is launched run using: python3 ghost.py
import socket
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect(("localhost", 443))
print("connected")
while True:
print("ghosting started")
data = sock.recv(4096) # read to block
if not data:
break
print(data)
print("done.")
```
Possible workarounds:
1. socket.setdefaulttimeout(2) - works but interferes with all possible socket operations
2. Patch the socket accept() operation and set the timeout value there before doing any socket operations, e.g.:
```
import socket
old_accept = socket.socket.accept
def patch_accept(self):
newsock, addr = old_accept(self)
newsock.settimeout(2) # sets the client socket timeout
print("socket.accept patched")
return newsock, addr
socket.socket.accept = patch_accept
# TODO: now run all the SSL server socket code here
```
|