1

これと非常によく似た質問を覚えている人もいるかもしれません。C で (libssh2 と openssl を使用して) 元のユーティリティを作成する際に助けを求めたからです。私は今それをpythonに移植しようとしていますが、予期しない場所で立ち往生しました。コアと機能の約 80% を 30 分で移植し、その後 10 時間以上を費やしましたが、まだその 1 つの機能を完了していません。

ソース全体 (~130 行、読みやすく、複雑ではない) は、http: //pastebin.com/Udm6Ehu3から入手できます。

接続、SSL の切り替え、ハンドシェイク、認証、さらには (暗号化された) コマンドの送信も正常に機能します (ルーターのログから、適切なユーザーとパスワードでログインしていることがわかります)。

問題は、トンネル シナリオの ftp_read にあります (self.proxy からの else は None です)。1つの試みはこれでした:

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 関数でのチャネル読み取り) の待機をブロックするか、皮肉なことに、私が処理しようとしている例外 OpenSSL.SSL.WantReadError のいずれかでスタックしてしまいます。

前述のように、ftp_read 呼び出しをコメント アウトすると、プロキシ シナリオは正常に機能します (ログイン、コマンドの送信は問題ありません)。したがって、暗号化されていない読み取り/書き込み、暗号化された読み取り/書き込みのうち、暗号化された読み取りトンネルがありません。

私は今12時間以上費やしていますが、どこにも行けていないように感じているので、どんな考えでも大歓迎です.

編集:私は誰かに私のために関数を書くように頼んでいるわけではないので、SSL (特に BIO) について 1 つまたは 2 つのことを知っていて、トンネルと BIO の間の相互作用に明らかな欠陥があることがわかっている場合は、それで十分です。回答 :) 同様に、おそらく ftp_write は要求された 10240 バイトよりも多くのデータを返す (または単に 2 つのテキスト ("blabla\n"、"command done.\n") を送信する) ため、適切にフラッシュされません。これは本当かもしれませんが、pyOpenSSL の .want_write()/.want_read() に依存して、利用可能な 0 バイト以外を報告することはできないようです。

4

1 に答える 1

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

ご意見ありがとうございます。これにより、物事が少し明確になり、操作が簡単になりました。ただし、私の問題は、エラー処理が1つ欠けているように見えました(SSL.WantReadError例外がすぐに発生しました)。

于 2011-04-09T12:13:31.897 に答える