Windows上针对Azure服务pipe理API的Python HTTPS失败

我最近为Windows Azure存储API(PyAzure)扩展了Python API,以包含对服务pipe理API的支持。 见https://github.com/bmb/pyazure 。

我正在使用一个HTTPSClientAuthHandler,就像使用pyOpenSSL创buildurllib自定义开启器一样 。 在Linux上,使用各种版本的Python 2.6和2.7,这很好。 不过,Windows是另一回事。 针对Azurepipe理主机地址的所有请求都会失败:

[Errno 10054]现有连接被远程主机强制closures

我认为,是socketserrno 10054“连接重置由对等”,在拖动。

这似乎不是我的API代码中的问题(除非我使用的客户端证书authentication方法是虚假的),但是更低一层。 我可以在不使用urllib2或httplib的情况下通过简单地设置一个SSL套接字并向urllib2发送相同的HTTP请求,例如列出有效的Azure数据中心位置来重现问题:

>>> import socket, ssl, sys >>> sys.version '2.7.1 (r271:86832, Nov 27 2010, 17:19:03) [MSC v.1500 64 bit (AMD64)]' >>> s = ssl.wrap_socket(socket.socket(), certfile='c:\\users\\blair\\research\\clouds\\azure\\BlairBethwaiteAzure1.pfx.pem') >>> s.connect(('management.core.windows.net',443)) >>> s.send("GET /SUBSCRIPTION_ID/locations HTTP/1.1\r\nAccept-Encoding: identity\r\nX-Ms-Version: 2011-10-01\r\nHost: management.core.windows.net\r\nConnection: close\r\nUser-Agent: Python-urllib/2.6\r\n\r\n") 202 >>> s.read() Traceback (most recent call last): c:\Users\blair\research\clouds\azure\pyazure\<ipython-input-63-3306c981d8a7> in <module>() ----> 1 s.read() C:\Python27\lib\ssl.pyc in read(self, len) 136 137 try: --> 138 return self._sslobj.read(len) 139 except SSLError, x: 140 if x.args[0] == SSL_ERROR_EOF and self.suppress_ragged_eofs: error: [Errno 10054] An existing connection was forcibly closed by the remote host 

用您的Azure订阅IDreplace上面的SUBSCRIPTION_ID。 调用SSLSocket.read之后,exception提升〜45s。 证书是一个格式正确的PEM文件,包括私钥和证书,它是从pfx(在Ubuntu 10.04中)转换的,使用:

openssl pkcs12 -in pfxfile -out pemfile -nodes

我认为这不重要,但是我也尝试了unix2dos-PEM文件,但是没有成功。 即使我没有提供任何证书,我也会得到相同的行为,但是在Linux上这样做会导致服务器出现适当的API错误:

'HTTP / 1.1 403 Forbidden \ r \ nContent-Length:0 \ r \ nServer:Microsoft-HTTPAPI / 2.0 \ r \ nDate:Thu,01 Dec 2011 13:59:29 GMT \ r \ nConnection:close \ r \ n \ r \ N”

这已经被另一个使用Windows 7的人独立validation(和我一样)。 这不是客户端的防火墙问题 – 相同的代码在同一主机上运行的NAT-Linux VM中工作。

我很难过 真的很感激任何帮助这里的人可能能够提供…

