mirror of
https://github.com/coder/coder.git
synced 2025-03-14 10:09:57 +00:00
Cherry-picked fix(vpn): fail early if wintun.dll is not present (#16707) Prevents the VPN startup from hanging for 5 minutes due to a startup backoff if `wintun.dll` cannot be loaded. Because the `wintun` package doesn't expose an easy `Load() error` method for us, the only way for us to force it to load (without unwanted side effects) is through `wintun.Version()` which doesn't return an error message. So, we call that function so the `wintun` package loads the DLL and configures the logging properly, then we try to load the DLL ourselves. `LoadLibraryEx` will not load the library multiple times and returns a reference to the existing library. Closes https://github.com/coder/coder-desktop-windows/issues/24 Co-authored-by: Dean Sheather <dean@deansheather.com>
This commit is contained in:
committed by
GitHub
parent
34740bc242
commit
780b2714ff
@ -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)
|
||||
|
Reference in New Issue
Block a user