Nov 19
Opening a TUN Device on UNIX
The TUN/TAP interface under Linux provides user space access to Transport (Ethernet) or Network Layer (IP) traffic by allowing a developer to create a “virtual” interface that can be openend in user space as a file descriptor.
What is it Used For?
The TUN/TAP interface is most often used by tunneling applications like openVPN. In that scenario, each end of the VPN creates a TUN interface and adds a route to the routing table that forwards all traffic destined for the other host to that interface. The tunneling program uses the device to capture the IP traffic and forward it to the other host, where the traffic is retrieved and placed on opposing TUN interface.
How do I create one?
This code works on CentOS 5, Unbuntu Linux, and RHEL 5.:
#include <sys/socket.h> #include <asm/types.h> #include <sys/types.h> #include <sys/stat.h> #include <string.h> #include <fcntl.h> #include <linux/if.h> #include <linux/if_tun.h> #include <sys/ioctl.h> #include <unistd.h> int tun_alloc(char *dev) { struct ifreq ifr; int fd, err; if( (fd = open("/dev/net/tun", O_RDWR)) < 0 ) return fd; memset(&ifr, 0, sizeof(ifr)); /* Flags: IFF_TUN - TUN device (no Ethernet headers) * IFF_TAP - TAP device * * IFF_NO_PI - Do not provide packet information */ ifr.ifr_flags = IFF_TUN | IFF_NO_PI; if( *dev ) strncpy(ifr.ifr_name, dev, IFNAMSIZ); if( (err = ioctl(fd, TUNSETIFF, (void *) &ifr)) < 0 ){ close(fd); return err; } strcpy(dev, ifr.ifr_name); return fd; } int main(){ int fd; char dev[IFNAMSIZ]; memset(dev, 0, sizeof(dev)); if( (fd = tun_alloc(dev)) < 0){ return 1; } //read/write raw packets to/from the FD ... }
How do I configure it?
Tun devices can be viewed and configured in the same way as any other network devices.
Viewing the device
#/sbin/ifconfig -a
tun0 Link encap:UNSPEC HWaddr 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00
POINTOPOINT NOARP MULTICAST MTU:1500 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:500
RX bytes:0 (0.0 b) TX bytes:0 (0.0 b)Setting the IP address
#ip addr add 10.8.0.1/24 dev tun0
#ifconfig -a
tun0 Link encap:UNSPEC HWaddr 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00
inet addr:10.1.0.1 P-t-P:10.1.0.1 Mask:255.255.255.0
UP POINTOPOINT RUNNING NOARP MULTICAST MTU:1500 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:500
RX bytes:0 (0.0 b) TX bytes:0 (0.0 b)Bringing up the link
At this point the address is configured, but the virtual link is not considered active
#ip link set tun0 up
Reading and writing to/from the device
Something that is not clear from the minimal tun documentation is that you have to write a single IP packet per write and have to read a full IP packet per read. If you try to write a partial packet it will be interpreted as erroneous by the interface. if your read doesn’t ask for enough bytes it will continue to return -1 until you read the full packet in one go.
1 comment1 Comment so far
Leave a comment
[...] In this case we’re going to provide a way to create, configure, and write data to a linux tun device allowing the manipulation of raw IP traffic from Java. (More information on tun here: http://4thmouse.com/index.php/2009/11/19/opening-a-tun-device-on-unix/). [...]