Better Port Scanner

この前イケてない connect scanner を書いてみたんだけど、local のシステムリソースを非常に食って実質使いものにはならないので、TCP の SYN scan のようなことを Perl でどう書くのかを調べてた。

いろいろ CPAN モジュールを調べてたんだけど、標準添付のモジュール Net::Ping には、Net::Ping->new("syn"); と SYN をなげるインターフェースがあることを発見。これはと思ってソースを見てみたんだけど、
Net::Ping::ping_syn から抜粋

...
# Set O_NONBLOCK property on filehandle
$self->socket_blocking_mode($fh, 0);

# Attempt the non-blocking connect
# by just sending the TCP SYN packet
if (connect($fh, $saddr)) {
...

non-blocking モードで connect してるだけのようだ。

いろいろテストしてみたんだけど、IO::Socket::INET で non-blocking な socket を作って、IO::Select と併用することで fork + socket よりはちょっとましな port scanner が作れますね。CPAN モジュールには他にも NetPacket とか Net::Packet とか raw packet に近いものを生成する奴があるみたいなんだけど、あんまり調べてません。TCP の packet を直接操作していじくり回したいプログラムを作るときは Perl じゃなくって C で書いた方が話が早い気がするので、これ以上 Perl で踏み込むのはやめときます。

で、成果というか、この前作った Winny の Scanner の port scan 部分を改良した新しい winny_scanner.pl を書いたので興味があったらどうぞ。(コードを直したときに Blog を修正するのが面倒なのでリンクにしました)