pyca / pyca/pyopenssl

How to set timeout for do_handshake()?

Open
#986 3 comments 2 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Python
Stars
944
Forks
440
Avg merge
1d 6h
Merged PRs (30d)
6

Description

Hello, I met a weird connection problem.

TCP connection is ok to establish with my target IP. However, it hangs for a long time at do_handshake().

Here is my code. conn.settimeout(3) and conn.setblocking(True) is used for TCP connection timeout.

import socket
from OpenSSL import crypto, SSL

ssl_context = SSL.Context(method=SSL.SSLv23_METHOD)
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
conn = SSL.Connection(ssl_context, sock)
conn.settimeout(3)
conn.connect(("some_ip", 443))
print('> connected')
conn.setblocking(True)
print('> set to blocking')
conn.do_handshake()
print('> done handshake')

Sometimes it just resets when calls do_handshake(). This is good, which I can ignore it and continue to proceed other targets.

$ python xxx.py
> connected
> set to blocking
Traceback (most recent call last):
  File "xxx.py", line 15, in <module>
    conn.do_handshake()
  File "/usr/local/lib/python3.7/site-packages/OpenSSL/SSL.py", line 1934, in do_handshake
    self._raise_ssl_error(self._ssl, result)
  File "/usr/local/lib/python3.7/site-packages/OpenSSL/SSL.py", line 1663, in _raise_ssl_error
    raise SysCallError(errno, errorcode.get(errno))
OpenSSL.SSL.SysCallError: (104, 'ECONNRESET')

It hangs! This is the worst situation. I have to interrupt it.

$ python xxx.py
> connected
> set to blocking
^CTraceback (most recent call last):
  File "xxx.py", line 15, in <module>
    conn.do_handshake()
  File "/usr/local/lib/python3.7/site-packages/OpenSSL/SSL.py", line 1933, in do_handshake
    result = _lib.SSL_do_handshake(self._ssl)
KeyboardInterrupt

I did a test. do_handshake() raises exception after 300 seconds. It surprises me that it's not due to timeout.

$ time python xxx.py
> connected
> set to blocking
Traceback (most recent call last):
  File "xxx.py", line 15, in <module>
    conn.do_handshake()
  File "/usr/local/lib/python3.7/site-packages/OpenSSL/SSL.py", line 1934, in do_handshake
    self._raise_ssl_error(self._ssl, result)
  File "/usr/local/lib/python3.7/site-packages/OpenSSL/SSL.py", line 1663, in _raise_ssl_error
    raise SysCallError(errno, errorcode.get(errno))
OpenSSL.SSL.SysCallError: (104, 'ECONNRESET')

real	5m3.233s
user	0m0.355s
sys	0m0.028s

300 seconds is not acceptable. There are thousands of targets to scan. I cannot wait for N*300 seconds, although it's a small portion.

python:3.7.9-slim
PyOpenSSL==19.1.0

How can it make do_handshake() succeed or fail within a small amount of time?

Thanks.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by reproducing the reported behavior with the Python script using PyOpenSSL 19.1.0 and inspect the call to conn.do_handshake(). The issue names no source file, test, or concrete change, so the expected timeout and a suitable implementation location would need to be established before work can be considered done.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
networking, security
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.