パケットデータがインターフェイスに到達する前と受信された後に傍受することは可能ですか?たとえば、前処理して再送しますか?
次のカスタムソリューションを作成したいと思います。この素晴らしいプログラムはvtunと呼ばれています。インターフェイスとして機能する仮想デバイスを作成します。これにより、トラフィック圧縮、暗号化、シェーピングなど、さまざまなタスクを実行できます。
もう少し簡単にできないかと思います(vtunはかなり古いですね…)。私のターゲットオペレーティングシステムはUbuntu 14.04です。
答え1
はい、LinuxカーネルのNetfilterフレームワークはそれを可能にするのに十分柔軟です。
君の期待がどうだったのか分からない「カスタムソリューション」そして「もう少し簡単にできれば」。私はあなたが低レベルのパケット処理を実行するコードを書くと仮定します。
一般的なアイデアは次のとおりです。
iptables
目的のテーブル(filter
、、、 )のトラフィックをnat
ターゲットmangle
を介してユーザースペースに転送するルールを作成しますQUEUE
。- 次のコマンドを使用して、キューに送信されたパケットにアクセスできます。libnetfilter_queue図書館nfqueueバインディング(PerlまたはPythonを使用している場合)
- 適切であると判断されたようにパケットを処理し、元に戻します。
処理するトラフィックの種類に応じて、生のIPパケット、TCPフラグメント、またはUDPデータグラムを使用し、トラフィックを正しく再組み立てし、パケットレベルのチェックサムの正確性およびその他すべての項目を維持することはあなたの責任です。オペレーティングシステムのTCP / IPスタックは後ろから魔法のように扱います。
Pythonで作業する予定の場合は、次のことをお勧めします。DPKTまたはオームパケットまたはTCPセグメントを処理します。これにより、仕事がはるかに簡単になります。
答え2
以下は@dkaragasidis提案を使用したサンプルコードです。パケットデータを読み取り、転送します。ハンドラ機能でパケットを変更できます。
編む:-lnetfilter_queue -lnfnetlink
ルールを追加(例):sudo iptables -A OUTPUT -p udp --dport 4444 -j NFQUEUE --queue-num 0
削除ルール(例):sudo iptables -D OUTPUT -p udp --dport 4444 -j NFQUEUE --queue-num 0
テスト:nc -lu 4444
とnc -u YOUR_IP 4444
#include <netinet/in.h>
#include <linux/netfilter.h>
#include <libnetfilter_queue/libnetfilter_queue.h>
#include <stdio.h>
int handler(struct nfq_q_handle *myQueue, struct nfgenmsg *msg, struct nfq_data *pkt, void *cbData) {
int id = 0;
struct nfqnl_msg_packet_hdr *header;
if( header = nfq_get_msg_packet_hdr(pkt) )
id = ntohl(header->packet_id);
unsigned char *pktData;
int len = nfq_get_payload(pkt, &pktData);
printf("data[ %d ]:\n", len);
int i;
for (i = 0; i < len; i++)
printf("%2d 0x%02x %3d %c\n", i, pktData[i], pktData[i], pktData[i]);
printf("\n");
return nfq_set_verdict(myQueue, id, NF_ACCEPT, len, pktData);
}
int main(int argc, char **argv) {
struct nfq_handle *nfqHandle;
struct nfq_q_handle *myQueue;
struct nfnl_handle *netlinkHandle;
int fd, res;
char buf[4096];
// queue connection
if (!(nfqHandle = nfq_open())) {
perror("Error in nfq_open()");
return(-1);
}
// bind this handler
if (nfq_bind_pf(nfqHandle, AF_INET) < 0) {
perror("Error in nfq_bind_pf()");
return(1);
}
// define a handler
if (!(myQueue = nfq_create_queue(nfqHandle, 0, &handler, NULL))) {
perror("Error in nfq_create_queue()");
return(1);
}
// turn on packet copy mode
if (nfq_set_mode(myQueue, NFQNL_COPY_PACKET, 0xffff) < 0) {
perror("Could not set packet copy mode");
return(1);
}
netlinkHandle = nfq_nfnlh(nfqHandle);
fd = nfnl_fd(netlinkHandle);
while ((res = recv(fd, buf, sizeof(buf), 0)) && res >= 0)
nfq_handle_packet(nfqHandle, buf, res);
nfq_destroy_queue(myQueue);
nfq_close(nfqHandle);
return 0;
}