@@ -25,7 +25,12 @@ import (
25
25
"github.com/coder/retry"
26
26
)
27
27
28
- const tunName = "Coder"
28
+ const (
29
+ tunName = "Coder"
30
+ tunGUID = "{0ed1515d-04a4-4c46-abae-11ad07cf0e6d}"
31
+
32
+ wintunDLL = "wintun.dll"
33
+ )
29
34
30
35
func GetNetworkingStack (t * Tunnel , _ * StartRequest , logger slog.Logger ) (NetworkStack , error ) {
31
36
// 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
44
49
45
50
// Set the name and GUID for the TUN interface.
46
51
tun .WintunTunnelType = tunName
47
- guid , err := windows .GUIDFromString ("{0ed1515d-04a4-4c46-abae-11ad07cf0e6d}" )
52
+ guid , err := windows .GUIDFromString (tunGUID )
48
53
if err != nil {
49
- panic ( err )
54
+ return NetworkStack {}, xerrors . Errorf ( "could not parse GUID %q: %w" , tunGUID , err )
50
55
}
51
56
tun .WintunStaticRequestedGUID = & guid
52
57
58
+ // Ensure wintun.dll is available, and fail early if it's not to avoid
59
+ // hanging for 5 minutes in tstunNewWithWindowsRetries.
60
+ //
61
+ // First, we call wintun.Version() to make the wintun package attempt to
62
+ // load wintun.dll. This allows the wintun package to set the logging
63
+ // callback in the DLL before we load it ourselves.
64
+ _ = wintun .Version ()
65
+
66
+ // Then, we try to load wintun.dll ourselves so we get a better error
67
+ // message if there was a problem. This call matches the wintun package, so
68
+ // we're loading it in the same way.
69
+ //
70
+ // Note: this leaks the handle to wintun.dll, but since it's already loaded
71
+ // it wouldn't be freed anyways.
72
+ const (
73
+ LOAD_LIBRARY_SEARCH_APPLICATION_DIR = 0x00000200
74
+ LOAD_LIBRARY_SEARCH_SYSTEM32 = 0x00000800
75
+ )
76
+ _ , err = windows .LoadLibraryEx (wintunDLL , 0 , LOAD_LIBRARY_SEARCH_APPLICATION_DIR | LOAD_LIBRARY_SEARCH_SYSTEM32 )
77
+ if err != nil {
78
+ 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 )
79
+ }
80
+
53
81
tunDev , tunName , err := tstunNewWithWindowsRetries (tailnet .Logger (logger .Named ("net.tun.device" )), tunName )
54
82
if err != nil {
55
83
return NetworkStack {}, xerrors .Errorf ("create tun device: %w" , err )
0 commit comments