TCP/IPの同時接続数限界を確認するのは結構大変
今日は技術ネタです。
あるシステムで最大いくつまでのTCP/IP接続を通せるのかを確認しようとすると、実は結構大変なものです。
【接続する側が困る】
ひたすらどんどん接続するプログラムを作ればいけそうな気がしますが、一つのIPアドレスから接続できるのは、ポート番号の数:65535個までです。それ以上つなごうとすると、仮想IPアドレスを割り当てて、送信元IPアドレスを複数個使う必要があります。
また、1プロセスでどんどん接続していくと、こんどは同時使用ディスクリプタ数の制限に引っかかります。
【受ける側も困る】
受ける側も、同時使用ディスクリプタ数やスレッド数の制限に引っかかります。
【どうするか?】
ディスクリプタ数やスレッド数の限界を調整するには、カーネルパラメータなどをいじればいいのですが、結構大変ですし、それでも上限はあります。
こういうときには、TCP/IPを真似てしまう方法が良いものです。私の大好きなリンクレイヤーソケットを使えば、どんなイーサーフレームのパケットでも送受信できます。
・受付プログラム
リンクレイヤーで飛んできたパケットをキャプチャし、対象のIPアドレス・ポート番号のSYNフラグの立ったパケットに対し、SYN+ACKパケットを応答するプログラムを作ればOKです。ただし、対象のポート番号を受け付ける本物のプログラムがいないと、カーネルがRSTパケットを返してしまうので、対象のポート番号はパケットフィルターで通過させないようにしておきます。linuxならiptablesを使えば簡単にできます。
・接続プログラム
リンクレイヤーでSYNパケットを宛先のMACアドレス・IPアドレス・ポート番号宛に送信し、SYN+ACKパケットが戻ってきたら、ACKを返す、というプログラムを作ればOKです。こちらもカーネルがRSTを返してしまうので、パケットフィルタで対象のポート番号のパケットは通過させないようにしておきます。
こうすると、受付側・接続側ともに、OSリソースなどはほとんど使わずに、ひたすら接続するテストができます!
ただし、この状態だと切断ができないので、まじめにやるなら、どちらかが一定時間経ったらRSTパケットでも送信すると丁寧です。
このような無茶なテストをすると、実は意外とファイアーウォールやルーターなどはひどい状態になってしまうものもあるものなのです。自分でルーターやフィルターなどを作る際にはこのような確認をしておくと、リリース時に胃が痛くなりません。