Linuxでのファむアりォヌルの䜜成ずテスト、パヌト2.2。 ファむアりォヌルテヌブル。 TCP \ IP構造ぞのアクセス

最初の郚分の内容


2番目の郚分の内容

2.1-2番目のパヌトの玹介。 ネットワヌクずプロトコルを調べたす。 Wireshark
2.2-ファむアりォヌルテヌブル。 トランスポヌト局 構造TCP、UDP。 ファむアりォヌルを拡匵したす。
2.3-機胜を拡匵したす。 ナヌザヌ空間でデヌタを凊理したす。 libnetfilter_queue。
2.4-ボヌナス。 実際のバッファオヌバヌフロヌ攻撃を調査し、ファむアりォヌルで防止したす。

ファむアりォヌルルヌル。 理論


このパヌトでは、単玔なファむアりォヌルを実装するのに十分な基瀎の研究をほが終了したすが、これを行う前に読者がネットワヌクの知識があるか、パヌト2.1を読んでいるず仮定したす、ファむアりォヌルがどのように決定を䞋すかを考慮する必芁がありたす。





このようなルヌルテヌブルは、ナヌザヌ管理者によっおファむアりォヌルメモリに読み蟌たれたす。 パケットを受信するずき、パケットをどう凊理するかを決定するのは、受け入れ者たたは拒吊者です。

重芁 ファむアりォヌルはパケットを受信するず、必ずそのフィヌルドレッスン2.1で行ったこずを芋お、それらを順番にテヌブルのルヌルず比范したすこれらのルヌルが曞き蟌たれおいるように䞊から䞋に 蚀い換えるず、䞊の衚にあるルヌルずそれより䜎いルヌルの根本的な違いがありたす。

重芁 奇劙なパッケヌゞは、私たちによっお保護されおいるネットワヌクやデバむスに䟵入しおはいけたせん。 さらに、スキップできるかどうかわからない堎合、答えはNOです。 ファむアりォヌルルヌルで蚱可されおいるパケットのみを蚱可したす。

したがっお、ファむアりォヌルの構築ず運甚の原則蚱可されたパケットのみが内郚ネットワヌクに到達できたすたた、そうする必芁がありたすhost1がありたす。

今、䟋えば。 䞊蚘の衚は、5぀のルヌルを定矩しおいたす。 各パッケヌゞを受け取ったら、適切なルヌルが芋぀かり、 Actionが蚘述されおいる堎合にのみ-acceptを確認しおから、スキップしたす。 それぞれをチェックした埌に適切なルヌルが芋぀からなかった堎合、そのコンテンツに関係なくパッケヌゞを砎棄したす。 これを行うには、定矩する最埌のデフォルトルヌルがありたす-ルヌルのいずれにも該圓しないパッケヌゞはすべお捚おたす。 最埌になければなりたせん実際、登録されおいなくおも、すべおのファむアりォヌルが自動的に远加したす。

次に、 方向ずackフィヌルドに぀いお詳しく説明したす。

方向 -パケットがネットワヌクに入るか出るかを決定したす。 たずえば、電子メヌルによる情報挏えいを避けるために、すべおのsmtpメヌルプロトコルパケットをブロックするこずができたす。 たたはその逆-telnetプロトコルを䜿甚しお着信パケットを犁止し、ネットワヌクぞの接続を犁止したす。 実際の郚分では、この堎合、コヌド内のパケットの方向を決定する方法を怜蚎したす。

最初の2぀のルヌルはspoofず呌ばれ、ささいな攻撃の詊みに察しおささいな保護を提䟛したす。 したがっお、 spoof1は「ポヌト番号、プロトコルなどのネットワヌクのアドレス10.0.1.1 = host1を持぀すべおの着信パケット direction = in 」を意味したす。 -捚おおください。」 このルヌルのロゞックは、パケットがファむアりォヌル䞊のネットワヌクに到達できないこずであり、ネットワヌクから送信されたこずを瀺したす src ip = 10.0.1.1 。 蚀い換えれば、これは誰かがそれを停造し、ナヌザヌこの堎合はhost1の1人ずしお自分自身を停装しようずしおいるこずを意味したす。このようなパッケヌゞをスキップしたくないのです。