更新:这似乎与Python中的底层SSL实现有关。 CPython 2.7.1具有如上所示的错误行为,但是我已经testing并且已经成功使用了ActiveState Python(2.7和2.6),例如:

 >>> import sys, socket, ssl >>> sys.version '2.7.1 (r271:86832, Feb 7 2011, 11:30:38) [MSC v.1500 32 bit (Intel)]' >>> s = ssl.wrap_socket(socket.socket(), certfile='\\\\VBOXSVR\\azure\\BlairBethwaiteAzure1.pfx.pem') >>> s.connect(('management.core.windows.net',443)) >>> s.send('GET /SUBSCRIPTION_ID/locations HTTP/1.1\r\nAccept-Encoding: identity\r\nX-Ms-Version: 2011-10-01\r\nHost: management.core.windows.net\r\nUser-Agent: Python-urllib/2.6\r\n\r\n') 183 >>> s.read(4096) 'HTTP/1.1 200 OK\r\nContent-Length: 908\r\nContent-Type: application/xml; charset=utf-8\r\nServer: Microsoft-HTTPAPI/2.0\r\nx-ms-request-id: 08ca048cda6b445da6b3a8f3e4890197\r\nDate: Fri, 02 Dec 2011 03:02:14 GMT\r\n\r\n<Locations xmlns="http://schemas.microsoft.com/windowsazure" xmlns:i="http://www.w3.org/2001/XMLSchema-instance"><Location><Name>Anywhere US</Name><DisplayName>Anywhere US</DisplayName></Location><Location><Name>South Central US</Name><DisplayName>South Central US</DisplayName></Location><Location><Name>North Central US</Name><DisplayName>North Central US</DisplayName></Location><Location><Name>Anywhere Europe</Name><DisplayName>Anywhere Europe</DisplayName></Location><Location><Name>North Europe</Name><DisplayName>North Europe</DisplayName></Location><Location><Name>West Europe</Name><DisplayName>West Europe</DisplayName></Location><Location><Name>Anywhere Asia</Name><DisplayName>Anywhere Asia</DisplayName></Location><Location><Name>Southeast Asia</Name><DisplayName>Southeast Asia</DisplayName></Location><Location><Name>East Asia</Name><DisplayName>East Asia</DisplayName></Location></Locations>' 

正如所料,我的API也是如此:

 ActivePython 2.6.7.20 (ActiveState Software Inc.) based on Python 2.6.7 (r267:88850, Jun 27 2011, 13:20:48) [MSC v.1500 64 bit (AMD64)] on win32 Type "help", "copyright", "credits" or "license" for more information. >>> from pyazure import pyazure >>> pa = pyazure.PyAzure(subscription_id=SUBSCRIPTION_ID, management_cert_path='c:\\users\\blair\\research\\clouds\\azure\\BlairBethwaiteAzure1.pfx.pem') >>> list(pa.wasm.list_locations()) ['Anywhere US', 'South Central US', 'North Central US', 'Anywhere Europe', 'North Europe', 'West Europe', 'Anywhere Asia', 'Southeast Asia', 'East Asia'] 

CPython2.7和ActivePython2.7中的Lib \ ssl.py文件是相同的,所以我想这一定是由于底层C库的一些不同,也许是CPython中的一个错误。 那里有哪位高手?

我一直无法确定这个决定性的解释,但经过一些反复试验,我相信问题的出现在哪里。

简短的回答:这是http://www.python.org/ Windows软件包中的ssl实现。 改用ActiveState Python。

长答案:从http://www.python.org/download/下载的Windows CPython发行版相当于旧版本的OpenSSL(0.9.8l),与基于CPython的ActiveState Python发行版相比, )定期更新OpenSSL等第三方内容(目前为0.9.8r)。

我下载了OpenSSL的Windows二进制文件,并通过openssl s_client接口进行测试,例如:

openssl s_client -connect management.core.windows.net:443 -cert /home/blair/nimrod-dev/BlairBethwaiteAzure1.pfx.pem

