diff --git a/dns/doq.go b/dns/doq.go index 7baeb700..7682a21e 100644 --- a/dns/doq.go +++ b/dns/doq.go @@ -1,5 +1,3 @@ -//go:build !no_doq - package dns import ( diff --git a/dns/no_doq.go b/dns/no_doq.go deleted file mode 100644 index b1d0a485..00000000 --- a/dns/no_doq.go +++ /dev/null @@ -1,10 +0,0 @@ -//go:build no_doq - -package dns - -import "github.com/Dreamacro/clash/log" - -func newDOQ(r *Resolver, addr, proxyAdapter string) dnsClient { - log.Fatalln("unsupported feature on the build") - return nil -} diff --git a/listener/tun/device/device.go b/listener/tun/device/device.go index 70115cbd..f7c3552a 100644 --- a/listener/tun/device/device.go +++ b/listener/tun/device/device.go @@ -1,3 +1,5 @@ +//go:build !no_gvisor + package device import ( diff --git a/listener/tun/device/device_no_gvisor.go b/listener/tun/device/device_no_gvisor.go new file mode 100644 index 00000000..b2d7225d --- /dev/null +++ b/listener/tun/device/device_no_gvisor.go @@ -0,0 +1,29 @@ +//go:build no_gvisor + +package device + +// Device is the interface that implemented by network layer devices (e.g. tun), +// and easy to use as stack.LinkEndpoint. +type Device interface { + + // Name returns the current name of the device. + Name() string + + // Type returns the driver type of the device. + Type() string + + // Read packets from tun device + Read(packet []byte) (int, error) + + // Write packets to tun device + Write(packet []byte) (int, error) + + // Close stops and closes the device. + Close() error + + // UseEndpoint work for gVisor stack + UseEndpoint() error + + // UseIOBased work for other ip stack + UseIOBased() error +} diff --git a/listener/tun/device/fdbased/fd_unix.go b/listener/tun/device/fdbased/fd_unix.go index 23474a5a..63f6e839 100644 --- a/listener/tun/device/fdbased/fd_unix.go +++ b/listener/tun/device/fdbased/fd_unix.go @@ -4,24 +4,13 @@ package fdbased import ( "fmt" - "os" "strconv" "github.com/Dreamacro/clash/listener/tun/device" "golang.org/x/sys/unix" - "gvisor.dev/gvisor/pkg/tcpip/stack" ) -type FD struct { - stack.LinkEndpoint - - fd int - mtu uint32 - - file *os.File -} - func Open(name string, mtu uint32) (device.Device, error) { fd, err := strconv.Atoi(name) if err != nil { diff --git a/listener/tun/device/fdbased/fd_unix_gvisor.go b/listener/tun/device/fdbased/fd_unix_gvisor.go new file mode 100644 index 00000000..cc327c77 --- /dev/null +++ b/listener/tun/device/fdbased/fd_unix_gvisor.go @@ -0,0 +1,17 @@ +//go:build !no_gvisor + +package fdbased + +import ( + "gvisor.dev/gvisor/pkg/tcpip/stack" + "os" +) + +type FD struct { + stack.LinkEndpoint + + fd int + mtu uint32 + + file *os.File +} diff --git a/listener/tun/device/fdbased/fd_unix_no_gvisor.go b/listener/tun/device/fdbased/fd_unix_no_gvisor.go new file mode 100644 index 00000000..a4ecf8b9 --- /dev/null +++ b/listener/tun/device/fdbased/fd_unix_no_gvisor.go @@ -0,0 +1,14 @@ +//go:build no_gvisor + +package fdbased + +import ( + "os" +) + +type FD struct { + fd int + mtu uint32 + + file *os.File +} diff --git a/listener/tun/device/fdbased/open_others.go b/listener/tun/device/fdbased/open_others.go index 57ad2c1a..a4d4687a 100644 --- a/listener/tun/device/fdbased/open_others.go +++ b/listener/tun/device/fdbased/open_others.go @@ -7,7 +7,6 @@ import ( "os" "github.com/Dreamacro/clash/listener/tun/device" - "github.com/Dreamacro/clash/listener/tun/device/iobased" ) func open(fd int, mtu uint32) (device.Device, error) { @@ -17,12 +16,7 @@ func open(fd int, mtu uint32) (device.Device, error) { } func (f *FD) useEndpoint() error { - ep, err := iobased.New(os.NewFile(uintptr(f.fd), f.Name()), f.mtu, 0) - if err != nil { - return fmt.Errorf("create endpoint: %w", err) - } - f.LinkEndpoint = ep - return nil + return newEp(f) } func (f *FD) useIOBased() error { diff --git a/listener/tun/device/fdbased/open_others_gvisor.go b/listener/tun/device/fdbased/open_others_gvisor.go new file mode 100644 index 00000000..7f7249eb --- /dev/null +++ b/listener/tun/device/fdbased/open_others_gvisor.go @@ -0,0 +1,19 @@ +//go:build !no_gvisor && !linux && !windows + +package fdbased + +import ( + "fmt" + "os" + + "github.com/Dreamacro/clash/listener/tun/device/iobased" +) + +func newEp(f *FD) error { + ep, err := iobased.New(os.NewFile(uintptr(f.fd), f.Name()), f.mtu, 0) + if err != nil { + return fmt.Errorf("create endpoint: %w", err) + } + f.LinkEndpoint = ep + return nil +} diff --git a/listener/tun/device/fdbased/open_others_no_gvisor.go b/listener/tun/device/fdbased/open_others_no_gvisor.go new file mode 100644 index 00000000..559881b4 --- /dev/null +++ b/listener/tun/device/fdbased/open_others_no_gvisor.go @@ -0,0 +1,11 @@ +//go:build no_gvisor && !linux && !windows + +package fdbased + +import ( + "fmt" +) + +func newEp(f *FD) error { + return fmt.Errorf("unsupported gvisor on the build") +} diff --git a/listener/tun/device/iobased/endpoint.go b/listener/tun/device/iobased/endpoint.go index e0a4583a..90871ee0 100644 --- a/listener/tun/device/iobased/endpoint.go +++ b/listener/tun/device/iobased/endpoint.go @@ -1,3 +1,5 @@ +//go:build !no_gvisor + // Package iobased provides the implementation of io.ReadWriter // based data-link layer endpoints. package iobased diff --git a/listener/tun/device/iobased/iobased.go b/listener/tun/device/iobased/iobased.go new file mode 100644 index 00000000..c16ee55c --- /dev/null +++ b/listener/tun/device/iobased/iobased.go @@ -0,0 +1 @@ +package iobased diff --git a/listener/tun/device/tun/tun_wireguard.go b/listener/tun/device/tun/tun_wireguard.go index 1aafae54..828dd56d 100644 --- a/listener/tun/device/tun/tun_wireguard.go +++ b/listener/tun/device/tun/tun_wireguard.go @@ -8,22 +8,10 @@ import ( "runtime" "github.com/Dreamacro/clash/listener/tun/device" - "github.com/Dreamacro/clash/listener/tun/device/iobased" "golang.zx2c4.com/wireguard/tun" ) -type TUN struct { - *iobased.Endpoint - - nt *tun.NativeTun - mtu uint32 - name string - offset int - - cache []byte -} - func Open(name string, mtu uint32) (_ device.Device, err error) { defer func() { if r := recover(); r != nil { @@ -91,11 +79,7 @@ func (t *TUN) Write(packet []byte) (int, error) { } func (t *TUN) Close() error { - defer func(ep *iobased.Endpoint) { - if ep != nil { - ep.Close() - } - }(t.Endpoint) + defer closeIO(t) return t.nt.Close() } @@ -105,12 +89,7 @@ func (t *TUN) Name() string { } func (t *TUN) UseEndpoint() error { - ep, err := iobased.New(t, t.mtu, t.offset) - if err != nil { - return fmt.Errorf("create endpoint: %w", err) - } - t.Endpoint = ep - return nil + return newEq(t) } func (t *TUN) UseIOBased() error { diff --git a/listener/tun/device/tun/tun_wireguard_gvisor.go b/listener/tun/device/tun/tun_wireguard_gvisor.go new file mode 100644 index 00000000..400b4219 --- /dev/null +++ b/listener/tun/device/tun/tun_wireguard_gvisor.go @@ -0,0 +1,34 @@ +//go:build !linux && !no_gvisor + +package tun + +import ( + "fmt" + "github.com/Dreamacro/clash/listener/tun/device/iobased" + "golang.zx2c4.com/wireguard/tun" +) + +type TUN struct { + *iobased.Endpoint + nt *tun.NativeTun + mtu uint32 + name string + offset int + + cache []byte +} + +func closeIO(t *TUN) { + if t.Endpoint != nil { + t.Endpoint.Close() + } +} + +func newEq(t *TUN) error { + ep, err := iobased.New(t, t.mtu, t.offset) + if err != nil { + return fmt.Errorf("create endpoint: %w", err) + } + t.Endpoint = ep + return nil +} diff --git a/listener/tun/device/tun/tun_wireguard_no_gvisor.go b/listener/tun/device/tun/tun_wireguard_no_gvisor.go new file mode 100644 index 00000000..c55487c7 --- /dev/null +++ b/listener/tun/device/tun/tun_wireguard_no_gvisor.go @@ -0,0 +1,24 @@ +//go:build !linux && no_gvisor + +package tun + +import ( + "golang.zx2c4.com/wireguard/tun" +) + +type TUN struct { + nt *tun.NativeTun + mtu uint32 + name string + offset int + + cache []byte +} + +func closeIO(t *TUN) { + +} + +func newEq(t *TUN) error { + return nil +} diff --git a/listener/tun/ipstack/gvisor/adapter/adapter.go b/listener/tun/ipstack/gvisor/adapter/adapter.go index 9a5649ef..08d0e780 100644 --- a/listener/tun/ipstack/gvisor/adapter/adapter.go +++ b/listener/tun/ipstack/gvisor/adapter/adapter.go @@ -1,3 +1,5 @@ +//go:build !no_gvisor + package adapter import ( diff --git a/listener/tun/ipstack/gvisor/adapter/handler.go b/listener/tun/ipstack/gvisor/adapter/handler.go index 715f6636..913922d6 100644 --- a/listener/tun/ipstack/gvisor/adapter/handler.go +++ b/listener/tun/ipstack/gvisor/adapter/handler.go @@ -1,3 +1,5 @@ +//go:build !no_gvisor + package adapter // Handler is a TCP/UDP connection handler that implements diff --git a/listener/tun/ipstack/gvisor/handler.go b/listener/tun/ipstack/gvisor/handler.go index 2e4ac9ff..ed119fc3 100644 --- a/listener/tun/ipstack/gvisor/handler.go +++ b/listener/tun/ipstack/gvisor/handler.go @@ -1,3 +1,5 @@ +//go:build !no_gvisor + package gvisor import ( diff --git a/listener/tun/ipstack/gvisor/nic.go b/listener/tun/ipstack/gvisor/nic.go index 0ca96778..77a1a349 100644 --- a/listener/tun/ipstack/gvisor/nic.go +++ b/listener/tun/ipstack/gvisor/nic.go @@ -1,3 +1,5 @@ +//go:build !no_gvisor + package gvisor import ( diff --git a/listener/tun/ipstack/gvisor/option/option.go b/listener/tun/ipstack/gvisor/option/option.go index 2076fd58..a2fb2851 100644 --- a/listener/tun/ipstack/gvisor/option/option.go +++ b/listener/tun/ipstack/gvisor/option/option.go @@ -1,3 +1,5 @@ +//go:build !no_gvisor + package option import ( diff --git a/listener/tun/ipstack/gvisor/route.go b/listener/tun/ipstack/gvisor/route.go index 5a3d3bf4..8e1ae94e 100644 --- a/listener/tun/ipstack/gvisor/route.go +++ b/listener/tun/ipstack/gvisor/route.go @@ -1,3 +1,5 @@ +//go:build !no_gvisor + package gvisor import ( diff --git a/listener/tun/ipstack/gvisor/stack.go b/listener/tun/ipstack/gvisor/stack.go index 1307bc71..c79bd0df 100644 --- a/listener/tun/ipstack/gvisor/stack.go +++ b/listener/tun/ipstack/gvisor/stack.go @@ -1,3 +1,5 @@ +//go:build !no_gvisor + // Package gvisor provides a thin wrapper around a gVisor's stack. package gvisor @@ -64,8 +66,9 @@ func New(device device.Device, dnsHijack []netip.AddrPort, tunAddress netip.Pref // Generate unique NIC id. nicID := tcpip.NICID(s.Stack.UniqueID()) - - opts = append(opts, + defaultOpts := []option.Option{option.WithDefault()} + defaultOpts = append(defaultOpts, opts...) + opts = append(defaultOpts, // Create stack NIC and then bind link endpoint to it. withCreatingNIC(nicID, device), diff --git a/listener/tun/ipstack/gvisor/stack_no_gvisor.go b/listener/tun/ipstack/gvisor/stack_no_gvisor.go new file mode 100644 index 00000000..7a424e74 --- /dev/null +++ b/listener/tun/ipstack/gvisor/stack_no_gvisor.go @@ -0,0 +1,19 @@ +//go:build no_gvisor + +package gvisor + +import ( + "fmt" + "github.com/Dreamacro/clash/adapter/inbound" + C "github.com/Dreamacro/clash/constant" + "github.com/Dreamacro/clash/listener/tun/device" + "github.com/Dreamacro/clash/listener/tun/ipstack" + "github.com/Dreamacro/clash/log" + "net/netip" +) + +// New allocates a new *gvStack with given options. +func New(device device.Device, dnsHijack []netip.AddrPort, tunAddress netip.Prefix, tcpIn chan<- C.ConnContext, udpIn chan<- *inbound.PacketAdapter) (ipstack.Stack, error) { + log.Fatalln("unsupported gvisor stack on the build") + return nil, fmt.Errorf("unsupported gvisor stack on the build") +} diff --git a/listener/tun/ipstack/gvisor/tcp.go b/listener/tun/ipstack/gvisor/tcp.go index a045d056..660912cb 100644 --- a/listener/tun/ipstack/gvisor/tcp.go +++ b/listener/tun/ipstack/gvisor/tcp.go @@ -1,3 +1,5 @@ +//go:build !no_gvisor + package gvisor import ( diff --git a/listener/tun/ipstack/gvisor/udp.go b/listener/tun/ipstack/gvisor/udp.go index 502e3a9c..f010ed8a 100644 --- a/listener/tun/ipstack/gvisor/udp.go +++ b/listener/tun/ipstack/gvisor/udp.go @@ -1,3 +1,5 @@ +//go:build !no_gvisor + package gvisor import ( diff --git a/listener/tun/tun_adapter.go b/listener/tun/tun_adapter.go index 9d0cad1b..7b69c5f3 100644 --- a/listener/tun/tun_adapter.go +++ b/listener/tun/tun_adapter.go @@ -13,7 +13,6 @@ import ( "github.com/Dreamacro/clash/listener/tun/ipstack" "github.com/Dreamacro/clash/listener/tun/ipstack/commons" "github.com/Dreamacro/clash/listener/tun/ipstack/gvisor" - "github.com/Dreamacro/clash/listener/tun/ipstack/gvisor/option" "github.com/Dreamacro/clash/listener/tun/ipstack/system" "github.com/Dreamacro/clash/log" "net/netip" @@ -63,7 +62,7 @@ func New(tunConf *config.Tun, tcpIn chan<- C.ConnContext, udpIn chan<- *inbound. return nil, fmt.Errorf("can't attach endpoint to tun: %w", err) } - tunStack, err = gvisor.New(tunDevice, tunConf.DNSHijack, tunAddress, tcpIn, udpIn, option.WithDefault()) + tunStack, err = gvisor.New(tunDevice, tunConf.DNSHijack, tunAddress, tcpIn, udpIn) if err != nil { _ = tunDevice.Close()