package aerotun import ( "encoding/binary" "fmt" "net" "os" "os/exec" "syscall" "unsafe" ) type VirtualDevice interface { Read(buf []byte) (int, error) Write(buf []byte) (int, error) Close() error Name() string } // CreateDevice creates either a native Linux TUN device, or falls back to a high-speed // veth pair with AF_PACKET raw socket if running in an unprivileged container without /dev/net/tun. func CreateDevice(name string, mtu int, localCIDR string) (VirtualDevice, error) { if mtu <= 0 { mtu = DefaultMTU } if _, err := os.Stat("/dev/net/tun"); err == nil { dev, err := createNativeTun(name, mtu, localCIDR) if err == nil { return dev, nil } } // Universal container / Proxmox LXC fallback: return createVethTun(name, mtu, localCIDR) } // --------------------------------------------------------------------------- // 1. Native Linux TUN Implementation (/dev/net/tun) // --------------------------------------------------------------------------- type nativeTun struct { file *os.File name string } func createNativeTun(name string, mtu int, localCIDR string) (*nativeTun, error) { fd, err := syscall.Open("/dev/net/tun", syscall.O_RDWR, 0) if err != nil { return nil, err } type ifreq struct { name [16]byte flags uint16 _pad [22]byte } var ifr ifreq copy(ifr.name[:], name) // IFF_TUN = 0x0001, IFF_NO_PI = 0x1000 ifr.flags = 0x0001 | 0x1000 _, _, errno := syscall.Syscall( syscall.SYS_IOCTL, uintptr(fd), uintptr(0x400454ca), // TUNSETIFF uintptr(unsafe.Pointer(&ifr)), ) if errno != 0 { _ = syscall.Close(fd) return nil, errno } // Configure MTU and IP _ = exec.Command("ip", "link", "set", name, "mtu", fmt.Sprintf("%d", mtu)).Run() _ = exec.Command("ip", "link", "set", name, "up").Run() if localCIDR != "" { _ = exec.Command("ip", "addr", "add", localCIDR, "dev", name).Run() } return &nativeTun{ file: os.NewFile(uintptr(fd), name), name: name, }, nil } func (t *nativeTun) Read(buf []byte) (int, error) { return t.file.Read(buf) } func (t *nativeTun) Write(buf []byte) (int, error) { return t.file.Write(buf) } func (t *nativeTun) Close() error { err := t.file.Close() _ = exec.Command("ip", "link", "delete", t.name).Run() return err } func (t *nativeTun) Name() string { return t.name } // --------------------------------------------------------------------------- // 2. High-Performance Container Fallback (VETH + AF_PACKET) // --------------------------------------------------------------------------- type vethTun struct { name string epName string sockFd int ifIndex int hwAddr [6]byte epHwAddr [6]byte packetBuf [2048]byte } func createVethTun(name string, mtu int, localCIDR string) (*vethTun, error) { epName := fmt.Sprintf("%s_ep", name) if len(epName) > 15 { epName = epName[:15] } // Clean up any stale interfaces _ = exec.Command("ip", "link", "delete", name).Run() _ = exec.Command("ip", "link", "delete", epName).Run() // 1. Create veth pair out, err := exec.Command("ip", "link", "add", name, "type", "veth", "peer", "name", epName).CombinedOutput() if err != nil { return nil, fmt.Errorf("failed to create veth pair %s: %s: %w", name, string(out), err) } // 2. Set Point-to-Point / ARP off behavior _ = exec.Command("ip", "link", "set", name, "arp", "off").Run() _ = exec.Command("ip", "link", "set", epName, "arp", "off").Run() _ = exec.Command("ip", "link", "set", name, "mtu", fmt.Sprintf("%d", mtu)).Run() _ = exec.Command("ip", "link", "set", epName, "mtu", fmt.Sprintf("%d", mtu)).Run() _ = exec.Command("ip", "link", "set", name, "up").Run() _ = exec.Command("ip", "link", "set", epName, "up").Run() // 3. Assign IP to main device if localCIDR != "" { _ = exec.Command("ip", "addr", "add", localCIDR, "dev", name).Run() } // 4. Get endpoint interface index epIface, err := net.InterfaceByName(epName) if err != nil { _ = exec.Command("ip", "link", "delete", name).Run() return nil, fmt.Errorf("failed to lookup %s: %w", epName, err) } // 5. Open AF_PACKET raw socket bound to endpoint // htons(ETH_P_ALL) = 0x0300 const ethPAll = 0x0300 sockFd, err := syscall.Socket(syscall.AF_PACKET, syscall.SOCK_RAW, int(htons(syscall.ETH_P_ALL))) if err != nil { _ = exec.Command("ip", "link", "delete", name).Run() return nil, fmt.Errorf("failed to open raw AF_PACKET socket: %w", err) } addr := syscall.SockaddrLinklayer{ Protocol: htons(syscall.ETH_P_ALL), Ifindex: epIface.Index, } if err := syscall.Bind(sockFd, &addr); err != nil { _ = syscall.Close(sockFd) _ = exec.Command("ip", "link", "delete", name).Run() return nil, fmt.Errorf("failed to bind raw socket to %s: %w", epName, err) } dev := &vethTun{ name: name, epName: epName, sockFd: sockFd, ifIndex: epIface.Index, } if len(epIface.HardwareAddr) >= 6 { copy(dev.epHwAddr[:], epIface.HardwareAddr[:6]) } if mainIface, err := net.InterfaceByName(name); err == nil && len(mainIface.HardwareAddr) >= 6 { copy(dev.hwAddr[:], mainIface.HardwareAddr[:6]) } return dev, nil } func (v *vethTun) Read(buf []byte) (int, error) { for { n, _, err := syscall.Recvfrom(v.sockFd, v.packetBuf[:], 0) if err != nil { return 0, err } if n <= 14 { continue // Too small for ethernet frame } // Ethernet frame header: [Dst MAC (6)][Src MAC (6)][EtherType (2)] etherType := binary.BigEndian.Uint16(v.packetBuf[12:14]) // Check for IPv4 (0x0800) or IPv6 (0x86DD) if etherType != 0x0800 && etherType != 0x86DD { continue // Ignore ARP, STP, etc. } ipPayload := v.packetBuf[14:n] copied := copy(buf, ipPayload) return copied, nil } } func (v *vethTun) Write(buf []byte) (int, error) { if len(buf) == 0 { return 0, nil } // Build raw Ethernet frame to inject into endpoint frameLen := 14 + len(buf) var frame []byte if frameLen <= len(v.packetBuf) { frame = v.packetBuf[:frameLen] } else { frame = make([]byte, frameLen) } // Dst MAC: main interface, Src MAC: endpoint copy(frame[0:6], v.hwAddr[:]) copy(frame[6:12], v.epHwAddr[:]) // Detect IP version var etherType uint16 = 0x0800 // IPv4 default if (buf[0] >> 4) == 6 { etherType = 0x86DD // IPv6 } binary.BigEndian.PutUint16(frame[12:14], etherType) copy(frame[14:], buf) addr := syscall.SockaddrLinklayer{ Protocol: htons(etherType), Ifindex: v.ifIndex, Halen: 6, } copy(addr.Addr[:], v.hwAddr[:]) err := syscall.Sendto(v.sockFd, frame, 0, &addr) if err != nil { return 0, err } return len(buf), nil } func (v *vethTun) Close() error { _ = syscall.Close(v.sockFd) _ = exec.Command("ip", "link", "delete", v.name).Run() return nil } func (v *vethTun) Name() string { return v.name } func htons(n uint16) uint16 { return (n<<8)&0xff00 | (n>>8)&0x00ff }