TUN / TAP Interfaces

Note

This module only works on BSD, Linux and macOS.

TUN/TAP lets you create virtual network interfaces from userspace. There are two types of devices:

TUN devices

Operates at Layer 3 (IP), and is generally limited to one protocol.

TAP devices

Operates at Layer 2 (Ether), and allows you to use any Layer 3 protocol (IP, IPv6, IPX, etc.)

Requirements

FreeBSD

Requires the if_tap and if_tun kernel modules.

See tap(4) and tun(4) manual pages for more information.

Linux

Load the tun kernel module:

# modprobe tun

udev normally handles the creation of device nodes.

See networking/tuntap.txt in the Linux kernel documentation for more information.

macOS

On macOS 10.14 and earlier, you need to install tuntaposx. macOS 10.14.5 and later will warn about the tuntaposx kexts not being notarised, but this works because it was built before 2019-04-07.

On macOS 10.15 and later, you need to use a notarized build of tuntaposx. Tunnelblick (OpenVPN client) contains a notarized build of tuntaposx which can be extracted.

Note

On macOS 10.13 and later, you need to explicitly approve loading each third-party kext for the first time.

Using TUN/TAP in Scapy

Tip

Using TUN/TAP generally requires running Scapy (and these utilities) as root.

TunTapInterface lets you easily create a new device:

>>> t = TunTapInterface('tun0')

You’ll then need to bring the interface up, and assign an IP address in another terminal.

Because TUN is a layer 3 connection, it acts as a point-to-point link. We’ll assign these parameters:

  • local address (for your machine): 192.0.2.1

  • remote address (for Scapy): 192.0.2.2

On Linux, you would use:

sudo ip link set tun0 up
sudo ip addr add 192.0.2.1 peer 192.0.2.2 dev tun0

On BSD and macOS, use:

sudo ifconfig tun0 up
sudo ifconfig tun0 192.0.2.1 192.0.2.2

Now, nothing will happen when you ping those addresses – you’ll need to make Scapy respond to that traffic.

TunTapInterface works the same as a SuperSocket, so lets setup an AnsweringMachine to respond to ICMP echo-request:

>>> am = t.am(ICMPEcho_am)
>>> am()

Now, you can ping Scapy in another terminal:

You should see those packets show up in Scapy:

>>> am()
Replying 192.0.2.1 to 192.0.2.2
Replying 192.0.2.1 to 192.0.2.2
Replying 192.0.2.1 to 192.0.2.2

You might have noticed that didn’t configure Scapy with any IP address… and there’s a trick to this: ICMPEcho_am swaps the source and destination fields of any Ether and IP headers on the ICMP packet that it receives. As a result, it actually responds to any IP address.

You can stop the ICMPEcho_am AnsweringMachine with ^C.

When you close Scapy, the tun0 interface will automatically disappear.

TunTapInterface reference

class TunTapInterface(SimpleSocket)

A socket to act as the remote side of a TUN/TAP interface.

__init__(iface: Text[, mode_tun][, strip_packet_info = True][, default_read_size = MTU])
Parameters:
  • iface (Text) –

    The name of the interface to use, eg: tun0.

    On BSD and macOS, this must start with either tun or tap, and have a corresponding /dev/ node (eg: /dev/tun0).

    On Linux, this will be truncated to 16 bytes.

  • mode_tun (bool) –

    If True, create as TUN interface (layer 3). If False, creates a TAP interface (layer 2).

    If not supplied, attempts to detect from the iface parameter.

  • strip_packet_info (bool) –

    If True (default), any TunPacketInfo will be stripped from the packet (so you get Ether or IP).

    Only Linux TUN interfaces have TunPacketInfo available.

    This has no effect for interfaces that do not have TunPacketInfo available.

  • default_read_size (int) –

    Sets the default size that is read by SuperSocket.raw_recv() and SuperSocket.recv(). This defaults to scapy.data.MTU.

    TunTapInterface always adds overhead for TunPacketInfo headers, if required.

class TunPacketInfo(Packet)

Abstract class used to stack layer 3 protocols on a platform-specific header.

See LinuxTunPacketInfo for an example.

guess_payload_class(payload)

The default implementation expects the field proto to be declared, with a value from scapy.data.ETHER_TYPES.

Linux-specific structures

class LinuxTunPacketInfo(TunPacketInfo)

Packet header used for Linux TUN packets.

This is struct tun_pi, declared in linux/if_tun.h.

flags

Flags to set on the packet. Only TUN_VNET_HDR is supported.

proto

Layer 3 protocol number, per scapy.data.ETHER_TYPES.

Used by TunTapPacketInfo.guess_payload_class().

class LinuxTunIfReq(Packet)

Internal “packet” used for TUNSETIFF requests on Linux.

This is struct ifreq, declared in linux/if.h.