PCにクライアントがあります。PCにサーバーがあります。クライアントとサーバーは、Linux OS ベースのファームウェアを備えたルーターを介して接続されます。
クライアントはサーバーにパケットを送信し、応答を受け取ります。ルーターはパケットを傍受して変更する必要があります。スニッフィングのようなものですが、パケットを変更する必要があるため、スニッフィングではありません。
このためのプログラムを書かなければなりません。
ルーターで raw ソケットを開こうとしましたが、raw ソケットの reсvfrom はパケットをインターセプトせず、コピーするだけです。パケットが進行中です。
この問題を解決する方法を教えてください。
PS 下手な英語で申し訳ありません。:)
3 に答える
と を組み合わせて使用します(カーネルが比較的新しいと仮定しますiptables
)libnetfilter_queue
カーネルからユーザー空間にパケットを取得するために
iptables
、すべての udp パケットを に転送するルールを追加します。NFQUEUE 0
iptables -A INPUT -p udp -m udp --dport xxxxx -j NFQUEUE --queue-num 0
をリッスンするプロセスを構築し、
NFQUEUE number 0
ペイロードを変更し、libnetfilter_queue
機能を使用して完全なパケットをカーネル空間に戻します。このリンクに従って、その方法を確認してください。
簡単に言えば、キュー 0 を開き ( nfq_create_queue
)、パケットの内容を取得するためにモードを設定し ( nfq_set_mode
)、無限にループして、recv
フィルター処理された udp パケットを取得する必要があります。iptables
fd = nfq_fd(h);
while ((rv = recv(fd, buf, sizeof(buf), 0)) >= 0) {
printf("pkt received\n");
nfq_handle_packet(h, buf, rv);
}
が呼び出されるたびに、フェーズnfq_handle_packet
中に定義されたコールバックが呼び出されます。nfq_create_queue
そのコールバックでは、ペイロードを変更し、サイズを更新してチェックサムを再計算し、「有効」として設定する必要がありますnfq_set_verdict
カーネルといくつかのアプリケーションのモジュールを書きました。モジュールは netfilter を使用し、netfilter_queue に必要なパケットを破棄します。アプリケーションはキューを処理し、私は各パッケージをどう処理するかを決定します。
uint hook_main(uint hooknum,
struct sk_buff *skb,
const struct net_device *in,
const struct net_device *out,
int (*okfn)(struct sk_buff *) )
{
struct iphdr *ip;
struct udphdr *udp;
if (skb->protocol == htons(ETH_P_IP)){
ip = (struct iphdr *)(skb->data);
if (ip->version == 4 && ip->protocol == IPPROTO_UDP){
udp = (struct udphdr *)(skb->data + sizeof(struct iphdr));
if(ntohs(udp->dest) == SOME_PORT){
return NF_QUEUE;
}
}
}
return NF_ACCEPT;
}
int init_module ()
{
printk("[udp-catch] start udp-catch\n");
catch_hook.hook = hook_main;
catch_hook.owner = THIS_MODULE;
catch_hook.pf = PF_INET;
catch_hook.hooknum = NF_INET_FORWARD;
catch_hook.priority = NF_IP_PRI_FIRST;
nf_register_hook(&catch_hook);
return 0;
}
そして、netfilter.org から再設計されたサンプルがアプリケーションです。
ルーターは、他のポートで受信したものを自動的に送信します。
たとえば、4 ポートのルーターの場合、ポート 1 に入るものはポート 2、3、および 4 で送信されます。
必要なことを行うには、2 枚のネットワーク カードを備えた別の PC が必要です。クライアント PC を 1 つのネットワーク カードに接続し、サーバー PC をもう 1 つのネットワーク カードに接続します。
次に、プログラムは一方のネットワーク カードでrecvfromを実行し、パケットを変更して、もう一方のネットワーク カードでsendtoする必要があります。