1

I try connect to specific https server:

socketHandler = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
socketWraped = ssl.wrap_socket(socketHandler)
socketWraped.connect(('certificatedetails.com', 443))

But the python says:

File "/usr/lib/python3.6/ssl.py", line 1109, in connect
self._real_connect(addr, False)
File "/usr/lib/python3.6/ssl.py", line 1100, in _real_connect
self.do_handshake()
File "/usr/lib/python3.6/ssl.py", line 1077, in do_handshake
self._sslobj.do_handshake()
File "/usr/lib/python3.6/ssl.py", line 689, in do_handshake
self._sslobj.do_handshake()
ssl.SSLError: [SSL: SSLV3_ALERT_HANDSHAKE_FAILURE] sslv3 alert handshake failure (_ssl.c:852)

I try using TLS1:

socketWraped = ssl.wrap_socket(
    socketHandler,
    ssl_version=ssl.PROTOCOL_TLSv1,
    ciphers='ADH-AES256-SHA'
)

But says:

ssl.SSLError: [SSL: NO_CIPHERS_AVAILABLE] no ciphers available (_ssl.c:852)

Have a upgraded ssl in python and operative system:

$ hostnamectl
   Static hostname: machine
         Icon name: computer-desktop
           Chassis: desktop
        Machine ID: ...
           Boot ID: ...
  Operating System: Ubuntu 18.04.2 LTS
            Kernel: Linux 4.15.0-51-generic
      Architecture: x86-64
$ openssl version
OpenSSL 1.1.1c  28 May 2019
$ python3 -c "import ssl; print(ssl.OPENSSL_VERSION)"
OpenSSL 1.1.1c  28 May 2019

From netcat can connect without problems:

$ ncat --ssl -v certificatedetails.com 443
Ncat: Version 7.60 ( https://nmap.org/ncat )
Ncat: SSL connection to 104.28.6.163:443.
Ncat: SHA-1 fingerprint: 75B3 C6AD 7A72 62B5 7104 0632 0585 A82A F542 641B

What is the problem and how to solve this?

e-info128
  • 3,727
  • 10
  • 40
  • 57
  • `ADH-AES256-SHA` appears to be an anonymous key exchange protocol; they are usually not supported nowadays. That is why you see *`no ciphers available`* - there are no common ciphers between client and server. You should use an ephemeral key exchange protocol like DH or ECDH. You can see a list of them at [Which Cipher Suites to enable for SSL Socket?](https://stackoverflow.com/a/1037713/608639) (though it is a Java question). The ephemeral protocols are the ones with `TLS_DHE_*` and `TLS_ECDHE_*` in the name. – jww Jun 23 '19 at 00:11
  • FYI your 'using TLS1' failed because you specified an ADH (anonymous) ciphersuite and OpenSSL 1.1.0 up in the default build doesn't support anonymous suites. If you used the default or a more sensible cipher it would fail in the same way as your original code, due to lack of SNI as diagnosed by Joseph. But I don't know why you thought TLS1 would help; OpenSSL 1.1.1 supports up to TLS1.3, and (the `_ssl` module in) the version of python you have probably up to TLS1.2. If you thought the SSL3_ and sslv3 in the error code and text mean it was using SSLv3 protocol, they don't. – dave_thompson_085 Jun 23 '19 at 00:16
  • @jww: it didn't even get that far. That error means the API call to configure OpenSSL locally failed (because it doesn't support ADH/anonymous). If OpenSSL did support it but the server didn't (and most servers today don't) the error would have been about an alert, or possibly just a disconnect or reset, from the server. – dave_thompson_085 Jun 23 '19 at 00:19
  • @Dave: *`ssl.SSLError: [SSL: NO_CIPHERS_AVAILABLE] no ciphers available (_ssl.c:852)`* is a runtime error. – jww Jun 23 '19 at 00:26
  • @jww: everything in a python script is runtime, but my point was it isn't due to 'not common between client and server'; that error will occur even if the server supports anonymous -- or doesn't exist at all. – dave_thompson_085 Jun 26 '19 at 16:09
  • @Dave - Good luck with things. – jww Jun 26 '19 at 16:24

2 Answers2

3

From the documentation:

Since Python 3.2 and 2.7.9, it is recommended to use the SSLContext.wrap_socket() of an SSLContext instance to wrap sockets as SSLSocket objects. The helper functions create_default_context() returns a new context with secure default settings. The old wrap_socket() function is deprecated since it is both inefficient and has no support for server name indication (SNI) and hostname matching.

When I use SSLContext.wrap_socket() instead of the deprecated wrap_socket(), it works:

socketHandler = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
socketWraped = ssl.create_default_context().wrap_socket(socketHandler, server_hostname='certificatedetails.com')
socketWraped.connect(('certificatedetails.com', 443))
1

To solve both SSLV3_ALERT_HANDSHAKE_FAILURE NO_CIPHERS_AVAILABLE the approch I recommend is

a) Find the maximum protocol accepted from the server using s_client on a linux box, for example :

 openssl s_client -connect my_host:443 -tls1

(check man s_client for all possible protocols).

b) Once Connected, note the Cipher used by openssl

New, SSLv3, Cipher is AES256-SHA
Server public key is 2048 bit
Secure Renegotiation IS supported
Compression: NONE
Expansion: NONE
No ALPN negotiated

c) Create your sslcontext accordingly

sslcontext = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
sslcontext.set_ciphers("AES256-SHA")
sslcontext.load_default_certs()

Works for all librairies (requests, aiohttp...)

safepost
  • 135
  • 12