запросы python к google.com выдают SSLError

При попытке использовать старый скрипт, который у меня был для использования Python API Google Диска, аутентификация начала выдавать мне ошибки SSL. После небольшого расследования я сузил причину до модуля запросов python или pyOpenSSL, который он использует. Я могу показать проблему только с помощью этого кода:

import requests

requests.get('https://google.com/')

В результате ошибка полностью:

Traceback (most recent call last):
  File "C:\Users\User\AppData\Local\Programs\Python\Python35\lib\site-packages\urllib3\contrib\pyopenssl.py", line 444, in wrap_socket
    cnx.do_handshake()
  File "C:\Users\User\AppData\Local\Programs\Python\Python35\lib\site-packages\OpenSSL\SSL.py", line 1907, in do_handshake
    self._raise_ssl_error(self._ssl, result)
  File "C:\Users\User\AppData\Local\Programs\Python\Python35\lib\site-packages\OpenSSL\SSL.py", line 1639, in _raise_ssl_error
    _raise_current_error()
  File "C:\Users\User\AppData\Local\Programs\Python\Python35\lib\site-packages\OpenSSL\_util.py", line 54, in exception_from_error_queue
    raise exception_type(errors)
OpenSSL.SSL.Error: [('SSL routines', 'tls_process_server_certificate', 'certificate verify failed')]

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "C:\Users\User\AppData\Local\Programs\Python\Python35\lib\site-packages\urllib3\connectionpool.py", line 600, in urlopen
    chunked=chunked)
  File "C:\Users\User\AppData\Local\Programs\Python\Python35\lib\site-packages\urllib3\connectionpool.py", line 343, in _make_request
    self._validate_conn(conn)
  File "C:\Users\User\AppData\Local\Programs\Python\Python35\lib\site-packages\urllib3\connectionpool.py", line 849, in _validate_conn
    conn.connect()
  File "C:\Users\User\AppData\Local\Programs\Python\Python35\lib\site-packages\urllib3\connection.py", line 356, in connect
    ssl_context=context)
  File "C:\Users\User\AppData\Local\Programs\Python\Python35\lib\site-packages\urllib3\util\ssl_.py", line 359, in ssl_wrap_socket
    return context.wrap_socket(sock, server_hostname=server_hostname)
  File "C:\Users\User\AppData\Local\Programs\Python\Python35\lib\site-packages\urllib3\contrib\pyopenssl.py", line 450, in wrap_socket
    raise ssl.SSLError('bad handshake: %r' % e)
ssl.SSLError: ("bad handshake: Error([('SSL routines', 'tls_process_server_certificate', 'certificate verify failed')],)",)

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "C:\Users\User\AppData\Local\Programs\Python\Python35\lib\site-packages\requests\adapters.py", line 445, in send
    timeout=timeout
  File "C:\Users\User\AppData\Local\Programs\Python\Python35\lib\site-packages\urllib3\connectionpool.py", line 638, in urlopen
    _stacktrace=sys.exc_info()[2])
  File "C:\Users\User\AppData\Local\Programs\Python\Python35\lib\site-packages\urllib3\util\retry.py", line 398, in increment
    raise MaxRetryError(_pool, url, error or ResponseError(cause))
urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='google.com', port=443): Max retries exceeded with url: / (Caused by SSLError(SSLError("bad handshake: Error([('SSL routines', 'tls_process_server_certificate', 'certificate verify failed')],)",),))

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "C:\Users\User\Documents\Email2notes\requtest.py", line 3, in <module>
    requests.get('https://google.com/')
  File "C:\Users\User\AppData\Local\Programs\Python\Python35\lib\site-packages\requests\api.py", line 72, in get
    return request('get', url, params=params, **kwargs)
  File "C:\Users\User\AppData\Local\Programs\Python\Python35\lib\site-packages\requests\api.py", line 58, in request
    return session.request(method=method, url=url, **kwargs)
  File "C:\Users\User\AppData\Local\Programs\Python\Python35\lib\site-packages\requests\sessions.py", line 512, in request
    resp = self.send(prep, **send_kwargs)
  File "C:\Users\User\AppData\Local\Programs\Python\Python35\lib\site-packages\requests\sessions.py", line 622, in send
    r = adapter.send(request, **kwargs)
  File "C:\Users\User\AppData\Local\Programs\Python\Python35\lib\site-packages\requests\adapters.py", line 511, in send
    raise SSLError(e, request=request)
