bpo-29970: Time out SSL handshake if not complete after 10 seconds#4825
bpo-29970: Time out SSL handshake if not complete after 10 seconds#4825asvetlov merged 14 commits intopython:masterfrom
Conversation
|
Hello, and thanks for your contribution! I'm a bot set up to make sure that the project can legally accept your contribution by verifying you have signed the PSF contributor agreement (CLA). Unfortunately our records indicate you have not signed the CLA. For legal reasons we need you to sign this before we can look at your contribution. Please follow the steps outlined in the CPython devguide to rectify this issue. Thanks again to your contribution and we look forward to looking at it! |
|
Please could the CLA check be rerun? |
|
A Python core developer has requested some changes be made to your pull request before we can consider merging it. If you could please address their requests along with any other requests in other reviews from core developers that would be appreciated. Once you have made the requested changes, please leave a comment on this pull request containing the phrase |
|
I have made the requested changes; please review again |
|
Thanks for making the requested changes! @asvetlov: please review the changes made to this pull request. |
|
I have a feeling that handshake timeout should be configurable. @1st1 do you have a suggestion? |
|
Yes, we need a way to configure it. Adding 10 seconds delay to asyncio test suite is not acceptable too. |
|
I've added handshake_timeout as a constructor argument, and reduced the timeout to 0.1s for the purposes of the tests. |
|
Parameter in |
Lib/asyncio/base_events.py
Outdated
| reuse_address=None, | ||
| reuse_port=None): | ||
| reuse_port=None, | ||
| handshake_timeout=10.0): |
There was a problem hiding this comment.
The parameter should be called ssl_handshake_timeout
|
It would be nice to research how long is handshake timeout in other frameworks. Quick google gave me this: https://support.f5.com/csp/article/K13834 -- which might deserve to be mentioned in a comment. Please try to find more resources on this. |
Lib/asyncio/base_events.py
Outdated
| def _make_ssl_transport(self, rawsock, protocol, sslcontext, waiter=None, | ||
| *, server_side=False, server_hostname=None, | ||
| extra=None, server=None): | ||
| extra=None, server=None, ssl_handshake_timeout=10.0): |
There was a problem hiding this comment.
Add SSL_HANDSHAKE_TIMEOUT = 10.0 to constants.py and reuse the constant everywhere.
There was a problem hiding this comment.
I mean everywhere you have 10.0 constant.
|
I've moved the constant into constants.py as SSL_HANDSHAKE_TIMEOUT. |
Lib/asyncio/base_events.py
Outdated
| sock.listen(backlog) | ||
| sock.setblocking(False) | ||
| self._start_serving(protocol_factory, sock, ssl, server, backlog) | ||
| self._start_serving(protocol_factory, sock, ssl, server, backlog, ssl_handshake_timeout) |
There was a problem hiding this comment.
Please make sure all lines are shorter than 79 characters (PEP 8).
1st1
left a comment
There was a problem hiding this comment.
Please also fix line lengths to be < 79
Lib/asyncio/sslproto.py
Outdated
| # the SSL handshake | ||
| self._write_backlog.append((b'', 1)) | ||
| self._loop.call_soon(self._process_write_backlog) | ||
| self._loop.call_later(self._ssl_handshake_timeout, self._check_handshake_timeout) |
There was a problem hiding this comment.
You should save a reference to this handle (self._handshake_timeout_handle = self._loop.call_later(...)) and cancel it (self. _handshake_timeout_handle.cancel()) if the handshake is successful.
| server_side=False, | ||
| server_hostname='python.org') | ||
| server_hostname='python.org', | ||
| ssl_handshake_timeout=ANY) |
There was a problem hiding this comment.
Using ANY kind of defeats the purpose of the test. Do this:
handshake_timeout = object()and then pass it instead of ANY and assert calls with that handshake_timeout object.
|
A Python core developer has requested some changes be made to your pull request before we can consider merging it. If you could please address their requests along with any other requests in other reviews from core developers that would be appreciated. Once you have made the requested changes, please leave a comment on this pull request containing the phrase |
|
I have made the requested changes; please review again |
Lib/asyncio/base_events.py
Outdated
| async def _create_connection_transport( | ||
| self, sock, protocol_factory, ssl, | ||
| server_hostname, server_side=False, | ||
| ssl_handshake_timeout=constants.SSL_HANDSHAKE_TIMEOUT |
There was a problem hiding this comment.
Move the ): one line up: ssl_handshake_timeout=constants.SSL_HANDSHAKE_TIMEOUT):
Lib/asyncio/selector_events.py
Outdated
| self, protocol_factory, sock, | ||
| sslcontext=None, server=None, backlog=100, | ||
| ssl_handshake_timeout=constants.SSL_HANDSHAKE_TIMEOUT | ||
| ): |
There was a problem hiding this comment.
Move ): one line up, don't let it hanging there alone :)
1st1
left a comment
There was a problem hiding this comment.
Aside from code-formatting nits (please fix ): in otherwise empty lines) LGTM.
|
The code is perfect but documentation should be updated to reflect new parameter. |
|
Documentation updated. |
|
Thanks! |
Currently if a SSL server is awaiting a handshake and never receives any data at all, it will remain stuck in that state indefinitely. This means that a client can open an unlimited number of connections to the server and not send any data, eventually exhausting the server's file handle limit if this continues.
This change is to add a timeout event that will abort a connection if the handshake does not complete within ten seconds of starting.
https://bugs.python.org/issue29970