Files
goodlink/netstack/setup.go
T

173 lines
3.7 KiB
Go

package netstack
import (
"fmt"
"log"
"net"
"sync"
"time"
"github.com/quic-go/quic-go"
"gvisor.dev/gvisor/pkg/tcpip"
"gvisor.dev/gvisor/pkg/tcpip/header"
"gvisor.dev/gvisor/pkg/tcpip/network/ipv4"
"gvisor.dev/gvisor/pkg/tcpip/stack"
"gvisor.dev/gvisor/pkg/tcpip/transport/icmp"
"gvisor.dev/gvisor/pkg/tcpip/transport/tcp"
"gvisor.dev/gvisor/pkg/tcpip/transport/udp"
)
const (
healthCheckInterval = 30 * time.Second
nicID = tcpip.NICID(1)
)
func setNetStack(s *stack.Stack, id tcpip.NICID) error {
s.SetRouteTable([]tcpip.Route{
{
Destination: header.IPv4EmptySubnet,
NIC: id,
},
})
if err := s.SetPromiscuousMode(id, true); err != nil {
return fmt.Errorf("promisc: %s", err)
}
if err := s.SetSpoofing(id, true); err != nil {
return fmt.Errorf("spoofing: %s", err)
}
return nil
}
var (
mu sync.Mutex
initStackDone bool
netstack_stack *stack.Stack
currentDevice Device
)
func initStack() error {
CleanupOldAdapter(GetName())
netstack_stack = stack.New(stack.Options{
NetworkProtocols: []stack.NetworkProtocolFactory{
ipv4.NewProtocol,
},
TransportProtocols: []stack.TransportProtocolFactory{
tcp.NewProtocol,
udp.NewProtocol,
icmp.NewProtocol4,
},
})
dev, err := Open(GetName(), 0)
if err != nil {
return fmt.Errorf("请管理员权限运行")
}
currentDevice = dev
SetTunIP(&dev, GetRemoteIP(), 32)
if err := netstack_stack.CreateNIC(nicID, dev); err != nil {
return fmt.Errorf("设备注册: %v", err)
}
remoteIP := net.ParseIP(GetRemoteIP()).To4()
protoAddr := tcpip.ProtocolAddress{
Protocol: ipv4.ProtocolNumber,
AddressWithPrefix: tcpip.AddressWithPrefix{
Address: tcpip.AddrFromSlice(remoteIP),
PrefixLen: 32,
},
}
if err := netstack_stack.AddProtocolAddress(nicID, protoAddr, stack.AddressProperties{}); err != nil {
return fmt.Errorf("绑定IP地址: %v", err)
}
if err := setNetStack(netstack_stack, nicID); err != nil {
return err
}
return nil
}
func Start() error {
mu.Lock()
defer mu.Unlock()
if initStackDone {
return nil
}
if err := initStack(); err != nil {
return err
}
initStackDone = true
go healthCheckLoop()
return nil
}
// healthCheckLoop 定期检查协议栈 NIC 状态,如果发现异常则尝试重建
func healthCheckLoop() {
for {
time.Sleep(healthCheckInterval)
mu.Lock()
if !initStackDone || netstack_stack == nil {
mu.Unlock()
continue
}
nicInfo, ok := netstack_stack.NICInfo()[nicID]
if !ok || nicInfo.Flags.Running == false {
log.Printf("[netstack] 健康检查: NIC %d 异常 (exists=%v), 尝试重建协议栈...", nicID, ok)
rebuildStack()
}
mu.Unlock()
}
}
// rebuildStack 重建整个协议栈(调用方需持有 mu 锁)
func rebuildStack() {
if currentDevice != nil {
currentDevice.Close()
currentDevice = nil
}
if netstack_stack != nil {
netstack_stack.Close()
netstack_stack = nil
}
if err := initStack(); err != nil {
log.Printf("[netstack] 重建协议栈失败: %v", err)
initStackDone = false
return
}
log.Printf("[netstack] 协议栈重建成功")
}
func SetForWarder(stun_quic_conn *quic.Conn) {
mu.Lock()
defer mu.Unlock()
if netstack_stack == nil {
return
}
netstack_stack.SetTransportProtocolHandler(tcp.ProtocolNumber, NewTcpForwarder(netstack_stack, stun_quic_conn).HandlePacket)
netstack_stack.SetTransportProtocolHandler(udp.ProtocolNumber, NewUdpForwarder(netstack_stack, stun_quic_conn).HandlePacket)
}
func GetRemoteIP() string {
return "192.17.19.1"
}
func GetName() string {
return "Goodlink"
}