使用 SocketServer.TCPServer 通过 SSL 的 TCP 服务器

发布于 2024-11-06 20:40:52 字数 1382 浏览 0 评论 0原文

我想将 ssl 支持添加到基于 SocketServer.TCPServer 类的现有 TCP 服务器。 所以我覆盖了 TCPServer 类的默认构造函数并添加了 ssl.wrap_socket(...) 调用:

class MyTCPServer(SocketServer.ThreadingMixIn, SocketServer.TCPServer):
    def __init__(self, server_address, RequestHandlerClass, bind_and_activate=True):
        # See SocketServer.TCPServer.__init__
        # (added ssl-support):
        SocketServer.BaseServer.__init__(self, server_address,
                                                        RequestHandlerClass)
        self.socket = ssl.wrap_socket(
                    socket.socket(self.address_family, self.socket_type),
                    server_side=True,
                    certfile='cert.pem'
                    )

        if bind_and_activate:
            self.server_bind()
            self.server_activate()

启动服务器时,不会发生错误。 所以我修改了我的简单测试客户端来支持 ssl:同样

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock = ssl.wrap_socket(s)
sock.connect(('192.168.1.1', 54321))

没有发生错误,但连接调用被阻止。当使用 Ctrl+C 关闭客户端时,它显示以下内容:

Traceback (most recent call last):
  File "exampleClient.py", line 10, in <module>
    sock.do_handshake()
  File "/usr/lib/python2.6/ssl.py", line 293, in do_handshake
    self._sslobj.do_handshake()
KeyboardInterrupt

因此 do_handshake 在连接时被阻塞。有谁知道如何解决这个问题?我只是想使用加密的 TCP 连接:)

i want to add ssl-support to an existing TCP-server which is based on the SocketServer.TCPServer class.
So i overrode the default constructor of the TCPServer class and added the ssl.wrap_socket(...)-call:

class MyTCPServer(SocketServer.ThreadingMixIn, SocketServer.TCPServer):
    def __init__(self, server_address, RequestHandlerClass, bind_and_activate=True):
        # See SocketServer.TCPServer.__init__
        # (added ssl-support):
        SocketServer.BaseServer.__init__(self, server_address,
                                                        RequestHandlerClass)
        self.socket = ssl.wrap_socket(
                    socket.socket(self.address_family, self.socket_type),
                    server_side=True,
                    certfile='cert.pem'
                    )

        if bind_and_activate:
            self.server_bind()
            self.server_activate()

When starting the server, no error occurrs.
So i modified my simple test-client to support ssl, too:

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock = ssl.wrap_socket(s)
sock.connect(('192.168.1.1', 54321))

Again no error occurrs, but the connect-call is blocking. When closing the client using Ctrl+C it shows the following:

Traceback (most recent call last):
  File "exampleClient.py", line 10, in <module>
    sock.do_handshake()
  File "/usr/lib/python2.6/ssl.py", line 293, in do_handshake
    self._sslobj.do_handshake()
KeyboardInterrupt

So the do_handshake is blocking when connecting. Does anyone knows how to fix the problem? I simply want to use an encrypted TCP-connection :)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

远昼 2024-11-13 20:40:52

握手被阻塞,因为您在绑定之后包装了套接字;套接字正在侦听新连接,尚无客户端接受您的连接。

改为在接受连接时包装套接字:

class MyTCPServer(SocketServer.ThreadingMixIn, SocketServer.TCPServer):
    def get_request(self):
        (socket, addr) = SocketServer.TCPServer.get_request(self)
        return (ssl.wrap_socket(socket, server_side=True, certfile="cert.pem"),
                addr)

现在握手成功,因为另一端有一个客户端要与之握手。

流处理程序不需要额外的工作; python ssl 库为您提供与 socket.socket() 具有相同接口的对象。

您也可以提前包装套接字,但请推迟握手,直到您接受连接:

class MyTCPServer(SocketServer.ThreadingMixIn, SocketServer.TCPServer):
    def server_bind(self):
        SocketServer.TCPServer.server_bind(self)
        self.socket = ssl.wrap_socket(
            self.socket, server_side=True, certfile="cert.pem",
            do_handshake_on_connect=False)

    def get_request(self):
        (socket, addr) = SocketServer.TCPServer.get_request(self)
        socket.do_handshake()
        return (socket, addr)

