Python请求SSL主机名与错误不匹配

时间:2015-10-30 05:46:38

标签: python ssl curl python-requests

我一直在尝试使用python请求库来访问使用SSL保护的API,如下所示

requests.get('https://path/to/url',cert=('cert.pem','key.pem'),verify='ca.pem')

但是收到错误

File "/usr/lib/python2.7/dist-packages/requests/adapters.py", line 385, in send
raise SSLError(e)
requests.exceptions.SSLError: hostname '10.10.10.10' doesn't match u'*' # IP address is not real.

如果我的理解是正确的,这个证书可以用于任何服务器,因为它们以'*'作为域签名。

我猜请求库正在严格匹配主机名验证而不是正则表达式匹配。

所以我的问题是它是否是请求库的错误,或者这是缩进工作的方式?

当我使用下面给出的curl命令时,它工作正常。

curl https://path/to/url  --cert cert.pem  --key key.pem --cacert ca.pem

所以我有两种可能性,卷曲库不执行主机名验证,或者他们正在使用正则表达式。

我在哪里错了?期待详细的答案

2 个答案:

答案 0 :(得分:2)

RFC 2818中描述了如何匹配通配符,RFC 6125中更准确地说明了这些通配符,CAB baseline requirements中也有信息。最后,浏览器实现以下内容:

  • 只有最左边的标签可以有一个通配符,而通配符只能匹配一个标签。这不是**.*.example.com等通配符。 *.example.com匹配www.example.com但不匹配sub.www.example.comexample.com
  • 此外还有一些限制,具体取决于公钥后缀,即没有浏览器允许*.com使用通配符,有些不允许*.co.uk使用通配符。
  • 并且通配符可以在证书中有限制。所有都支持主题备用名称部分中的通配符,但并非所有通配名都允许使用通配符。
  • 除了通配符仅用于主机名。这意味着不允许IP地址与通配符条目匹配。要将IP地址包含在证书中,您必须使用iPAdress作为主题备用名称(除IE之外的所有浏览器)或dNSName(除IE之外没有浏览器)或IP地址必须在CN(除Safari之外的所有浏览器)。 / LI>

像python这样的几种语言过去根本没有对主机名进行任何检查,但2.7.9 python默认情况下也会检查主机名,并且其实现与浏览器的内容大致兼容。

至于curl:它取决于你使用的卷曲版本。 7.36应该没问题,但旧版本有flaws in the validation

答案 1 :(得分:0)

没有关于如何在证书中解释通配符的真实,批准的标准。无论它们是匹配一个标签还是多个标签,它们是否匹配ips(SAN扩展中的标签肯定不是),是否可以匹配标签的一部分(prefix-*.example.com)等都不是很好定义

我建议不要在其上使用*,而只能使用一个完整标签(*.example.com)。并且不要将它用于IP,只是名称。