vnet: fix issues (#4771)

This commit is contained in:
fatedier
2025-04-27 15:22:28 +08:00
parent 27f66baf54
commit 3c8d648ddc
18 changed files with 271 additions and 185 deletions

View File

@@ -16,35 +16,44 @@ package vnet
import (
"context"
"crypto/sha256"
"encoding/hex"
"fmt"
"net"
"strconv"
"strings"
"github.com/vishvananda/netlink"
"golang.zx2c4.com/wireguard/tun"
)
const (
defaultTunName = "utun"
defaultMTU = 1420
baseTunName = "utun"
defaultMTU = 1420
)
func openTun(_ context.Context, addr string) (tun.Device, error) {
dev, err := tun.CreateTUN(defaultTunName, defaultMTU)
name, err := findNextTunName(baseTunName)
if err != nil {
name = getFallbackTunName(baseTunName, addr)
}
tunDevice, err := tun.CreateTUN(name, defaultMTU)
if err != nil {
return nil, fmt.Errorf("failed to create TUN device '%s': %w", name, err)
}
actualName, err := tunDevice.Name()
if err != nil {
return nil, err
}
name, err := dev.Name()
ifn, err := net.InterfaceByName(actualName)
if err != nil {
return nil, err
}
ifn, err := net.InterfaceByName(name)
if err != nil {
return nil, err
}
link, err := netlink.LinkByName(name)
link, err := netlink.LinkByName(actualName)
if err != nil {
return nil, err
}
@@ -69,7 +78,34 @@ func openTun(_ context.Context, addr string) (tun.Device, error) {
if err = addRoutes(ifn, cidr); err != nil {
return nil, err
}
return dev, nil
return tunDevice, nil
}
func findNextTunName(basename string) (string, error) {
interfaces, err := net.Interfaces()
if err != nil {
return "", fmt.Errorf("failed to get network interfaces: %w", err)
}
maxSuffix := -1
for _, iface := range interfaces {
name := iface.Name
if strings.HasPrefix(name, basename) {
suffix := name[len(basename):]
if suffix == "" {
continue
}
numSuffix, err := strconv.Atoi(suffix)
if err == nil && numSuffix > maxSuffix {
maxSuffix = numSuffix
}
}
}
nextSuffix := maxSuffix + 1
name := fmt.Sprintf("%s%d", basename, nextSuffix)
return name, nil
}
func addRoutes(ifn *net.Interface, cidr *net.IPNet) error {
@@ -82,3 +118,14 @@ func addRoutes(ifn *net.Interface, cidr *net.IPNet) error {
}
return nil
}
// getFallbackTunName generates a deterministic fallback TUN device name
// based on the base name and the provided address string using a hash.
func getFallbackTunName(baseName, addr string) string {
hasher := sha256.New()
hasher.Write([]byte(addr))
hashBytes := hasher.Sum(nil)
// Use first 4 bytes -> 8 hex chars for brevity, respecting IFNAMSIZ limit.
shortHash := hex.EncodeToString(hashBytes[:4])
return fmt.Sprintf("%s%s", baseName, shortHash)
}