From b24a15ea34cd9b6e106e6379c115c7745eb37fa4 Mon Sep 17 00:00:00 2001 From: ginuerzh Date: Sat, 20 Aug 2022 19:41:50 +0800 Subject: [PATCH] change tun from water to wireguard --- go.mod | 2 ++ go.sum | 4 +++ listener/tun/conn.go | 4 +-- listener/tun/listener.go | 4 +-- listener/tun/tun.go | 57 +++++++++++++++++++++++++++++++++++++ listener/tun/tun_darwin.go | 13 ++++----- listener/tun/tun_linux.go | 32 +++++++++++---------- listener/tun/tun_unix.go | 12 ++++---- listener/tun/tun_windows.go | 17 ++++------- 9 files changed, 99 insertions(+), 46 deletions(-) create mode 100644 listener/tun/tun.go diff --git a/go.mod b/go.mod index 8439418..ff8bee9 100644 --- a/go.mod +++ b/go.mod @@ -30,6 +30,7 @@ require ( golang.org/x/crypto v0.0.0-20220817201139-bc19a97f63c8 golang.org/x/net v0.0.0-20220812174116-3211cb980234 golang.org/x/sys v0.0.0-20220817070843-5a390386f1f2 + golang.zx2c4.com/wireguard v0.0.0-20220703234212-c31a7b1ab478 google.golang.org/grpc v1.45.0 google.golang.org/protobuf v1.27.1 gopkg.in/yaml.v2 v2.4.0 @@ -88,6 +89,7 @@ require ( golang.org/x/text v0.3.7 // indirect golang.org/x/tools v0.1.12 // indirect golang.org/x/xerrors v0.0.0-20220609144429-65e65417b02f // indirect + golang.zx2c4.com/wintun v0.0.0-20211104114900-415007cec224 // indirect google.golang.org/genproto v0.0.0-20220126215142-9970aeb2e350 // indirect gopkg.in/ini.v1 v1.66.4 // indirect gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect diff --git a/go.sum b/go.sum index b75edd2..e6fe632 100644 --- a/go.sum +++ b/go.sum @@ -743,6 +743,10 @@ golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20220609144429-65e65417b02f h1:uF6paiQQebLeSXkrTqHqz0MXhXXS1KgF41eUdBNvxK0= golang.org/x/xerrors v0.0.0-20220609144429-65e65417b02f/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= +golang.zx2c4.com/wintun v0.0.0-20211104114900-415007cec224 h1:Ug9qvr1myri/zFN6xL17LSCBGFDnphBBhzmILHsM5TY= +golang.zx2c4.com/wintun v0.0.0-20211104114900-415007cec224/go.mod h1:deeaetjYA+DHMHg+sMSMI58GrEteJUUzzw7en6TJQcI= +golang.zx2c4.com/wireguard v0.0.0-20220703234212-c31a7b1ab478 h1:vDy//hdR+GnROE3OdYbQKt9rdtNdHkDtONvpRwmls/0= +golang.zx2c4.com/wireguard v0.0.0-20220703234212-c31a7b1ab478/go.mod h1:bVQfyl2sCM/QIIGHpWbFGfHPuDvqnCNkT6MQLTCjO/U= google.golang.org/api v0.0.0-20180910000450-7ca32eb868bf/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0= google.golang.org/api v0.0.0-20181030000543-1d582fd0359e/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0= google.golang.org/api v0.1.0/go.mod h1:UGEZY7KEX120AnNLIHFMKIo4obdJhkp2tPbaPlQx13Y= diff --git a/listener/tun/conn.go b/listener/tun/conn.go index 65429c9..3471121 100644 --- a/listener/tun/conn.go +++ b/listener/tun/conn.go @@ -2,15 +2,15 @@ package tun import ( "errors" + "io" "net" "time" mdata "github.com/go-gost/core/metadata" - "github.com/songgao/water" ) type conn struct { - ifce *water.Interface + ifce io.ReadWriteCloser laddr net.Addr raddr net.Addr } diff --git a/listener/tun/listener.go b/listener/tun/listener.go index a73ad47..8e7aef0 100644 --- a/listener/tun/listener.go +++ b/listener/tun/listener.go @@ -50,7 +50,7 @@ func (l *tunListener) Init(md mdata.Metadata) (err error) { return } - ifce, ip, err := l.createTun() + ifce, name, ip, err := l.createTun() if err != nil { if ifce != nil { ifce.Close() @@ -58,7 +58,7 @@ func (l *tunListener) Init(md mdata.Metadata) (err error) { return } - itf, err := net.InterfaceByName(ifce.Name()) + itf, err := net.InterfaceByName(name) if err != nil { return } diff --git a/listener/tun/tun.go b/listener/tun/tun.go new file mode 100644 index 0000000..6c8d21a --- /dev/null +++ b/listener/tun/tun.go @@ -0,0 +1,57 @@ +package tun + +import ( + "io" + + "github.com/go-gost/core/common/bufpool" + "golang.zx2c4.com/wireguard/tun" +) + +const ( + tunOffsetBytes = 4 +) + +type tunDevice struct { + dev tun.Device +} + +func (d *tunDevice) Read(p []byte) (n int, err error) { + b := bufpool.Get(tunOffsetBytes + 65535) + defer bufpool.Put(b) + + n, err = d.dev.Read(*b, tunOffsetBytes) + if n <= tunOffsetBytes || err != nil { + d.dev.Flush() + if n <= tunOffsetBytes { + err = io.EOF + } + return + } + + n = copy(p, (*b)[tunOffsetBytes:tunOffsetBytes+n]) + return +} + +func (d *tunDevice) Write(p []byte) (n int, err error) { + b := bufpool.Get(tunOffsetBytes + len(p)) + defer bufpool.Put(b) + + copy((*b)[tunOffsetBytes:], p) + return d.dev.Write(*b, tunOffsetBytes) +} + +func (d *tunDevice) Close() error { + return d.dev.Close() +} + +func (l *tunListener) createTunDevice() (dev io.ReadWriteCloser, name string, err error) { + ifce, err := tun.CreateTUN(l.md.config.Name, l.md.config.MTU) + if err != nil { + return + } + + dev = &tunDevice{dev: ifce} + name, err = ifce.Name() + + return +} diff --git a/listener/tun/tun_darwin.go b/listener/tun/tun_darwin.go index 32db1e7..2a78d34 100644 --- a/listener/tun/tun_darwin.go +++ b/listener/tun/tun_darwin.go @@ -2,23 +2,21 @@ package tun import ( "fmt" + "io" "net" "os/exec" "strings" tun_util "github.com/go-gost/x/internal/util/tun" - "github.com/songgao/water" ) -func (l *tunListener) createTun() (ifce *water.Interface, ip net.IP, err error) { +func (l *tunListener) createTun() (ifce io.ReadWriteCloser, name string, ip net.IP, err error) { ip, _, err = net.ParseCIDR(l.md.config.Net) if err != nil { return } - ifce, err = water.New(water.Config{ - DeviceType: water.TUN, - }) + ifce, name, err = l.createTunDevice() if err != nil { return } @@ -27,9 +25,8 @@ func (l *tunListener) createTun() (ifce *water.Interface, ip net.IP, err error) if peer == "" { peer = ip.String() } - cmd := fmt.Sprintf("ifconfig %s inet %s %s mtu %d up", - ifce.Name(), l.md.config.Net, l.md.config.Peer, l.md.config.MTU) + name, l.md.config.Net, l.md.config.Peer, l.md.config.MTU) l.logger.Debug(cmd) args := strings.Split(cmd, " ") @@ -37,7 +34,7 @@ func (l *tunListener) createTun() (ifce *water.Interface, ip net.IP, err error) return } - if err = l.addRoutes(ifce.Name(), l.md.config.Routes...); err != nil { + if err = l.addRoutes(name, l.md.config.Routes...); err != nil { return } diff --git a/listener/tun/tun_linux.go b/listener/tun/tun_linux.go index aac1543..83836a4 100644 --- a/listener/tun/tun_linux.go +++ b/listener/tun/tun_linux.go @@ -2,38 +2,40 @@ package tun import ( "fmt" + "io" "net" "os/exec" "strings" tun_util "github.com/go-gost/x/internal/util/tun" - "github.com/songgao/water" ) -func (l *tunListener) createTun() (ifce *water.Interface, ip net.IP, err error) { - ifce, err = water.New(water.Config{ - DeviceType: water.TUN, - PlatformSpecificParams: water.PlatformSpecificParams{ - Name: l.md.config.Name, - }, - }) +func (l *tunListener) createTun() (ifce io.ReadWriteCloser, name string, ip net.IP, err error) { + ip, _, err = net.ParseCIDR(l.md.config.Net) if err != nil { return } - if err = l.exeCmd(fmt.Sprintf("ip link set dev %s mtu %d", ifce.Name(), l.md.config.MTU)); err != nil { + ifce, name, err = l.createTunDevice() + if err != nil { + return + } + + /* + if err = l.exeCmd(fmt.Sprintf("ip link set dev %s mtu %d", name, l.md.config.MTU)); err != nil { + l.logger.Warn(err) + } + */ + + if err = l.exeCmd(fmt.Sprintf("ip address add %s dev %s", l.md.config.Net, name)); err != nil { l.logger.Warn(err) } - if err = l.exeCmd(fmt.Sprintf("ip address add %s dev %s", l.md.config.Net, ifce.Name())); err != nil { + if err = l.exeCmd(fmt.Sprintf("ip link set dev %s up", name)); err != nil { l.logger.Warn(err) } - if err = l.exeCmd(fmt.Sprintf("ip link set dev %s up", ifce.Name())); err != nil { - l.logger.Warn(err) - } - - if err = l.addRoutes(ifce.Name(), l.md.config.Routes...); err != nil { + if err = l.addRoutes(name, l.md.config.Routes...); err != nil { return } diff --git a/listener/tun/tun_unix.go b/listener/tun/tun_unix.go index 72b2531..d9e822b 100644 --- a/listener/tun/tun_unix.go +++ b/listener/tun/tun_unix.go @@ -4,29 +4,27 @@ package tun import ( "fmt" + "io" "net" "os/exec" "strings" tun_util "github.com/go-gost/x/internal/util/tun" - "github.com/songgao/water" ) -func (l *tunListener) createTun() (ifce *water.Interface, ip net.IP, err error) { +func (l *tunListener) createTun() (ifce io.ReadWriteCloser, name string, ip net.IP, err error) { ip, _, err = net.ParseCIDR(l.md.config.Net) if err != nil { return } - ifce, err = water.New(water.Config{ - DeviceType: water.TUN, - }) + ifce, name, err = l.createTunDevice() if err != nil { return } cmd := fmt.Sprintf("ifconfig %s inet %s mtu %d up", - ifce.Name(), l.md.config.Net, l.md.config.MTU) + name, l.md.config.Net, l.md.config.MTU) l.logger.Debug(cmd) args := strings.Split(cmd, " ") @@ -35,7 +33,7 @@ func (l *tunListener) createTun() (ifce *water.Interface, ip net.IP, err error) return } - if err = l.addRoutes(ifce.Name(), l.md.config.Routes...); err != nil { + if err = l.addRoutes(name, l.md.config.Routes...); err != nil { return } diff --git a/listener/tun/tun_windows.go b/listener/tun/tun_windows.go index 8bbe7f4..b5fbf23 100644 --- a/listener/tun/tun_windows.go +++ b/listener/tun/tun_windows.go @@ -2,35 +2,28 @@ package tun import ( "fmt" + "io" "net" "os/exec" "strings" tun_util "github.com/go-gost/x/internal/util/tun" - "github.com/songgao/water" ) -func (l *tunListener) createTun() (ifce *water.Interface, ip net.IP, err error) { +func (l *tunListener) createTun() (ifce io.ReadWriteCloser, name string, ip net.IP, err error) { ip, ipNet, err := net.ParseCIDR(l.md.config.Net) if err != nil { return } - ifce, err = water.New(water.Config{ - DeviceType: water.TUN, - PlatformSpecificParams: water.PlatformSpecificParams{ - ComponentID: "tap0901", - InterfaceName: l.md.config.Name, - Network: l.md.config.Net, - }, - }) + ifce, name, err = l.createTunDevice() if err != nil { return } cmd := fmt.Sprintf("netsh interface ip set address name=%s "+ "source=static addr=%s mask=%s gateway=none", - ifce.Name(), ip.String(), ipMask(ipNet.Mask)) + name, ip.String(), ipMask(ipNet.Mask)) l.logger.Debug(cmd) args := strings.Split(cmd, " ") @@ -39,7 +32,7 @@ func (l *tunListener) createTun() (ifce *water.Interface, ip net.IP, err error) return } - if err = l.addRoutes(ifce.Name(), l.md.config.Gateway, l.md.config.Routes...); err != nil { + if err = l.addRoutes(name, l.md.config.Gateway, l.md.config.Routes...); err != nil { return }