zoukankan      html  css  js  c++  java
  • 将收到的ping包转发给tun设备并回应

    组网环境:

    A为host上的虚拟机,使用host-only的方式连接。

    使用网上《Linux的TUN/TAP编程》中的例子,打开一个tun0端口,响应此端口收到的icmp报文。代码如下:

    #include <sys/ioctl.h>
    #include <linux/if_tun.h>
    #include <stddef.h>
    #include <net/if.h>
    #include <fcntl.h>
    #include <assert.h>
    
    int tun_create(char *dev, int flags)
    {
        struct ifreq ifr;
        int fd, err;
    
        assert(dev != NULL);
    
        if ((fd = open("/dev/net/tun", O_RDWR)) < 0) //open character device
            return fd;
    
        memset(&ifr, 0, sizeof(ifr));
        ifr.ifr_flags |= flags;
        if (*dev != '\0')
            strncpy(ifr.ifr_name, dev, IFNAMSIZ);
    
        err = ioctl(fd, TUNSETIFF, (void *)&ifr);
    
        if (err < 0)
        {
            close(fd);
            return err;
        }
        strcpy(dev, ifr.ifr_name);
    
        return fd;
    }
    
    int main(int argc, char *argv[])
    {
        int tun, ret;
        char tun_name[IFNAMSIZ];
        unsigned char buf[4096] = {0};
    
        tun_name[0] = '\0';
        tun = tun_create(tun_name, IFF_TUN | IFF_NO_PI);
        if (tun < 0) {
            perror("tun_create");
            return 1;
        }
        printf("TUN name is %s\n", tun_name);
    
        while (1) {
            unsigned char ip[4];
    
            ret = read(tun, buf, sizeof(buf));
            if (ret < 0)
                break;
            int i = 0;
            for (i = 0; i < ret; i++)
            {
                printf("%02x ", buf + i);
                if (i % 16 == 0)
                    printf("\n");
            }
            printf("\n");
            memcpy(ip, &buf[12], 4);
            memcpy(&buf[12], &buf[16], 4);
            memcpy(&buf[16], ip, 4);
            buf[20] = 0;
            *((unsigned short*)&buf[22]) += 8;
            printf("read %d bytes\n", ret);
            ret = write(tun, buf, ret);
            printf("write %d bytes\n", ret);
        }
    
        return 0;
    }

    运行程序,在A上打开tun0接口:

    tony@ubuntu-a:~/code/nat-pt$ sudo ifconfig tun0 0.0.0.0 up

    并增加一条路由,将目的IP为10.10.10.1的报文送至tun0接口:

    tony@ubuntu-a:~/code/nat-pt$ sudo route add 10.10.10.1 dev tun0

    在A上还要添加一条规则,将A的eth1接口收到的icmp报文的目的地址改为10.10.10.1:

    tony@ubuntu-a:~/code$ sudo iptables -t nat -A PREROUTING -d 192.168.16.130 -p icmp -j DNAT --to-destination 10.10.10.1

    这样,我们ping 192.168.16.130这个地址的时候,icmp报文被送到host后,目的地址变成10.10.10.1,然后命中路由,送至tun0,经过处理后,从tun0发出去。

  • 相关阅读:
    Spring框架学习09——基于AspectJ的AOP开发
    Spring框架学习08——自动代理方式实现AOP
    Spring框架学习07——基于传统代理类的AOP实现
    Spring框架学习06——AOP底层实现原理
    Spring框架学习05——AOP相关术语详解
    SpringMVC框架09——@ResponseBody的用法详解
    Spring框架学习04——复杂类型的属性注入
    Spring框架学习03——Spring Bean 的详解
    Spring框架学习01——使用IDEA开发Spring程序
    sqlserver 迁移
  • 原文地址:https://www.cnblogs.com/tonybuaa/p/3055621.html
Copyright © 2011-2022 走看看