diff options
author | Jason A. Donenfeld <Jason@zx2c4.com> | 2019-02-28 17:41:30 +0100 |
---|---|---|
committer | Jason A. Donenfeld <Jason@zx2c4.com> | 2019-03-01 01:38:30 +0100 |
commit | 1c56fb8996d9014e1b96332344f663fa201f3a5e (patch) | |
tree | dd411c7c77d655164621b5ed623d945346b2ebf7 | |
parent | tunnel: log the builtin go log to elog (diff) | |
download | wireguard-windows-1c56fb8996d9014e1b96332344f663fa201f3a5e.tar.xz wireguard-windows-1c56fb8996d9014e1b96332344f663fa201f3a5e.zip |
tunnel: make winipcfg sort of work
The duplicate route thing is silly, and we currently don't do DNS or the
fancy socket routing. But this is a step in the right direction,
perhaps.
Diffstat (limited to '')
-rw-r--r-- | conf/config.go | 15 | ||||
-rw-r--r-- | conf/parser.go | 8 | ||||
-rw-r--r-- | service/errors.go | 1 | ||||
-rw-r--r-- | service/service_tunnel.go | 84 | ||||
m--------- | wireguard-go | 0 |
5 files changed, 95 insertions, 13 deletions
diff --git a/conf/config.go b/conf/config.go index a321bc0c..d802ec61 100644 --- a/conf/config.go +++ b/conf/config.go @@ -64,6 +64,21 @@ func (r *IPCidr) String() string { return fmt.Sprintf("%s/%d", r.IP.String(), r.Cidr) } +func (r *IPCidr) Bits() uint8 { + if r.IP.To4() != nil { + return 32 + } else { + return 128 + } +} + +func (r *IPCidr) IPNet() net.IPNet { + return net.IPNet{ + IP: r.IP, + Mask: net.CIDRMask(int(r.Cidr), int(r.Bits())), + } +} + func (e *Endpoint) String() string { if strings.IndexByte(e.Host, ':') > 0 { return fmt.Sprintf("[%s]:%d", e.Host, e.Port) diff --git a/conf/parser.go b/conf/parser.go index 6a397a9d..48cf88b6 100644 --- a/conf/parser.go +++ b/conf/parser.go @@ -40,17 +40,21 @@ func parseIPCidr(s string) (ipcidr *IPCidr, err error) { if addr == nil { return } + maybeV4 := addr.To4() + if maybeV4 != nil { + addr = maybeV4 + } if len(cidrStr) > 0 { err = &ParseError{"Invalid network prefix length", s} cidr, err = strconv.Atoi(cidrStr) if err != nil || cidr < 0 || cidr > 128 { return } - if cidr > 32 && addr.To4() != nil { + if cidr > 32 && maybeV4 != nil { return } } else { - if addr.To4() != nil { + if maybeV4 != nil { cidr = 32 } else { cidr = 128 diff --git a/service/errors.go b/service/errors.go index 04f0638c..e2d17ab9 100644 --- a/service/errors.go +++ b/service/errors.go @@ -17,4 +17,5 @@ const ( ERROR_SERVER_SID_MISMATCH uint32 = 0x00000274 ERROR_NETWORK_BUSY uint32 = 0x00000036 ERROR_NO_TRACKING_SERVICE uint32 = 0x00000494 + ERROR_OBJECT_ALREADY_EXISTS uint32 = 0x00001392 ) diff --git a/service/service_tunnel.go b/service/service_tunnel.go index 37e0de4c..f600aa36 100644 --- a/service/service_tunnel.go +++ b/service/service_tunnel.go @@ -7,15 +7,17 @@ package service import ( "bufio" + "golang.org/x/sys/windows" + "golang.zx2c4.com/winipcfg" "log" "net" + "os" "strings" "golang.org/x/sys/windows/svc" "golang.org/x/sys/windows/svc/debug" "golang.org/x/sys/windows/svc/eventlog" - "golang.zx2c4.com/winipcfg" "golang.zx2c4.com/wireguard/windows/conf" "golang.zx2c4.com/wireguard/windows/service/tun" ) @@ -79,9 +81,9 @@ func (service *tunnelService) Execute(args []string, r <-chan svc.ChangeRequest, logger.Info.Println("Starting wireguard-go version", WireGuardGoVersion) logger.Debug.Println("Debug log enabled") - tun, err := tun.CreateTUN(conf.Name) + wintun, err := tun.CreateTUN(conf.Name) if err == nil { - realInterfaceName, err2 := tun.Name() + realInterfaceName, err2 := wintun.Name() if err2 == nil { conf.Name = realInterfaceName } @@ -92,7 +94,7 @@ func (service *tunnelService) Execute(args []string, r <-chan svc.ChangeRequest, return } - device := NewDevice(tun, logger) + device := NewDevice(wintun, logger) device.Up() logger.Info.Println("Device started") @@ -127,17 +129,77 @@ func (service *tunnelService) Execute(args []string, r <-chan svc.ChangeRequest, } ipcSetOperation(device, bufio.NewReader(strings.NewReader(uapiConf))) - //TODO: configure addresses, routes, and DNS with winipcfg - iface, err := winipcfg.InterfaceFromFriendlyName(conf.Name) + guid := wintun.(*tun.NativeTun).GUID() + iface, err := winipcfg.InterfaceFromGUID(&guid) + if err != nil { + logger.Error.Println("Unable to find Wintun device:", err) + changes <- svc.Status{State: svc.StopPending} + exitCode = ERROR_NETWORK_BUSY + device.Close() + return + } + + routeCount := len(conf.Interface.Addresses) + for _, peer := range conf.Peers { + routeCount += len(peer.AllowedIPs) + } + routes := make([]winipcfg.RouteData, routeCount) + routeCount = 0 + var firstGateway *net.IP + addresses := make([]*net.IPNet, len(conf.Interface.Addresses)) + for i, addr := range conf.Interface.Addresses { + ipnet := addr.IPNet() + addresses[i] = &ipnet + gateway := ipnet.IP.Mask(ipnet.Mask) + if firstGateway == nil { + firstGateway = &gateway + } + routes[routeCount] = winipcfg.RouteData{ + Destination: net.IPNet{ + IP: gateway, + Mask: ipnet.Mask, + }, + NextHop: gateway, + Metric: 1, + } + routeCount++ + } + + for _, peer := range conf.Peers { + for _, allowedip := range peer.AllowedIPs { + routes[routeCount] = winipcfg.RouteData{ + Destination: allowedip.IPNet(), + NextHop: *firstGateway, + Metric: 1, + } + routeCount++ + } + } + + err = iface.SetAddresses(addresses) if err == nil { - a := make([]*net.IPNet, len(conf.Interface.Addresses)) - for i, addr := range conf.Interface.Addresses { - a[i] = &net.IPNet{addr.IP, net.CIDRMask(int(addr.Cidr), len(addr.IP))} + err = iface.FlushRoutes() + if err == nil { + for _, route := range routes { + err = iface.AddRoute(&route, true) + + //TODO: Ignoring duplicate errors like this maybe isn't very reasonable. + // instead we should make sure we're not adding duplicates ourselves when + // inserting the gateway routes. + if syserr, ok := err.(*os.SyscallError); ok { + if syserr.Err == windows.Errno(ERROR_OBJECT_ALREADY_EXISTS) { + err = nil + } + } + + if err != nil { + break + } + } } - err = iface.SetAddresses(a) } if err != nil { - logger.Error.Println("Unable to setup interface addresses:", err) + logger.Error.Println("Unable to set interface addresses and routes:", err) changes <- svc.Status{State: svc.StopPending} exitCode = ERROR_NETWORK_BUSY device.Close() diff --git a/wireguard-go b/wireguard-go -Subproject 88ff67fb6f55456e46877b71aa5d33060468f95 +Subproject d435be35cac49af9367b2005d831d55e570c4b1 |