Python - requests.exceptions.SSLError - dh键太小

Feo*_*cco 13 python ssl python-requests

我正在使用Python和请求抓取一些内部页面.我已经关闭了SSL验证和警告.

requests.packages.urllib3.disable_warnings()
page = requests.get(url, verify=False)
Run Code Online (Sandbox Code Playgroud)

在某些服务器上,我收到一个SSL错误,我无法通过.

Traceback (most recent call last):
  File "scraper.py", line 6, in <module>
    page = requests.get(url, verify=False)
  File "/cygdrive/c/Users/jfeocco/VirtualEnv/scraping/lib/python3.4/site-packages/requests/api.py", line 71, in get
    return request('get', url, params=params, **kwargs)
  File "/cygdrive/c/Users/jfeocco/VirtualEnv/scraping/lib/python3.4/site-packages/requests/api.py", line 57, in request
    return session.request(method=method, url=url, **kwargs)
  File "/cygdrive/c/Users/jfeocco/VirtualEnv/scraping/lib/python3.4/site-packages/requests/sessions.py", line 475, in request
    resp = self.send(prep, **send_kwargs)
  File "/cygdrive/c/Users/jfeocco/VirtualEnv/scraping/lib/python3.4/site-packages/requests/sessions.py", line 585, in send
    r = adapter.send(request, **kwargs)
  File "/cygdrive/c/Users/jfeocco/VirtualEnv/scraping/lib/python3.4/site-packages/requests/adapters.py", line 477, in send
    raise SSLError(e, request=request)
requests.exceptions.SSLError: [SSL: SSL_NEGATIVE_LENGTH] dh key too small (_ssl.c:600)
Run Code Online (Sandbox Code Playgroud)

这种情况发生在Cygwin的内部/外部,Windows和OSX中.我的研究暗示了服务器上过时的OpenSSL.我正在寻找一个理想的修复客户端.

编辑:我能够通过使用密码集来解决这个问题

import requests

requests.packages.urllib3.util.ssl_.DEFAULT_CIPHERS += 'HIGH:!DH:!aNULL'
try:
    requests.packages.urllib3.contrib.pyopenssl.DEFAULT_SSL_CIPHER_LIST += 'HIGH:!DH:!aNULL'
except AttributeError:
    # no pyopenssl support used / needed / available
    pass

page = requests.get(url, verify=False)
Run Code Online (Sandbox Code Playgroud)

小智 10

我遇到过同样的问题。

它是通过评论修复的

CipherString = DEFAULT@SECLEVEL=2
Run Code Online (Sandbox Code Playgroud)

线在/etc/ssl/openssl.cnf


bgo*_*man 10

这也对我有用:

import requests
import urllib3
requests.packages.urllib3.util.ssl_.DEFAULT_CIPHERS = 'ALL:@SECLEVEL=1'
Run Code Online (Sandbox Code Playgroud)

openssl SECLEVELs 文档:https ://www.openssl.org/docs/manmaster/man3/SSL_CTX_set_security_level.html

SECLEVEL=2 是现在的 openssl 默认值,(至少在我的设置中:ubuntu 20.04,openssl 1.1.1f);SECLEVEL=1 降低了标准。

安全级别旨在避免修改单个密码的复杂性。

我相信我们中的大多数人都没有对个人密码的安全强度/弱点有深入的了解,我当然没有。安全级别似乎是一种很好的方法,可以控制您打开安全门的距离。

注意:我得到了一个不同的 SSL 错误,WRONG_SIGNATURE_TYPE 而不是 SSL_NEGATIVE_LENGTH,但根本问题是相同的。

错误:

Traceback (most recent call last):
  [...]
  File "/usr/lib/python3/dist-packages/requests/sessions.py", line 581, in post
    return self.request('POST', url, data=data, json=json, **kwargs)
  File "/usr/lib/python3/dist-packages/requests/sessions.py", line 533, in request
    resp = self.send(prep, **send_kwargs)
  File "/usr/lib/python3/dist-packages/requests/sessions.py", line 646, in send
    r = adapter.send(request, **kwargs)
  File "/usr/lib/python3/dist-packages/requests/adapters.py", line 514, in send
    raise SSLError(e, request=request)
