2000-01-29  ポートスキャン入門

近頃インターネット上でのイタズラがちょっとした流行りです。特に中央省庁のサーバが荒らされるという一連の事件は,社会に大きな影響を齎(もたら)しています。NHKのニュースによると,事件の発端はサーバに特殊な信号が発せられたことだったそうです。「特殊な信号」の正体がとても気になりますよね。そこで私も「特殊な信号」を発するプログラムに挑戦してみました*1

開発ツールには,「最近の出来事 Microsoft Visual J++ 6.0 導入前夜 #1998-1012-01」でもお話したMicrosoft Visual J++ 6.0を使ってみました。マイクロソフト製開発ツールの良いところは,この手のコードを目玉焼きや卵焼きを料理するくらいの手間で作ることができるということです(拍子抜けするくらい簡単だという意味)。

開発風景
import java.net.Socket;
import java.io.IOException;

public class PortScanner implements Runnable {
    String hostname = "127.0.0.1";
    int interval = 0;
    int startPort;
    int endPort;
    Thread myThread;

    public PortScanner(int start, int end) {
        startPort = start;
        endPort = end;
        myThread = new Thread(this);
    }

    public PortScanner(String hostname, int start, int end) {
        this(start, end);
        this.hostname = hostname;
    }

    public PortScanner(String hostname, int start, int end, int interval) {
        this(hostname, start, end);
        this.interval = interval;
    }

    public void start() {
        myThread.start();
    }

    public void stop() {
        myThread.stop();
    }

    public void run() {
        ////
        // この try ブロック,もうちょっとキレイにならないもんかな
        ////
        try {
            for (int port = startPort; port <= endPort; port ++) {
                System.out.print(port +"...");
                try {
                    Socket s = new Socket(hostname, port);
                    System.out.println("...OK");
                } catch (IOException e) {
                    System.out.println("NG");
                }
                Thread.sleep(interval);
            }
        } catch (InterruptedException e) {}
        System.out.println("done.");
    }

    public static void main(String[] args) {
        int interval = 0;
        int start = 0;
        int end = 1024;
        String hostname = "127.0.0.1";

        switch (args.length) {
            case 4:
                interval = Integer.parseInt(args[3]);
            case 3:
                start = Integer.parseInt(args[1]);
                end = Integer.parseInt(args[2]);
            case 1:
                hostname = args[0];
            case 0:
            default:
        }

        System.out.println("target = " +hostname);
        System.out.println("start = " +start);
        System.out.println("end = " +end);
        System.out.println("interval = " +interval +"msec");

        System.out.println();
        System.out.println("Scanning...");

        PortScanner ps;
        ps = new PortScanner(hostname, start, end, interval);
        ps.start();
    }
}

さて,それなりに仕上がったので早速使ってみましょう。私のコンピュータの75番から84番ポートを調べてみます。注意しておきますが,ヨソのサーバホストに特殊な信号を発してはいけませんよ。自称ネットワークの偉い人に怒られます。

実行画面

実行結果を見ると80番ポートに陽性反応が出ました。80番ポートは,Webサーバ(HTTPデーモン)の暗黙のポート番号です。つまりポートスキャナは,ローカルに立ち上げているWebサーバを検出したということです。ちなみに検出したからといって,この先どうなるわけでもありません。私もよく知らない(ことにしておく)のですが,はっかーたちは探し当てたポートがどのようなプロトコルを受け付けるのか,引き続き調べていくそうですよ。

プロトコルの挙動を調べるといえばTelnetです。次はTelnetクライアントの製作に挑戦しましょう。

*1 断っておきますが,私は「はっかー」でも「くらっかー」でも「おかき」でもありません。また私の友人にそのような趣味の悪い人は一人もいません。