CodeRed Baster of NetBSD
2001年7月頃からCodeRed WormによるCrackが頻繁に発生しています。
NetBSDに対しては大きな影響は考えられませんが、パケットが入ってくるのは悔しいし、いちいち
サービスレベルで止めるのもいやだったので、kernel内部でDirty Hackして止めてます。
kernelで処理した理由は
- ipfでTCP payload見られるとは思えなかった
- tcpdumpしてpacket引っかけてipfで止めるのはまどろっこしかった
- tcpdump+ipfではいつかはipfの設定ファイルからエントリーを消す必要がある
- 消すタイミングが判断できない
- ipfなどのuserlandで処理をすると、context switchが大量に起こり、遅くなりそう
です。
出来ればtcp_inputで処理したかったんですが、処理させたいマシンがrouterなので、
敢えてip_input.cの中で処理しました。
sys/netinet/ip_input.cのpatchを掲載しておきます。
kernelのconfiguration fileで、options _WORM_CHECK_を指定して下さい。
なお、このpatchはNetBSD-1.5.1用です。
使い方は単純で、
- このpatchを当てて、kernelをrecompileする
- /etc/syslog.confにlocal7.debugエントリーを加える
- エントリーに指定したファイルを作成する
- newsyslog.confにrotateするように指示する
(syslogdにSIGINTを送るようにするのを忘れないように)
だけです。これで、CodeRed Wormのパケットのlogも取れます。
このpatchは無保証です。動作保証はしませんし、今後の亜種にまでは対応できるか判りません。
次の野望
このcodeを書いていて判ったことは、Applicationが使用するTCP/UDP Payloadを見て処理を
するのは非常に重たいことです。そこで、以下のようなことを考えました。
- ip_input.cに文字列テーブルを読ませる
- TCP Payloadの内部を文字列テーブルの内容と比較する
- matchしたらpacketをdropする
こうすると、NetBSDでもLayer7 switchが出来るようになります。
問題は、
- kernel内部にどうやってuserlandで定義した文字列を読ませるか?
- Memory Leakが起きないようにする方法
- payloadのどこでもcheck出来るようにする方法
にあります。特に3番目は難しく、TCPのWindow Sizeがある値を超え、TCP Payloadが
Fragmentされている場合、どうやってパケットを再構成し、比較するかが重要な問題
になります。再構成するだけなら単純ですが、それで遅くならないように処理するこ
とはなかなか難しそうです。
おかげで、世の中のLayer7 switchと呼ばれる機器がどのくらい大変な処理をしている
か良く判りました。
何か良いアイデアはありませんかね?