//go:build windows // Package netstack 提供了基于 WireGuard TUN 设备的网络栈实现 // 该包实现了虚拟网络接口,允许在用户空间处理网络数据包 // 主要用于实现 VPN 和网络代理功能 package netstack import ( "fmt" "sync" "golang.zx2c4.com/wireguard/tun" "gvisor.dev/gvisor/pkg/tcpip/stack" ) // Device is the interface that implemented by network layer devices (e.g. tun), // and easy to use as stack.LinkEndpoint. type Device interface { stack.LinkEndpoint // Name returns the current name of the device. Name() string // Type returns the driver type of the device. Type() string } // 常量定义 const ( offset = 0 // 数据包偏移量,用于处理TUN_PI头,0表示不使用TUN_PI defaultMTU = 0 // 默认MTU值,0表示使用系统自动配置的MTU ) // TUN 结构体实现了 TUN 设备的核心功能 // 它封装了 WireGuard 的 TUN 接口和基本的 I/O 操作 // 该结构体实现了 Device 接口,提供了与网络栈交互的能力 type TUN struct { *Endpoint // 嵌入Endpoint接口,提供网络栈接口功能,实现数据包的收发 nt *tun.NativeTun // 原生的 TUN 设备接口,用于与系统TUN设备交互 mtu uint32 // 最大传输单元,限制单个数据包的最大大小 name string // TUN 设备名称,用于系统识别 offset int // 数据包偏移量,用于处理TUN_PI头 rSizes []int // 读取数据包大小数组,用于存储每个数据包的实际大小 rBuffs [][]byte // 读取缓冲区数组,用于存储接收到的数据包 wBuffs [][]byte // 写入缓冲区数组,用于存储待发送的数据包 rMutex sync.Mutex // 读取互斥锁,保护并发读取操作 wMutex sync.Mutex // 写入互斥锁,保护并发写入操作 } // Open 创建一个新的 TUN 设备 // 该函数负责初始化TUN设备,设置MTU,并创建必要的端点 // 参数: // - name: TUN 设备名称,用于系统识别 // - mtu: 最大传输单元大小,如果为 0 则使用系统默认值 // // 返回: // - Device: 实现了Device接口的TUN设备 // - error: 创建过程中的错误信息 func Open(name string, mtu uint32) (_ Device, err error) { // 使用defer和recover处理可能的panic,确保错误被正确捕获和包装 defer func() { if r := recover(); r != nil { err = fmt.Errorf("open tun: %v", r) } }() // 初始化 TUN 结构体,设置基本参数 t := &TUN{ name: name, // 设置设备名称 mtu: mtu, // 设置MTU值 offset: offset, // 设置数据包偏移量 rSizes: make([]int, 1), // 初始化大小为1的数组,用于存储单个数据包大小 rBuffs: make([][]byte, 1), // 初始化大小为1的数组,用于存储单个接收缓冲区 wBuffs: make([][]byte, 1), // 初始化大小为1的数组,用于存储单个发送缓冲区 } // 设置 MTU,如果指定了MTU则使用指定值,否则使用系统默认值 forcedMTU := defaultMTU if t.mtu > 0 { forcedMTU = int(t.mtu) } // 创建 TUN 设备,使用WireGuard的tun包创建原生TUN接口 nt, err := tun.CreateTUN(t.name, forcedMTU) if err != nil { return nil, fmt.Errorf("create tun: %w", err) } t.nt = nt.(*tun.NativeTun) // 类型断言,确保使用NativeTun实现 // 获取实际的 MTU 值,从系统获取TUN设备的实际MTU tunMTU, err := nt.MTU() if err != nil { return nil, fmt.Errorf("get mtu: %w", err) } t.mtu = uint32(tunMTU) // 更新为系统实际的MTU值 // 创建 I/O 端点,用于处理数据包的收发 ep, err := NewEndpoint(t, t.mtu, offset) if err != nil { return nil, fmt.Errorf("create endpoint: %w", err) } t.Endpoint = ep // 设置端点,使TUN设备能够与网络栈交互 return t, nil } // Read 从 TUN 设备读取数据包 // 该方法实现了io.Reader接口,用于从TUN设备读取网络数据包 // 参数: // - packet: 用于存储读取到的数据包的缓冲区 // // 返回: // - int: 读取的字节数 // - error: 读取过程中的错误信息 func (t *TUN) Read(packet []byte) (int, error) { t.rMutex.Lock() // 加锁保护并发读取 defer t.rMutex.Unlock() t.rBuffs[0] = packet // 设置接收缓冲区,将传入的缓冲区设置为读取目标 _, err := t.nt.Read(t.rBuffs, t.rSizes, t.offset) // 从TUN设备读取数据,rSizes[0]将被设置为实际读取的字节数 return t.rSizes[0], err // 返回读取的字节数和错误 } // Name 返回 TUN 设备的名称 // 该方法实现了Device接口的Name方法 // 返回: // - string: TUN设备的名称 func (t *TUN) Name() string { name, _ := t.nt.Name() // 忽略错误,因为设备名称获取失败不影响主要功能 return name } // Close 关闭 TUN 设备 // 该方法负责清理资源,确保TUN设备和相关端点被正确关闭 func (t *TUN) Close() { defer t.Endpoint.Close() // 确保端点被正确关闭,使用defer确保即使后续操作失败也能关闭端点 t.nt.Close() // 关闭TUN设备 } // Write 向 TUN 设备写入数据包 // 该方法实现了io.Writer接口,用于向TUN设备写入网络数据包 // 参数: // - packet: 要发送的数据包 // // 返回: // - int: 写入的字节数 // - error: 写入过程中的错误信息 func (t *TUN) Write(packet []byte) (int, error) { t.wMutex.Lock() // 加锁保护并发写入 defer t.wMutex.Unlock() t.wBuffs[0] = packet // 设置发送缓冲区,将待发送的数据包放入缓冲区 return t.nt.Write(t.wBuffs, t.offset) // 向TUN设备写入数据,offset用于处理TUN_PI头 } // Type 返回设备类型,用于标识这是一个TUN设备 // 该方法实现了Device接口的Type方法 // 返回: // - string: 设备类型标识符 func (t *TUN) Type() string { return "tun" // 返回固定的设备类型标识符 } func (t *TUN) GetNt() *tun.NativeTun { return t.nt }