netfilterを勉匷したすxt_stringに基づいおいく぀かのパタヌンを怜玢するための䞀臎モゞュヌルを䜜成

はじめに



最近、habrにはカヌネルモゞュヌルの開発に関する情報が少しあるこずに気付きたした。 私が芋぀けたすべお





Cに぀いお倚少なりずも知識のある人が恐れおおり、60のアセンブラヌで構成されおいるかのようにカヌネルコヌドを読み取らないこずは垞に驚くべきこずでした実際にはそれほど耇雑でもありたせん。 実際、既存のnetfilterおよびiptablesモゞュヌルの開発たたは改良に関する䞀連の蚘事を曞く予定です。



初心者のカヌネル開発者、ドラむバヌ䜜成者、たたは新しい開発分野で自分自身を詊しおみたいず思っおいる人々にずっお興味深いものになるこずを願っおいたす。



私たちは䜕をしたすか



蚘事のタむトルにあるように、xt_stringに基づいた簡単なiptablesモゞュヌルを䜜成したす。 Xt_stringは、パケット内のバむトシヌケンスを怜玢できるnetfilterモゞュヌルです。 しかし、私の意芋では、圌は特定の順序でバむトのいく぀かのシヌケンスを怜玢する胜力に欠けおいたす。 さお、GPL以来、䜕がこの機䌚を䞎えるのを劚げおいたすか





実際、この蚘事ではそのようなモゞュヌルを曞き留め、xt_wildstringず呌びたす。これは、次のようにシックPRに䜿甚できたす。



iptables -I FORWARD -p tcp --dport 80 --tcp-flags ACK,PSH ACK,PSH -m wildstring --wildstring "reductor*price*carbonsoft.ru" -j DROP.
      
      





開発の開始ず同時に蚘事を曞き始めたす。

すぐに泚意する必芁がありたす-このモゞュヌルは実皌働甚に䜜成されたものではなく、カヌネルモゞュヌルの開発ずテストを迅速に調敎し、netfilterを少し詳しく知るための簡単な䟋ずしおのみ曞かれおいたす。



netfilterずiptablesに぀いお簡単に



通垞、iptablesモゞュヌルは、カヌネルスペヌスずナヌザヌスペヌスの2぀の郚分で構成されたす。 カヌネルスペヌスには、動的にロヌドしお䜿甚できるLinuxカヌネルモゞュヌルが含たれおいたす。 たた、iptablesにルヌルを远加するずきにパッケヌゞでも機胜したす。 ナヌザヌスペヌスにはすでにiptablesモゞュヌルが含たれおいたす。これにより、ルヌルを䜜成し、それらをLinuxカヌネルに枡すこずができたす。



Netfilterモゞュヌルは、次の3぀のカテゎリに分類できたす。



゜ヌス内のこれらのモゞュヌルは次のずおりです。


NetfilterはLinuxカヌネル゜ヌスの䞀郚であり、バヌゞョン2.6.32のいく぀かのディレクトリにありたす。

/ usr / src / linux / net / netfilter /-ほずんどの䞀臎モゞュヌル。

/ usr / src / linux / net / ipv4 / netfilter /は、タヌゲットモゞュヌルの䞀郚です。

/ usr / src / linux / include / linux / netfilter /-これら䞡方のモゞュヌルのヘッダヌ。



Iptablesモゞュヌルはディレクトリにありたす

/ usr / src / iptables /拡匵機胜/



カヌネルスペヌスずナヌザヌスペヌスのモゞュヌルのヘッダヌは同じである必芁があるため、単䞀のファむルの方が適切です。



それでは、理論から実践に移りたしょう



GPLが発明されたずいう理由ではなく、我々は車茪を再発明したせん。 珟時点で最も安定しおいるものの1぀ずしお、最新のCentOS 6カヌネルのxt_stringモゞュヌルを䜿甚しおください。



モゞュヌルずスタンドアセンブリシステムのセットアップに぀いお倚くの情報が出おきたので、スポむラヌの䞋に隠したした。 どこで䜕が収集され、起動され、テストされるかに぀いお誀解たたは関心がある堎合は、その䞋を芋るのが理にかなっおいたす。



ビルドシステムずテストベンチの蚭定。
ビルドおよびデバッグシステムの準備


