web-dev-qa-db-fra.com

Erreur de poignée de main SSL incorrecte 10054 "WSAECONNRESET"

Notes:

versions

Python 2.7.11 and my requests version is '2.10.0'
'OpenSSL 1.0.2d 9 Jul 2015'
Please read the below comment by Martijn Pieters before reproducing 

Au départ, j'ai essayé d'obtenir le pdf à partir de https://www.neco.navy.mil/necoattach/N6945016R0626_2016-06-20__INFO_NAS_Pensacola_Base_Access.docx en utilisant le code comme ci-dessous

code1:

>>> import requests
>>> requests.get("https://www.neco.navy.mil/necoattach/N6945016R0626_2016-06-20__INFO_NAS_Pensacola_Base_Access.docx",verify=False)

Erreur:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "C:\Users\mob140003207\AppData\Local\Enthought\Canopy\User\lib\site-packa
ges\requests\api.py", line 67, in get
    return request('get', url, params=params, **kwargs)
  File "C:\Users\mob140003207\AppData\Local\Enthought\Canopy\User\lib\site-packa
ges\requests\api.py", line 53, in request
    return session.request(method=method, url=url, **kwargs)
  File "C:\Users\mob140003207\AppData\Local\Enthought\Canopy\User\lib\site-packa
ges\requests\sessions.py", line 468, in request
    resp = self.send(prep, **send_kwargs)
  File "C:\Users\mob140003207\AppData\Local\Enthought\Canopy\User\lib\site-packa
ges\requests\sessions.py", line 576, in send
    r = adapter.send(request, **kwargs)
  File "C:\Users\mob140003207\AppData\Local\Enthought\Canopy\User\lib\site-packa
ges\requests\adapters.py", line 447, in send
    raise SSLError(e, request=request)
