diff --git a/go.mod b/go.mod index ff8bee9..e382112 100644 --- a/go.mod +++ b/go.mod @@ -24,6 +24,7 @@ require ( github.com/sirupsen/logrus v1.8.1 github.com/songgao/water v0.0.0-20200317203138-2b4b6d7c09d8 github.com/spf13/viper v1.10.1 + github.com/vishvananda/netlink v1.1.0 github.com/xtaci/kcp-go/v5 v5.6.1 github.com/xtaci/smux v1.5.16 github.com/xtaci/tcpraw v1.2.25 @@ -85,6 +86,7 @@ require ( github.com/templexxx/xorsimd v0.4.1 // indirect github.com/tjfoc/gmsm v1.3.2 // indirect github.com/ugorji/go/codec v1.2.7 // indirect + github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df // indirect golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 // indirect golang.org/x/text v0.3.7 // indirect golang.org/x/tools v0.1.12 // indirect diff --git a/go.sum b/go.sum index e6fe632..c1b5a07 100644 --- a/go.sum +++ b/go.sum @@ -450,6 +450,10 @@ github.com/ugorji/go/codec v1.2.7 h1:YPXUKf7fYbp/y8xloBqZOw2qaVggbfwMlI8WM3wZUJ0 github.com/ugorji/go/codec v1.2.7/go.mod h1:WGN1fab3R1fzQlVQTkfxVtIBhWDRqOviHU95kRgeqEY= github.com/viant/assertly v0.4.8/go.mod h1:aGifi++jvCrUaklKEKT0BU95igDNaqkvz+49uaYMPRU= github.com/viant/toolbox v0.24.0/go.mod h1:OxMCG57V0PXuIP2HNQrtJf2CjqdmbrOx5EkMILuUhzM= +github.com/vishvananda/netlink v1.1.0 h1:1iyaYNBLmP6L0220aDnYQpo1QEV4t4hJ+xEEhhJH8j0= +github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYppBueQtXaqoE= +github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df h1:OviZH7qLw/7ZovXvuNyL3XQl8UFofeikI1NW1Gypu7k= +github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17pCcGlemwknint6hfoeCVQrEMVwxRLRjXpq+BU= github.com/xtaci/kcp-go/v5 v5.6.1 h1:Pwn0aoeNSPF9dTS7IgiPXn0HEtaIlVb6y5UKWPsx8bI= github.com/xtaci/kcp-go/v5 v5.6.1/go.mod h1:W3kVPyNYwZ06p79dNwFWQOVFrdcBpDBsdyvK8moQrYo= github.com/xtaci/lossyconn v0.0.0-20190602105132-8df528c0c9ae h1:J0GxkO96kL4WF+AIT3M4mfUVinOCPgf2uUWYFUzN0sM= @@ -612,6 +616,7 @@ golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190606203320-7fc4e5ec1444/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= diff --git a/listener/tun/tun_darwin.go b/listener/tun/tun_darwin.go index 2a78d34..8c22d9e 100644 --- a/listener/tun/tun_darwin.go +++ b/listener/tun/tun_darwin.go @@ -10,12 +10,19 @@ import ( tun_util "github.com/go-gost/x/internal/util/tun" ) +const ( + defaultTunName = "utun" +) + 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 l.md.config.Name == "" { + l.md.config.Name = defaultTunName + } ifce, name, err = l.createTunDevice() if err != nil { return diff --git a/listener/tun/tun_linux.go b/listener/tun/tun_linux.go index 83836a4..d79dfe6 100644 --- a/listener/tun/tun_linux.go +++ b/listener/tun/tun_linux.go @@ -4,63 +4,63 @@ import ( "fmt" "io" "net" - "os/exec" - "strings" + + "github.com/vishvananda/netlink" tun_util "github.com/go-gost/x/internal/util/tun" ) -func (l *tunListener) createTun() (ifce io.ReadWriteCloser, name string, ip net.IP, err error) { - ip, _, err = net.ParseCIDR(l.md.config.Net) +func (l *tunListener) createTun() (dev io.ReadWriteCloser, name string, ip net.IP, err error) { + ip, ipNet, err := net.ParseCIDR(l.md.config.Net) if err != nil { return } - ifce, name, err = l.createTunDevice() + dev, 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) + ifce, err := net.InterfaceByName(name) + if err != nil { + return } - if err = l.exeCmd(fmt.Sprintf("ip link set dev %s up", name)); err != nil { - l.logger.Warn(err) + link, err := netlink.LinkByName(name) + if err != nil { + return } - if err = l.addRoutes(name, l.md.config.Routes...); err != nil { + if err = netlink.AddrAdd(link, &netlink.Addr{ + IPNet: &net.IPNet{ + IP: ip, + Mask: ipNet.Mask, + }, + }); err != nil { + return + } + if err = netlink.LinkSetUp(link); err != nil { + return + } + + if err = l.addRoutes(ifce, l.md.config.Routes...); err != nil { return } return } -func (l *tunListener) exeCmd(cmd string) error { - l.logger.Debug(cmd) - - args := strings.Split(cmd, " ") - if err := exec.Command(args[0], args[1:]...).Run(); err != nil { - return fmt.Errorf("%s: %v", cmd, err) - } - - return nil -} - -func (l *tunListener) addRoutes(ifName string, routes ...tun_util.Route) error { +func (l *tunListener) addRoutes(ifce *net.Interface, routes ...tun_util.Route) error { for _, route := range routes { - cmd := fmt.Sprintf("ip route add %s dev %s", route.Net.String(), ifName) - l.logger.Debug(cmd) - - args := strings.Split(cmd, " ") - if er := exec.Command(args[0], args[1:]...).Run(); er != nil { - l.logger.Warnf("%s: %v", cmd, er) + r := netlink.Route{ + Dst: &route.Net, + Gw: route.Gateway, + } + if r.Gw == nil { + r.LinkIndex = ifce.Index + } + if err := netlink.RouteReplace(&r); err != nil { + return fmt.Errorf("add route %v %v: %v", r.Dst, r.Gw, err) } } return nil diff --git a/listener/tun/tun_unix.go b/listener/tun/tun_unix.go index d9e822b..83d434d 100644 --- a/listener/tun/tun_unix.go +++ b/listener/tun/tun_unix.go @@ -12,12 +12,19 @@ import ( tun_util "github.com/go-gost/x/internal/util/tun" ) +const ( + defaultTunName = "tun0" +) + 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 l.md.config.Name == "" { + l.md.config.Name = defaultTunName + } ifce, name, err = l.createTunDevice() if err != nil { return