Netfilter学習ノート
17552 ワード
この2、3日
第1編ではnetfilterとiptablesの関係、iptablesの原理を紹介します.第2編では,
netfilter
簡単に言えば、netfilterは、Linux Kernelに一連のhookを挿入し、kernelが異なるレイヤのネットワークスタックにコールバック関数を登録することを許可する一連のコンピュータネットワークスタックのフレームワークであり、これらのコールバック関数は、パケットが対応するhookに入るときに呼び出される.
ネットワークスタック内のnetfilterのサポートを図に示します.
リンク層とネットワーク層においてパケットフローをカプセル化する経路に従って5種類のhooks:prerouting,input,forward,output,postroutingが見られる.この5つのhooksは、パケットが到着すると、パケットフローの順序に従って対応するコールバック関数を呼び出し、4つのタイプのテーブルのchain(iptablesで説明される)をフィルタリングし、修正します.filter、nat、mangle、rawです.これらのフィルタを定義するルールは、1つのユーザ状態のコマンド
iptables
ここには6つのシリーズの文章がiptablesを紹介しています.はっきり言っていて、入門学習に適しています.
iptablesには4つのタイプのテーブルがあります.filter、nat、mangle、rawです.ここではfilterテーブルについて説明します.
filterテーブルは主にパッケージをフィルタリングするために使用され、このテーブルにはデフォルトのchain:INPUT,FOrWARD,OUTPUTの3つがあります.
chainは何をしていますか?(ここから)
chainとは、すべての外部パケットの侵入を防止するルールをINPUT chainに追加することができるパケットフィルタリングルールのセットです.OUTPUT chainに、ユーザーがWebサーバーに接続しないようにする方法を追加できます.ネットワークへのアクセスを準備するパケットは、chain内のフィルタリングルールに従って検証され、パケットがルールに合致しない場合は、INPUTとOUTPUTはLinux kernelでACCEPTとして予め設定され、FOrWARDはDROPとして予め設定されているため、ネットワーク内に直接アクセスします.
たとえば、あるアドレス(192.168.1.2など)に送信されたパケットを破棄する場合は、次のようにします.
ここで
すなわち,異なるソースアドレス,ターゲットアドレス,ポート,プロトコルなどの規則に従って分類し,異なるchainで処理することができ,フィルタ条件をより合理的に管理することができる.
また、いくつかの一般的なオプションについて説明します.
次の記事では、
前にnetfilterとiptablesの簡単な原理と使い方について話しましたが、iptablesにとって、パッケージをDROP、ACCEPT操作しかできないと弱いように見えますが、実はiptablesの中でfilterテーブルの中で一番すごいのはQUEUE(NFQUEUE)というtargetです.
では、iptablesがQUEUEにパッケージを挿入すると、queueのデータを読み取るにはどのような方法がありますか?
ここでは、C言語で使用される
libipq
またコンパイルされたファイルは
ここでは主にデータ構造を用いた
さらに、
その後のパス:
queueuのパッケージをユーザースペースに1つずつコピーし、ユーザーが操作し、ユーザーは次のことを実行できます.
得られるパケットのタイプは、
上段のコードは、
ここでの意味は,従来のルールではtargetをACCEPTとすることに相当し,もちろん
ここで疑問なのは、ここで
nfqueue
Cのlibipqに比べてpythonをサポートするnfqueueは強く見えますが、特にscapyと組み合わせて使う場合です.
まず、iptablesにおけるtargetは、前述の5つの項目(ACCEPT,DROP,RETURN,QUEUE,other_chain)に加えて、QUEUEの拡張である
nfqueueを使用する前に、次のパッケージをインストールする必要があります.
その後pythonを用いてNFQUEUEを操作することができるようになった.
ホストA(
まず、ホストAでiptablesを操作する必要があります.
次に、次のコードを使用します.
ここでは、
次のように実行できます.
scapyのインタラクティブモードを直接オンにしました.
原文の出典:http://ytliu.github.io/blog/archives/中の文章は全部いいですね.
iptables
を勉强しています.これは本当にすごいと思います.2編のブログで紹介したいです.第1編ではnetfilterとiptablesの関係、iptablesの原理を紹介します.第2編では,
libipq
およびnfqueue-bindings-python
を用いて,user状態がどのようにCおよびPythonを用いてiptablesのインタフェースを呼び出してパッケージを取得するかについて説明する.netfilter
簡単に言えば、netfilterは、Linux Kernelに一連のhookを挿入し、kernelが異なるレイヤのネットワークスタックにコールバック関数を登録することを許可する一連のコンピュータネットワークスタックのフレームワークであり、これらのコールバック関数は、パケットが対応するhookに入るときに呼び出される.
ネットワークスタック内のnetfilterのサポートを図に示します.
リンク層とネットワーク層においてパケットフローをカプセル化する経路に従って5種類のhooks:prerouting,input,forward,output,postroutingが見られる.この5つのhooksは、パケットが到着すると、パケットフローの順序に従って対応するコールバック関数を呼び出し、4つのタイプのテーブルのchain(iptablesで説明される)をフィルタリングし、修正します.filter、nat、mangle、rawです.これらのフィルタを定義するルールは、1つのユーザ状態のコマンド
iptables
によって構成されます.つまり、私が次に詳細に説明するコマンドです.iptables
ここには6つのシリーズの文章がiptablesを紹介しています.はっきり言っていて、入門学習に適しています.
iptablesには4つのタイプのテーブルがあります.filter、nat、mangle、rawです.ここではfilterテーブルについて説明します.
filterテーブルは主にパッケージをフィルタリングするために使用され、このテーブルにはデフォルトのchain:INPUT,FOrWARD,OUTPUTの3つがあります.
chainは何をしていますか?(ここから)
chainとは、すべての外部パケットの侵入を防止するルールをINPUT chainに追加することができるパケットフィルタリングルールのセットです.OUTPUT chainに、ユーザーがWebサーバーに接続しないようにする方法を追加できます.ネットワークへのアクセスを準備するパケットは、chain内のフィルタリングルールに従って検証され、パケットがルールに合致しない場合は、INPUTとOUTPUTはLinux kernelでACCEPTとして予め設定され、FOrWARDはDROPとして予め設定されているため、ネットワーク内に直接アクセスします.
たとえば、あるアドレス(192.168.1.2など)に送信されたパケットを破棄する場合は、次のようにします.
$ sudo iptables -A OUTPUT -d 192.168.1.2 -j DROP
ここで
-A
はOUTPUTというチェーンのルールを修正することを指し、-d
はこのパッケージのdestinationを表し、-j
の後にtargetを加え、ACCEPT(何もせずにパケットを流す)、DROP(パケットを破棄する)、QUEUE(パケットをキューに挿入し、ユーザ状態処理に渡す、第2編で詳細に説明する)、RETURN(このchainから直接戻り、前のchainの次のルールに進む)、および自己定義のCHAINの5つの選択肢があります.$ sudo iptables -N SELF_CHAIN
すなわち,異なるソースアドレス,ターゲットアドレス,ポート,プロトコルなどの規則に従って分類し,異なるchainで処理することができ,フィルタ条件をより合理的に管理することができる.
また、いくつかの一般的なオプションについて説明します.
-A chain # modify a chain
-D chain rulenum # delete a specific rule of chain
-I chain rulenum rule # insert rule in rulenum of chain
-R chain rulenum rule # replace rule with rulenum of chain
-L [chain] # list rules of chain
-F [chain] # flush the rules of chain
-N chain # new a chain
-X [chain] # delete chain
-p protocol # e.g., tcp, udp, icmp...
-s source address # e.g., 192.168.1.22
-d destination address # e.g., 192.168.1.13
-j target # e.g., ACCEPT, DROP, RETURN, QUEUE, other-chain
-i in-interface # e.g., eth0
-o out-interface # e.g., eth0
次の記事では、
iptables
のtargetがQUEUEまたはNFQUEUEである場合、ユーザ状態が関連インタフェースをどのように呼び出すかについて主に説明します.前にnetfilterとiptablesの簡単な原理と使い方について話しましたが、iptablesにとって、パッケージをDROP、ACCEPT操作しかできないと弱いように見えますが、実はiptablesの中でfilterテーブルの中で一番すごいのはQUEUE(NFQUEUE)というtargetです.
では、iptablesがQUEUEにパッケージを挿入すると、queueのデータを読み取るにはどのような方法がありますか?
ここでは、C言語で使用される
libipq
とpythonで使用されるnfqueue
の2つの方法を紹介します.libipq
libipq
は開発者に提供されたiptables queueを読み取るためのCライブラリです.具体的な使い方はlinux man pageとここの使い方を参照してください.注意しなければならないのは、私のマシンに3つのヘッダファイルを追加しなければなりません.#include
#include
#include
またコンパイルされたファイルは
sudo
で実行しなければなりません!!ここでは主にデータ構造を用いた
1
2
3
struct ipq_handle *h;
h = ipq_create_handle(0, PF_INET);
さらに、
IPQ_COPY_PACKET
、すなわちqueue内のパッケージのpayloadをヘッダとともにユーザ空間にコピーするモードを設定する必要がある.1
status = ipq_set_mode(h, IPQ_COPY_PACKET, BUFSIZE);
その後のパス:
1
status = ipq_read(h, buf, BUFSIZE, 0);
queueuのパッケージをユーザースペースに1つずつコピーし、ユーザーが操作し、ユーザーは次のことを実行できます.
1
ipq_message_type(buf)
得られるパケットのタイプは、
NLMSG_ERROR
であってもよいし、IPQM_PACKET
であってもよい.後者であれば、通常のパケットであり、以下のようなコードによってパケットを操作することができる.1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
case IPQM_PACKET: {
ipq_packet_msg_t *m = ipq_get_packet(buf);
struct iphdr *ip = (struct iphdr*) m->payload;
struct tcphdr *tcp = (struct tcphdr*) (m->payload + (4 * ip->ihl));
int port = htons(tcp->dest);
status = ipq_set_verdict(h, m->packet_id, NF_ACCEPT, 0, NULL);
if (status < 0)
die(h);
break;
}
}
上段のコードは、
buf
からパッケージm全体を取得した後、struct iphdr
およびstruct tcphdr
を介してipパッケージヘッダおよびtcpパッケージヘッダを取得することができ、最後に最も重要なコードがあることを意味する.1
status = ipq_set_verdict(h, m->packet_id, NF_ACCEPT, 0, NULL);
ここでの意味は,従来のルールではtargetをACCEPTとすることに相当し,もちろん
NF_DROP
などとしてもよい.ここで疑問なのは、ここで
struct tcphdr
を獲得した以外に、TCPのpayloadに関連する構造が見つからず、どのように獲得すればいいか分からないことです.nfqueue
Cのlibipqに比べてpythonをサポートするnfqueueは強く見えますが、特にscapyと組み合わせて使う場合です.
まず、iptablesにおけるtargetは、前述の5つの項目(ACCEPT,DROP,RETURN,QUEUE,other_chain)に加えて、QUEUEの拡張である
NFQUEUE
と呼ばれる.QUEUEと比較して、ユーザによって異なるqueue numberを指定することができる.nfqueueを使用する前に、次のパッケージをインストールする必要があります.
$ sudo aptitude install libnetfilter-queue-dev
$ sudo aptitude install nfqueue-bindings-python
$ sudo aptitude install python-scapy
その後pythonを用いてNFQUEUEを操作することができるようになった.
ホストA(
192.168.1.1
)からホストB(192.168.1.2
)にパケットを転送する場合、パケットを解析する必要があり、TCPプロトコルのパケットであり、そのflagsがACK|PSHである場合、そのpayloadを修正する(例えば「hack」に置き換える):まず、ホストAでiptablesを操作する必要があります.
$ sudo iptables -A OUTPUT -d 192.168.1.2 -p tcp -j NFQUEUE
次に、次のコードを使用します.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
import os,sys,nfqueue,socket
from scapy.all import *
def ch_payload_and_send(pkt):
pkt[TCP].payload == "hack"
send(pkt, verbose=0)
def process(i, payload):
data = payload.get_data()
pkt = IP(data)
# Check if TCP flags is ACK|PSH
if pkt[TCP].flags == 24:
# Dropping the packet
payload.set_verdict(nfqueue.NF_DROP)
ch_payload_and_send(pkt)
else:
# Accepting the packet
payload.set_verdict(nfqueue.NF_ACCEPT)
def main():
q = nfqueue.queue()
q.open()
q.unbind(socket.AF_INET)
q.bind(socket.AF_INET)
q.set_callback(process)
q.create_queue(0)
try:
q.try_run()
except KeyboardInterrupt:
print "Exiting..."
q.unbind(socket.AF_INET)
q.close()
sys.exit(1)
main()
ここでは、
scapy
という非常に強力なモジュールを使用しています.IP()
TCP()
などを通じて直接パッケージを説明し、操作することができ、非常に便利で、具体的にはドキュメントを参照することができます.ここでは、インストール方法について説明します.$ wget scapy.net
$ mv index.html scapy-latest.zip
$ chmod +x scapy-latest.zip
$ mv scapy-latest.zip /usr/local/bin/scapy
次のように実行できます.
$ sudo scapy
scapyのインタラクティブモードを直接オンにしました.
原文の出典:http://ytliu.github.io/blog/archives/中の文章は全部いいですね.