正如预期的那样,当前版本正常工作 不幸的是,在Windows上使用旧的OpenSSL二进制文件似乎很难,因为它是一个安全库,可能并不奇怪…但是无论如何,我在Ubuntu 10.04下从源代码创建了0.9.8l,发现它在发送HTTP请求后挂起下来管道,大概是服务器由于某种原因悄悄地丢弃了连接:

 blair@venus-vm:~/Downloads/openssl-0.9.8l/apps$ ./openssl s_client -connect management.core.windows.net:443 -cert ./BlairAzure.pem CONNECTED(00000003) depth=2 /CN=Microsoft Internet Authority verify error:num=20:unable to get local issuer certificate verify return:0 --- Certificate chain 0 s:/CN=management.core.windows.net i:/DC=com/DC=microsoft/DC=corp/DC=redmond/CN=Microsoft Secure server Authority 1 s:/DC=com/DC=microsoft/DC=corp/DC=redmond/CN=Microsoft Secure server Authority i:/CN=Microsoft Internet Authority 2 s:/CN=Microsoft Internet Authority i:/C=US/O=GTE Corporation/OU=GTE CyberTrust Solutions, Inc./CN=GTE CyberTrust Global Root --- server certificate -----BEGIN CERTIFICATE----- MIIGhDCCBWygAwIBAgIKFnL3ogAIAAIjlDANBgkqhkiG9w0BAQUFADCBizETMBEG CgmSJomT8ixkARkWA2NvbTEZMBcGCgmSJomT8ixkARkWCW1pY3Jvc29mdDEUMBIG CgmSJomT8ixkARkWBGNvcnAxFzAVBgoJkiaJk/IsZAEZFgdyZWRtb25kMSowKAYD VQQDEyFNaWNyb3NvZnQgU2VjdXJlIFNlcnZlciBBdXRob3JpdHkwHhcNMTEwNjE2 MDg0MjI3WhcNMTMwNjE1MDg0MjI3WjAmMSQwIgYDVQQDExttYW5hZ2VtZW50LmNv cmUud2luZG93cy5uZXQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCS Z9PTUqQLh5keX/IRJ6JxaQkVBIy/iyoCIx2Y0zy5F5tll8CRydGzFDjXMLWEG425 EuuRDQrBgQnmVtlZ2t42QfIRBSvfJheZVh8k27g/tH5wpchZ47gxxatUKsVJ84P8 Me2S0RP9xtk3P14dVqTDJIhUC3k8JYdBiTTtk64EB5Dbq8sxEtjVb/68XDgTZKek te/vqWSW/KcduKEjsfjOwNSM9UbYrFOTbelac+mf/L+CluAJpYAlIhOMUP2afy5e tYIg6zK04pDNjPjizpfN3xrGX7NRY16kaafrdqJQixfmEVlMDN8FsXLWDweXWfMM XRh4vuAVb6tA9wBkPDhZAgMBAAGjggNMMIIDSDALBgNVHQ8EBAMCBLAwHQYDVR0l BBYwFAYIKwYBBQUHAwIGCCsGAQUFBwMBMHgGCSqGSIb3DQEJDwRrMGkwDgYIKoZI hvcNAwICAgCAMA4GCCqGSIb3DQMEAgIAgDALBglghkgBZQMEASowCwYJYIZIAWUD BAEtMAsGCWCGSAFlAwQBAjALBglghkgBZQMEAQUwBwYFKw4DAgcwCgYIKoZIhvcN AwcwHQYDVR0OBBYEFEaKqx6Auvu3fvHS6KqQl8KXoOoAMB8GA1UdIwQYMBaAFAhC 49tOEWbztQjFQNtVfDNGEYM4MIIBCgYDVR0fBIIBATCB/jCB+6CB+KCB9YZYaHR0 cDovL21zY3JsLm1pY3Jvc29mdC5jb20vcGtpL21zY29ycC9jcmwvTWljcm9zb2Z0 JTIwU2VjdXJlJTIwU2VydmVyJTIwQXV0aG9yaXR5KDgpLmNybIZWaHR0cDovL2Ny bC5taWNyb3NvZnQuY29tL3BraS9tc2NvcnAvY3JsL01pY3Jvc29mdCUyMFNlY3Vy ZSUyMFNlcnZlciUyMEF1dGhvcml0eSg4KS5jcmyGQWh0dHA6Ly9jb3JwcGtpL2Ny bC9NaWNyb3NvZnQlMjBTZWN1cmUlMjBTZXJ2ZXIlMjBBdXRob3JpdHkoOCkuY3Js MIG/BggrBgEFBQcBAQSBsjCBrzBeBggrBgEFBQcwAoZSaHR0cDovL3d3dy5taWNy b3NvZnQuY29tL3BraS9tc2NvcnAvTWljcm9zb2Z0JTIwU2VjdXJlJTIwU2VydmVy JTIwQXV0aG9yaXR5KDgpLmNydDBNBggrBgEFBQcwAoZBaHR0cDovL2NvcnBwa2kv YWlhL01pY3Jvc29mdCUyMFNlY3VyZSUyMFNlcnZlciUyMEF1dGhvcml0eSg4KS5j cnQwPwYJKwYBBAGCNxUHBDIwMAYoKwYBBAGCNxUIg8+JTa3yAoWhnwyC+sp9geH7 dIFPg8LthQiOqdKFYwIBZAIBCjAnBgkrBgEEAYI3FQoEGjAYMAoGCCsGAQUFBwMC MAoGCCsGAQUFBwMBMCYGA1UdEQQfMB2CG21hbmFnZW1lbnQuY29yZS53aW5kb3dz Lm5ldDANBgkqhkiG9w0BAQUFAAOCAQEAsqHBR/JxRnGQMTXxJzCau49dDgeum1JH heA38lzsoUaRELHxxrQZskjSqc0HrI7cnJPSipWQseDDwKtLwXzukCdZNk84u7xo uHa7/dmxo1m+z353HSvEr85ZE2mzwF6qmwGMmvvVzIJ94M8fcN55yoF64vQsAWFF k2QJC9ccb8eDoTs5NX4ntpz02xf8eEBQ5yKZySfi3+oFJEUnLmXcvHTTMl/1N/NI fWiKIZ9PDTBlPxL5kNJ/aDGIgiqCi7Vm7KfjvWSFhopUPtVeeItgW9wMLEkuQsw6 sViSbU50CMPWTJAslLZgCju6cxszgpLl19xrgNteHRw2HouwTTsJnA== -----END CERTIFICATE----- subject=/CN=management.core.windows.net issuer=/DC=com/DC=microsoft/DC=corp/DC=redmond/CN=Microsoft Secure server Authority --- No client certificate CA names sent --- SSL handshake has read 4691 bytes and written 450 bytes --- New, TLSv1/SSLv3, Cipher is AES128-SHA server public key is 2048 bit Compression: NONE Expansion: NONE SSL-Session: Protocol : TLSv1 Cipher : AES128-SHA Session-ID: <SNIP> Session-ID-ctx: Master-Key: <SNIP> Key-Arg : None Start Time: 1324443511 Timeout : 300 (sec) Verify return code: 20 (unable to get local issuer certificate) --- GET /<SUBSCRIPTION_ID>/locations HTTP/1.1 Accept-Encoding: identity X-Ms-Version: 2011-10-01 Host: management.core.windows.net Connection: close 

