【问题标题】:using requests with TLS doesn't give SNI support使用带有 TLS 的请求不会提供 SNI 支持
【发布时间】:2013-09-05 20:54:07
【问题描述】:

我正在使用请求与 django 应用程序进行通信,但是

当我尝试时

requests.get('https://mysite.com', verify=True)

我得到错误:

主机名“mysite.com”与“*.myhost.com”、“myhost.com”中的任何一个都不匹配

但是,当我查看浏览器或http://www.digicert.com/help/ 时,证书看起来不错。

我的主人认为这是由于请求缺乏 SNI 支持(Github 似乎证实了这一点 https://github.com/kennethreitz/requests/issues/749 )。有没有人找到使用请求的解决方法?

【问题讨论】:

  • 我编辑了 Lukasa 答案(正确的答案),以便在您无法使用最新的 github 版本的情况下,在较旧的请求中支持 SNI。请确保您的系统中安装了所需的依赖项(不仅是 python 依赖项,还有 openssl)。编辑审核后将可用 :)
  • 我认为最好创建一个新答案,而不是在某人的帖子中进行重新编辑
  • 嗯,他的回答是正确的,所以我认为对于另一种情况有另一个答案并不好,我个人真的更喜欢一个包含所有信息的答案。但我会发布另一个答案。
  • 很好奇,你用什么操作系统来测试这个?使用 Ubuntu Precise 打 SNI 主机对我有用,但对 Lucid 无效,我不知道为什么。 stackoverflow.com/questions/24522757/…

标签: python ssl ssl-certificate python-requests sni


【解决方案1】:

当前版本的 Requests 应该可以使用 SNI。 Further down the GitHub issue可以看需求:

尝试安装这些软件包,然后再试一次。

编辑:从 Requests v2.12.1 开始,不再需要 ndg-httpsclient 和 pyasn1。所需软件包的完整列表现在是:

【讨论】:

  • 谢谢。我还看到了这个拉取请求github.com/kennethreitz/requests/pull/1347,它与安装 urllib3、ndg-httpsclient 和 pyasn1 一起解决了它。
  • @qarma 提到的 bug 正在被 issue 1732 跟踪,并且已经在 master 中修复。
  • 此修复仍然有效吗?我得到[Errno bad handshake] [('SSL routines', 'SSL3_GET_SERVER_CERTIFICATE', 'certificate verify failed')]
  • 此修复程序绝对仍然有效。证书似乎无效。
  • 请注意,您的答案在页面末尾的this FAQ 中引用。
【解决方案2】:

为了让我得到公认的答案,我必须按以下顺序安装一堆其他软件包:

  • yum 安装 libffi-devel
  • yum 安装 gcc
  • yum install openssl-devel
  • 点安装 urllib3
  • pip install pyopenssl
  • pip install ndg-httpsclient
  • pip install pyasn1

【讨论】:

  • 我还必须安装:yum install python-devel,然后再进行 pip 安装..
  • 实际上,对我来说,ndg-httpsclient 安装了除 urllib3 之外的所有这些 python 包。但是请注意获取最新版本的 pip,否则它将无法正常工作..
  • @ihue 几年前需要这些安装来解决标准库中的 Python SSL 模块不支持 SNI 的事实。现在不再是这种情况了,使用最新版本的 Python 2 或 3 不需要这些额外的安装。
【解决方案3】:

像这样安装请求模块。这将安装额外的安全包。

pip install requests[security]

【讨论】:

  • 当心,这现在需要 setuptools-rust 和 rust 支持。
【解决方案4】:

或者您可以只使用 Python 2.7.9 及更高版本:

“Python 3.4 的全部 ssl 模块已向后移植到 Python 2.7.9。有关理由,请参见 PEP 466。”

https://www.python.org/downloads/release/python-279/

【讨论】:

  • 我不断收到requests.exceptions.SSLError: [SSL: SSLV3_ALERT_HANDSHAKE_FAILURE] sslv3 alert handshake failure (_ssl.c:590),我收到了Python 2.7.10
【解决方案5】:

@Lukasa 对当前(来自 github)请求的回答是正确的。除了他提到的 pip 依赖项之外,请记住在您的系统中添加 OpenSSL。

如果出于部署原因,您更喜欢 pip 中的 1.2.3 之类的稳定请求版本,您可以修改该版本以使用 SNI,如下所示:

import requests


def fileno(self):
    return self.socket.fileno()


def close(self):
    return self.connection.shutdown()


requests.pyopenssl.WrappedSocket.close = close
requests.pyopenssl.WrappedSocket.fileno = fileno

【讨论】:

    【解决方案6】:

    Accessing https sites with IP address复制我的答案

    在 MAC High Sierra 和 Python 3.6.4 上,我尝试了解决方案:requests toolbelt:HostHeaderSSLAdapter 1st,不幸的是,它对我不起作用,然后我尝试了 forcediphttpsadapter,终于成功了。

    作者在自述文件部分解释了所有内容,并提供了一个示例脚本,可以轻松遵循。

    1.pip install requests[security] forcediphttpsadapter安装库

    2.运行示例脚本:

    import requests
    from forcediphttpsadapter.adapters import ForcedIPHTTPSAdapter
    session = requests.Session()
    session.mount("https://example.com", ForcedIPHTTPSAdapter(dest_ip='1.2.3.4'))
    response = session.get(
        '/some/path', headers={'Host': 'example.com'}, verify=False)
    

    注意:在某些情况下,您可能需要从 url 中删除前缀:'www'。

    【讨论】:

      猜你喜欢
      • 2017-01-03
      • 2015-12-23
      • 1970-01-01
      • 1970-01-01
      • 2020-06-14
      • 2017-06-12
      • 1970-01-01
      • 1970-01-01
      • 2011-02-17
      相关资源
      最近更新 更多