tun

package
v1.0.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 8, 2026 License: LGPL-2.1, LGPL-2.1-or-later Imports: 5 Imported by: 0

Documentation

Overview

Package tun provides a TUN network interface for Linux.

It opens /dev/net/tun via ioctl and configures the resulting interface with an IP address, peer address, and MTU using the SIOCSIFADDR, SIOCSIFDSTADDR, SIOCSIFMTU, and SIOCSIFFLAGS ioctls — all without CGo.

Only Linux is supported (CGO_ENABLED=0, golang.org/x/sys/unix).

Typical usage:

dev, err := tun.Open("tun0")         // allocate /dev/net/tun
if err != nil { ... }
defer dev.Close()

if err := dev.Configure(tun.Config{
    LocalIP:  net.ParseIP("10.8.0.6"),
    PeerIP:   net.ParseIP("10.8.0.5"),
    MTU:      1500,
}); err != nil { ... }

// dev.File() is an *os.File; read/write raw IPv4 packets from it.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Config

type Config struct {
	// LocalIP is the IP address assigned to this end of the tunnel.
	LocalIP net.IP
	// PeerIP is the P2P peer address for net30 topology.
	// Mutually exclusive with Mask — set one or the other.
	PeerIP net.IP
	// Mask is the subnet mask for subnet topology.
	// When set, the interface is configured as a regular (non-P2P) subnet
	// rather than point-to-point, where the platform supports the difference.
	Mask net.IPMask
	// MTU is the maximum transmission unit for the interface (default 1500).
	MTU int
}

Config is the addressing to give a TUN interface.

type Device

type Device struct {
	// contains filtered or unexported fields
}

Device represents an open TUN interface.

func Open

func Open(ifaceName string) (*Device, error)

Open allocates a TUN interface.

If ifaceName is empty, the kernel assigns a name (e.g. "tun0"). The interface is unconfigured; call Configure before writing packets.

Opening sequence (mirrors wireguard-go tun/tun_linux.go):

  1. Open /dev/net/tun with unix.Open (O_RDWR|O_CLOEXEC) — raw syscall, no Go runtime involvement yet.
  2. Issue TUNSETIFF directly on the raw fd.
  3. Set O_NONBLOCK on the raw fd so Go's runtime poller can use epoll.
  4. Wrap with os.NewFile — this registers the fd with epoll and enables deadline-based reads.

os.OpenFile instead of unix.Open registers the fd with epoll before TUNSETIFF runs. On some kernels /dev/net/tun is not epoll-able until a TUN interface is attached; epoll registration then fails silently and every os.File.Read returns poll.ErrNotPollable ("read /dev/net/tun: not pollable") at once.

func (*Device) Close

func (d *Device) Close() error

Close closes the TUN device file descriptor.

func (*Device) Configure

func (d *Device) Configure(cfg Config) error

Configure sets the local IP, peer IP, MTU, and brings the interface up. It must be called after Open and before writing packets.

func (*Device) File

func (d *Device) File() *os.File

File returns the underlying file, for a caller that needs the descriptor.

func (*Device) Name

func (d *Device) Name() string

Name returns the interface name, for example "tun0" or "utun4".

func (*Device) Read

func (d *Device) Read(buf []byte) (int, error)

Read reads one IP packet from the TUN device. Linux TUN with IFF_NO_PI has no packet-info header; packets are raw IP.

func (*Device) Write

func (d *Device) Write(pkt []byte) (int, error)

Write writes one IP packet to the TUN device.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL