预处理发送到/从接口发送的数据包

预处理发送到/从接口发送的数据包

是否有可能在数据包数据到达接口之前和接收之后拦截数据包数据?例如,对其进行预处理并将其送回原路?

我想创建一个自定义解决方案,例如这个很棒的程序叫做 vtun。它创建一个充当接口的虚拟设备。这使其能够执行各种操作,例如流量压缩、加密、整形等。

我想知道现在是否可以更容易地完成(vtun 已经很旧了......)。我的目标操作系统是 Ubuntu 14.04。

答案1

是的,Linux 内核的 Netfilter 框架足够灵活,足以使这成为可能。

我不知道你的期望是什么“定制解决方案”“如果现在可以做得更容易的话”。我假设您准备编写代码来进行低级数据包处理。

总体思路如下:

  1. 创建iptables规则,将流量从所需的表 ( filternatmangle) 通过目标传递到用户空间QUEUE
  2. 您将能够使用以下命令访问发送到队列的数据包libnetfilter_queue图书馆或nfqueue 绑定(如果您使用 Perl 或 Python)。
  3. 按照您认为合适的方式处理数据包并将其按原路发送回去。

请记住,您将使用原始 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 4444nc -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;
}

相关内容