Documentation
¶
Overview ¶
Package tuntap provides cross-platform support for creating and managing TUN (network tunnel) devices.
TUN devices operate at layer 3 (network layer), handling raw IP packets without Ethernet framing. They are commonly used to implement VPNs, virtual networks, and other packet tunneling applications.
Supported Platforms ¶
This package supports Linux, macOS (Darwin), FreeBSD, OpenBSD, and Windows. Each platform provides a NativeTun type that implements the tun.Tun interface from github.com/asciimoth/gonnect/tun.
Basic Usage ¶
Create a TUN device by calling CreateTUN with the desired interface name and MTU:
tun, err := tuntap.CreateTUN("utun0", 1420)
if err != nil {
log.Fatal(err)
}
defer tun.Close()
name, _ := tun.Name()
fmt.Printf("Created interface: %s\n", name)
Reading and Writing Packets ¶
Use the Read and Write methods to exchange IP packets with the TUN device. Read accepts a slice of buffers and populates them with incoming packets, returning the count and the size of each packet:
bufs := make([][]byte, tuntap.IdealBatchSize)
for i := range bufs {
bufs[i] = make([]byte, 65535)
}
sizes := make([]int, tuntap.IdealBatchSize)
n, err := tun.Read(bufs, sizes, 0)
if err != nil {
// handle error
}
for i := 0; i < n; i++ {
packet := bufs[i][0:sizes[i]]
// process IP packet
}
Write sends one or more IP packets from the provided buffers:
_, err = tun.Write(bufs[:1], 0)
Platform-Specific Batch Sizes ¶
On Linux, when the kernel supports IFF_VNET_HDR, the TUN device enables virtio network header mode. This allows batched I/O (up to IdealBatchSize packets per call) and enables TCP/UDP generic receive offload (GRO) and generic segmentation offload (GSO). On all other platforms, BatchSize() returns 1.
Device Events ¶
The Events method returns a channel that emits device state changes (interface up/down, MTU updates). Callers should consume from this channel in a goroutine:
go func() {
for event := range tun.Events() {
// handle event
}
}()
Windows ¶
On Windows, this package uses the Wintun driver (golang.zx2c4.com/wintun). The global variables WintunTunnelType and WintunStaticRequestedGUID can be set before calling CreateTUN to customize the adapter type and GUID.
Index ¶
- Constants
- Variables
- func CreateTUN(name string, mtu int) (gtun.Tun, error)
- func CreateTUNFromFile(file *os.File, mtu int) (gtun.Tun, error)
- func CreateUnmonitoredTUNFromFD(fd int) (gtun.Tun, string, error)
- type NativeTun
- func (tun *NativeTun) BatchSize() int
- func (tun *NativeTun) Close() error
- func (tun *NativeTun) Events() <-chan gtun.Event
- func (tun *NativeTun) File() *os.File
- func (t *NativeTun) IsNative() bool
- func (tun *NativeTun) MRO() int
- func (tun *NativeTun) MTU() (int, error)
- func (tun *NativeTun) MWO() int
- func (tun *NativeTun) Name() (string, error)
- func (tun *NativeTun) Read(bufs [][]byte, sizes []int, offset int) (int, error)
- func (tun *NativeTun) Write(bufs [][]byte, offset int) (int, error)
Constants ¶
const ( // IdealBatchSize is the maximum number of packets that can be processed // in a single Read or Write call. On Linux with virtio network header // support (IFF_VNET_HDR), NativeTun.BatchSize() returns this value. // On all other platforms, BatchSize() returns 1. IdealBatchSize = 128 )
Variables ¶
var ( // ErrTooManySegments is returned by NativeTun.Read when a virtio GSO // frame needs more output buffers than the caller supplied. Read returns // no packets and does not change the supplied buffers or sizes when this // error occurs. The input frame has already been consumed, so a retry // cannot recover that frame. ErrTooManySegments = errors.New("too many segments") )
Functions ¶
func CreateTUN ¶
CreateTUN creates a TUN device with the given interface name and MTU.
The name must be a valid Linux interface name. If IFF_VNET_HDR is supported by the kernel, the device will automatically enable TCP/UDP offload features (GRO/GSO).
The returned NativeTun starts background goroutines that monitor the device state and emit events on the Events channel.
func CreateTUNFromFile ¶
CreateTUNFromFile creates a TUN device from an existing os.File with the given MTU. The file must be a valid TUN file descriptor (e.g., opened from /dev/net/tun). This is useful when the file descriptor has been passed from a parent process or obtained through other means.
Like CreateTUN, this starts background goroutines for device monitoring.
func CreateUnmonitoredTUNFromFD ¶
CreateUnmonitoredTUNFromFD creates a TUN device from a raw file descriptor without starting any background monitoring goroutines. Unlike CreateTUN and CreateTUNFromFile, no netlink or hack-listener goroutines are spawned, so the Events channel will not receive automatic state updates. This is useful in scenarios where the caller manages the device lifecycle externally or when embedding the TUN fd in an existing event loop.
It returns the Tun device, the interface name, and any error that occurred.
Types ¶
type NativeTun ¶
type NativeTun struct {
// contains filtered or unexported fields
}
NativeTun is a Linux-specific TUN device. It implements the tun.Tun interface from github.com/asciimoth/gonnect/tun.
On Linux, NativeTun supports batched I/O and TCP/UDP generic receive offload (GRO) / generic segmentation offload (GSO) when the kernel provides IFF_VNET_HDR. These features are detected automatically during construction. Read returns an error that matches io.ErrShortBuffer when a packet does not fit in the visible part of an output buffer. If a GSO frame cannot be split into the supplied buffers, Read returns no packets and does not change the output buffers or sizes. The frame is still consumed.
func (*NativeTun) BatchSize ¶
BatchSize returns the maximum number of packets that can be processed in a single Read or Write call. On Linux with IFF_VNET_HDR support, this returns IdealBatchSize (128). Otherwise, it returns 1.
func (*NativeTun) Events ¶
Events returns a channel that emits device state changes. The channel emits EventUp, EventDown, and EventMTUUpdate values. The channel is closed when the TUN device is closed.