The handshake is blocking because you are wrapping the socket after binding; the socket is listening for new connections, there is no client yet to accept your connections.

Wrap the socket when accepting a connection instead:

class MyTCPServer(SocketServer.ThreadingMixIn, SocketServer.TCPServer):
    def get_request(self):
        (socket, addr) = SocketServer.TCPServer.get_request(self)
        return (ssl.wrap_socket(socket, server_side=True, certfile="cert.pem"),
                addr)

Now the handshake succeeds because there is a client on the other side to shake hands with.

There is no additional work necessary for the stream handler; the python ssl library gives you objects with the same interface as socket.socket().

You can also wrap the socket early, but do postpone the handshake until you accept a connection:

class MyTCPServer(SocketServer.ThreadingMixIn, SocketServer.TCPServer):
    def server_bind(self):
        SocketServer.TCPServer.server_bind(self)
        self.socket = ssl.wrap_socket(
            self.socket, server_side=True, certfile="cert.pem",
            do_handshake_on_connect=False)

    def get_request(self):
        (socket, addr) = SocketServer.TCPServer.get_request(self)
        socket.do_handshake()
        return (socket, addr)
岁月染过的梦 2024-11-13 20:40:52

好的,我找到了解决方案。现在我使用类似的东西
使用 OpenSSL 包:

在 MyTCPServer-Constructor 内部:

SocketServer.BaseServer.__init__(self, server_address, RequestHandlerClass)
ctx = SSL.Context(SSL.SSLv23_METHOD)
cert = 'cert.pem'
ctx.use_privatekey_file(cert)
ctx.use_certificate_file(cert)
self.socket = SSL.Connection(ctx, socket.socket(self.address_family,
                                                        self.socket_type))
if bind_and_activate:
    self.server_bind()
    self.server_activate()

在 StreamRequestHandler 的设置方法中:

self.connection = self.request
self.rfile = socket._fileobject(self.request, "rb", self.rbufsize)
self.wfile = socket._fileobject(self.request, "wb", self.wbufsize)

这似乎工作正常:-)

Ok, i found a solution. Now i use something similar to
this using the OpenSSL-package:

Inside the MyTCPServer-Constructor:

SocketServer.BaseServer.__init__(self, server_address, RequestHandlerClass)
ctx = SSL.Context(SSL.SSLv23_METHOD)
cert = 'cert.pem'
ctx.use_privatekey_file(cert)
ctx.use_certificate_file(cert)
self.socket = SSL.Connection(ctx, socket.socket(self.address_family,
                                                        self.socket_type))
if bind_and_activate:
    self.server_bind()
    self.server_activate()

And in the setup-method of the StreamRequestHandler:

self.connection = self.request
self.rfile = socket._fileobject(self.request, "rb", self.rbufsize)
self.wfile = socket._fileobject(self.request, "wb", self.wbufsize)

This seems to work fine :-)

硪扪都還晓 2024-11-13 20:40:52

这是因为您必须在对 ssl.wrap_socket 的调用中设置 do_handshake_on_connect 参数:

参数do_handshake_on_connect
指定是否进行SSL
完成后自动握手
socket.connect(),或者是否
应用程序会调用它
明确地,通过调用
SSLSocket.do_handshake() 方法。
调用 SSLSocket.do_handshake()
明确地给予程序控制
的阻塞行为
握手中涉及的套接字 I/O。

来源:http://docs.python.org/library/ssl.html

That's because you have to set the do_handshake_on_connect argument in your call to ssl.wrap_socket:

The parameter do_handshake_on_connect
specifies whether to do the SSL
handshake automatically after doing a
socket.connect(), or whether the
application program will call it
explicitly, by invoking the
SSLSocket.do_handshake() method.
Calling SSLSocket.do_handshake()
explicitly gives the program control
over the blocking behavior of the
socket I/O involved in the handshake.

Source: http://docs.python.org/library/ssl.html

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文