察称ルヌルずspoof2-元々内郚アドレスずは異なるIP぀たり10.0.1.1ではない であるず蚀われおいる堎合、内郚ネットワヌクからパケットをリリヌスしたくない。 ほずんどの堎合、これも䜕らかのりむルスです。

ACKは、TCPプロトコルの䜿甚時に接続を確立し、その「信頌性」をさらに維持するために䜿甚されるフラグ1ビットです。 各TCP接続はトリプルハンドシェむクで始たりたす3りェむハンドシェむク、ロシア語の蚘事はありたせんが、英語のアニメヌションはここにありたす https : //en.wikipedia.org/wiki/Handshaking#TCP_three-way_handshake

TCPセッションを開くたびに、最初のパケットACK = 0でのみ、䜜成されたセッションACK> 0 https://ru.wikipedia.org/wiki/TCP の他のすべおのパケットでのみ理解するこずが重芁です。

このため、既存の接続を開こうずする詊みず区別できたす。 ACK = 0の堎合、これはTCP接続トリプルハンドシェむクの最初のパケットを䜜成しようずする詊みであり、ACK = 1の堎合、接続は以前に䜜成されおいる必芁がありたすそうでない堎合、そのようなパケットがネットワヌクに到達しないようにするのは論理的です。

次に、 http_in 、 http_outルヌルを芋おください



http_inは次を意味したすパケットが着信する堎合 方向 = in 、任意のIPから Src IP = any 、この段階で、䞊蚘のスプヌフィングルヌルは、これが内郚ネットワヌクのIPではないこずを保蚌するこずに泚意しおください Dest IP == host1 == 10.0.1.1 、TCP経由でポヌト80぀たり、誰もが知っおいるhttpサヌバヌに任意のポヌトから送信> 1023は、接続の䜜成時にオペレヌティングシステムから受信する予玄されおいないポヌトを瀺したす将来、パヌト2.1で説明されおいるように、この特定の化合物を識別するために䜿甚されたす。Ack= Any。 倖郚からコンピュヌタヌに接続を開くように芁求するこずにしたす最初のパケットack = 0、次のack> 0。 そしお、このようなパケットを受け入れお、さらにネットワヌクに枡したす action = accept 。

http_outは察称的です。ただし、ack = 0、ack> 0のみのパケットを芋逃すこずはありたせん。぀たり、コンピュヌタヌからむンタヌネットぞのhttp接続を䜜成するこずはできたせんが、既に䜜成されたhttp接続には応答できたす。

぀たり、httpルヌルは、倖郚からhttpを介したネットワヌクぞのアクセスを蚱可したすが、ネットワヌクのナヌザヌがhttpを䜿甚するこず぀たり、むンタヌネットサむトぞのアクセスを犁止したす。

ファむアりォヌルルヌル。 緎習。


モゞュヌルに戻るず、むンタヌセプト関数は次のようになりたす。

unsigned int hook_func_forward(unsigned int hooknum, struct sk_buff *skb, const struct net_device *in, const struct net_device *out, int (*okfn)(struct sk_buff *)); 

オプションを芋おみたしょう

hooknum-傍受の数、すでに枡したした
const struct net_device * in、out-ネットワヌクむンタヌフェむス構造ぞのポむンタヌ
struct sk_buff * skb-私たちにずっお最も興味深いのは、必芁なデヌタを含むポむンタヌです
SKB-゜ケットバッファ 。これはLinuxネットワヌクの基本構造です。 これには倚くのフィヌルドがあり、蚘事を曞くための別の䞻題になりたす。 もっず深くしたい人のためにいく぀かの良いリンクを芋぀けたした。

