wrap_socket()收到了意外的关键字参数"server_hostname"? [英] wrap_socket() got an unexpected keyword argument 'server_hostname'?
问题描述
我正在尝试使用Python测试Web服务器.我几乎没有使用Python的经验,但是鼓励使用它,因为它易于学习且易于操作(其他人的观点,目前还不是我的观点).我正在使用的脚本是:
I'm trying to use Python to test a web server. I have nearly no experience with Python, but encouraged to use it because its easy to learn and simple to do things with (someone else's opinion, not mine at the moment). The script I am using is:
s1 = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s2 = ssl.wrap_socket(s1,
ca_certs="./pki/signing-dss-cert.pem",
cert_reqs=ssl.CERT_REQUIRED,
ssl_version=ssl.PROTOCOL_TLSv1,
server_hostname="localhost")
s2.connect( ("localhost", 8443) )
s2.send("GET / ")
time.sleep(1)
s2.send("HTTP/1.1")
错误是:
Traceback (most recent call last):
File "./fetch.sh", line 10, in <module>
server_hostname="localhost")
TypeError: wrap_socket() got an unexpected keyword argument 'server_hostname'
我也曾尝试使用servername
,name
,hostname
和sni
,但没有任何乐趣.
I've also tried using servername
, name
, hostname
and sni
with no joy.
Python文档未提及SNI(套接字对象的TLS/SSL包装器和 SSL Wiki页面).但是我知道SNI和server_hostname
的补丁是4年前在2010年合并的(添加* SSLContext.wrap_socket
的server_hostname *参数,更改集65593:846c0e1342d0 ).
The Python docs don't mention SNI (TLS/SSL wrapper for socket objects and SSL wiki page). But I know the patch for SNI and server_hostname
was incorporated 4 years ago in 2010 (Add a *server_hostname* argument to SSLContext.wrap_socket
, changeset 65593:846c0e1342d0).
我需要访问的等效OpenSSL调用是SSL_set_tlsext_host_name
.
The equivalent OpenSSL call I need access to is SSL_set_tlsext_host_name
.
如何指定SNI主机名? (最终,由于我正在测试代理服务器,因此我需要将其设置为任意名称).
How do I specify the SNI hostname? (Eventually, I'll need to set it to an arbitrary name because I am testing a proxy).
推荐答案
向您修补提及是针对Python 3.2的,而您使用的是Python 2.7. 问题5639 似乎也表明没有计划向后移植SNI对Python 2.7的支持.
The patch you're mentioning is for Python 3.2, and you're using Python 2.7. Issue 5639 also seems to indicate there is no plan to back-port SNI support for Python 2.7.
您可以改为使用pyOpenSSL包装套接字(其Connection
类具有 set_tlsext_host_name
从0.13版开始.(我不确定Debian 7.3随附哪个版本,如果需要,您可能需要设置virtualenv并在本地升级到较新的版本.)
You could wrap the socket with pyOpenSSL instead (its Connection
class has a set_tlsext_host_name
since version 0.13. (I'm not sure which version comes with Debian 7.3, you might want to set up a virtualenv and upgrade to a newer version locally, if needed.)
有一个 SNI示例是pyOpenSSL存储库.
There is an SNI example is the pyOpenSSL repository.
如果要替换httplib
连接中的sock
值为wrap_socket
,则使wrap_socket
的用法与该技巧更加兼容,那么可以看看
If you want your usage of wrap_socket
to be more compatible with the trick were you replace the value of sock
in an httplib
connection, you could have a look at how urllib3 does this with pyOpenSSL. Essentially, it creates an OpenSSL.SSL.Connection
from an existing socket, but since that connection isn't compatible with a socket, it wraps it into a class that implements the required method.
(顺便说一句,在Python 2.7中,urllib
,urllib2
和httpconnection
根本不执行任何证书验证,除非您通过包装它们的套接字来实现它.)
(By the way, in Python 2.7, urllib
, urllib2
and httpconnection
don't do any certificate verification at all, unless you implement it yourself by wrapping their sockets.)
这是您的代码版本,应与Python 3.2一起使用.不幸的是,server_name
参数不是在普通的ssl.wrap_socket
中,而是在SSLContext.wrap_socket
中,但是您可以直接使用SSLSocket
.
Here is a version of your code that should work with Python 3.2. Unfortunately, the server_name
parameter isn't in the plain ssl.wrap_socket
, only in SSLContext.wrap_socket
, but you can use SSLSocket
directly.
import socket
import ssl
CA_BUNDLE_FILE="/etc/ssl/certs/ca-certificates.crt"
HOST = "sni.velox.ch"
s1 = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s2 = ssl.SSLSocket(sock=s1, ca_certs=CA_BUNDLE_FILE,
cert_reqs=ssl.CERT_REQUIRED,
ssl_version=ssl.PROTOCOL_TLSv1,
server_hostname=HOST)
s2.connect((HOST, 443))
s2.send(bytes("GET / HTTP/1.1\n", "UTF-8"))
# This might need to be modified when using another port
s2.send(bytes("Host: %s\n" % (HOST,), "UTF-8"))
s2.send(bytes("\n", "UTF-8"))
# Certainly not the best way to read the response, but it works.
while True:
x = s2.read()
if not x:
break
print(x)
这篇关于wrap_socket()收到了意外的关键字参数"server_hostname"?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!