this Matasano crypto challenge私は、人工的に減速した文字列比較関数を持つサーバーに対してタイミング攻撃を行うことを試みています。 「あなたの選択したWebフレームワーク」を使用すると言われていましたが、Webフレームワークをインストールする気がなかったので、モジュールにHTTPServer classを組み込みました。urllib.requestからHTTPServerへの多数の同時要求を行うときの不思議な例外
私はうまくいきましたが、それは非常に遅かったので、multiprocessing.dummy
に組み込まれた(あまりにも文書化された)スレッドプールを使用してスピードアップしようとしました。はるかに高速でしたが、私は奇妙なことに気付きました。私が8つ以下の要求を同時に行うとうまくいきます。それ以上のものがあれば、それはしばらくの間働き、一見無作為な時に私にエラーを与えます。エラーは一貫性がなく、常に同じではないようですが、通常はConnection refused, invalid argument
,OSError: [Errno 22] Invalid argument
,urllib.error.URLError: <urlopen error [Errno 22] Invalid argument>
,BrokenPipeError: [Errno 32] Broken pipe
、またはurllib.error.URLError: <urlopen error [Errno 61] Connection refused>
です。
サーバーで処理できる接続の数に制限はありますか。私はスレッド自体の数は問題ではないと思います。なぜなら、Webサーバーを実行せずにスローダウンした文字列の比較を行い、同時に500個のスレッドを呼び出す単純な関数を書いたからです。 100スレッド以上を使用しているクローラを作成しているので(同じWebサイトに同時にリクエストを出している)、うまく機能しているため、多くのスレッドから要求を出すだけで問題になるとは思わない。おそらく、HTTPServerは大量のトラフィックを受け取った本番Webサイトを確実にホストするためのものではないようですが、クラッシュさせるのは簡単なことですが驚いています。
このような不思議なバグを診断するときに通常行っているように、問題に無関係に見えるコードから徐々に削除することを試みましたが、この場合はあまり役に立ちませんでした。一見無関係なコードを削除していたように見えましたが、サーバーが処理できる接続の数は徐々に増加しましたが、クラッシュの原因は明確ではありませんでした。
私は一度に行うことができるリクエストの数を増やす方法を知っていますか、それともなぜこれが起こっているのですか?
私のコードは複雑ですが、私は、問題を示し、この簡単なプログラムを思い付いた:何らかの理由で
#!/usr/bin/env python3
import os
import random
from http.server import BaseHTTPRequestHandler, HTTPServer
from multiprocessing.dummy import Pool as ThreadPool
from socketserver import ForkingMixIn, ThreadingMixIn
from threading import Thread
from time import sleep
from urllib.error import HTTPError
from urllib.request import urlopen
class FancyHTTPServer(ThreadingMixIn, HTTPServer):
pass
class MyRequestHandler(BaseHTTPRequestHandler):
def do_GET(self):
sleep(random.uniform(0, 2))
self.send_response(200)
self.end_headers()
self.wfile.write(b"foo")
def log_request(self, code=None, size=None):
pass
def request_is_ok(number):
try:
urlopen("http://localhost:31415/test" + str(number))
except HTTPError:
return False
else:
return True
server = FancyHTTPServer(("localhost", 31415), MyRequestHandler)
try:
Thread(target=server.serve_forever).start()
with ThreadPool(200) as pool:
for i in range(10):
numbers = [random.randint(0, 99999) for j in range(20000)]
for j, result in enumerate(pool.imap(request_is_ok, numbers)):
if j % 20 == 0:
print(i, j)
finally:
server.shutdown()
server.server_close()
print("done testing server")
それは100以上のスレッドかそこらを持っていない限り、上記のプログラムが正常に動作しますが、私のチャレンジの実際のコードは8つのスレッドしか扱えません。私は9でそれを実行すると、私は通常接続エラーを取得し、10と、私は常に接続エラーを取得します。 multiprocessing.dummy.pool
の代わりにconcurrent.futures.ThreadPoolExecutor
,concurrent.futures.ProcessPoolExecutor
、multiprocessing.pool
を使ってみましたが、どれも役に立たないようでした。私は平文HTTPServer
オブジェクト(ThreadingMixIn
なし)を使ってみましたが、非常にゆっくりと動作させただけで問題を解決できませんでした。私はForkingMixIn
を使ってみましたが、それはそれを修正しませんでした。
私はこれについて何をすべきですか?私は、2013年後半のMacBook ProでOS X 10.11.3を実行しているPython 3.5.1を実行しています。
EDIT:私はForkingMixIn
と、そしてThreadingMixIn
で、シンプルHTTPServer
として、代わりにスレッドのプロセスでサーバーを実行しているなど、いくつかのより多くの事を、試してみました。誰も助けなかった。
編集:この問題は私が思ったよりも見知らぬです。私はサーバーで1つのスクリプトを作成しようとしました。スレッドをたくさん作成してリクエストを作成し、端末のさまざまなタブでそれらを実行しました。サーバーのプロセスは正常に実行されましたが、要求を作成したプロセスがクラッシュしました。例外は、ConnectionResetError: [Errno 54] Connection reset by peer
,urllib.error.URLError: <urlopen error [Errno 54] Connection reset by peer>
,OSError: [Errno 41] Protocol wrong type for socket
,urllib.error.URLError: <urlopen error [Errno 41] Protocol wrong type for socket>
,urllib.error.URLError: <urlopen error [Errno 22] Invalid argument>
の組み合わせであった。
上記のようなダミーサーバーで試してみましたが、同時リクエスト数を5以下に制限してもうまくいきましたが、6つのリクエストでクライアントプロセスがクラッシュしました。サーバーからいくつかのエラーがありましたが、それは継続しました。要求を行うためにスレッドまたはプロセスを使用していたかどうかにかかわらず、クライアントはクラッシュしました。私はその後、サーバに遅い機能を入れようとしましたが、同時に60件のリクエストを処理できましたが、70でクラッシュしました。これは、サーバに問題があるという証拠と矛盾するようです。
EDIT:私はrequests
代わりのurllib.request
を用いて説明し、同様の問題に遭遇したことのほとんどを試してみました。
EDIT:私は現在、OS X 10.11.4を実行しており、同じ問題が発生しています。
あなたがあなたの未使用のクライアント接続を閉じている確保していますか? –
@Cory Shay、私は 'x = urlopen(何でも)'と 'x.close()'をやってみましたが、それは役に立たなかったようです。 –
私が述べた理由が必ずしもこの問題が起こっている理由ではないことを認めなければならない。潜在的に他人がいる可能性があります。しかし、これを調べるのに役立つかもしれない質問がいくつかあります。「ulimit -r $((32 * 1024))を発行すればどうなるでしょうか?」と "netstat -anp | grep SERVERPROCESSNAME'の出力は何ですか?" –