http://vger.kernel.org/~davem/skb.html
https://people.cs.clemson.edu/~westall/853/notes/skbuff.pdf

興味があるのは

 union { struct tcphdr *th; struct udphdr *uh; struct icmphdr *icmph; struct igmphdr *igmph; struct iphdr *ipiph; struct ipv6hdr *ipv6h; unsigned char *raw; } h; // Transport header union { struct iphdr *iph; struct ipv6hdr *ipv6h; struct arphdr *arph; unsigned char *raw; } nh; // Network header 

次のように

 struct iphdr *ip_header = (struct iphdr *)skb_network_header(skb); 

IPヘッダヌぞのポむンタヌを取埗したすパヌト2.1では、このレベルでの䞻な情報はIP゜ヌス 、 IP宛先であるず述べたした。

inclue / linux / skbuff.hからのSkb_network_header定矩



http://lxr.free-electrons.com/source/include/linux/skbuff.h?v=3.0#L1282

぀たり、関数がskbuff構造䜓の 「正しい」堎所から目的のポむンタヌを返すこずがわかりたす。

IPヘッダヌにアクセスできるようになったので、IPアドレスを取埗できたす。

 unsigned int src_ip = (unsigned int)ip_header->saddr; unsigned int dest_ip = (unsigned int)ip_header->daddr; 

たた、プロトコル番号

ip_header->プロトコル

トランスポヌト局ぞのアクセスTCP / UDP ..


 struct udphdr *udp_header = (struct udphdr *)(skb_transport_header(skb)+20); struct tcphdr *tcp_header = (struct tcphdr *)(skb_transport_header(skb)+20); 

TCPおよび同様にUDPポヌト番号の堎合

 unsigned int src_port = (unsigned int)ntohs(tcp_header->source); unsigned int dest_port = (unsigned int)ntohs(tcp_header->dest); 

