{"record":{"id":"c4f71f41b2e4fc2f","repo":"fatedier/frp","slug":"failed-to-create-tun-device-s-w","errorCode":null,"errorMessage":"failed to create TUN device '%s': %w","messagePattern":"failed to create TUN device '(.+?)': %w","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/vnet/tun_linux.go","lineNumber":43,"sourceCode":"\n\t\"github.com/vishvananda/netlink\"\n\t\"golang.zx2c4.com/wireguard/tun\"\n)\n\nconst (\n\tbaseTunName = \"utun\"\n\tdefaultMTU  = 1420\n)\n\nfunc openTun(_ context.Context, addr string) (tun.Device, error) {\n\tname, err := findNextTunName(baseTunName)\n\tif err != nil {\n\t\tname = getFallbackTunName(baseTunName, addr)\n\t}\n\n\ttunDevice, err := tun.CreateTUN(name, defaultMTU)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to create TUN device '%s': %w\", name, err)\n\t}\n\n\tactualName, err := tunDevice.Name()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tifn, err := net.InterfaceByName(actualName)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tlink, err := netlink.LinkByName(actualName)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tip, cidr, err := net.ParseCIDR(addr)","sourceCodeStart":25,"sourceCodeEnd":61,"githubUrl":"https://github.com/fatedier/frp/blob/6c8a8d0a97d03b44e9528d30b30c70cb9d61b405/pkg/vnet/tun_linux.go#L25-L61","documentation":"Linux implementation of vnet's openTun: wireguard/tun's CreateTUN failed to create the utun device, and this wraps the driver-level error. Creating a TUN device requires the kernel TUN/TAP module and privileges (CAP_NET_ADMIN), so on Linux this almost always means /dev/net/tun is missing/inaccessible or the process lacks permission.","triggerScenarios":"frpc started with vnet.enabled = true in an environment where: /dev/net/tun does not exist (module not loaded / not passed into container), the process runs as non-root without CAP_NET_ADMIN, the container lacks --device /dev/net/tun / --privileged, or the tun kernel module is blacklisted.","commonSituations":"Running frpc in Docker/Kubernetes without privileged mode or without mounting /dev/net/tun; minimal VMs/WSL2 where the tun module is absent; systemd hardening (RestrictAddressFamilies, CapabilityBoundingSet) dropping AF_UNIX/CAP_NET_ADMIN; already-exhausted or locked-down device creation.","solutions":["Load the module on the host: `sudo modprobe tun` and ensure /dev/net/tun exists (mknod /dev/net/tun c 10 200)","Run frpc with CAP_NET_ADMIN (root, or setcap/ambients); in Docker add --cap-add=NET_ADMIN --device /dev/net/tun (or --privileged)","If the kernel truly lacks TUN support, disable vnet: set vnet.enabled = false in frpc.toml","Check dmesg/audit for SELinux/AppArmor denials when the device node exists yet creation fails"],"exampleFix":"# before\ndocker run myfrpc  # vnet enabled -> failed to create TUN device 'utun0': operation not permitted\n\n# after\ndocker run --cap-add=NET_ADMIN --device /dev/net/tun myfrpc","handlingStrategy":"validation","validationCode":"// capability check before enabling vnet on linux\nfunc tunAvailable() bool {\n    f, err := os.OpenFile(\"/dev/net/tun\", os.O_RDWR, 0)\n    if err != nil { return false }\n    f.Close()\n    return os.Geteuid() == 0 || hasCapNetAdmin() // hasCapNetAdmin: parse /proc/self/status CapEff\n}","typeGuard":null,"tryCatchPattern":"if err := startVnet(); err != nil {\n    if strings.Contains(err.Error(), \"failed to create TUN device\") {\n        log.Printf(\"vnet needs /dev/net/tun + CAP_NET_ADMIN; disabling vnet: %v\", err)\n        cfg.Vnet.Enabled = false // degrade gracefully\n    }\n}","preventionTips":["In containers: --cap-add=NET_ADMIN --device /dev/net/tun","Pre-check /dev/net/tun existence at startup and fail with a clear message","Run frpc as root or grant CAP_NET_ADMIN via setcap/systemd"],"tags":["vnet","tun","linux","permissions"],"backgroundTag":null,"analyzedSha":"6c8a8d0a97d03b44e9528d30b30c70cb9d61b405","analyzedAt":"2026-08-15T06:53:27.215Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}