From 81ac55a01919740ad29afc5a46b9657b2e783359 Mon Sep 17 00:00:00 2001 From: ginuerzh Date: Fri, 27 Dec 2019 09:47:06 +0800 Subject: [PATCH] tun: replace ip command with syscall --- go.mod | 2 ++ go.sum | 4 ++++ tun.go | 59 ++++++++------------------------------------------- tun_darwin.go | 44 ++++++++++++++++++++++++++++++++++++++ tun_linux.go | 52 +++++++++++++++++++++++++++++++++++++++++++++ tun_win.go | 13 ++++++++++++ 6 files changed, 124 insertions(+), 50 deletions(-) create mode 100644 tun_darwin.go create mode 100644 tun_linux.go create mode 100644 tun_win.go diff --git a/go.mod b/go.mod index 6f783d0..382d100 100644 --- a/go.mod +++ b/go.mod @@ -10,6 +10,7 @@ require ( github.com/bifurcation/mint v0.0.0-20181105071958-a14404e9a861 // indirect github.com/cheekybits/genny v1.0.0 // indirect github.com/dchest/siphash v1.2.1 // indirect + github.com/docker/libcontainer v2.2.1+incompatible // indirect github.com/ginuerzh/gosocks4 v0.0.1 github.com/ginuerzh/gosocks5 v0.2.0 github.com/ginuerzh/tls-dissector v0.0.1 @@ -25,6 +26,7 @@ require ( github.com/lucas-clemente/quic-go v0.10.0 github.com/lucas-clemente/quic-go-certificates v0.0.0-20160823095156-d2f86524cced // indirect github.com/miekg/dns v1.1.3 + github.com/milosgajdos83/tenus v0.0.0-20190415114537-1f3ed00ae7d8 github.com/onsi/ginkgo v1.7.0 // indirect github.com/onsi/gomega v1.4.3 // indirect github.com/pkg/errors v0.8.1 // indirect diff --git a/go.sum b/go.sum index ef42f7b..6263837 100644 --- a/go.sum +++ b/go.sum @@ -16,6 +16,8 @@ github.com/dchest/siphash v1.2.0 h1:YWOShuhvg0GqbQpMa60QlCGtEyf7O7HC1Jf0VjdQ60M= github.com/dchest/siphash v1.2.0/go.mod h1:q+IRvb2gOSrUnYoPqHiyHXS0FOBBOdl6tONBlVnOnt4= github.com/dchest/siphash v1.2.1 h1:4cLinnzVJDKxTCl9B01807Yiy+W7ZzVHj/KIroQRvT4= github.com/dchest/siphash v1.2.1/go.mod h1:q+IRvb2gOSrUnYoPqHiyHXS0FOBBOdl6tONBlVnOnt4= +github.com/docker/libcontainer v2.2.1+incompatible h1:++SbbkCw+X8vAd4j2gOCzZ2Nn7s2xFALTf7LZKmM1/0= +github.com/docker/libcontainer v2.2.1+incompatible/go.mod h1:osvj61pYsqhNCMLGX31xr7klUBhHb/ZBuXS0o1Fvwbw= github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/ginuerzh/gosocks4 v0.0.1 h1:ojDKUyz+uaEeRm2usY1cyQiXTqJqrKxfeE6SVBXq4m0= @@ -52,6 +54,8 @@ github.com/lucas-clemente/quic-go-certificates v0.0.0-20160823095156-d2f86524cce github.com/lucas-clemente/quic-go-certificates v0.0.0-20160823095156-d2f86524cced/go.mod h1:NCcRLrOTZbzhZvixZLlERbJtDtYsmMw8Jc4vS8Z0g58= github.com/miekg/dns v1.1.3 h1:1g0r1IvskvgL8rR+AcHzUA+oFmGcQlaIm4IqakufeMM= github.com/miekg/dns v1.1.3/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= +github.com/milosgajdos83/tenus v0.0.0-20190415114537-1f3ed00ae7d8 h1:4WFQEfEJ7zaHYViIVM2Cd6tnQOOhiEHbmQtlcV7aOpc= +github.com/milosgajdos83/tenus v0.0.0-20190415114537-1f3ed00ae7d8/go.mod h1:G95Wwn625/q6JCCytI4VR/a5VtPwrtI0B+Q1Gi38QLA= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.7.0 h1:WSHQ+IS43OoUrWtD1/bbclrwK8TTH5hzp+umCiuxHgs= github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= diff --git a/tun.go b/tun.go index 68ee620..f228f09 100644 --- a/tun.go +++ b/tun.go @@ -5,8 +5,6 @@ import ( "io" "net" "os" - "os/exec" - "strconv" "sync" "time" @@ -26,6 +24,7 @@ type TunConfig struct { type tunHandler struct { raddr string options *HandlerOptions + ipNet *net.IPNet } // TunHandler creates a handler for tun tunnel. @@ -92,50 +91,8 @@ func (h *tunHandler) Handle(conn net.Conn) { } func (h *tunHandler) createTun() (conn net.Conn, err error) { - cfg := h.options.TunConfig - - ip, _, err := net.ParseCIDR(cfg.Addr) - if err != nil { - return - } - - ifce, err := water.New(water.Config{ - DeviceType: water.TUN, - PlatformSpecificParams: water.PlatformSpecificParams{ - Name: cfg.Name, - }, - }) - if err != nil { - return - } - - setup := func(args ...string) error { - cmd := exec.Command("/sbin/ip", args...) - cmd.Stdout = os.Stdout - cmd.Stderr = os.Stderr - return cmd.Run() - } - - mtu := cfg.MTU - if mtu <= 0 { - mtu = DefaultMTU - } - - if err = setup("link", "set", "dev", ifce.Name(), "mtu", strconv.Itoa(mtu)); err != nil { - return - } - if err = setup("addr", "add", cfg.Addr, "dev", ifce.Name()); err != nil { - return - } - if err = setup("link", "set", "dev", ifce.Name(), "up"); err != nil { - return - } - - tc := &tunConn{ - ifce: ifce, - addr: &net.IPAddr{IP: ip}, - } - return tc, nil + conn, h.ipNet, err = createTun(h.options.TunConfig) + return } func (h *tunHandler) transportTun(tun net.Conn, conn net.PacketConn, raddr net.Addr) error { @@ -223,10 +180,12 @@ func (h *tunHandler) transportTun(tun net.Conn, conn net.PacketConn, raddr net.A header.Len, header.TotalLen, header.ID, header.Flags, header.Protocol) } - if actual, loaded := routes.LoadOrStore(header.Src.String(), addr); loaded { - if actual.(net.Addr).String() != addr.String() { - log.Logf("[tun] %s <- %s: unexpected address mapping %s -> %s(actual %s)", - tun.LocalAddr(), addr, header.Dst.String(), addr, actual.(net.Addr).String()) + if h.ipNet != nil && h.ipNet.Contains(header.Src) { + if actual, loaded := routes.LoadOrStore(header.Src.String(), addr); loaded { + if actual.(net.Addr).String() != addr.String() { + log.Logf("[tun] %s <- %s: unexpected address mapping %s -> %s(actual %s)", + tun.LocalAddr(), addr, header.Dst, addr, actual.(net.Addr)) + } } } diff --git a/tun_darwin.go b/tun_darwin.go new file mode 100644 index 0000000..5b29bd1 --- /dev/null +++ b/tun_darwin.go @@ -0,0 +1,44 @@ +// +build darwin + +package gost + +import ( + "net" + "os/exec" + "strconv" + + "github.com/songgao/water" +) + +func createTun(cfg TunConfig) (conn net.Conn, ipNet *net.IPNet, err error) { + ip, ipNet, err := net.ParseCIDR(cfg.Addr) + if err != nil { + return + } + + ifce, err := water.New(water.Config{ + DeviceType: water.TUN, + }) + if err != nil { + return + } + + mtu := cfg.MTU + if mtu <= 0 { + mtu = DefaultMTU + } + + if err = exec.Command( + "ifconfig", ifce.Name(), + "inet", cfg.Addr, + "mtu", strconv.Itoa(mtu), + "up").Run(); err != nil { + return + } + + conn = &tunConn{ + ifce: ifce, + addr: &net.IPAddr{IP: ip}, + } + return +} diff --git a/tun_linux.go b/tun_linux.go new file mode 100644 index 0000000..53b2bf0 --- /dev/null +++ b/tun_linux.go @@ -0,0 +1,52 @@ +// +build linux + +package gost + +import ( + "net" + + "github.com/milosgajdos83/tenus" + "github.com/songgao/water" +) + +func createTun(cfg TunConfig) (conn net.Conn, ipNet *net.IPNet, err error) { + ip, ipNet, err := net.ParseCIDR(cfg.Addr) + if err != nil { + return + } + + ifce, err := water.New(water.Config{ + DeviceType: water.TUN, + PlatformSpecificParams: water.PlatformSpecificParams{ + Name: cfg.Name, + }, + }) + if err != nil { + return + } + + link, err := tenus.NewLinkFrom(ifce.Name()) + if err != nil { + return + } + + mtu := cfg.MTU + if mtu <= 0 { + mtu = DefaultMTU + } + if err = link.SetLinkMTU(mtu); err != nil { + return + } + if err = link.SetLinkIp(ip, ipNet); err != nil { + return + } + if err = link.SetLinkUp(); err != nil { + return + } + + conn = &tunConn{ + ifce: ifce, + addr: &net.IPAddr{IP: ip}, + } + return +} diff --git a/tun_win.go b/tun_win.go new file mode 100644 index 0000000..3a99c5c --- /dev/null +++ b/tun_win.go @@ -0,0 +1,13 @@ +// +build windows + +package gost + +import ( + "errors" + "net" +) + +func createTun(cfg TunConfig) (conn net.Conn, ipNet *net.IPNet, err error) { + err = errors.New("tun is not supported on Windows") + return +}