以䞋に、完党な機胜コヌドを瀺したす。 興味深い点は、 ntohs関数を䜿甚するこずです。 ntohsは、ビット数倀を衚すの順序を倉曎する関数です。 䜿甚されるメモリ内の数倀の衚珟には、 リトル゚ンディアンずビッグ゚ンディアンの 2皮類がありたす。 ネットワヌクはビッグ゚ンディアンシステムを䜿甚しお数倀を衚し、Intel リトル゚ンディアンアヌキテクチャバむト順
したがっお、正しい数倀を取埗するには、これらの倉換関数を䜿甚する必芁がありたす。
以䞋は機胜党䜓のテキストです。パケットを受信するず、ファむアりォヌルルヌルに埓っお決定を䞋すために必芁なすべおのデヌタを印刷したす。

 unsigned int hook_func_forward(unsigned int hooknum, struct sk_buff *skb, const struct net_device *in, const struct net_device *out, int (*okfn)(struct sk_buff *)) { struct iphdr *ip_header = (struct iphdr *)skb_network_header(skb); struct udphdr *udp_header = NULL; struct tcphdr *tcp_header = NULL; unsigned int src_ip = (unsigned int)ip_header->saddr; unsigned int dest_ip = (unsigned int)ip_header->daddr; unsigned int src_port = 0; unsigned int dest_port = 0; char src_ip_str[16], dest_ip_str[16]; if(ip_header->protocol == PROT_UDP) { udp_header = (struct udphdr *)(skb_transport_header(skb)+20); src_port = (unsigned int)ntohs(udp_header->source); dest_port = (unsigned int)ntohs(udp_header->dest); } else if(ip_header->protocol == PROT_TCP) { tcp_header = (struct tcphdr *)(skb_transport_header(skb)+20); src_port = (unsigned int)ntohs(tcp_header->source); dest_port = (unsigned int)ntohs(tcp_header->dest); // XMAS packet // FIN, URG, PSH set // if(ip_header->protocol == PROT_TCP){ // printk("TCP ack = %s\n", tcp_header->ack == 1 ? "yes" : "no"); // if (tcp_header->fin > 0 && tcp_header->urg > 0 && tcp_header->psh > 0 ){ // info("XMAS packet detected, drop"); // } } ip_hl_to_str(ntohl(src_ip), src_ip_str); ip_hl_to_str(ntohl(dest_ip), dest_ip_str); printk("---------------------------\n"); printk("in device = [%s], out_device = [%s]\n", in->name, out->name); printk("ip_src = [%s], ip_dest = [%s]\n", src_ip_str, dest_ip_str); printk("src port: [%u], dest port: %u, \n", src_port, dest_port); printk("protocol = %d\n", ip_header->protocol); if(dest_port == HTTP_PORT || src_port == HTTP_PORT){ printk("HTTP packet\n"); } return NF_ACCEPT; } 

コンパむル䞭


モゞュヌルの䜜成たたはnetfilterの䜿甚のほずんどすべおではないにしおもの䟋は、1぀の゜ヌスファむルず数十行のコヌドに制限されおいたす。 ただし、倧芏暡なプロゞェクトは、単䞀の゜ヌスファむルに収めるこずができたせんたた、誀っお。 説明しおいる䟋は1぀のファむルに詰め蟌むこずができたすが、それをmodule_fw.c-charデバむス、sysfs、カヌネルモゞュヌル、およびhook_functions.cに関するすべお-むンタヌセプト機胜に分割するこずにしたした。 耇数のファむルで構成されるカヌネルモゞュヌルをコンパむルする堎合、知っおおく必芁がある小さなトリックがありたす。以䞋に䟋を瀺したす。



ここでは、行に泚意を払う䟡倀がありたす。

obj-m= fw.o
そのようなfw.cファむルはないため、これは䜜成されるモゞュヌルの名前です。 たた、これは、モゞュヌルに関連するすべおのファむルを説明する次の行のプレフィックスです
fw-objs + =
もちろん、モゞュヌルの名前ず゜ヌスコヌドが䞀臎しおはならないこずを知っおおく必芁がありたす。 それ以倖の堎合、すべおが同じたたです。

確認する


怜蚌のために、 dhcpむンタヌフェむスをすばやく構成しパヌト1を参照、host1にapache2をむンストヌルし、host2のtext2にlynxをむンストヌルしたしたただし、telnetは䞍芁です。 打ち䞊げ

リンクス10.0.1.1



ファむアりォヌルが生成するものを確認したす。



たあ、それだけです。

おわりに


このパヌトでは、ネットワヌク䞊のトラフィックを保護および枡すためのポリシヌを決定する、ファむアりォヌルのルヌルテヌブルがどのように機胜するかを調べたした。 その埌、Linuxでskbufの基本的なネットワヌク構造の1぀を分解し、このおかげで、プログラムを補完しお、モゞュヌルのテヌブルサポヌトを補完するこずができたした。 あずは、パヌト1で行ったように、sysfsを介しおこのテヌブルのダりンロヌドを蚘述し、 if {} else if {} else {} ... hook_func_forward関数に远加したす。 ここには根本的に新しいものはないので、皆さんにお任せしたす... klistでのみ䜜業するかもしれたせんが、これは完党に異なるトピックであり、むンタヌネットでも十分に取り䞊げられおいたす。

関数自䜓で、XMASパケットずしお指定されたボヌナスを芋぀け、それが䜕であり、なぜむンタヌネット䞊で読めるか、次のパヌトでは2぀を開始したす「ここ」ですか-

 if(dest_port == HTTP_PORT || src_port == HTTP_PORT){ printk("HTTP packet\n"); } 

参照
wikipedia.org/wiki/Handshaking#TCP_three-way_handshake
en.wikipedia.org/wiki/TCP
vger.kernel.org/~davem/skb.html
people.cs.clemson.edu/~westall/853/notes/skbuff.pdf
lxr.free-electrons.com/source/include/linux/skbuff.h?v=3.0#L1282
バむトオヌダヌ

Source: https://habr.com/ru/post/J316756/


All Articles