requests.exceptions.SSLError: HTTPSConnectionPool(host='somehost.com', port=443): Max retries exceeded with url: myurl (Caused by SSLError(SSLError(1, '[SSL: WRONG_SIGNATURE_TYPE] wrong signature type (_ssl.c:1108)')))
Run Code Online (Sandbox Code Playgroud)


Lar*_*Cai 9

这不是额外的答案,只需尝试将问题的解决方案代码与额外的信息结合起来,这样其他人就可以直接复制它而无需额外的尝试

这不仅是服务器端的DH密钥问题,而且python模块中还有许多不同的库不匹配。

下面的代码段用于忽略这些安全问题,因为它可能无法在服务器端解决。例如,如果它是内部旧式服务器,则没人愿意对其进行更新。

除了的hacked字符串外'HIGH:!DH:!aNULL',还可以导入urllib3模块以禁用警告

import requests
import urllib3

requests.packages.urllib3.disable_warnings()
requests.packages.urllib3.util.ssl_.DEFAULT_CIPHERS += 'HIGH:!DH:!aNULL'
try:
    requests.packages.urllib3.contrib.pyopenssl.DEFAULT_SSL_CIPHER_LIST += 'HIGH:!DH:!aNULL'
except AttributeError:
    # no pyopenssl support used / needed / available
    pass

page = requests.get(url, verify=False)
Run Code Online (Sandbox Code Playgroud)

  • 如果您直接与套接字交互,则可以通过上下文设置这些密码(在 Python 3.2+ 和 2.7.9+ 中): `context.set_ciphers('HIGH:!DH:!aNULL')` (2认同)
  • 您通过此评论挽救了一家企业..我们用于付款的银行弄乱了他们的 SSL,这暂时挽救了这一天..给我们足够的时间进行更改并与另一家银行合作 (2认同)

Rob*_*per 8

从 的版本 2urllib3或 2.30 版本开始requests,该DEFAULT_CIPHERS属性已被删除,并且此处提出的大多数解决方案不再有效。相反,您必须创建一个SSLContext

from urllib3.util import create_urllib3_context
from urllib3 import PoolManager

ctx = create_urllib3_context(ciphers=":HIGH:!DH:!aNULL")
http = PoolManager(ssl_context=ctx)
http.request("GET", ...)
Run Code Online (Sandbox Code Playgroud)

如果您正在使用,requests则必须对您自己的HTTPAdapter子类进行初始化PoolManager,并将其安装到 a 中Session

from urllib3.util import create_urllib3_context
from urllib3 import PoolManager
from requests.adapters import HTTPAdapter
from requests import Session

class AddedCipherAdapter(HTTPAdapter):
  def init_poolmanager(self, connections, maxsize, block=False):
    ctx = create_urllib3_context(ciphers=":HIGH:!DH:!aNULL")
    self.poolmanager = PoolManager(
      num_pools=connections,
      maxsize=maxsize,
      block=block,
      ssl_context=ctx
    )

s = Session()
s.mount("https://example.org", AddedCipherAdapter())
s.get("https://example.org/path")
Run Code Online (Sandbox Code Playgroud)

此方法的优点是其范围仅限于受影响的服务器(此处)https://example.org


Ste*_*ich 5

禁用警告或证书验证将无济于事。根本的问题是服务器使用的DH密钥较弱,可能会在Logjam Attack中被滥用。

要解决此问题,您需要选择一种不使用Diffie Hellman密钥交换且因此不受弱DH密钥影响的密码。并且该密码必须由服务器支持。服务器支持什么是未知的,但您可以尝试使用以下密码AES128-SHA或一组密码HIGH:!DH:!aNULL

使用带有自己的密码集的请求非常棘手。请参阅为什么Python请求忽略了verify参数?举个例子