asyncio icon indicating copy to clipboard operation
asyncio copied to clipboard

SSL socket exhaustion?

Open kyuupichan opened this issue 7 years ago • 10 comments

I have written a fairly widely used server, ElectrumX, with asyncio. This issue

https://github.com/kyuupichan/electrumx/issues/94

is essentially about clients that connect to the SSL port and then do nothing during the SSL handshake. The number of connections doing this seems to gradually increase over time. It is easily confirmed these never time out by simply making a telnet connection to the SSL port and doing nothing.

An SSL server created with create_server() creates protocols using the protocol factory when the initial connection comes in, but because of the socket wrapping it will not call connection_made() until the handshake is complete. As a result it seems I have no way of getting the socket or the transport of these ghost connections, and therefore I cannot close them if stale. I also don't see anywhere I can specify SSL handshake timeouts in asyncio.

I've looked over the code and pored over the docs, but cannot find anything about this. Am I missing something obvious?

kyuupichan avatar Jan 11 '17 04:01 kyuupichan

This would seem to be an easy avenue to exhaust the open file limit of any asyncio server that accepts SSL connections as it is out of the control of the application author.

Should there not be some timeout on SSL handshakes - both initial handshake and shutdown handshake?

kyuupichan avatar Jan 13 '17 10:01 kyuupichan

Hi,

I didn't dig too deep, but it think that's indeed an issue which should be fixed: it's probably easy to DOS an asyncio server by keeping SSL connections open without completing the handshake. We don't need to do anything for client SSL streams, wrapping open_connection() (or the equivalent for other streams) in wait_for() with a timeout is sufficient.

I'm interested in working on this. The simplest solution is probably to set a timeout on idle streams. We have to keep in mind that either solution must work for any kind of stream transport.

I can look at how we can update the API to include a timeout argument to the right methods and coroutine functions.

Martiusweb avatar Jan 13 '17 11:01 Martiusweb

Any progress on this? This is a huge flaw for asyncio SSL servers in a hostile environment.

kyuupichan avatar Mar 28 '17 04:03 kyuupichan

here is fix https://github.com/python/cpython/pull/480

fafhrd91 avatar Mar 28 '17 04:03 fafhrd91

Fantastic, thank you. I hope this can be back-ported to 3.5.x and 3.6.x.

kyuupichan avatar Mar 28 '17 04:03 kyuupichan

fix is trivial, we can include it into aiohttp for old python versions.

fafhrd91 avatar Mar 28 '17 04:03 fafhrd91

aiohttp? Not using that; using simple SSL sockets with raw TCP

kyuupichan avatar Mar 28 '17 04:03 kyuupichan

ah, ok. just saw aiohttp in install_requires. then you can do monkey patch yourself.

fafhrd91 avatar Mar 28 '17 04:03 fafhrd91

Well I can for myself, but not for my 100 users. As this is a remotely exploitable resource leakage I think it should be backported.

kyuupichan avatar Mar 28 '17 04:03 kyuupichan

I mean fix should be included in library that you use. and sure it should be backported, but this will take some time.

fafhrd91 avatar Mar 28 '17 04:03 fafhrd91