diff --git a/vpn/tun_windows.go b/vpn/tun_windows.go index a70cb8f28d60d..52778a8a9d08b 100644 --- a/vpn/tun_windows.go +++ b/vpn/tun_windows.go @@ -25,7 +25,12 @@ import ( "github.com/coder/retry" ) -const tunName = "Coder" +const ( + tunName = "Coder" + tunGUID = "{0ed1515d-04a4-4c46-abae-11ad07cf0e6d}" + + wintunDLL = "wintun.dll" +) func GetNetworkingStack(t *Tunnel, _ *StartRequest, logger slog.Logger) (NetworkStack, error) { // Initialize COM process-wide so Tailscale can make calls to the windows @@ -44,12 +49,35 @@ func GetNetworkingStack(t *Tunnel, _ *StartRequest, logger slog.Logger) (Network // Set the name and GUID for the TUN interface. tun.WintunTunnelType = tunName - guid, err := windows.GUIDFromString("{0ed1515d-04a4-4c46-abae-11ad07cf0e6d}") + guid, err := windows.GUIDFromString(tunGUID) if err != nil { - panic(err) + return NetworkStack{}, xerrors.Errorf("could not parse GUID %q: %w", tunGUID, err) } tun.WintunStaticRequestedGUID = &guid + // Ensure wintun.dll is available, and fail early if it's not to avoid + // hanging for 5 minutes in tstunNewWithWindowsRetries. + // + // First, we call wintun.Version() to make the wintun package attempt to + // load wintun.dll. This allows the wintun package to set the logging + // callback in the DLL before we load it ourselves. + _ = wintun.Version() + + // Then, we try to load wintun.dll ourselves so we get a better error + // message if there was a problem. This call matches the wintun package, so + // we're loading it in the same way. + // + // Note: this leaks the handle to wintun.dll, but since it's already loaded + // it wouldn't be freed anyways. + const ( + LOAD_LIBRARY_SEARCH_APPLICATION_DIR = 0x00000200 + LOAD_LIBRARY_SEARCH_SYSTEM32 = 0x00000800 + ) + _, err = windows.LoadLibraryEx(wintunDLL, 0, LOAD_LIBRARY_SEARCH_APPLICATION_DIR|LOAD_LIBRARY_SEARCH_SYSTEM32) + if err != nil { + return NetworkStack{}, xerrors.Errorf("could not load %q, it should be in the same directory as the executable (in Coder Desktop, this should have been installed automatically): %w", wintunDLL, err) + } + tunDev, tunName, err := tstunNewWithWindowsRetries(tailnet.Logger(logger.Named("net.tun.device")), tunName) if err != nil { return NetworkStack{}, xerrors.Errorf("create tun device: %w", err)
Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.
Alternative Proxies: