diff --git a/tun_windows.go b/tun_windows.go index ada043a..b15c1fc 100644 --- a/tun_windows.go +++ b/tun_windows.go @@ -4,14 +4,16 @@ import ( "fmt" "net" "os/exec" + "strconv" "github.com/songgao/water" ) type Tun struct { - Device string - Cidr *net.IPNet - MTU int + Device string + Cidr *net.IPNet + MTU int + UnsafeRoutes []route *water.Interface } @@ -20,13 +22,12 @@ func newTun(deviceName string, cidr *net.IPNet, defaultMTU int, routes []route, if len(routes) > 0 { return nil, fmt.Errorf("Route MTU not supported in Windows") } - if len(unsafeRoutes) > 0 { - return nil, fmt.Errorf("unsafeRoutes not supported in Windows") - } + // NOTE: You cannot set the deviceName under Windows, so you must check tun.Device after calling .Activate() return &Tun{ - Cidr: cidr, - MTU: defaultMTU, + Cidr: cidr, + MTU: defaultMTU, + UnsafeRoutes: unsafeRoutes, }, nil } @@ -66,6 +67,20 @@ func (c *Tun) Activate() error { return fmt.Errorf("failed to run 'netsh' to set MTU: %s", err) } + iface, err := net.InterfaceByName(c.Device) + if err != nil { + return fmt.Errorf("failed to find interface named %s: %v", c.Device, err) + } + + for _, r := range c.UnsafeRoutes { + err = exec.Command( + "C:\\Windows\\System32\\route.exe", "add", r.route.String(), r.via.String(), "IF", strconv.Itoa(iface.Index), + ).Run() + if err != nil { + return fmt.Errorf("failed to add the unsafe_route %s: %v", r.route.String(), err) + } + } + return nil }