イメージはこんな感じ。Portに接続すると、そこから内部でひたすらポートフォワードしまくって、一番奥底にある80/tcpに到達するとようやくコンテンツが取り出せます。ここでは大きめのポートとして10080/tcpを仮定してみたので、http://:10080/に接続すると、10080/tcp→9980/tcp→9880/tcp→......と少しずつ小さいポートにリダイレクトされていき、最終的に「......→280/tcp→180/tcp→80/tcp」と80/tcpに到達して、コンテンツが取り出されます。100個入れ子のマトリョーシカです。言われると、何もありません。構築のしかたやり方は色々とあると思いますが、ここではmod_proxy_httpを使って構築してみます。具体的には、1リダイレクトごとに1つのコンフィグファイルを作ります。「ポートnからポートn-100へリダイレクトする」confファイルは以下のような設定とします。これはn=2480の例ですね。http://127.0.0.1:2380/</VirtualHost>ファイル名は、「proxy_(受付ポート番号).conf」とします。ここでは一番外側のマトリョーシカを10080/tcpとしましたから、proxy_10080.confからproxy_180.confまで、100個のファイルができます。conf.d/*.conf」として100個読み込みます。マトリョーシカ状態の確認Apacheを起動した段階で、ssコマンドを使って待ち受けポートの確認をします。sockets"で、netstatコマンドと似た機能を持ちます。ここでは、ssコマンドの-l(LISTEN状態のソケット表示)・-n(名前解決をしない)・-t(TCPソケットのみを表示)のオプションを利用しています。80/tcpで待ち受けているのが一番内側のApacheで、その「外側の容器」として9580/tcp,8780/tcp,7980/tcpなどの末尾80のポートがずらりと並んでいるのが分かります。通信のキャプチャこのApacheマトリョーシカは内部でリダイレクトしているだけなので、通常のログレベルではログが出力されずリダイレクトの様子が分かりません。そこでtcpdumpでパケットキャプチャして確認してみましょう。iptablesをOFFにしておきます。stopマトリョーシカの一番外側には以下のようにwgetでアクセスします。http://127.0.0.1:10080/上記wgetコマンドを、tcpdumpでパケットをダンプしながら実行します。kernel”と表示されました。パケットがドロップされ、取りこぼしが出ています。Apacheのポートフォワード動作を少し遅くする必要があるかな?Apacheの動作を意図的に遅くするには前述の通り、そのままだとtcpdumpがパケットを取りこぼしてしまうため、Apacheの動作に少し遅延を入れることにしました。本当は「全てのリクエストに対してm秒の遅延を入れる」みたいな設定ができればいいなと思って探しましたが、「Apacheで遅延をいかに減らすか」という記事は山ほど見つかるものの、意図的に動作を遅くする設定は無いようです(あるかも。そんなに本気で調べていないので)。それよりも、Apacheのソースに手を入れて、全てのリクエストに決め打ちのディレイをusleep(3)で入れた方が簡単そうです。いうわけでこのアプローチを取ることにしました。この際には2ヶ所に遅延を入れる必要があります。HTTPリクエストを投げる部分HTTPレスポンスを返す部分リクエストに遅延を入れないと、マトリョーシカを「開けていく」部分が早すぎてtcpdumpがパケットを取りこぼします。返されるレスポンスにも遅延を入れて、マトリョーシカを「閉めていく」部分もパケットを取りこぼさないようにする必要があります。HTTPリクエストに遅延を入れるApacheのHTTPリクエストを処理しているのは、server/protocol.cのap_read_request関数です。いうわけで、この関数の最後にusleepを入れてやれば良いでしょう。ApacheのソースコードをWebブラウザで見るには、公式のSubversionリポジトリが見やすいです(2.2.27/server/protocol.c)。r;}usleepではマイクロ秒を指定しますので、ここでは50000マイクロ秒=50ミリ秒=0.05秒の遅延を1リクエストごとに入れています。HTTPレスポンスに遅延を入れるApacheのHTTPレスポンスに遅延を入れるのには、同じserver/protocol.cというファイルのap_finalize_request_protocol関数を利用しました。名前の通り、レスポンスのファイナライズに呼ばれる関数ですから、ここにusleepを入れておけば遅延をかけることができます。usleep(50000);}ソースから再ビルドソースをいじったので、手でビルドしてインストールします。install設定ファイルに追記&再起動まず、以下行をhttpd.confの最後に入れます。ディレクトリに、先ほどの「proxy_(受付ポート番号).conf」という100個のファイルを入れて、Apacheを起動します。Portを表示するようにしておきましょう。リクエスト部分のパケットキャプチャを見てみます。3点ほど注目ポイントがあります。HTTPリクエストが10080/tcp→9980/tcp→9880/tcp→......とドミノ倒しのように小さいポートへと順々に流れているのが分かります。ここが、マトリョーシカを「開けて」いる部分です。画像左上の[Time]を見ると、先ほどソースを改造して50ミリ秒の遅延を入れたことから、それぞれのリクエスト間隔がほぼ50ミリ秒+αとなっています。画像下部のパケットの中身を見ると、HTTPヘッダに[X-Forwarded-Host]が付き、そこに10080/tcpからここまで順々に開けてきたマトリョーシカが記載されていることが分かります。ApacheのProxyPassディレクティブは、このようにしてリクエストをプロキシしているわけです。続いて、マトリョーシカの一番奥、中身に到達したところを見てみます。Portが順に100ずつ増えていっています。ここが折り返し地点で、HTTPリクエストが一番奥まで通って、HTTPレスポンスが始まる部分です。80/tcp→180/tcp→280/tcp→......と、順にマトリョーシカを「閉めて」いきます。HTTPレスポンスについても先ほどApacheのソースに手を入れて50ミリ秒の遅延を入れたことから、[Time]のカラムを見るとおおむね50ミリ秒ほどの間隔になっています。最後に、マトリョーシカの一番外側を閉じてリクエストが完了した部分です。リクエストした10080/tcpから、無事に応答が返りました。これでApacheマトリョーシカが完了です。関する罪」の情報公開請求をしました月別アーカイブはてなブログをはじめよう!ozumaさんは、はてなブログを使っています。ブログを報告するスターをつけました引用をストックしましたストック一覧を見る閉じる引用するにはまずログインしてくださいログイン閉じる引用をストックできませんでした。再度お試しください閉じる限定公開記事のため引用できません。