[New-bugs-announce] [issue46518] SSL socket timeout not set after client connects via accept
tomazas
report at bugs.python.org
Tue Jan 25 07:38:41 EST 2022
New submission from tomazas <tomas.uktveris at gmail.com>:
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
```
----------
files: https.py
messages: 411585
nosy: tomazas
priority: normal
severity: normal
status: open
title: SSL socket timeout not set after client connects via accept
type: behavior
versions: Python 3.10, Python 3.11
Added file: https://bugs.python.org/file50584/https.py
_______________________________________
Python tracker <report at bugs.python.org>
<https://bugs.python.org/issue46518>
_______________________________________
More information about the New-bugs-announce
mailing list