6715.jp

2017-05-17

新入生向けCTF体験会のスコアサーバが重かった

sekaisekai
CTFDNSDockerインフラネットワーク日記

重い

CPCTF

https://ctf-no.pro/

こういうのをやりました。

出題された問題の雰囲気はこういうかんじ(参加してくださった方のwriteupです)

サーバ周りは全てボクが担当したんですが、ゴミクソ重くて申し訳なさがXDです。

構成

問題が60個とかそれくらいありました。多すぎる。 で、この問題たちとスコアサーバを全て1台のサーバ(cpu:8Core mem:16GB)で動かしました。

全てのアプリはDockerで環境が分離されています。 自作のソフトウェア(Dockerのラッパみたいな何か)によって、PaaSみたいな使い心地で問題を更新できる仕組みにしてました。

👆のお陰で、出題ミスが見つかっても更新が非常にスムーズでした。 最終的に100アカウントくらいが登録されてましたが、サーバも落ちたりせずに概ね順調でした。

が、HTTPでのアクセスがクッッッッッソ遅い問題にぶち当たって険しい感じでした。 なんか変な感じの挙動で、一度繋がるとそれ以後数10分は快適に繋がるが、 繋がらない人は永遠につながらない(HTTPレスポンスが帰ってこない)感じ。

で、サーバ全体の負荷も大したことなかったし、ネットワーク帯域も余裕っぽかったので、謎かった。

重い理由

サーバが1台で、アプリが沢山乗ってる構成なので、HTTPリクエストを捌いてくれるリバースプロキシとしてOpenRestyさんを使っていて、 HTTPS化を手っ取り早くやるためにlua-resty-auto-sslを採用していました。

lua-resty-auto-sslは非常に優秀で、 正しく設定すれば勝手にすべてのページをHTTPS化してくれて便利便利floatです。

でまぁ、結論を言うと重いのはこの人が原因でした。

この人はOCSP Staplingもやってくれるんですが、コレを正しく動作させるためにはOpenRestyのresolver設定をしてあげないとダメです。 どうダメかというと、遅くなります。おそらくDNSの問い合わせができずにそこでワーカーが止まってしまい永遠にレスポンスが帰ってこないのかな?

エラーログにはOCSPが失敗したよ!っていうログがいっぱい出ていなので、コレが問題なのは間違いないんですが詳しい原因はコレ以上分からずです。 一旦繋がると以後は素早く繋がるのは多分、一度OCSPで証明書の正当性が確認されるとしばらくは確認しないから……? でもOCSP Staplingってサーバ側が能動的に送ってるものな気がするし違うのでしょうか……

それと、lua-resty-auto-sslが内部で使ってるLetsencryptクライアントの dehydratedは、デフォルトだとRSA 4096bitの証明書を作成します。 4096bitは結構遅いです。適当にabで計測したら4096bitは2048bitを比較してリクエスト完了まで10倍くらいの時間がかかってました。

Dockerの内部DNS

さっきのOpenRestyはDockerコンテナ内で動かしてたんですが、 Docker内部だとデフォルトゲートウェイがDockerネットワーク内でのホストのアドレスなので、 DNSのについてもこの人がやってくれてるんだろうな〜〜って勝手に思って勝手にそう指定してたんですが、これが間違いでした。

Dockerネットワーク内でのDNSサーバは、127.0.0.11が正しいそうです。 というか、resolve.confを見たらちゃんと書いてあったわ……

おわり

わからないことが多いです。 誰か鉞投げて欲しい。