在较新的甚至稍微老一些(例如,Ubuntu10.04的0.9.8e)的OpenSSLs服务器响应请求与预期:

 <Locations xmlns="http://schemas.microsoft.com/windowsazure" xmlns:i="http://www.w3.org/2001/XMLSchema-instance"><Location><Name>Anywhere US</Name><DisplayName>Anywhere US</DisplayName></Location><Location><Name>South Central US</Name><DisplayName>South Central US</DisplayName></Location><Location><Name>Anywhere Europe</Name><DisplayName>Anywhere Europe</DisplayName></Location><Location><Name>West Europe</Name><DisplayName>West Europe</DisplayName></Location><Location><Name>Anywhere Asia</Name><DisplayName>Anywhere Asia</DisplayName></Location><Location><Name>Southeast Asia</Name><DisplayName>Southeast Asia</DisplayName></Location><Location><Name>East Asia</Name><DisplayName>East Asia</DisplayName></Location><Location><Name>North Central US</Name><DisplayName>North Central US</DisplayName></Location><Location><Name>North Europe</Name><DisplayName>North Europe</DisplayName></Location></Locations> 

但是对于OpenSSL 0.9.8l,我什么也得不到。

以下方式按照预期在Windows 7上使用IronPython 2.7.1和在OS X 10.6.8上使用CPython 2.6.6:

 import socket, ssl, sys sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.connect(('management.core.windows.net',443)) s = ssl.wrap_socket(sock, certfile=sys.argv[1]) s.send('GET /SUBSCRIPTION_ID/locations HTTP/1.1\r\nAccept-Encoding: identity\r\nX-Ms-Version: 2011-10-01\r\nHost: management.core.windows.net\r\nUser-Agent: Python-urllib/2.6\r\n\r\n') print(s.read(4096)) 

[注:我传递MYKEYFILENAME.pem作为命令行参数。]

快乐天青黑客!

我不是Python开发人员,但是在处理来自iPhone和Windows Phone的Azure服务时遇到了很多问题。请确保以下内容