requests.exceptions.SSLError: HTTPSConnectionPool(host='google.com', port=443): Max retries exceeded with url: / (Caused by SSLError(SSLError("bad handshake: Error([('SSL routines', 'tls_process_server_certificate', 'certificate verify failed')],)",),))

Я думаю, что могу предположить, что сертификаты Google в порядке, а код представляет собой одну строку, поэтому я думаю, что исключение должно быть вызвано одним из модулей. Я видел другие проблемы этого типа, которые рекомендуют обновить их (например, ). Однако я уже использую последнюю версию запросов и urllib3 и pyOpenSSL (обновил их с помощью pip), я не могу их обновлять дальше, так как я могу это исправить?

Я установил requests[security], как это предлагается в другом месте. Также предлагается перейти на более старую версию certifi, но pip не смог найти предложенную версию.

Моя версия Python — 3.5.0, и я работаю над Windows 10. Обратите внимание, что это не повторяющийся вопрос; в других вопросах с этой проблемой проблема была с SSL-сертификатами веб-сайта. Если есть проблема с SSL-сертификатами Google, это мне не под силу.

Кроме того, использование verify=False устраняет эту ошибку для этого фрагмента кода. Однако в моем реальном коде (с использованием google-auth-oauthlib, который сам использует запросы) мне негде это применить - я просто вызываю, например. google_auth_oauthlib.flow.run_local_server(), см. здесь.


person Cycloneblaze    schedule 06.09.2018    source источник
comment
Это как-то связано с этим? stackoverflow.com/questions/50246084/   -  person Julien Cochennec    schedule 06.09.2018
comment
Очень возможно. Python действительно перечисляет мою версию OpenSSL как 'OpenSSL 1.0.2d 9 Jul 2015'. Но даже после установки версии 1.0.2p и версии 1.1.0i и обновления нескольких переменных среды Python их не распознает; он по-прежнему дает версию 1.0.2d. Есть идеи, как я могу это исправить? Любой ответ, который я могу найти, говорит об OS X и варке, не очень мне полезен.   -  person Cycloneblaze    schedule 06.09.2018
comment
В конце концов я обновил сам python до 3.6.6. Теперь моя установка OpenSSL сообщается как 'OpenSSL 1.0.2o 27 Mar 2018', что должно быть достаточно новым. Но исходная ошибка SSL все еще происходит таким же образом, поэтому я думаю, что мы можем исключить версию OpenSSL как причину.   -  person Cycloneblaze    schedule 07.09.2018


Ответы (1)


Я понял! TL;DR: мой антивирус выполнял некоторую фильтрацию HTTPS/TLS.

Я просмотрел ответ что @Juilen Cochennec снова ссылается в своем комментарии и заметил, что он предлагает использовать openssl непосредственно из командной строки, чтобы проверить, какая цепочка сертификатов на самом деле возвращается.

Так что я побежал

openssl s_client -showcerts -connect googleapis.com:443

и я не получил ожидаемую цепочку сертификатов; первый промежуточный сертификат был выпущен не Google, а Bullguard. Это было

i:/C=GB/ST=Hounslow/L=Heathrow/O=BullGuard Ltd./OU=DevelTeam/CN=BullGuard SSL Proxy CA 

Bullguard — это название моего антивируса, поэтому я подозревал, что он каким-то образом блокирует мои запросы. После некоторых исследований я нашел точную причину , а именно, функция безопасного просмотра Bullguard. Он сканирует веб-сайты и блокирует их, если считает их небезопасными.

Подмножеством этого являются безопасные результаты, которые показывают галочки (или X) рядом с результатами в поисковых системах, таких как Google. Похоже, для этого используется фильтрация HTTPS/TLS; он вставляется между вами и вашими результатами поиска, чтобы он мог изменить страницу с помощью галочек. Глядя сейчас, это даже не было безопасно в Firefox; галочки не отображаются, поскольку он не может получить результаты безопасного просмотра.

В результате эта фильтрация вызывала ошибки SSL во всех доменах Google, что приводило к сбою запросов. Чтобы исправить все, что мне нужно было сделать, это отключить безопасные результаты для Google; даже не сам безопасный просмотр, а только безопасные результаты. Это отключило фильтрацию, и теперь мои запросы снова работают.

Я надеюсь, что это поможет кому-то еще с этой проблемой!

P.S. Я нашел эту информацию полезной, чтобы увидеть, что цепочка SSL-сертификатов предполагалась< /em> to be, что помогло мне понять, что это неправильно.

person Cycloneblaze    schedule 08.09.2018