自分の実験環境(端末)の使用/未使用ポート(ウェルノウンポート
のみでok)を確認するポートスキャンプログラムを作成せよ。
さらに、任意のリモート端末の使用/未使用ポートを確認するように
改良せよ(加点ポイント)。なお、スクリプトを使って内部で'netstat -l'
コマンドを実行し、その結果を利用するのは不可とする
(ソケットプログラムを作成すること)。
portscan.cは、引数で指定されたホストの
ウェルノウンポートをスキャンするプログラムである。
引数は複数指定可能で、それぞれのホストに順番にポートスキャンを行い、
使用されているポート(接続できたポート)とその合計数を表示する。
全てのホストへのポートスキャンを終了したら、指定されたホスト数、
スキャンを実行したホスト数、見つからなかったホスト数を
表示して終了する。
図2は、このプログラムが実行している
ポートスキャンをイメージ化したものである。
このプログラムではポートに接続できるかどうかを確認するために
connect()関数を複数回利用して全ポートに総当たりを行っている。
実行結果では、ホスト133.13.54.209とホストnw0439.st.ie.u-ryukyu.ac.jp
(同一ホスト)は合計4つのポートが接続可能である事がわかる。
また、ホストmokeQは存在しないアドレスのため、ホストが見つからない。
この例で接続可能なホストとそのポートが対応するサービスは以下の通りである。
ポートとそれに対応するサービス(括弧内は関連するMacのサービス)
Port 22 -> SSH Remote Login Protocol(リモートログイン)
Port 80 -> World Wide Web HTTP(パーソナルWeb共有)
Port 427 -> Server Location(パーソナルWeb共有、パーソナルファイル共有)
Port 548 -> AFP over TCP(パーソナルファイル共有)
ポートスキャンプログラムとは、対象ホストのポート(こっこでは0〜1023
のウェルノウンポート)の接続の可不可を確認するプログラムである。
netstatコマンドで言えば、stateが“LISTEN”になっているポートは
接続可能なポートになる。
この作業で脆弱なポートを発見したりすると、そこから不正侵入
を受ける事もある。また、接続できないポートを突破して侵入される
場合もある。システム管理者は、このプログラムを利用して
管理しているシステムの弱点などを調べる事もできる。
表示すると情報量が大幅に増えるのでコメントアウトしてあるが、
接続不可能なポートを表示する機能も一応付加してある。
(ソース78行目〜82行目)
portscan.c
01: /******************************************************
02: *
03: * PortScan program
04: *
05: * auther : Yuichiro Tomoyose
06: * file : portscan.c
07: * date : 2006/01/26
08: * usage : ./portscan address [address address ...]
09: *
10: *****************************************************/
11:
12: #include <stdio.h>
13: #include <ctype.h>
14: #include <string.h>
15: #include <sys/types.h>
16: #include <sys/socket.h>
17: #include <netinet/in.h>
18: #include <netdb.h>
19:
20: int main( int argc, char *argv[] )
21: {
22: int SocketNumber; /* Socket descripter */
23: int usedport; /* Used port count */
24: int i; /* argument count */
25: int nconnect = 0; /* cannot connected hosts count */
26: struct hostent *HostEntry; /* host entry */
27: struct sockaddr_in sin; /* Socket Entry */
28:
29: /* Set protocol family name */
30: sin.sin_family = AF_INET;
31:
32: /* Argument check */
33: if( argc == 1 )
34: {
35: printf("usage: ./portscan address [address address ...]\n");
36: exit(1);
37: }
38:
39: /* Arguments (Host-Name) loop */
40: for( i = 1 ; i <= (argc - 1) ; i++ )
41: {
42: usedport = 0;
43:
44: printf("----- %s -----\n",argv[i]);
45:
46: /* Host check & Get Host Entry by Host-Name */
47: if((struct hostent *)NULL == (HostEntry = gethostbyname(argv[i])))
48: {
49: printf("\7No Hosts.\n\n");
50: nconnect++;
51: }else
52: {
53:
54: bcopy(HostEntry->h_addr,&sin.sin_addr.s_addr,HostEntry->h_length);
55:
56: /* Connect Wellknown Port */
57: unsigned short count;
58: int useport;
59: for( count = 0 ; count < 1023 ; count++ )
60: {
61:
62: /* Make Socket */
63: if(0 > (SocketNumber = (socket(AF_INET,SOCK_STREAM,0))))
64: {
65: printf("\7Cannot get Socket.\n");
66: exit(1);
67: }
68:
69: /* PortNumber set */
70: sin.sin_port = htons(count);
71:
72: /* Try Connect */
73: if( 0 == connect(SocketNumber, (struct sockaddr *)(&sin), sizeof(sin)))
74: {
75: printf("--Port No.%d used.\n",count);
76: usedport++;
77: }
78: //else
79: //{
80: // printf("--Port No.%d not used.\n",count);
81: //}
82:
83: /* Close Socket */
84: close(SocketNumber);
85:
86: }
87:
88: /* Result print */
89: printf("%d port is used\n\n",usedport);
90:
91: }
92: }
93:
94: printf("Total %d hosts.\n",(argc - 1));
95: printf(" %d hosts portscan end.\n",((argc - 1) - nconnect));
96: printf(" %d hosts can't find.\n\n",nconnect);
97:
98: }
実行結果
[nw0439]% ./portscan
usage: ./portscan adress [address address ...]
[nw0439]% ./portscan 133.13.54.209 nw0439.st.ie.u-ryukyu.ac.jp mokeQ
----- 133.13.54.209 -----
--Port No.22 used.
--Port No.80 used.
--Port No.427 used.
--Port No.548 used.
4 port is used
----- nw0439.st.ie.u-ryukyu.ac.jp -----
--Port No.22 used.
--Port No.80 used.
--Port No.427 used.
--Port No.548 used.
4 port is used
----- mokeQ -----
No Hosts.
Total 3 hosts.
2 hosts portscan end.
1 hosts can't find.
[nw0439]%