2011-04-09 64 views
1

您可能會記得一個與此非常相似的問題,因爲我在C中使用libssh2和openssl尋求原始util的幫助。 我現在試圖將它移植到python,並陷入了一個意想不到的地方。在30分鐘內移植了大約80%的核心和功能,然後花費10小時+仍然沒有完成那一項功能,所以我再次要求您再幫助一次:)使用openssl(python)在ssl中包裝ssh隧道幾乎完成

整個來源(〜130行,應該很容易讀,不復雜)可在這裏:http://pastebin.com/Udm6Ehu3

連接,切換SSL,握手,身份驗證,甚至發送(加密)命令工作正常(我可以從我的路由器日誌中看到我用正確的用戶和密碼登錄)。

問題是在隧道方案中的ftp_read(否則從self.proxy是None)。一種嘗試是這樣的:

def ftp_read(self, trim=False): 
    if self.proxy is None: 
    temp = self.s.read(READBUFF) 
    else: 
    while True: 
     try: 
     temp = self.sock.bio_read(READBUFF) 
     except Exception, e: 
     print type(e) 
     if type(e) == SSL.WantReadError: 
      try: 
      self.chan.send(self.sock.bio_read(10240)) 
      except Exception, e: 
      print type(e) 
      self.chan.send(self.sock.bio_read(10240)) 
     elif type(e) == SSL.WantWriteError: 
      self.chan.send(self.sock.bio_read(10240)) 

但是我最終停留在任一具有封等生物讀取(或通道在ftp_write函數read),或異常OpenSSL.SSL.WantReadError其中,ironicly,是我正在努力處理。

如上所述,如果我註釋掉ftp_read調用,代理方案工作正常(登錄,發送命令沒有問題)。因此,讀/寫未加密,讀/寫加密我是只是缺少讀取隧道加密。

我已經花了12小時+現在,覺得我無處可去,所以任何任何想法是高度讚賞。

編輯:我不要求別人寫的功能對我來說,如果你知道一件事或兩個關於SSL(尤其是BIOS),你可以在我的隧道和生物之間的相互作用看到一個明顯的缺陷,那就足以作爲答案了:)例如:也許ftp_write返回比請求的10240字節更多的數據(或者只發送兩個文本(「blabla \ n」,「完成命令。\ n」)),所以它不是適當地沖洗。哪個可能是真的,但顯然我不能依靠pyOpenSSL中的.want_write()/。want_read()來報告除0字節外的任何內容。

+1

在SSL中包裝SSH?除了明顯的批評之外,請記住,通過TCP隧道化TCP是導致瘋狂的黑暗之路。 http://sites.inka.de/bigred/devel/tcp-tcp.html – tylerl 2011-04-09 08:29:22

+0

我並不感到驚訝,你已經瘋了:)我建議寫一些包裝,將閱讀像'more_to_server()'來隱藏所有這些'self.chan.send(self.sock.bio_read())'和反向操作。或者完全從非代理代碼中分離代理代碼。任何東西,以減少'我'vs' s'堆vs'sock' vs'chan' :) – sarnold 2011-04-09 08:32:35

+0

有效的點,你們倆,嘿嘿。謝謝。我計劃將它們寫成ssl_wants_read()和ssl_wants_write(),正如我在C代碼中所做的一樣,但現在我只是試圖獲得** something ** working :) – Josh 2011-04-09 08:37:06

回答

0

好的,所以我覺得我可以把它整理一下。

sarnold,你會喜歡這個更新版本:

def ftp_read(self, trim=False): 
    if self.proxy is None: 
     temp = self.s.read(READBUFF) 
    else: 
     temp = "" 
     while True: 
     try: 
      temp += self.sock.recv(READBUFF) 
      break 
     except Exception, e: 
      if type(e) == SSL.WantReadError: 
      self.ssl_wants_read() 
      elif type(e) == SSL.WantWriteError: 
      self.ssl_wants_write() 

其中ssl_wants_ *是:

def ssl_wants_read(self): 
    try: 
     self.chan.send(self.sock.bio_read(10240)) 
    except Exception, e: 
     chan_output = None 
    chan_output = self.chan.recv(10240) 
    self.sock.bio_write(chan_output) 

    def ssl_wants_write(self): 
    self.chan.send(self.sock.bio_read(10240)) 

感謝您的輸入,sarnold。它使事情變得更清晰和更容易。但是,我的問題似乎是錯過了一個錯誤處理(太快爆發了SSL.WantReadError異常)。