tun device is virtual network interface that can send raw IP packets to user space instead of link/phy layer. tun/tap devices are used with IPSec application like OpenVPN. more details in the wiki. This is a write up based on the answer in SO
in this example, we will use 3 to create tun, run application and capture pacp.
Shell 1 - How to create tun device Link to heading
create the tun0
interface and update the route table for that device.. and up
to bring up the interface
sudo ip tuntap add mode tun dev tun0
sudo ip addr add 10.0.3.0/24 dev tun0
sudo ip link set dev tun0 up
Then in the same shell, run ping to that IP
ping 10.0.3.50
Shell 2 -How can user-space read the virtual tun network interface Link to heading
From linux kernel docs, The application has to ioctl
to register fd
to that tun0
interface.
#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() */
#include <unistd.h> /* read(), close() */
/* 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); // devname = "tun0" or "tun1", etc
/* ioctl will use ifr.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 ("tun0", "tun1", etc)*/
return fd;
}
int main(int argc, char *argv[])
{
int fd, nbytes;
char buf[1600];
fd = tun_open("tun0"); /* devname = ifr.if_name = "tun0" */
printf("Device tun0 opened\n");
while(1) {
nbytes = read(fd, buf, sizeof(buf));
printf("Read %d bytes from tun0\n", nbytes);
}
return 0;
}
Shell 3 - Capture pcap Link to heading
we can see the network traffic using tcpdump
sudo tcpdump -i tun0 -w samepl.pcap
and using thark
, we can that raw frame has IP and ICMP(the protocol for ping)..
Frame 1: 84 bytes on wire (672 bits), 84 bytes captured (672 bits)
Encapsulation type: Raw IP (7)
....
[Protocols in frame: raw:ip:icmp:data]
Raw packet data
Internet Protocol Version 4, Src: 10.0.3.0, Dst: 10.0.3.50
....
Source: 10.0.3.0
Destination: 10.0.3.50
Internet Control Message Protocol
Type: 8 (Echo (ping) request)
Code: 0
....