requests.exceptions.SSLError: ("bad handshake: SysCallError(10054, 'WSAECONNRESE
T')",)

Après avoir googlé et cherché, j'ai constaté que vous aviez utilisé la vérification SSL et que l'utilisation d'une session avec des adaptateurs pouvait résoudre le problème. Mais j'ai encore des erreurs, veuillez trouver le code et l'erreur ci-dessous

Code2:

import requests
from requests.adapters import HTTPAdapter
from requests.packages.urllib3.poolmanager import PoolManager
import ssl
import traceback

class MyAdapter(HTTPAdapter):
    def init_poolmanager(self, connections, maxsize, block=False):
        self.poolmanager = PoolManager(num_pools=connections,
                                       maxsize=maxsize,
                                       block=block,
                                       ssl_version=ssl.PROTOCOL_TLSv1)


s = requests.Session()
s.mount('https://', MyAdapter())
print "Mounted    "
r = s.get("https://www.neco.navy.mil/necoattach/N6945016R0626_2016-06-20__INFO_NAS_Pensacola_Base_Access.docx", stream=True, timeout=120)

Erreur:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "C:\Users\mob140003207\AppData\Local\Enthought\Canopy\User\lib\site-packa
ges\requests\sessions.py", line 480, in get
    return self.request('GET', url, **kwargs)
  File "C:\Users\mob140003207\AppData\Local\Enthought\Canopy\User\lib\site-packa
ges\requests\sessions.py", line 468, in request
    resp = self.send(prep, **send_kwargs)
  File "C:\Users\mob140003207\AppData\Local\Enthought\Canopy\User\lib\site-packa
ges\requests\sessions.py", line 576, in send
    r = adapter.send(request, **kwargs)
  File "C:\Users\mob140003207\AppData\Local\Enthought\Canopy\User\lib\site-packa
ges\requests\adapters.py", line 447, in send
    raise SSLError(e, request=request)
requests.exceptions.SSLError: ("bad handshake: SysCallError(10054, 'WSAECONNRESET')",)
11
The6thSense

Tout d'abord, je confirme que l'hôte, www.neco.navy.mil, n'est pas accessible de partout. De certains réseaux (géographie) cela fonctionne *, d'autres se bloque simplement:

$ curl www.neco.navy.mil
curl: (7) couldn't connect to Host
$ curl https://www.neco.navy.mil
curl: (7) couldn't connect to Host

Deuxièmement, lorsque la connexion peut être établie, il y a un problème de certificat:

$ curl -v https://www.neco.navy.mil
* Rebuilt URL to: https://www.neco.navy.mil/
* Hostname was NOT found in DNS cache
*   Trying 205.85.2.133...
* Connected to www.neco.navy.mil (205.85.2.133) port 443 (#0)
* successfully set certificate verify locations:
*   CAfile: none
  CApath: /etc/ssl/certs
* SSLv3, TLS handshake, Client hello (1):
* SSLv3, TLS handshake, Server hello (2):
* SSLv3, TLS handshake, CERT (11):
* SSLv3, TLS alert, Server hello (2):
* SSL certificate problem: unable to get local issuer certificate
* Closing connection 0
curl: (60) SSL certificate problem: unable to get local issuer certificate
More details here: http://curl.haxx.se/docs/sslcerts.html

curl performs SSL certificate verification by default, using a "bundle"
 of Certificate Authority (CA) public keys (CA certs). If the default
 bundle file isn't adequate, you can specify an alternate file
 using the --cacert option.
If this HTTPS server uses a certificate signed by a CA represented in
 the bundle, the certificate verification probably failed due to a
 problem with the certificate (it might be expired, or the name might
 not match the domain name in the URL).
If you'd like to turn off curl's verification of the certificate, use
 the -k (or --insecure) option.

Pour vous en assurer, il vous suffit de l'introduire dans Testeur Qualys SSL : enter image description here

La CA ( DoD Root CA 2 ) n'est pas approuvée. De plus, ce n'est pas dans la chaîne. Notez que le processus de validation OpenSSL a besoin de toute la chaîne :

Tout d'abord, une chaîne de certificats est créée à partir du certificat fourni et se terminant par l'autorité de certification racine. C'est une erreur si toute la chaîne ne peut pas être constituée.

Mais il n'y a que www.neco.navy.mil -> DODCA-28 . Cela peut être lié au TLD et à une mesure de sécurité supplémentaire, mais le grade C seul n'est pas beaucoup de toute façon ;-)

De leur côté Python ce ne sera pas très différent. Si vous n'avez pas accès à l'autorité de certification, vous ne pouvez désactiver complètement la validation de certificat (après avoir résolu le problème de connectivité, bien sûr) Si vous l'avez, vous pouvez utiliser cafile.

#!/usr/bin/env python
# -*- coding: utf-8 -*-


import urllib2
import ssl


ctx = ssl.create_default_context()
ctx.check_hostname = False
ctx.verify_mode = ssl.CERT_NONE

r = urllib2.urlopen('https://www.neco.navy.mil/'
  'necoattach/N6945016R0626_2016-06-20__INFO_NAS_Pensacola_Base_Access.docx', 
  timeout = 5, context = ctx)
print(len(r.read()))

r = urllib2.urlopen('https://www.neco.navy.mil/'
  'necoattach/N6945016R0626_2016-06-20__INFO_NAS_Pensacola_Base_Access.docx', 
  timeout = 5, cafile = '/path/to/DODCA-28_and_DoD_Root_CA_2.pem')
print(len(r.read()))

Pour reproduire avec une certaine version de Python, utilisez un Dockerfile simple comme suit:

FROM python:2.7.11

WORKDIR /opt
ADD . ./

CMD dpkg -s openssl | grep Version && ./app.py

Exécutez ensuite:

docker build -t ssl-test .
docker run --rm ssl-test
7
saaj

Cet extrait fonctionne pour moi (py2.7.11 64bits + requêtes == 2.10.0) sur windows7:

import requests
import ssl
import traceback
import shutil
from requests.adapters import HTTPAdapter
from requests.packages.urllib3.poolmanager import PoolManager


class MyAdapter(HTTPAdapter):

    def init_poolmanager(self, connections, maxsize, block=False):
        self.poolmanager = PoolManager(num_pools=connections,
                                       maxsize=maxsize,
                                       block=block,
                                       ssl_version=ssl.PROTOCOL_TLSv1)


if __name__ == "__main__":
    s = requests.Session()
    s.mount('https://', MyAdapter())
    print "Mounted    "
    filename = "N6945016R0626_2016-06-20__INFO_NAS_Pensacola_Base_Access.docx"
    r = s.get(
        "https://www.neco.navy.mil/necoattach/{0}".format(filename), verify=False, stream=True, timeout=120)

    if r.status_code == 200:
        with open(filename, 'wb') as f:
            r.raw.decode_content = True
            shutil.copyfileobj(r.raw, f)
1
BPL

J'utilise python 2.7.6 et cet exemple simple fonctionne toujours sur mon ubuntu 14.04

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import requests
from requests.packages.urllib3.exceptions import InsecureRequestWarning

requests.packages.urllib3.disable_warnings(InsecureRequestWarning)

with open('out.docx', 'wb') as h :
    r = requests.get("https://www.neco.navy.mil/necoattach/N6945016R0626_2016-06-20__INFO_NAS_Pensacola_Base_Access.docx", verify=False, stream=True)

    for block in r.iter_content(1024):
        h.write(block)
0
vatay