diff --git a/cmd/gost/route.go b/cmd/gost/route.go index 265bb74..8eef1f1 100644 --- a/cmd/gost/route.go +++ b/cmd/gost/route.go @@ -437,18 +437,20 @@ func (r *route) GenRouters() ([]router, error) { handler = gost.SNIHandler() case "tun": cfg := gost.TunConfig{ - Name: node.Get("name"), - Addr: node.Get("net"), - MTU: node.GetInt("mtu"), - Routes: strings.Split(node.Get("route"), ","), + Name: node.Get("name"), + Addr: node.Get("net"), + MTU: node.GetInt("mtu"), + Routes: strings.Split(node.Get("route"), ","), + Gateway: node.Get("gw"), } handler = gost.TunHandler(node.Remote, gost.TunConfigHandlerOption(cfg)) case "tap": cfg := gost.TapConfig{ - Name: node.Get("name"), - Addr: node.Get("net"), - MTU: node.GetInt("mtu"), - Routes: strings.Split(node.Get("route"), ","), + Name: node.Get("name"), + Addr: node.Get("net"), + MTU: node.GetInt("mtu"), + Routes: strings.Split(node.Get("route"), ","), + Gateway: node.Get("gw"), } handler = gost.TapHandler(node.Remote, gost.TapConfigHandlerOption(cfg)) default: diff --git a/tuntap.go b/tuntap.go index 65635ec..db137c0 100644 --- a/tuntap.go +++ b/tuntap.go @@ -38,10 +38,11 @@ func ipProtocol(p waterutil.IPProtocol) string { } type TunConfig struct { - Name string - Addr string - MTU int - Routes []string + Name string + Addr string + MTU int + Routes []string + Gateway string } type tunRouteKey [16]byte @@ -355,14 +356,15 @@ func etherType(et waterutil.Ethertype) string { if s, ok := mEtherTypes[et]; ok { return s } - return "unknown" + return fmt.Sprintf("unknown(%v)", et) } type TapConfig struct { - Name string - Addr string - MTU int - Routes []string + Name string + Addr string + MTU int + Routes []string + Gateway string } type tapRouteKey [6]byte diff --git a/tuntap_linux.go b/tuntap_linux.go index 8256640..f2c53fc 100644 --- a/tuntap_linux.go +++ b/tuntap_linux.go @@ -57,7 +57,7 @@ func createTun(cfg TunConfig) (conn net.Conn, itf *net.Interface, err error) { return } - if err = addRoutes("tun", ifce.Name(), cfg.Routes...); err != nil { + if err = addTunRoutes(ifce.Name(), cfg.Routes...); err != nil { return } @@ -120,7 +120,7 @@ func createTap(cfg TapConfig) (conn net.Conn, itf *net.Interface, err error) { return } - if err = addRoutes("tap", ifce.Name(), cfg.Routes...); err != nil { + if err = addTapRoutes(ifce.Name(), cfg.Gateway, cfg.Routes...); err != nil { return } @@ -136,16 +136,30 @@ func createTap(cfg TapConfig) (conn net.Conn, itf *net.Interface, err error) { return } -func addRoutes(ifType, ifName string, routes ...string) error { +func addTunRoutes(ifName string, routes ...string) error { for _, route := range routes { if route == "" { continue } cmd := fmt.Sprintf("ip route add %s dev %s", route, ifName) - log.Logf("[%s] %s", ifType, cmd) + log.Logf("[tun] %s", cmd) if err := netlink.AddRoute(route, "", "", ifName); err != nil { return fmt.Errorf("%s: %v", cmd, err) } } return nil } + +func addTapRoutes(ifName string, gw string, routes ...string) error { + for _, route := range routes { + if route == "" { + continue + } + cmd := fmt.Sprintf("ip route add %s via %s dev %s", route, gw, ifName) + log.Logf("[tap] %s", cmd) + if err := netlink.AddRoute(route, "", gw, ifName); err != nil { + return fmt.Errorf("%s: %v", cmd, err) + } + } + return nil +} diff --git a/tuntap_unix.go b/tuntap_unix.go index 249c575..479dc31 100644 --- a/tuntap_unix.go +++ b/tuntap_unix.go @@ -38,7 +38,7 @@ func createTun(cfg TunConfig) (conn net.Conn, itf *net.Interface, err error) { return } - if err = addRoutes("tun", ifce.Name(), cfg.Routes...); err != nil { + if err = addTunRoutes(ifce.Name(), cfg.Routes...); err != nil { return } @@ -80,7 +80,7 @@ func createTap(cfg TapConfig) (conn net.Conn, itf *net.Interface, err error) { return } - if err = addRoutes("tap", ifce.Name(), cfg.Routes...); err != nil { + if err = addTapRoutes(ifce.Name(), cfg.Gateway, cfg.Routes...); err != nil { return } @@ -96,13 +96,31 @@ func createTap(cfg TapConfig) (conn net.Conn, itf *net.Interface, err error) { return } -func addRoutes(ifType, ifName string, routes ...string) error { +func addTunRoutes(ifName string, routes ...string) error { for _, route := range routes { if route == "" { continue } cmd := fmt.Sprintf("route add -net %s -interface %s", route, ifName) - log.Logf("[%s] %s", ifType, cmd) + log.Logf("[tun] %s", cmd) + args := strings.Split(cmd, " ") + if er := exec.Command(args[0], args[1:]...).Run(); er != nil { + return fmt.Errorf("%s: %v", cmd, er) + } + } + return nil +} + +func addTapRoutes(ifName string, gw string, routes ...string) error { + for _, route := range routes { + if route == "" { + continue + } + cmd := fmt.Sprintf("route add -net %s dev %s", route, ifName) + if gw != "" { + cmd += " gw " + gw + } + log.Logf("[tap] %s", cmd) args := strings.Split(cmd, " ") if er := exec.Command(args[0], args[1:]...).Run(); er != nil { return fmt.Errorf("%s: %v", cmd, er) diff --git a/tuntap_windows.go b/tuntap_windows.go index 92e784f..e19692a 100644 --- a/tuntap_windows.go +++ b/tuntap_windows.go @@ -38,7 +38,7 @@ func createTun(cfg TunConfig) (conn net.Conn, itf *net.Interface, err error) { return } - if err = addRoutes("tun", ifce.Name(), cfg.Routes...); err != nil { + if err = addTunRoutes(ifce.Name(), cfg.Gateway, cfg.Routes...); err != nil { return } @@ -82,7 +82,7 @@ func createTap(cfg TapConfig) (conn net.Conn, itf *net.Interface, err error) { return } - if err = addRoutes("tap", ifce.Name(), cfg.Routes...); err != nil { + if err = addTapRoutes(ifce.Name(), cfg.Gateway, cfg.Routes...); err != nil { return } @@ -98,7 +98,7 @@ func createTap(cfg TapConfig) (conn net.Conn, itf *net.Interface, err error) { return } -func addRoutes(ifType, ifName string, routes ...string) error { +func addTunRoutes(ifName string, gw string, routes ...string) error { for _, route := range routes { if route == "" { continue @@ -108,7 +108,32 @@ func addRoutes(ifType, ifName string, routes ...string) error { cmd := fmt.Sprintf("netsh interface ip add route prefix=%s interface=%s store=active", route, ifName) - log.Logf("[%s] %s", ifType, cmd) + if gw != "" { + cmd += " nexthop=" + gw + } + log.Logf("[tun] %s", cmd) + args := strings.Split(cmd, " ") + if er := exec.Command(args[0], args[1:]...).Run(); er != nil { + return fmt.Errorf("%s: %v", cmd, er) + } + } + return nil +} + +func addTapRoutes(ifName string, gw string, routes ...string) error { + for _, route := range routes { + if route == "" { + continue + } + + deleteRoute(ifName, route) + + cmd := fmt.Sprintf("netsh interface ip add route prefix=%s interface=%s store=active", + route, ifName) + if gw != "" { + cmd += " nexthop=" + gw + } + log.Logf("[tap] %s", cmd) args := strings.Split(cmd, " ") if er := exec.Command(args[0], args[1:]...).Run(); er != nil { return fmt.Errorf("%s: %v", cmd, er)