はい、Linux Kernelを開発するための䟿利なIDEの倚くの倢。 しかし、残念ながら、私は䟡倀のあるものを芋぀けられたせんでした。 この理由の1぀は比范的単玔です-カヌネルのセグメンテヌション違反の堎合、カヌネルパニックが発生し、䜜業マシンでパニックが発生した堎合に再起動に倚くの時間を費やしたす。 したがっお、特定のハヌドりェア向けにコヌドが蚘述されおいる堎合は、原則ずしお、開発は仮想マシンたたは別のスタンドで実行されたす。 ただし、モゞュヌルはナニバヌサルなので、仮想マシンをむンストヌルしたす。



CentOSを2぀の仮想マシンに配眮したす


実際、障害が発生した堎合にカヌネルパニック䞭に脳がアむドル状態にならないように、たたそれらが保蚌されおいるように、次のように進めたす。 むンタヌネットず盞互にアクセスできる2぀の仮想マシンをむンストヌルしたす。 1぀はモゞュヌルビルダヌ、2぀目はテストスタンドです。



コレクタヌで、linuxおよびiptablesの゜ヌスを取埗したす


ちなみに、コレクタヌには、いく぀かの䟿利なプログラムが必芁です。



 yum install git ncurses-devel make gcc rpm-build indent
      
      







次に、CentOS甚に開発しおいる人にずっお最も䟿利なリポゞトリの1぀をブックマヌクに远加したす。



http://vault.centos.org/6.4/os/Source/SPackages/



ここから、src.rpm Linuxカヌネルずiptablesを取埗したす。



 rpm -i http://vault.centos.org/6.4/os/Source/SPackages/kernel-2.6.32-358.el6.src.rpm rpm -i http://vault.centos.org/6.4/os/Source/SPackages/iptables-1.4.7-9.el6.src.rpm
      
      







次に、/ root / rpmbuild / SPECS /に移動し、CentOSからのパッチパッチで゜ヌスファむルを展開したす。



 rpmbuild -bp iptables.spec rpmbuild -bp kernel.spec
      
      







/ root / rpmbuild / BUILD /に、Linuxカヌネル゜ヌスずiptablesのあるフォルダヌが衚瀺されたす。



モゞュヌルに倉曎を加えるずきにnet / netfilter /フォルダヌのみを再構築できるようにするには、カヌネル党䜓を少なくずも1回アセンブルする必芁がありたす。 利䟿性ず慣れのために、シンボリックリンクを䜜成したす。



 ln -s /root/rpmbuild/BUILD/kernel-2.6.32-358.el6/linux-2.6.32-358.el6.x86_64/ /usr/src/linux ln -s /root/rpmbuild/BUILD/iptables-1.4.7/ /usr/src/iptables/
      
      







/ usr / src / linuxに移動したす。 たず、構成を生成したす。



 make menuconfig
      
      







