Ruby TUN/TAP interface

December 4th, 2007 by kowsik

The universal TUN/TAP drivers have been shipping with the Linux kernel for a while now. vtun builds on this to set up point-to-point tunnels that essentially encapsulate Ethernet frames over a TCP connection. Here’s the Ruby code to setup a tap interface so we can start receiving raw Ethernet frames that are being written to this interface.

class TunTap
    # Linux 2.6.17: from /usr/include/linux/if_tun.h
    TUNSETIFF = 0x400454ca
    IFF_TAP   = 0x0002
    IFF_NO_PI = 0x1000

    def self.open
        Kernel.open("/dev/net/tun", "w+") do |tap|
            # struct ifreq
            ifr = [ "", IFF_TAP|IFF_NO_PI ].pack("a16S")
            tap.ioctl(TUNSETIFF, ifr)
            ifname = ifr[0, 16].gsub(/x00/, "")

            yield(tap, ifname)
        end
    end
end

So how do you use this? You first open the TunTap interface with a block. The ifname argument will typically be “tap0″ for the first interface opened, “tap1″ for the second and so on.

TunTap.open do |tap, ifname|
end

Inside the block, you can do

pkt = tap.sysread(64*1024)

to receive a raw Ethernet frame written by the networking stack. To inject a frame into the networking stack, use tap.syswrite which are all standard Ruby IO object methods.

When the block returns, the tap interface is automatically destroyed.

Posted in Ruby, Tools | Permalink | Trackback

Leave a Comment

Please note: Comment moderation is enabled and may delay your comment. There is no need to resubmit your comment.