【问题标题】:Converting raw packet data received from a TUN interface转换从 TUN 接口接收的原始数据包数据
【发布时间】:2014-06-11 19:05:25
【问题描述】:

我正在尝试拦截通过 TUN 接口的数据包。 我想将原始数据包信息转换为可读信息,以便以后使用。

我正在使用以下代码:

int main(){
    char tun_name[IFNAMSIZ];
    char data[1500];
    int nread = 0;
    int tun_fd = 0;

    /* Connect to the device */
    strcpy(tun_name, "tun1");
    tun_fd = tun_alloc(tun_name);  /* tun interface, no Ethernet headers*/
    if(tun_fd < 0){
        perror("Allocating interface");
        exit(1);
    }

    /* Now read data coming from the kernel */
    int i=0;
    int count=0;
    char src[INET_ADDRSTRLEN];
    u_int8_t protocol;

    while(1) {
        count ++;

        nread = read(tun_fd, data, sizeof(data));
        if(nread < 0) {
            perror("Reading from interface");
            close(tun_fd);
            exit(1);
        }

        struct ip *iphdr = (struct ip *) data;

        /* Do whatever with the data */
        printf("Packet N° %d\n", count);
        printf("Read %d bytes from device %s\n", nread, tun_name);

        protocol = iphdr->ip_p;
        inet_ntop(AF_INET, &(iphdr->ip_src), src, INET_ADDRSTRLEN);

        printf("\nProtocol: %d", protocol);
        printf("\nIP source address: %s", src);
        printf("\n\n");
    }
    return 0;
}

似乎我无法读取数据包的协议和 ip src 地址。我得到了奇怪的结果。

你能帮忙吗?

谢谢!

【问题讨论】:

    标签: c networking tun


    【解决方案1】:

    问题出在这一行:

    tun_fd = tun_alloc(tun_name);  /* tun interface, no Ethernet headers*/
    

    这里是函数tun_alloc()的定义:

    int tun_alloc(char *dev) {
    
        struct ifreq ifr;
        int fd, err;
        char *clonedev = "/dev/net/tun";
    
        /* open the clone device */
        if( (fd = open(clonedev, O_RDWR)) < 0 ) {
            return fd;
        }
    
        /* preparation of the struct ifr, of type "struct ifreq" */
        memset(&ifr, 0, sizeof(ifr));
    
        ifr.ifr_flags = IFF_TUN;   /* IFF_TUN or IFF_TAP, plus maybe IFF_NO_PI */
    
        if (*dev) {
            strncpy(ifr.ifr_name, dev, IFNAMSIZ);
         }
    
        /* try to create the device */
        if( (err = ioctl(fd, TUNSETIFF, (void *) &ifr)) < 0 ) {
            close(fd); 
        return err;
        }
        strcpy(dev, ifr.ifr_name);
        return fd;
    

    }

    这里,在创建TUN接口时,我们必须使用“IFF_NO_PI”标志来删除数据包添加信息,只接收原始数据包。

    所以,我们必须使用这个:

    ifr.ifr_flags = IFF_TUN | IFF_NO_PI; 
    

    而不仅仅是:

    ifr.ifr_flags = IFF_TUN; 
    

    希望对你有帮助,谢谢。

    【讨论】:

    • 只要没有 IPv6,它就可以工作。在这种情况下,您可以请求内核在 tun 数据包中添加的前 4 个字节。这些字节包含标志和协议 (INET/INET6)。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-04-09
    • 1970-01-01
    • 2011-08-06
    • 2015-12-23
    相关资源
    最近更新 更多