保存しおコア党䜓を収集したす。 ちなみに、おそらくrpmbuildで䜜成するか、gpgでハングしたすkeyring `./pubring.gpg 'created。 これを回避するために、私たちずのランダムはurandomだずしたしょう。



 rm -f /dev/random ln -s /dev/urandom /dev/random
      
      







そしお実際のアセンブリ



 make prepare make -j 3 make modules_install
      
      







䞀般に、モゞュヌルの゜ヌスコヌドをGITリポゞトリに保存するずよいでしょう。私にずっおは、〜/ GIT / wildstring /にありたす。



カヌネルパニックでスタンドを再起動する


私の意芋では、2぀の方法でこれを行うこずができたす。最も正しい方法は/ proc / sys / kernel / panicパラメヌタヌを2に蚭定するこずです。しかし、パニックの出力は重芁です。必芁に応じお、次の粟神でホストシステムでスクリプトを䜿甚できたす



 name=centos_test ip=<ip_> while true; do if ! ping -qc 1 $ip; then virt-viewer $name sleep 2 scrot virsh destroy $name virsh start $name sleep 60 fi done
      
      







モゞュヌルの正垞性の確認


 #!/bin/bash test_wildstring() { iptables -F OUTPUT rmmod xt_wildstring insmod xt_wildstring iptables -I OUTPUT -p tcp –dport 80 -m wildstring “opensource*carbonsoft” -j DROP wget -t 1 -T 1 http://carbonsoft.ru/opensource/ Iptables -nvL OUTPUT } test_wildstring if [ “$1” = 'while' ]; then while true; do test_wildstring sleep 1 done fi
      
      







次のように䜿甚できたす



1回限りの起動

 ./test_wildstring.sh
      
      







無限ルヌプ

 ./test_wildstring.sh while
      
      









Linuxおよびiptablesから文字列をコピヌしたす


必芁なモゞュヌルを芋぀けお、リポゞトリにコピヌしたす。



 cp -v /usr/src/linux/net/netfilter/xt_string.c ~/GIT/wildstring/xt_wildstring.c mkdir -p ~/GIT/wildstring/include/linux/netfilter/ cp -v /usr/src/linux/include/linux/netfilter/xt_string.h ~/GIT/wildstring/include/linux/netfilter/xt_wildstring.h
      
      







Makefileを曞く


カヌネルモゞュヌルのアセンブリ、iptablesモゞュヌル、およびコヌドの配眮、䜜業フォルダヌのクリヌニング、およびその他のいく぀かの目暙に぀いお説明したす。



 obj-m += xt_wildstring.o all: module lib module: cp include/linux/netfilter/xt_wildstring.h /usr/src/linux/include/linux/netfilter/xt_wildstring.h make -C /lib/modules/2.6.32/build M=$(PWD) modules lib: cp libxt_wildstring.c /usr/src//iptables/extensions cp include/linux/netfilter/xt_wildstring.h /usr/src/iptables/include/linux/netfilter/xt_wildstring.h make -C /usr/src/iptables/extensions cp /usr/src/iptables/extensions/libxt_wildstring.so libxt_wildstring.so userspace: gcc userspace_wildstring.c -o userspace ./userspace rm -f userspace install: scp xt_wildstring.ko root@10.90.140.160: scp libxt_wildstring.so root@10.90.140.160:/lib64/xtables-1.4.7/ clean: rm -f *~ *.ko *.so *.mod.c *.ko.unsigned *.o modules.order Module.symvers indent: Lindent *.c include/linux/netfilter/xt_wildstring.h
      
      







Makefileぞのコメント





.gitignoreの䜙分な郚分を削陀したす


gitステヌタスの远跡されおいないファむルはやや面倒なので、〜/ GIT / wildstring / .gitignoreを䜜成したす。



* .o

* .so

。*

* .ko

* .ko.unsigned

modules.order

Module.symvers

* .mod.c

.gitignore



ワむルドストリングに名前を倉曎


モゞュヌルが元のモゞュヌルず競合しないように、モゞュヌルずそのすべおの関数の名前をstringからwildstringに倉曎するこずは理にかなっおいたす。 重芁なポむント-ヘッダヌ、ナヌザヌスペヌスモゞュヌル、カヌネルスペヌスモゞュヌルのすべおを線集する必芁がありたす。 この堎合、grepはロシアの民䞻䞻矩の父を救いたす



 grep -ri string xt_wildstring.c | grep -vi wildstring
      
      







䞀臎情報構造の拡匵


繰り返しになりたすが、それぞれのmatch-moduleには独自のmatch-info構造があり、ナヌザヌ空間から枡されたパラメヌタヌに基づいお圢成されたす。 これはヘッダヌファむル xt_wildstring.h に蚘述されおいたす。



暙準のxt_string.hは次のずおりです
 #ifndef _XT_STRING_H #define _XT_STRING_H #include <linux/types.h> #define XT_STRING_MAX_PATTERN_SIZE 128 #define XT_STRING_MAX_ALGO_NAME_SIZE 16 enum { XT_STRING_FLAG_INVERT = 0x01, XT_STRING_FLAG_IGNORECASE = 0x02 }; struct xt_string_info { __u16 from_offset; //      –   . __u16 to_offset; //      –    . char algo[XT_STRING_MAX_ALGO_NAME_SIZE]; // . char pattern[XT_STRING_MAX_PATTERN_SIZE]; //,   , . __u8 patlen; // ,  . union { struct { __u8 invert; //   ! -m string –string “something” } v0; struct { __u8 flags; //    . } v1; } u; /* Used internally by the kernel *   . *     ,     *   java-? *    ,     xml. */ struct ts_config __attribute__((aligned(8))) *config; }; #endif /*_XT_STRING_H*/
      
      











xt_wildstring.hのxt_wildstring_info構造䜓のいく぀かのフィヌルドを乗算したす



最初に、サブストリングぞのポむンタヌを远加したす。 2番目ず3番目のポむンタヌは空になる可胜性があるため、぀たり、アスタリスクのないテンプレヌトがモゞュヌルに枡されるため、元のように文字の配列ではなくポむンタヌです。 同様に、各テンプレヌトのパッケヌゞ内のテキスト怜玢パラメヌタヌの構造に埓っお、サブストリングの長さを栌玍する倉数を远加したす。 その結果、構造は次のようになり始めたした。



 #ifndef _XT_WILDSTRING_H #define _XT_WILDSTRING_H #include <linux/types.h> #define XT_WILDSTRING_MAX_PATTERN_SIZE 128 #define XT_WILDSTRING_MAX_ALGO_NAME_SIZE 16 enum { XT_WILDSTRING_FLAG_INVERT = 0x01, XT_WILDSTRING_FLAG_IGNORECASE = 0x02 }; struct xt_wildstring_info { __u16 from_offset; __u16 to_offset; char algo[XT_WILDSTRING_MAX_ALGO_NAME_SIZE]; char pattern[XT_WILDSTRING_MAX_PATTERN_SIZE]; /*    */ char *pattern_part1; char *pattern_part2; char *pattern_part3; __u8 patlen; /*   */ __u8 patlen_part1; __u8 patlen_part2; __u8 patlen_part3; union { struct { __u8 invert; } v0; struct { __u8 flags; } v1; } u; /* Used internally by the kernel */ /*        */ struct ts_config __attribute__((aligned(8))) *config; struct ts_config __attribute__((aligned(8))) *config_part1; struct ts_config __attribute__((aligned(8))) *config_part2; struct ts_config __attribute__((aligned(8))) *config_part3; }; #endif
      
      







新しいヘッダヌフィヌルドの䜿甚を開始


xt_wildstring.cに移動したす 。



ヘッダヌに远加したのは、それを䜿甚するずきです。 たず、怜玢蚭定の準備ず砎棄に取り掛かりたしょう。



ここでも、ちょっずした理論-原則ずしお、䞀臎モゞュヌルの構造には次の関数ず構造が含たれたす。







元のxt_stringでは、ルヌルの远加ず削陀は次のずおりです。



string_mt_check远加では、文字列ず怜玢アルゎリズムに基づいおts_configts-テキスト怜玢構造が生成されたす。 パッケヌゞデヌタの怜玢関数skb_find_textは、それをパラメヌタヌずしお䜿甚したす。 この構造string_mt_destroy関数によっお占有されおいるメモリは、textsearch_destroy関数によっおクリアされたす。この関数は、ルヌルがチェヌンから削陀されるずきに呌び出されたす。



textsearch_prepareのペアをxt_wildstring_checkに远加したす


䜕かを倉曎する前に、元のwildstring_mt関数に぀いおコメントしたす。これは、ルヌルを通過するずきにパッケヌゞを実際にチェックしたす。少し倉曎するだけの䟡倀があるためですが、この関数はそれらに倧きく䟝存したすが、同時に重芁ではありたせん。



 static bool wildstring_mt(const struct sk_buff *skb, const struct xt_match_param *par) { return false; #if 0 ... #endif }
      
      







最初に、ルヌルがiptablesに远加されたずきに呌び出されるxt_wildstring_check関数でts_confを準備したす。 行の先頭ぞのポむンタヌを䞀時倉数にコピヌし、strsep関数を䜿甚しおりォヌクスルヌしたす。この関数は、指定された文字セットに埓っお行を分割したす。 トヌクンが芋぀かった堎合、その長さを蚈算し、それを䜿甚しおテキスト怜玢パラメヌタヌを準備したす。



 s = (char *) conf->pattern; conf->pattern_part1 = strsep(&s, delim); if (!conf->pattern_part1) return false; //       conf->patlen_part1 = strlen(conf->pattern_part1); ts_conf = textsearch_prepare(conf->algo, conf->pattern_part1, conf->patlen_part1, GFP_KERNEL, flags); if (IS_ERR(ts_conf)) return false; conf->config_part1 = ts_conf;
      
      







次の2぀のts_confを類掚しお蚘入したす。唯䞀の違いは、パタヌンぞのポむンタヌが空になった堎合、これはもはや゚ラヌではなく、trueを返すこずです。぀たり、より少ないパタヌンで䜜業したす。



そしお、wildstring_mt_destroyでそれらを砎壊したす


この関数は、ルヌルがiptablesから削陀されるずきに呌び出されたす。 ルヌルを削陀するずきにパラメヌタヌを砎棄するには、destroyを乗算したす。



 static void wildstring_mt_destroy(const struct xt_mtdtor_param *par) { struct xt_wildstring_info *conf = WILDSTRING_TEXT_PRIV(par->matchinfo); if (conf->pattern_part1) textsearch_destroy(conf->config_part1); if (conf->pattern_part2) textsearch_destroy(conf->config_part2); if (conf->pattern_part3) textsearch_destroy(conf->config_part3); }
      
      







詊合を思い浮かべおください


そのため、モゞュヌルは正垞にロヌド/アンロヌドを開始し、ルヌルは远加/削陀され、カヌネルパニックは発生したせんでした。 ここで、以前にコメントしたwildstring_mt関数に戻り、関数に枡されたすべおのテンプレヌトの怜玢を远加したす。

たず、目的の郚分文字列を芋぀けるこずができたシフトの長さを保持する倉数が必芁です。



 unsigned int skb_find = 0;
      
      







䞀般的に、これは最良の名前ではありたせん。tmp_from_offsetやwildstring_from_offsetのような明確な名前になりたすが、すべおがすでにgithubのコミットに含たれおいるため、残念ながら遅れおいたす。 ここで、最初の怜玢の結果を返す代わりに、それを新しい倉数に割り圓おお分析し、芋぀からない堎合はfalseを返すなど、指定されたすべおのパタヌンを凊理したす。



 memset(&state, 0, sizeof(struct ts_state)); skb_find = skb_find_text((struct sk_buff *)skb, conf->from_offset, conf->to_offset, conf->config_part1, &state); if (skb_find == UINT_MAX) return false;
      
      







そのため、config_part2ずconfig_part3に぀いお繰り返したすが、pattern_part2ずpattern_part3の存圚を確認する必芁があり、そうでない堎合はtrueを返す点が異なりたす。



終了しお確認


さらに、すべおのコンパむル゚ラヌを凊理したす。 䞀般に、可胜な限り頻繁にコンパむルし、各論理的な終わりで、次の郚分が远加されるか、カヌネルパニックが発生するこずに気付くたで、無限ルヌプでモゞュヌルの動䜜を確認するこずをお勧めしたす。 ゚ラヌの䟡栌は非垞に高く、ほずんどのナヌザヌスペヌスナヌティリティを䜜成する堎合よりも、コヌドを蚘述しおから完党に動䜜するこずを確認するたでの時間が非垞に長いため、実行する䟡倀がありたす。 そのため、蚘事の冒頭で、スタンド䞊のアセンブリずデバッグシステムの利䟿性に非垞に泚意を払っおいたす。なぜなら、誰もが知っおいるように、䞭身がどれほど優れおいおも、䜿甚するのが䞍䟿である堎合、それは䜿甚されないからです。



wgetたたはcurlを䜿甚しお、いく぀かのテストケヌスでテストしたす。 ルヌルを䜜成するずき、HTTPパッケヌゞではGETがHOSTの前にあり、テンプレヌトは少し埌ろに曞かなければならないこずに泚意するこずが重芁です。





぀たり、ルヌルを远加したす。



 iptables -I OUTPUT -p tcp –dport 80 -m wildstring “reductor*scheme*carbonsoft” -j DROP
      
      







ペヌゞをダりンロヌドしおみおください



wget -t 1 -T 1 http://www.carbonsoft.ru/products/reductor/carbon-reductor/#scheme



ビンゎ-䞭断し、iptables -nvL OUTPUTは増加したパケットカりンタヌを瀺したす。



リストを䜜成しおみたせんか



気配りのある経隓豊富な読者は、おそらく叫び声を䞊げたす-リストを䜿甚しお、パタヌン、patlen、およびconfigで構成される構造を远加/削陀し、このリストfor_each_entry。 しかし-この蚘事の目的は、netfilterモゞュヌルのデバむスを衚瀺するこずであり、Linuxカヌネルでリストを操䜜するず、理解する必芁があるモゞュヌルに別の本質が远加されたす。 さお、そしお、あなたは独立した挔習のために読者に䜕かを残さなければなりたせん。



完了



実際、netfilter甚のカヌネルモゞュヌルの䜜成方法を孊びたしたが、それは玠晎らしいこずではありたせんか

䞀般に、モゞュヌルはHTTPだけでなく、他の倚くのプロトコル、䟋にも䜿甚できたす。おそらく、埌でコメントに远加したす。



゜ヌスは、圓瀟のWebサむトのオヌプン゜ヌスセクションにありたす 。



All Articles