FreeBSD 3.0 における IPSec 機能を独立検証するには
- -IPsec をインストールした時,
+
+
問題
- -まず, IPsec - がインストールされていることを前提に話を進めます. - IPsec がきちんと動作しているかどうか知るにはどうしたら良いでしょう? + ここでは, IPsec の動作を検証する実験的な方法を紹介します. + +
解
- -最初に, 暗号に使われている情報理論について考えます.
- --
-
-
-
暗号化されたデータは, 一様に分布している. つまり, - 各情報源シンボルは最大のエントロピーを持っている.
-
-
- -
-
通常, 未処理のデータや圧縮されていないデータは冗長である. - つまり, 各情報源シンボルのエントロピーは最大ではない.
-
-
ネットワークインターフェイスを入出力するデータのエントロピーを測定できると仮定すると, + 接続状態は &man.netstat.1; コマンドで確かめることができます. + しかし, それを独立して検証することは可能なのでしょうか?
MUST
- -Ueli Maurer 氏の "Universal Statistical Test for Random Bit Generators" - ("MUST") は, サンプルデータのエントロピーを高速に測定します. - これには圧縮と良く似たアルゴリズムが使われています. - - 文末に示すのは, 一つのファイル中で連続するデータ (最大 0.25 メガバイト) - を測定するコードです.
- -Tcpdump
- -さて次に, 上記に加えてネットワーク上の生データを捕捉するための手段も必要になります.
- それを実現するプログラムに, "tcpdump" と呼ばれるものがあります.
+ データの一部が暗号化モード
で暗号化されなかったとしても成立します.
Universal Statistical Test for Random + Bit Generators+ (
次のコマンド
+ カーネルコンフィグレーションファイルにおいて +tcpdump -c 4000 -s 10000 -w - dumpfile.bin- -
は, 4000 個の生パケットを捕捉し, dumpfile.bin に記録します. - この例のでは 10,000 バイト以下のパケットのみ記録されます.
- -実験
- -では, 実験してみましょう. - まず, IPsec ホストと IPsec - を使っていないホストの両方にネットワーク接続してください.
- -そしてパケットの捕捉を開始します.
- -次に, IPsec を使っている接続で "yes" という unix コマンドを実行します.
- これは, "y" という文字の連続データを出力するものです.
+
IPsec を使っている接続で &man.yes.1; という unix コマンドを実行します. + これは,
ここで, MUST - を捕捉したパケットに実行すると, 次のような出力が得られるはずです. + こちらも, しばらくしたらコマンドを停止させてください.
% tcpdump -c 4000 -s 10000 -w ipsecdemo.bin -% uliscan ipsecdemo.bin +通常の接続が 29% (2.1) + という結果になっていることです.
注意
- -この実験は暗号化の理論が示すとおり, IPsec
- を使った通信では確かにペイロード中のデータに含まれるシンボルの生起確率が一様に分布する,
+
IPsec の定義
+ これらはソースを調べれば確かめることができます. + -インターネットプロトコル セキュリティ拡張
+
IPsec のインストール
+ここでは FreeBSD 3.0 stable を想定しています.
- --
-
-
-
IPsec v0.04 をインストールして, - カーネル再構築とインストールを行なう.
-
-
- -
-
管理用のツール (たとえば ipsecadm) を実行し, - 暗号鍵を配布 (もしくは Photuris を使って鍵交換) する.
-
-
- -
-
ネットワーク経路 (rt) を適切に設定する.
-
-
ipsecadm および rt を実行して - IPsec トンネルを確立するための "ipsec_setup" - スクリプトを作成しても良いでしょう. - スクリプトは, 起動時に /etc/rc.local から自動で実行させることができます. - ipsec_setup でトンネルを確立するには, 少なくとも 2 つの - ipsecadm コマンドと, 1 つの - rt コマンドが含まれている必要があるでしょう.
- -usr/src/sys/i386/conf/KERNELNAME
- -IPsec を実行するには, - カーネルコンフィグレーションファイルに以下の行が含まれていなければなりません. - これらの行を追加して config を実行し, - カーネルの再構築とインストールを行なってください.
- -# The `bpfilter' pseudo-device enables the Berkeley Packet Filter. Be -# aware of the legal and administrative consequences of enabling this -# option. Heh heh. The number of devices determines the maximum number of -# simultaneous BPF clients programs runnable. -pseudo-device bpfilter 2 #Berkeley packet filter - -# IPSEC -options IPSEC -options "MD5" -pseudo-device enc 1- -
Maurer's Universal Statistical Test - (ブロックサイズ = 8 ビット)
- -/* ULISCAN.c ---blocksize of 8 1 Oct 98 1 Dec 98 21 Dec 98 uliscan.c derived from ueli8.c This version has // comments removed for Sun cc This implements Ueli M Maurer's "Universal Statistical Test for Random Bit Generators" using L=8 Accepts a filename on the command line; writes its results, with other info, to stdout. Handles input file exhaustion gracefully. Ref: J. Cryptology v 5 no 2, 1992 pp 89-105 also on the web somewhere, which is where I found it. -David Honig honig@sprynet.com Usage: ULISCAN filename outputs to stdout */ #define L 8 -#define V (1<- - - - +} +-#include +#include <stdio.h> +#include <math.h> int main(argc, argv) int argc; char **argv; { FILE *fptr; int i,j; int b, c; int table[V]; double sum = 0.0; int iproduct = 1; int run; extern double log(/* double x */); printf("Uliscan 21 Dec 98 \nL=%d %d %d \n", L, V, MAXSAMP); - if (argc < 2) { + if (argc < 2) { printf("Usage: Uliscan filename\n"); exit(-1); } else { printf("Measuring file %s\n", argv[1]); } fptr = fopen(argv[1],"rb"); if (fptr == NULL) { printf("Can't find %s\n", argv[1]); exit(-1); } - for (i = 0; i < V; i++) { + for (i = 0; i < V; i++) { table[i] = 0; } - for (i = 0; i < Q; i++) { + for (i = 0; i < Q; i++) { b = fgetc(fptr); table[b] = i; } printf("Init done\n"); printf("Expected value for L=8 is 7.1836656\n"); run = 1; while (run) { sum = 0.0; iproduct = 1; if (run) - for (i = Q; run && i < Q + K; i++) { + for (i = Q; run && i < Q + K; i++) { j = i; b = fgetc(fptr); - if (b < 0) + if (b < 0) run = 0; if (run) { - if (table[b] > j) + if (table[b] > j) j += K; sum += log((double)(j-table[b])); table[b] = i; } } if (!run) printf("Premature end of file; read %d blocks.\n", i - Q); sum = (sum/((double)(i - Q))) / log(2.0); printf("%4.4f ", sum); - for (i = 0; i < (int)(sum*8.0 + 0.50); i++) + for (i = 0; i < (int)(sum*8.0 + 0.50); i++) printf("-"); printf("\n"); /* refill initial table */ if (0) { - for (i = 0; i < Q; i++) { + for (i = 0; i < Q; i++) { b = fgetc(fptr); - if (b < 0) { + if (b < 0) { run = 0; } else { table[b] = i; } } } } -}]]>