4

SocketServer.TCPServer クラスに基づく既存の TCP サーバーに ssl サポートを追加したいと考えています。そこで、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))

ここでもエラーは発生しませんが、connect-call がブロックされています。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接続を使用したいだけです:)

4

3 に答える 3

9

バインド後にソケットをラップしているため、ハンドシェイクがブロックされています。ソケットは新しい接続をリッスンしています。接続を受け入れるクライアントはまだありません。

代わりに、接続を受け入れるときにソケットをラップします。

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)

握手をするクライアントが反対側にいるため、握手は成功ます。

ストリーム ハンドラに必要な追加作業はありません。pythonsslライブラリは、 と同じインターフェイスを持つオブジェクトを提供します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)
于 2013-09-20T15:49:53.957 に答える
3

わかりました、私は解決策を見つけました。ここで、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のsetup-methodで:

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

これはうまくいくようです:-)

于 2011-05-17T16:47:27.970 に答える
0

do_handshake_on_connectこれは、ssl.wrap_socket への呼び出しで引数を設定する必要があるためです。

パラメータ do_handshake_on_connect は、socket.connect() の実行後に SSL ハンドシェイクを自動的に行うか、またはアプリケーション プログラムが SSLSocket.do_handshake() メソッドを呼び出して明示的に呼び出すかを指定します。SSLSocket.do_handshake() を明示的に呼び出すと、プログラムはハンドシェイクに関連するソケット I/O のブロック動作を制御できます。

ソース: http://docs.python.org/library/ssl.html

于 2011-05-14T12:12:22.997 に答える