leiiwang

Linux网络工具学习之:IP命令学习10

标签(空格分隔): 网络


本文旨在通过IP命令介绍和学习Linux网络的相关知识

1. 概述

3. ip addr

4 ip addrlabel

5 ip route

6 ip rule

7 ip neighbour

8 ip ntable

9 ip tunnel

10 ip tuntap

10.1 概述

TUN/TAP provides packet reception and transmission for user space programs. It can be seen as a simple Point-to-Point or Ethernet device, which, instead of receiving packets from physical media, receives them from user space program and instead of sending packets via physical media writes them to the user space program.

此处输入图片的描述 此处输入图片的描述

tun,tap的区别见下面的参考

Usage: ip tuntap { add | del } [ dev PHYS_DEV ] 
          [ mode { tun | tap } ] [ user USER ] [ group GROUP ]
          [ one_queue ] [ pi ] [ vnet_hdr ] [ multi_queue ]

Where: USER  := { STRING | NUMBER }
       GROUP := { STRING | NUMBER }

10.2 ip tuntap add/del

添加/删除 tun/tap设备

##control program <--read/write--> TUN interface <--send/receive IP packets--> any networking program 

#1. Setting up a virtual TUN interface.
ip tuntap add dev asa0 mode tun
ip addr add 10.0.0.1/24 dev asa0
ip link set dev asa0 up



# 2.  tun-reader.c 

#include <fcntl.h>  /* O_RDWR */
#include <string.h> /* memset(), memcpy() */
#include <stdio.h> /* perror(), printf(), fprintf() */
#include <stdlib.h> /* exit(), malloc(), free() */
#include <sys/ioctl.h> /* ioctl() */

/* includes for struct ifreq, etc */
#include <sys/types.h>
#include <sys/socket.h>
#include <linux/if.h>
#include <linux/if_tun.h>

int tun_open(char *devname)
{
    struct ifreq ifr;
    int fd, err;

    if ( (fd = open("/dev/net/tun", O_RDWR)) == -1 ) {
        perror("open /dev/net/tun");
        exit(1);
    }

    memset(&ifr, 0, sizeof(ifr));
    ifr.ifr_flags = IFF_TUN;
    strncpy(ifr.ifr_name, devname, IFNAMSIZ);

    /* ioctl will use if_name as the name of TUN
    * interface to open: "tun0", etc. */
    if ( (err = ioctl(fd, TUNSETIFF, (void *) &ifr)) == -1 ) {
        perror("ioctl TUNSETIFF");close(fd);exit(1);
    }

    /* After the ioctl call the fd is "connected" to tun device
    * specified
    * by devname */

    return fd;
}

int main(int argc, char *argv[])
{
    int fd, nbytes;
    char buf[1600];

    fd = tun_open("asa0") ;
    printf("Device asa0 opened\n");

    while(1) {
        nbytes = read(fd, buf, sizeof(buf));
        printf("Read %d bytes from asa0\n", nbytes);
    }
    return 0;
}


# 3. 运行
gcc tun-reader.c
./a.out

It will open the file descriptor of the asa0 interface and will wait for any packets. Let's send some packets to the asa0 interface as follows to see whether our program receive those packets.

# 4. 测试
ping 10.0.0.1

无输出
In the above case, we are pinging to the exact IP address of the asa0 interface. Therefore we receive ping responses from the interface directly without directing the ICMP packets to the back-end program. Now, let's ping to some other IP address in the same network.

ping 10.0.0.2
[root@10-9-151-160 ~]# ./a.out 
Device asa0 opened
Read 88 bytes from asa0
Read 88 bytes from asa0
Read 88 bytes from asa0
Read 88 bytes from asa0
Read 88 bytes from asa0
Read 88 bytes from asa0

[root@10-9-151-160 ~]# tcpdump -vvi asa0
tcpdump: listening on asa0, link-type RAW (Raw IP), capture size 65535 bytes
18:46:22.633821 IP (tos 0x0, ttl 64, id 37266, offset 0, flags [DF], proto ICMP (1), length 84)
    10-9-151-160 > 10.0.0.2: ICMP echo request, id 2304, seq 1332, length 64
18:46:23.633767 IP (tos 0x0, ttl 64, id 37267, offset 0, flags [DF], proto ICMP (1), length 84)
    10-9-151-160 > 10.0.0.2: ICMP echo request, id 2304, seq 1333, length 64
18:46:24.633776 IP (tos 0x0, ttl 64, id 37268, offset 0, flags [DF], proto ICMP (1), length 84)
    10-9-151-160 > 10.0.0.2: ICMP echo request, id 2304, seq 1334, length 64


# 5. 这时候新建一个tun0
ip tuntap add dev tun0 mode tun
ip addr add 10.0.0.2/24 dev tun0
ip link set dev tun0 up

# 6. 修改一下tun-reader.c 把数据写到tun0; 即 data->asa0->tun0
#include <fcntl.h>  /* O_RDWR */
#include <string.h> /* memset(), memcpy() */
#include <stdio.h> /* perror(), printf(), fprintf() */
#include <stdlib.h> /* exit(), malloc(), free() */
#include <sys/ioctl.h> /* ioctl() */

/* includes for struct ifreq, etc */
#include <sys/types.h>
#include <sys/socket.h>
#include <linux/if.h>
#include <linux/if_tun.h>

int tun_open(char *devname)
{
    struct ifreq ifr;
    int fd, err;

    if ( (fd = open("/dev/net/tun", O_RDWR)) == -1 ) {
        perror("open /dev/net/tun");
        exit(1);
    }

    memset(&ifr, 0, sizeof(ifr));
    ifr.ifr_flags = IFF_TUN;
    strncpy(ifr.ifr_name, devname, IFNAMSIZ);

    /* ioctl will use if_name as the name of TUN
    * interface to open: "tun0", etc. */
    if ( (err = ioctl(fd, TUNSETIFF, (void *) &ifr)) == -1 ) {
        perror("ioctl TUNSETIFF");close(fd);exit(1);
    }

    /* After the ioctl call the fd is "connected" to tun device
    * specified
    * by devname */

    return fd;
}

int main(int argc, char *argv[])
{
    int fd, nbytes, fd2;
    char buf[1600];

    fd = tun_open("asa0") ;
    fd2 = tun_open("tun0") ;
    printf("Device asa0 opened\n");
    printf("Device tun0 opened\n");

    while(1) {
        nbytes = read(fd, buf, sizeof(buf));
        printf("Read %d bytes from asa0\n", nbytes);
	nbytes = write(fd2, buf, sizeof(buf));
        printf("Write %d bytes to tun0\n", nbytes);
    }
    return 0;
}

# 7. 测试可以看到 tun0 端口有和asa0端口一样的数据
[root@10-9-151-160 ~]# tcpdump -vvi tun0
tcpdump: listening on tun0, link-type RAW (Raw IP), capture size 65535 bytes
18:50:19.642816 IP (tos 0x0, ttl 64, id 37503, offset 0, flags [DF], proto ICMP (1), length 84)
    10-9-151-160 > 10.0.0.2: ICMP echo request, id 2304, seq 1569, length 64
18:50:20.642842 IP (tos 0x0, ttl 64, id 37504, offset 0, flags [DF], proto ICMP (1), length 84)
    10-9-151-160 > 10.0.0.2: ICMP echo request, id 2304, seq 1570, length 64

参考:TUN/TAP MACVLAN MACVTAP 参考:Linux 上的基础网络设备详解 参考:tuntap 参考:tun/tap driver 参考:Tun/Tap interface tutorial 参考:tun & veth设备 参考:openstack网络的介绍,里面用了tap

comments powered by Disqus