- val (b,s) = pfm_start pfm s;
> val b = true : bool val s = <store> : store
まず,アウトバウンド フィルタの動作を確認するために,内部ホストから外部ホストへ パケットを送信してみる.パケットの生成は次のように行う.
- val (p,s) = new_packet 20 1070 250 80 TCP s;
> val p = <packet> : packet val s = <store> : store
これは送信元アドレ スが(20,1070),宛先アドレ スが(250,80),プ ロトコルがTCPのパ ケットである.
このパケットに対しアウトバウンド フィルタpfm_filterOutを適用する.
- val (msg,p,s) = pfm_filterOut pfm p s;
> val msg = "pass: new connection" : string val p = <packet> : packet
val s = <store> : store
入力パケットはフィルタルールを満たすので,通過が許可される.出力メッセージmsgは,
入力パケットを新しい接続のパケットとして通過許可したことを表している.実際に次の ように接続表を表示することにより,新しい接続が生成されていることがわかる.
- pfm_getConnections pfm s;
> val it = [((20, 1070), (250, 80), 300)] : ((int * int) * (int * int) * int) list val s = <store> : store
300という値は,この接続のタイムアウト残り時間である.
また,アドレス変換表は次のようになっている.
- pfm_getNatrules pfm s;
> val it = [((20, 1070), (200, 1200), 500)]
: (((int * int) * (int * int)) * int) list
これは,接続が生成された際に動的に生成された変換規則であり,内部アドレス(20, 1070) をファイアウォールの公開アドレス (200,1200)に変換するという規則である.この規則 のタイムアウト残り時間は 500である.
送出されたパケットの送信元アドレスが確かに変換されていることは次のように確認す ることができる.
- packet_getInfo p s;
> val it = ((200, 1200), (250, 80), 0) : (int * int) * (int * int) * int
これは,パケット pの送信元アドレスが(200,1200),宛先アドレスが(250,80),プロトコ ルが 0(変数TCPの値)であることを意味する.したがって,確かに送信元アドレスが最 初の(20,1070)から公開アドレス(200,1200)に変換されている.
一方,次のアウトバウンド パケットは通過拒否される.
- val (p,s) = new_packet 20 1070 250 53 TCP s;
- val (msg,p,s) = pfm_filterOut pfm p s;
> val msg = "drop: rule not match" : string val p = <packet> : packet
val s = <store> : store
このパケットは宛先ポートが 53となっており,フィルタルールを満たさないために拒否 される.
次に,インバウンド フィルタの動作を確認するために,先程通過したパケットに対する リプライのパケットを生成し,インバウンド フィルタpfm_filterInを適用する.
- val (p,s) = new_packet 250 80 200 1200 TCP s;
- val (msg,p,s) = pfm_filterIn pfm p s;
> val msg = "pass: existing connection" : string val p = <packet> : packet
val s = <store> : store
このパケットは既存の接続に属すものであるから,無条件に通過が許可される.この出力 パケットの内容は次のようになっている.
- packet_getInfo p s;
> val it = ((250, 80), (20, 1070), 0) : (int * int) * (int * int) * int
インバウンド 送信ではアウトバウンド 送信の際に生成された変換規則を用いて,宛先アド レスを(200,1200)から(20,1070)に変換する.結果としてリプライがアウトバウンド 送信 を行った内部アドレスに届くことになる.
一方,次のインバウンド パケットは通過拒否される.
- val (p,s) = new_packet 250 80 200 1210 TCP s; (3)
- val (p,msg,s) = pfm_filterIn pfm p s;
> val p = <packet> : packet
val msg = "drop: no dstnat rule" : string val s = <store> : store
このパケットは外部アドレ ス(250,80)からファイアウォールの公開アドレ ス(200,1210) へ送信されたものである.このパケットが拒否されるのは,(200,1210)に対する宛先アド レス変換規則が定義されていないためである.仮に,これが許可されたアウトバウンド パ ケットのリプライのパケットであればアウトバウンド 送信時に(200,1210)に対応する変換 規則が定義されていたはずである.したがって,このパケットは新しいインバウンド 送信 とみなされ,通過拒否される.
ここで,タイムアウト時間の動作を確かめるため,時間を 100秒経過させ,接続表,ア ドレス変換表を表示してみる.
- val s = pfm_incSec pfm 100 s;
> val s = <store> : store - pfm_getConnections pfm s;
> val it = [((20, 1070), (250, 80), 200)]
: ((int * int) * (int * int) * int) list - pfm_getNatrules pfm s;
> val it = [((20, 1070), (200, 1200), 400)]
: ((int * int) * (int * int) * int) list
pfm_incSecは時間を引数で与えられる秒数だけ進める関数である.それぞれのタイムア
ウト時間が 100秒減少し,200, 400となっていることがわかる.タイムアウト時間は,接 続の場合,その接続に属すパケット送受信があったとき,変換規則の場合,その変換規則 が使用されたとき,再設定される.そこで,リプライのアウトバウンド パケットを次のよ うに送信する.
- val (p,s) = new_packet 20 1070 250 80 TCP s;
- val (p,msg,s) = pfm_filterOut pfm p s;
val p = <packet> : packet
val msg = "pass: existing connection" : string val s = <store> : store
これは既存の接続に属すアウトバウンド パケットであるから,フィルタルールに無条件に 通過する.
ここで,接続表,アドレス変換表を表示すると,確かにタイムアウト時間がもとの300, 500に再設定されていることが分かる.
- pfm_getConnections pfm s;
> val it = [((20, 1070), (250, 80), 300)]
: ((int * int) * (int * int) * int) list - pfm_getNatrules pfm s;
> val it = [((20, 1070), (200, 1200), 500)]
: ((int * int) * (int * int) * int) list
次の 3つのパケット送受信はいずれも許可される.
- val (p,s) = new_packet 10 1050 250 80 TCP s; (1) - val (p,msg,s) = pfm_filterOut pfm p s;
- val (p,s) = new_packet 30 1100 250 80 TCP s; (2) - val (p,msg,s) = pfm_filterOut pfm p s;
- val s = pfm_incSec pfm 100 s;
- val (p,s) = new_packet 250 80 200 1220 TCP s; (3) - val (p,msg,s) = pfm_filterIn pfm p s;
(1)は新しい接続のパケットであり,フィルタルールを満たすので通過する(この時点で,
図6.1の状態となる).(2)も同様に新しい接続のパケットであり,フィルタルールを満た すので通過する(図6.2).(3)は(2)に対するリプライであり,直前に100秒経過している が,(2)の接続はまだタイムアウトしていない(残り時間200)ため,通過する(図6.3).
この時点で接続表,アドレス変換表は次のようになっている.
- pfm_getConnections pfm s;
> val it =
[((30, 1100), (250, 80), 300), ((10, 1050), (250, 80), 200), ((20, 1070), (250, 80), 200)]
: ((int * int) * (int * int) * int) list - pfm_getNatrules pfm s;
> val it =
[((30, 1100), (200, 1220), 500), ((10, 1050), (200, 1210, 400)), ((20, 1070), (200, 1200), 400)]
: ((int * int) * (int * int) * int) list
ここで,時間を200秒経過させ,残り時間が 200となっている2 つの接続を切断する.
- val s = pfm_incSec pfm 200 s;
- pfm_getConnections pfm s;
> val it = [((30, 1100), (250, 80), 100)] : ((int * int) * (int * int) * int) list - pfm_getNatrules pfm s;
> val it =
[((30, 1100), (200, 1220), 300), ((10, 1050), (200, 1210), 200), ((20, 1070), (200, 1200), 200)]
: ((int * int) * (int * int) * int) list
この状態から次のように様々な場合のパケット送受信を行う.
- val (p,s) = new_packet 10 1100 250 80 TCP s; (1) - val (p,msg,s) = pfm_filterOut pfm p s;
val p = <packet> : packet
val msg = "drop: physically unconnectable" : string val s = <store> : store
- val (p,s) = new_packet 20 1070 250 80 TCP s; (2) - val (p,msg,s) = pfm_filterOut pfm p s;
val p = <packet> : packet
val msg = "pass: new connection" : string val s = <store> : store
- val (p,s) = new_packet 250 80 200 1210 TCP s; (3) - val (p,msg,s) = pfm_filterIn pfm p s;
val p = <packet> : packet
val msg = "drop: inbound not permit" : string val s = <store> : store
(1)は内部アドレス(10,1100)からの新しい接続のパケットである.このアドレスに対する 変換規則は定義されていないので新しく生成されなければならないが,現時点で 3 つの
ポート 1050, 1070, 1100すべてが占有されているため,変換規則が生成できない状態であ
る.したがって,物理的に接続不可能というメッセージとともに通過拒否される.(2)も 同様に内部アドレス(20,1070)からの新しい接続のパケットであるが,この場合,変換規 則がすでに定義されている(変換表の最後の要素)ため,新たに規則を生成する必要がな い.したがって,物理的容量の問題はクリアし ,接続可能となる.(3)は,外部アドレス (250,80)からファイアウォールの公開アドレス(200,1210)へのインバウンド 送信である.
この場合,(200, 1210)に対する宛先アドレ ス変換規則は定義されているが,変換先の内 部アドレス(10,1050)との間に接続が存在しないということで新しいインバウンド 送信と みなし ,通過拒否される.
ここで,DoSカウンタの動作を確認するために,次の3つの不正インバウンドパケット を受信する.
- val (p,s) = new_packet 250 80 200 1210 TCP s; (4) - val (p,msg,s) = pfm_filterIn pfm p s;
val p = <packet> : packet
val msg = "drop: inbound not permit" : string val s = <store> : store
- val (p,s) = new_packet 250 80 200 1210 TCP s; (5) - val (p,msg,s) = pfm_filterIn pfm p s;
val p = <packet> : packet
val msg = "drop: inbound not permit" : string val s = <store> : store
- val (p,s) = new_packet 250 80 200 1210 TCP s; (6) - val (p,msg,s) = pfm_filterIn pfm p s;
val p = <packet> : packet
val msg = "drop: inbound not permit" : string val s = <store> : store
この時点で,この秒間における拒否されたパケットの数が,(4)(5)(6)と,前の(1)(3)を 合わせてDoSカウンタ閾値である 5に達したため,次のように,警告フラグが立ってい るのが確認できる.
- pfm_getDosAlert pfm s;
> val it = true
最後に,パケットフィルタを停止する.停止時には接続表,変換表がリセットされる.
- val (b,s) = pfm_stop pfm s;
> val b = true : string val s = <store> : store - pfm_getConnections pfm s;
> val it = [] : ((int * int) * (int * int) * int) list - pfm_getNatrules pfm s;
> val it = [] : ((int * int) * (int * int) * int) list