禁用Twisted Agents的SSL证书检查

4

我正在使用Twisted (16.3)和Treq (15.1)在Python (2.7)中进行异步请求。

我在使用HTTPS时遇到了一些问题。

某些网站有无效的证书,因此当我向它们发出请求时,会得到以下结果:

twisted.python.failure.Failure OpenSSL.SSL.Error

我希望我的客户端信任任何服务器,包括那些没有证书或使用自签名证书的服务器。

我该如何在客户端上禁用证书检查?

这个问题与我的问题基本相同:https://stackoverflow.com/questions/34357439/ssl-options-for-twisted-agents

谢谢!

2个回答

6

2019年2月7日更新

这是一个简单的方法,用于为treq创建域名白名单。

from treq.client import HTTPClient
from twisted.web.iweb import IPolicyForHTTPS
from twisted.web.client import BrowserLikePolicyForHTTPS, Agent
from twisted.internet.ssl import CertificateOptions
from twisted.internet import task, defer, ssl
from zope.interface import implementer

@implementer(IPolicyForHTTPS)
class WhitelistContextFactory(object):
    def __init__(self, good_domains=None):
        """
        :param good_domains: List of domains. The URLs must be in bytes
        """
        if not good_domains:
            self.good_domains = []
        else:
            self.good_domains = good_domains

        # by default, handle requests like a browser would
        self.default_policy = BrowserLikePolicyForHTTPS()

    def creatorForNetloc(self, hostname, port):
        # check if the hostname is in the the whitelist, otherwise return the default policy
        if hostname in self.good_domains:
            return ssl.CertificateOptions(verify=False)
        return self.default_policy.creatorForNetloc(hostname, port)

@task.react
@defer.inlineCallbacks
def main(reactor):
    # make a custom client, agent, and context factory
    # NOTE: WhitelistContextFactory() takes a list of BYTES
    treq = HTTPClient(Agent(reactor, contextFactory=WhitelistContextFactory([b'example.net'])))
    response = yield treq.get('https://example.net/version')
    content = yield response.content()
    print(content)

WhitelistContextFactory接受一个URLs列表(用bytes表示),并检查hostname是否在列表中以忽略TLS验证。您还可以使用正则表达式等高级技术。感谢https://github.com/twisted/treq/issues/213

不要这样做!

我最近几天也一直尝试着去做这件事。为了规避证书验证所付出的努力,我本可以更容易地创建一对密钥并继续我的工作:D。我在treq问题列表中发现了这个评论,通过代码修改解决了这个问题:

from twisted.internet import _sslverify
_sslverify.platformTrust = lambda : None

我相信有一种复杂的方法可以“正确”地完成它,但在我看来,这不值得努力。我做了一个补丁,这样它就不会覆盖platformTrust(),我会尝试将其合并,但我不会过分乐观。从我看到的一些与信任根、ssl和证书有关的错误评论的语气来看,我不认为它会被合并。希望这可以帮到您。

嗨!谢谢你的回答!我也看到了那个评论,但它并没有帮助我。我正在使用代理来发送请求,从 twisted.web.client import Agent。我猜测代码 _sslverify.platformTrust = lambda : None 特别是覆盖了 platformTrust 以不执行任何操作。你知道吗,这适用于代理吗?如果使用代理,是否还有其他需要更改的内容? - mayk93
这个问题困扰了我将近一天的时间。我简直无法相信 Python / Twisted 在处理生产/开发场景下的证书验证方面有多么糟糕 - 是不是 Python 社区的每个人都在使用真正的证书,或者污染他们的机器与自己的 CA,或者根本没有测试 SSL/TLS? - jmc
我完全同意!有几个treq的开发人员正在开发“白名单”功能,允许选择的站点不经过验证就可以通过。希望它很快推出。 - notorious.no
很高兴知道白名单功能即将推出。老实说,至少对于我的项目来说,我发现转向Python3.5的aiohttp要容易得多。在我看来,它以更优雅的方式提供了异步请求,相比Twisted,提供了SSL证书处理和更简便的代理操作方法,只是其中一些方面。当然,这涉及一些重写,但从长远来看是值得的。 - mayk93
诚实没有错 :) 只是提醒一下,tornado 也可以很好地与 twisted 集成。你可以使用 tornado 的 "AsyncHTTPClient.fetch()",然后将事件循环与 twisted 集成。"asyncio" 集成也即将推出。这样你就不必重写太多代码了。 - notorious.no

1

如果你想要完全地忽略SSL检查,这里有一个解决方法:

from twisted.internet import ssl, _sslverify
from twisted.web.iweb import IPolicyForHTTPS

@implementer(IPolicyForHTTPS)
class IgnoreHTTPS:
    def creatorForNetloc(self, hostname, port):
        options = ssl.CertificateOptions(verify=False)
        return _sslverify.ClientTLSOptions(hostname.decode('ascii'), options.getContext())

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接