Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to set timeout for do_handshake()? #986

Open
vvoody opened this issue Dec 31, 2020 · 3 comments
Open

How to set timeout for do_handshake()? #986

vvoody opened this issue Dec 31, 2020 · 3 comments

Comments

@vvoody
Copy link

vvoody commented Dec 31, 2020

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.

@vvoody
Copy link
Author

vvoody commented Jan 4, 2021

I found 300 seconds as well in openssl command.

$ time openssl s_client -connect some_ip:443
CONNECTED(00000003)
write:errno=104
---
no peer certificate available
---
No client certificate CA names sent
---
SSL handshake has read 0 bytes and written 305 bytes
---
New, (NONE), Cipher is (NONE)
Secure Renegotiation IS NOT supported
Compression: NONE
Expansion: NONE
No ALPN negotiated
SSL-Session:
    Protocol  : TLSv1.2
    Cipher    : 0000
    Session-ID:
    Session-ID-ctx:
    Master-Key:
    Key-Arg   : None
    PSK identity: None
    PSK identity hint: None
    SRP username: None
    Start Time: 1609729737
    Timeout   : 300 (sec)   # <=== 300 seconds
    Verify return code: 0 (ok)
---

real    5m3.172s
user    0m0.004s
sys     0m0.000s

@rustymagnet3000
Copy link

Hey @vvoody,

I would also like to see the pyOpenSSL Connection object have a settimeout(). There is a settimeout() function within the <class 'ssl.SSLSocket'>. You can see it fire below, after running c_rehash:

#!/usr/bin/env python3
from socket import socket
import ssl

hostname = 'google.com'
port = 443
with socket() as sock:
    sock.setblocking(True)
    sock.connect((hostname, port))
    context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
    context.load_verify_locations(cafile=None,
                                  cadata=None,
                                  capath="/path/to/ca_files/")
    with context.wrap_socket(sock=sock,
                             server_hostname=hostname,
                             do_handshake_on_connect=False) as ssl_sock:
        ssl_sock.settimeout(2.0)
        ssl_sock.do_handshake()
        print(hostname, ssl_sock.getpeername(), ssl_sock.version())
        print(ssl_sock)

@bortzmeyer
Copy link

Unfortunately, it is an old issue, see #168

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

No branches or pull requests

3 participants