055745F:仲本拡
提出日 :2006/12/11
目的
課題1
課題2
課題3
課題4
課題5
課題6
参考

目的
 本実験テーマ「TCP/IPプログラミング」では、インターネットアプリケーションで用いられるパケット転送プロトコルの中核であるTCP/IPについて、パケット交換の仕組みやIPアドレス・ポート番号の概念を理解し、基本的なソケットプログラミング(クライアントサーバプログラミング)技術を身につけることを目的とする。また、TCP/IPプログラミング(ソケットプログラミング)における基本的なセキュリティについても、例題プログラムの検証を通して身に付ける。
課題1:telnetコマンドによるWWWサーバへのアクセス
telnetコマンドを使って任意のWWWサーバにアクセスし、任意のURLのページデータ(htmlソースプログラム)を画面に表示せよ。(報告書にはそのURLとページデータの先頭の20行程度を添付せよ)

実行結果

[SEED-~]> telnet www21.tok2.com 80
Trying 124.38.187.122...
Connected to www21.tok2.com.
Escape character is '^]'.
GET /home/nh20051217/index.htm HTTP/1.0

HTTP/1.1 200 OK
Date: Wed, 29 Nov 2006 04:18:16 GMT
Server: Apache/1.3.26 (Unix) PHP/5.0.3 mod_layout/2.8.2 PHP/3.0.18-i18n-ja-2
ModLayout: 2.8.2
Last-Modified: Mon, 27 Nov 2006 05:13:29 GMT
Cache-Control: no-cache
Connection: close
Content-Type: text/html

@<BODY bgcolor="#ffffff"><!-- TOK2_TOP -->ryukyu.ac.jp">arset=shift_jis">

<style TYPE="text/css">
<!--
body{
margin-top:5px;
margin-right:5px;
margin-left:5px;
}
.TOK2-FONT{
color:#000000;
font-size:12px;
}


課題2:inetdを使用するサーバプログラムの作成
サンプルプログラム(1)はサーバ(server.c)をinetdから起動することで、サーバはクライアント(client.c)の標準入力から入力された文字に対応するキーワードをクライアントに返すプログラムである。サンプルプログラム(1)を自分の実験環境で動作するようにし、実行結果を示すとともに、プログラムの中で使われている関数(Connect,Disconnect, Send Data, Recv Dataなど)の動作を説明し、サーバ・クライアント動作全体をフローを示して説明せよ。

実行結果
[SEED-slab2]> sudo xinetd -inetd_compat
Password:
[SEED-slab2]> client
Connected.
Input Keyword = warning: this program uses gets(), which is unsafe.
yama
Keyword = [yama] / Data = [kawa]

Input Keyword = 123
Keyword = [123] / Data = [456]

Connect()の動作
ソケットを生成して、サーバーに接続要求を出す。

Disconnect()の動作
ソケットを閉じて、サーバーとの接続を切る。

SendData()の動作
標準入力から入力された文字列を、サーバに送る。

RecvData()の動作
サーバから受け取った文字列を、標準出力に出力する。

動作全体




課題3:inetdを使用しないサーバプログラムの作成

サンプルプログラム(1)のサーバプログラム(server.c)はinetdから起動するものであるが、inetdを使用せずに同じ動作をするデーモン型のサーバプログラムを作成し、実行結果を示すとともに、inetdを使用するサーバプログラムとそうでないものとの実装上の違いを説明せよ。


client.c
server.c
実行結果
[SEED-slab2-2]> server
now waiting for client connect
Connected from 127.0.0.1
[SEED-slab2-2]> client
Connected.
Input Keyword = warning: this program uses gets(), which is unsafe.
yama
Keyword = [yama] / Data = [kawa]

Input Keyword = 123
Keyword = [123] / Data = [456]

 inetdを使用するサーバプログラムが、クライアントから要求のあった時にのみ動作するのに対し、デーモン型は常に動いている。
 故にデーモン型は、クライアントからの要求に常に答える為に、プログラムにソケットを用意しておく必要がある。


課題4:HTTPクライアントの作成
ソケットおよびHTMLを使ってWWWサーバから任意のURLのページを取得し、標準出力に出力するプログラムを作成せよ。


kadai4.c
実行結果
[SEED-slab2]> kadai4 www21.tok2.com/home/nh20051217/ | nkf -euc
HTTP/1.1 200 OK
Date: Mon, 04 Dec 2006 06:17:25 GMT
Server: Apache/1.3.26 (Unix) PHP/5.0.3 mod_layout/2.8.2 PHP/3.0.18-i18n-ja-2
ModLayout: 2.8.2
Last-Modified: Sun, 03 Dec 2006 08:03:48 GMT
Cache-Control: no-cache
Connection: close
Content-Type: text/html

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<HTML lang="ja">
<HEAD>
省略
<td><input type="image" name="searchbox" src="http://image.tok2.com/btn3/ss.gif" align="absmiddle" height="18" /></td>
</tr>
</form>
</table>

</td>
</tr>
</table>

</center>

<!-- TOK2_UNDER_END-->
</BODY>
</HTML>


課題5:ポートスキャンの実験
自分の実験環境(端末)の使用/未使用ポート(ウェルノウンポートのみでok)を確認するポートスキャンプログラムを作成せよ。さらに、任意のリモート端末の使用/未使用ポートを確認するように改良せよ(加点ポイント)。なお、スクリプトを使って内部で'netstat -l'コマンドを実行し、その結果を利用するのは不可とする(ソケットプログラムを作成すること)。


portscan.c
gethostbyname()関数によって、引数として与えられたホストの構造体を探して、それを返す。

実行結果
[SEED-portscan]> portscan localhost
localhost use port 80
localhost use port 427
localhost use port 548
localhost use port 631


課題6:バッファオーバーフローの実験
サンプルプログラム(2)を実行せよ。このプログラムはgets()関数を用いて、標準入力からの入力をバッファにデータを読み込むものであるが、結果を見ると、プログラム中で操作していないバッファdmy[]に値が入ることがある。この原因を考察し、解決策を示せ。また、この問題によって引き起こされるTCP/IP通信におけるセキュリティ上の欠陥はどのようなものが考えられるか、具体例を挙げて述べよ。

※実験をする際に、BUFLENの値を1に変更した。
実行結果
[SEED-bufovf]> bufovf
before
buf(Len:0) =
dmy(Len:0) =
warning: this program uses gets(), which is unsafe.
1234567891123456789212345678931234567894123456789512345678961
after
buf(Len:61) = 1234567891123456789212345678931234567894123456789512345678961
dmy(Len:0) =
Segmentation fault

 gets()関数には、上限値を設定できないという欠陥がある。その欠陥のせいで、BUFLENの値が有効にならない。
 bufとdmyで、メモリを分割している。上限値を設定できなければ、bufに格納したものが、dmyに割り当てられた領域にまでおよび、上の事態になる。

 この状態を改善するには、上限値の設定ができるfgets()関数を使えばよい。

 上記の実行結果からわかるように、バッファオーバーフローは、プログラマの意図していない場所に値が書き込まれる事である。これがあると、他のプログラムに悪影響を及ぼしかねない。

参考

JM Project(http://www.linux.or.jp/JM/index.html)