2011-05-14 43 views
4

我想添加ssl支持到基於SocketServer.TCPServer類的現有TCP服務器。 所以我推翻了TCPSERVER類的默認構造函數,並添加ssl.wrap_socket(...) - 撥打:使用SocketServer.TCPServer通過SSL的TCP服務器

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() 

當啓動服務器時,沒有錯誤occurrs。 所以我修改了簡單的測試,客戶端支持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連接:)

+0

不算什麼,請把您的解決方案出了問題,並重新發布的回答爲你自己的問題。然後您可以接受它,並收到upvotes解決方案。 – 2011-05-17 10:08:16

+0

也許你想嘗試使用標準的python ssl模塊:http://stackoverflow.com/questions/8582766/adding-ssl-support-to-socketserver/17501900#17501900 – 2013-07-06 10:18:08

回答

3

好,我發現了一個解決方案。現在我用類似 this使用OpenSSL的包東西:

的MyTCPServer-構造函數中:

​​

而在StreamRequestHandler的設置法:

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

這似乎工作正常:-)

+0

嗨,你有這個服務器的完整工作python代碼。我正在努力設置代碼的位置。謝謝。 – Ketan 2012-08-23 18:34:00

+0

我根據我的舊代碼攻擊了一個工作示例:[Server](http://pastebin.com/1PDX3HRY),[Client](http://pastebin.com/VaWuMpf7)。這是一個簡單的echo-server(支持SSL),爲每個客戶端使用一個處理程序線程。它已經包含了一些輔助方法,用於閱讀/寫作:)注意:對於服務器,您需要指定證書文件! – Biggie 2012-08-25 13:21:15

0

那是因爲你必須在你的呼叫do_handshake_on_connect參數設置爲ssl.wrap_socket:

do_handshake_on_connect 該參數指定是否做SSL 在執行 socket.connect()之後自動握手,或者 應用程序將通過調用 SSLSocket.do_handshake()方法顯式調用 。 調用SSLSocket.do_handshake() 明確給出程序控制 在握手中涉及的套接字I/O的阻塞行爲。

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

+0

是的,但'do_handshake_on_connect'默認爲'True'。我認爲沒關係,因爲握手需要交換加密密鑰。當把它設置爲'False'時,我想我需要手動調用'do_handshake',這個塊也是:-)但是我不知道爲什麼這個調用會阻塞並且不會返回。當不手動調用'do_handshake'而使用'do_handshake_on_connect = False',然後調用套接字對象(在客戶端)的'send'方法時,'send'方法將被阻塞。 – Biggie 2011-05-14 12:54:03

6

握手被阻止,因爲你正在包裝套接字後binding;該套接字正在偵聽新的連接,沒有客戶端尚未接受您的連接。

裹在接受連接,而不是當插座:

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) 
+0

這是答覆。 – gatopeich 2015-06-26 11:22:55

相關問題