mirror of
https://gitee.com/konyshe/goodlink.git
synced 2025-12-24 08:13:00 +08:00
add support for linux and udp
This commit is contained in:
17
netstack/device.go
Normal file
17
netstack/device.go
Normal file
@@ -0,0 +1,17 @@
|
||||
package netstack
|
||||
|
||||
import (
|
||||
"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
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
// Package iobased provides the implementation of io.ReadWriter
|
||||
// based data-link layer endpoints.
|
||||
//go:build windows
|
||||
|
||||
package netstack
|
||||
|
||||
import (
|
||||
@@ -1,5 +1,3 @@
|
||||
//go:build windows
|
||||
|
||||
package netstack
|
||||
|
||||
import (
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
//go:build windows
|
||||
|
||||
package netstack
|
||||
|
||||
import (
|
||||
|
||||
80
netstack/setup.go
Normal file
80
netstack/setup.go
Normal file
@@ -0,0 +1,80 @@
|
||||
package netstack
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"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/tcp"
|
||||
"gvisor.dev/gvisor/pkg/tcpip/transport/udp"
|
||||
)
|
||||
|
||||
func setNetStack(s *stack.Stack, nicID tcpip.NICID) error {
|
||||
s.SetRouteTable([]tcpip.Route{
|
||||
{
|
||||
Destination: header.IPv4EmptySubnet,
|
||||
NIC: nicID,
|
||||
},
|
||||
})
|
||||
|
||||
if err := netstack_stack.SetPromiscuousMode(nicID, true); err != nil {
|
||||
return fmt.Errorf("promisc: %s", err)
|
||||
}
|
||||
|
||||
if err := netstack_stack.SetSpoofing(nicID, true); err != nil {
|
||||
return fmt.Errorf("spoofing: %s", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
var (
|
||||
init_stack_suss = false
|
||||
netstack_stack *stack.Stack
|
||||
)
|
||||
|
||||
func Start() error {
|
||||
if init_stack_suss {
|
||||
return nil
|
||||
}
|
||||
|
||||
netstack_stack = stack.New(stack.Options{
|
||||
NetworkProtocols: []stack.NetworkProtocolFactory{ipv4.NewProtocol},
|
||||
TransportProtocols: []stack.TransportProtocolFactory{tcp.NewProtocol},
|
||||
})
|
||||
|
||||
wintunEP, err := Open(GetName(), 1490) //因为要加自定义头,防止超出1500
|
||||
if err != nil {
|
||||
return fmt.Errorf("请管理员权限运行")
|
||||
}
|
||||
|
||||
SetTunIP(&wintunEP, GetRemoteIP(), 32)
|
||||
|
||||
// 将TUN设备注册到协议栈中,使用NIC ID 1
|
||||
nicID := tcpip.NICID(1)
|
||||
if err := netstack_stack.CreateNIC(nicID, wintunEP); err != nil {
|
||||
return fmt.Errorf("设备注册: %v", err)
|
||||
}
|
||||
|
||||
setNetStack(netstack_stack, nicID)
|
||||
|
||||
init_stack_suss = true
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func SetForWarder(stun_quic_conn quic.Connection) {
|
||||
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"
|
||||
}
|
||||
@@ -3,24 +3,100 @@
|
||||
package netstack
|
||||
|
||||
import (
|
||||
"github.com/quic-go/quic-go"
|
||||
"fmt"
|
||||
"log"
|
||||
"net"
|
||||
"os/exec"
|
||||
"unsafe"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
// setupNetstack 初始化并配置网络栈
|
||||
// 该函数负责创建协议栈、设置网络接口、配置IP地址和路由表
|
||||
// 返回:
|
||||
// - *stack.Stack: 配置好的网络栈实例
|
||||
// - error: 初始化过程中的错误信息
|
||||
func Start() error {
|
||||
func setUnixIP(name string, ip net.IP, mask net.IPMask) error {
|
||||
log.Printf("setUnixIP: %s %s %s", name, ip, mask)
|
||||
|
||||
// 新增接口存在性检查
|
||||
if err := checkInterfaceExists(name); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// 修改标志位设置流程(先关闭再开启)
|
||||
ifreq, _ := unix.NewIfreq(name)
|
||||
_, _, errno := unix.Syscall(unix.SYS_IOCTL, uintptr(unix.AF_INET), unix.SIOCGIFFLAGS, uintptr(unsafe.Pointer(ifreq)))
|
||||
if errno != 0 {
|
||||
return fmt.Errorf("SIOCGIFFLAGS(pre-check) failed: %s", unix.ErrnoName(errno))
|
||||
}
|
||||
originalFlags := ifreq.Uint16()
|
||||
|
||||
// 临时关闭接口(关键步骤)
|
||||
ifreq.SetUint16(originalFlags &^ unix.IFF_UP)
|
||||
_, _, errno = unix.Syscall(unix.SYS_IOCTL, uintptr(unix.AF_INET), unix.SIOCSIFFLAGS, uintptr(unsafe.Pointer(ifreq)))
|
||||
if errno != 0 {
|
||||
return fmt.Errorf("SIOCSIFFLAGS(down) failed: %s", unix.ErrnoName(errno))
|
||||
}
|
||||
|
||||
// 设置IP地址结构体(修复掩码处理)
|
||||
addr, _ := unix.NewIfreq(name)
|
||||
addr.SetInet4Addr(ip.To4())
|
||||
_, _, errno = unix.Syscall(unix.SYS_IOCTL, uintptr(unix.AF_INET), unix.SIOCSIFADDR, uintptr(unsafe.Pointer(addr)))
|
||||
if errno != 0 {
|
||||
return fmt.Errorf("SIOCSIFADDR failed: %s", unix.ErrnoName(errno)) // 显示具体错误名称
|
||||
}
|
||||
|
||||
// 设置子网掩码(修复变量名错误)
|
||||
maskAddr, _ := unix.NewIfreq(name)
|
||||
maskAddr.SetInet4Addr(net.IP(mask).To4()) // 显式转换掩码类型
|
||||
_, _, errno = unix.Syscall(unix.SYS_IOCTL, uintptr(unix.AF_INET), unix.SIOCSIFNETMASK, uintptr(unsafe.Pointer(maskAddr)))
|
||||
if errno != 0 {
|
||||
return fmt.Errorf("SIOCSIFNETMASK failed: %s", unix.ErrnoName(errno))
|
||||
}
|
||||
|
||||
// 修改接口激活逻辑(关键修复)
|
||||
ifreq, _ = unix.NewIfreq(name)
|
||||
ifreq.SetUint16((originalFlags | unix.IFF_UP) &^ unix.IFF_NOARP) // 保留原始标志位并添加UP标志
|
||||
_, _, errno = unix.Syscall(unix.SYS_IOCTL, uintptr(unix.AF_INET), unix.SIOCSIFFLAGS, uintptr(unsafe.Pointer(ifreq)))
|
||||
if errno != 0 {
|
||||
return fmt.Errorf("SIOCSIFFLAGS failed: %s", unix.ErrnoName(errno))
|
||||
}
|
||||
|
||||
log.Printf("Configuration applied successfully")
|
||||
return nil
|
||||
}
|
||||
|
||||
func SetForWarder(stun_quic_conn quic.Connection) {
|
||||
// 新增辅助函数
|
||||
func checkInterfaceExists(name string) error {
|
||||
ifreq, _ := unix.NewIfreq(name)
|
||||
_, _, errno := unix.Syscall(unix.SYS_IOCTL, uintptr(unix.AF_INET), unix.SIOCGIFFLAGS, uintptr(unsafe.Pointer(ifreq)))
|
||||
if errno != 0 {
|
||||
return fmt.Errorf("interface %s not exists: %s", name, unix.ErrnoName(errno))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func GetRemoteIP() string {
|
||||
return "Linux暂不支持Local端"
|
||||
}
|
||||
// 修改调用端错误处理
|
||||
func SetTunIP(wintunEP *Device, ip string, mask int) error {
|
||||
// ip addr add 192.17.0.1/32 dev GoodLink
|
||||
// ip link set GoodLink up
|
||||
// ip route add 192.17.19.1 dev GoodLink
|
||||
|
||||
func Stop() {
|
||||
// 设置网卡eth0的IP地址为192.168.1.10/24
|
||||
cmd := exec.Command("ip", "addr", "add", "192.17.0.1/32", "dev", GetName())
|
||||
if err := cmd.Run(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
cmd = exec.Command("ip", "link", "set", GetName(), "up")
|
||||
if err := cmd.Run(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
cmd = exec.Command("ip", "route", "add", GetRemoteIP(), "dev", GetName())
|
||||
if err := cmd.Run(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
/*if err := setUnixIP(GetName(), net.ParseIP(ip), net.CIDRMask(mask, 32)); err != nil {
|
||||
return fmt.Errorf("setUnixIP failed: %w", err)
|
||||
}*/
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -11,17 +11,9 @@ import (
|
||||
"net/http"
|
||||
"net/netip"
|
||||
"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/tcp"
|
||||
"gvisor.dev/gvisor/pkg/tcpip/transport/udp"
|
||||
)
|
||||
|
||||
func SetWinTunIP(wintunEP *Device, ip string, mask int) error {
|
||||
func SetTunIP(wintunEP *Device, ip string, mask int) error {
|
||||
var ipf netip.Prefix
|
||||
var err error
|
||||
|
||||
@@ -51,30 +43,6 @@ func SetWinTunIP(wintunEP *Device, ip string, mask int) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func setNetStack(s *stack.Stack, nicID tcpip.NICID) error {
|
||||
s.SetRouteTable([]tcpip.Route{
|
||||
{
|
||||
Destination: header.IPv4EmptySubnet,
|
||||
NIC: nicID,
|
||||
},
|
||||
})
|
||||
|
||||
if err := netstack_stack.SetPromiscuousMode(nicID, true); err != nil {
|
||||
return fmt.Errorf("promisc: %s", err)
|
||||
}
|
||||
|
||||
if err := netstack_stack.SetSpoofing(nicID, true); err != nil {
|
||||
return fmt.Errorf("spoofing: %s", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
var (
|
||||
init_stack_suss = false
|
||||
netstack_stack *stack.Stack
|
||||
)
|
||||
|
||||
func InitWintunDll() error {
|
||||
if gogo.Utils().FileExist("wintun.dll") {
|
||||
return nil
|
||||
@@ -105,48 +73,3 @@ func InitWintunDll() error {
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
const (
|
||||
tunIP = "192.17.19.1"
|
||||
)
|
||||
|
||||
func Start() error {
|
||||
InitWintunDll()
|
||||
|
||||
if init_stack_suss {
|
||||
return nil
|
||||
}
|
||||
|
||||
netstack_stack = stack.New(stack.Options{
|
||||
NetworkProtocols: []stack.NetworkProtocolFactory{ipv4.NewProtocol},
|
||||
TransportProtocols: []stack.TransportProtocolFactory{tcp.NewProtocol},
|
||||
})
|
||||
|
||||
wintunEP, err := Open("GoodLink", 1490) //因为要加自定义头,防止超出1500
|
||||
if err != nil {
|
||||
return fmt.Errorf("请管理员权限运行")
|
||||
}
|
||||
|
||||
SetWinTunIP(&wintunEP, tunIP, 32)
|
||||
|
||||
// 将TUN设备注册到协议栈中,使用NIC ID 1
|
||||
nicID := tcpip.NICID(1)
|
||||
if err := netstack_stack.CreateNIC(nicID, wintunEP); err != nil {
|
||||
return fmt.Errorf("设备注册: %v", err)
|
||||
}
|
||||
|
||||
setNetStack(netstack_stack, nicID)
|
||||
|
||||
init_stack_suss = true
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func SetForWarder(stun_quic_conn quic.Connection) {
|
||||
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 tunIP
|
||||
}
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
//go:build windows
|
||||
|
||||
package netstack
|
||||
|
||||
import (
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
//go:build windows
|
||||
|
||||
package netstack
|
||||
|
||||
import (
|
||||
|
||||
105
netstack/tun_linux.go
Normal file
105
netstack/tun_linux.go
Normal file
@@ -0,0 +1,105 @@
|
||||
//go:build linux
|
||||
|
||||
package netstack
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
"gvisor.dev/gvisor/pkg/rawfile"
|
||||
"gvisor.dev/gvisor/pkg/tcpip/link/fdbased"
|
||||
"gvisor.dev/gvisor/pkg/tcpip/link/tun"
|
||||
"gvisor.dev/gvisor/pkg/tcpip/stack"
|
||||
)
|
||||
|
||||
type TUN struct {
|
||||
stack.LinkEndpoint
|
||||
|
||||
fd int
|
||||
mtu uint32
|
||||
name string
|
||||
}
|
||||
|
||||
func Open(name string, mtu uint32) (Device, error) {
|
||||
t := &TUN{name: name, mtu: mtu}
|
||||
|
||||
if len(t.name) >= unix.IFNAMSIZ {
|
||||
return nil, fmt.Errorf("interface name too long: %s", t.name)
|
||||
}
|
||||
|
||||
fd, err := tun.Open(t.name)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("create tun: %w", err)
|
||||
}
|
||||
t.fd = fd
|
||||
|
||||
if t.mtu > 0 {
|
||||
if err := setMTU(t.name, t.mtu); err != nil {
|
||||
return nil, fmt.Errorf("set mtu: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
_mtu, err := rawfile.GetMTU(t.name)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("get mtu: %w", err)
|
||||
}
|
||||
t.mtu = _mtu
|
||||
|
||||
ep, err := fdbased.New(&fdbased.Options{
|
||||
FDs: []int{fd},
|
||||
MTU: t.mtu,
|
||||
// TUN only, ignore ethernet header.
|
||||
EthernetHeader: false,
|
||||
// SYS_READV support only for TUN fd.
|
||||
PacketDispatchMode: fdbased.Readv,
|
||||
// TAP/TUN fd's are not sockets and using the WritePackets calls results
|
||||
// in errors as it always defaults to using SendMMsg which is not supported
|
||||
// for tap/tun device fds.
|
||||
//
|
||||
// This CL changes WritePackets to gracefully degrade to using writev instead
|
||||
// of sendmmsg if the underlying fd is not a socket.
|
||||
//
|
||||
// Fixed: https://github.com/google/gvisor/commit/f33d034fecd7723a1e560ccc62aeeba328454fd0
|
||||
MaxSyscallHeaderBytes: 0x00,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("create endpoint: %w", err)
|
||||
}
|
||||
t.LinkEndpoint = ep
|
||||
|
||||
return t, nil
|
||||
}
|
||||
|
||||
func (t *TUN) Name() string {
|
||||
return t.name
|
||||
}
|
||||
|
||||
func (t *TUN) Close() {
|
||||
defer t.LinkEndpoint.Close()
|
||||
_ = unix.Close(t.fd)
|
||||
}
|
||||
|
||||
func (t *TUN) Type() string {
|
||||
return "tun" // 返回固定的设备类型标识符
|
||||
}
|
||||
|
||||
func setMTU(name string, n uint32) error {
|
||||
// open datagram socket
|
||||
fd, err := unix.Socket(
|
||||
unix.AF_INET,
|
||||
unix.SOCK_DGRAM,
|
||||
0,
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
defer unix.Close(fd)
|
||||
|
||||
ifr, err := unix.NewIfreq(name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
ifr.SetUint32(n)
|
||||
return unix.IoctlIfreq(fd, unix.SIOCSIFMTU, ifr)
|
||||
}
|
||||
@@ -10,21 +10,8 @@ import (
|
||||
"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
|
||||
@@ -59,6 +46,8 @@ type TUN struct {
|
||||
// - Device: 实现了Device接口的TUN设备
|
||||
// - error: 创建过程中的错误信息
|
||||
func Open(name string, mtu uint32) (_ Device, err error) {
|
||||
InitWintunDll()
|
||||
|
||||
// 使用defer和recover处理可能的panic,确保错误被正确捕获和包装
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
Reference in New Issue
Block a user