<div dir="ltr"><div>Hello,</div><div><br></div><div>I've been very intrigued by WinTUN, and the option of a small, simple TUN driver, especially one with good golang bindings offers a lot of opportunity to build interesting things on Windows.</div><div><br></div><div>I've been building a minimal program based on the go libraries, my goal being to just write a simple ICMP endpoint to be able to ping, as a way to learn the WinTUN code and libraries. Unfortunately, I've run into an issue that I'm unable to actually read from the tun device, my code always getting errors like <span style="font-family:courier new,monospace">open \\.\Global\WINTUN32768: Access is denied</span>.</div><div><br></div><div>In a nutshell, my code does the following (error checking and some other ancillary code is omitted, please see <a href="https://gist.github.com/jwriteclub/4f0fa081cb4eb39620702d7f7e212afd">this gist</a> for the complete code):</div><div><br></div><div><span style="font-family:courier new,monospace">func main() {</span></div><div><span style="font-family:courier new,monospace">    // These two functions are taken from wireguard windows, added just to make sure that</span></div><div><span style="font-family:courier new,monospace">    // this code is running from the same privilege level as the WireGuard windows code<br></span></div><div><span style="font-family:courier new,monospace">    checkForAdminGroup()</span></div><div><span style="font-family:courier new,monospace">    checkForWow64()</span></div><div><span style="font-family:courier new,monospace">    // Create a tun. This works, with the small patch to tun_windows.go which I submitted earlier<br></span></div><div><span style="font-family:courier new,monospace">    t, err := tun.CreateTun("My Test Tun")</span></div><div><span style="font-family:courier new,monospace">    nt := t.(*tun.NativeTun)<br></span></div><div><span style="font-family:courier new,monospace">    // Get the interface and set IPs, etc<br></span></div><div><span style="font-family:courier new,monospace">    iface, err := winipccfg.InterfaceFromLUID(nt.LUID())</span></div><div><span style="font-family:courier new,monospace">    iface.SetAddresses("<a href="http://172.16.16.1/24">172.16.16.1/24</a>")// Omitting all the mangly code to create an IPNet</span></div><div><span style="font-family:courier new,monospace">    // Listen for Reads<br></span></div><div><span style="font-family:courier new,monospace">    wg := &sync.WaitGroup{}</span></div><div><span style="font-family:courier new,monospace">    wg.Add(1)</span></div><div><span style="font-family:courier new,monospace">    go func() {</span></div><div><span style="font-family:courier new,monospace">        defer wg.Done()</span></div><div><span style="font-family:courier new,monospace">        for {</span></div><div><span style="font-family:courier new,monospace">            bt := make([]byte, 15000) // Lots of packets</span></div><div><span style="font-family:courier new,monospace">            read, err := nt.Read(bt, 0) // Offset of 0 for now, just trying to read</span></div><div><span style="font-family:courier new,monospace">            if err != nil {</span></div><div><span style="font-family:courier new,monospace">                fmt.Printf("%#v\n", err)</span></div><div><span style="font-family:courier new,monospace">                return<br></span></div><div><span style="font-family:courier new,monospace">            }</span></div><div><span style="font-family:courier new,monospace">            fmt.Printf("Read %d bytes\n", read)<br></span></div><div><span style="font-family:courier new,monospace">        }<br></span></div><div><span style="font-family:courier new,monospace">    }()</span></div><div><span style="font-family:courier new,monospace">    wg.Wait()<br></span></div><div><span style="font-family:courier new,monospace">}</span></div><div><br></div><div>I've tried this using two different versions of the WinTUN driver, one where I just created a simple installer using the v0.1 MSM file on WinTun.net, and the other by installing WireGuard v0.0.8 from the main website. In both cases, <span style="font-family:courier new,monospace">CreateTun</span> and interface calls work, and I'm able to see the network adapter added to Windows. However, in both cases, the call to <span style="font-family:courier new,monospace">Read</span> fails. Ultimately, after drilling down, the failing call is in tun_windows.go in <span style="font-family:courier new,monospace">func (tun *NativeTun) openTUN</span>, and the offending line is <span style="font-family:courier new,monospace">tun.tunFileRead, err = os.OpenFile(name, os.O_RDONLY, 0)</span>.</div><div><br></div><div>To test out my code, and see if I am missing some key component, I compiled and ran <a href="http://golang.zx2c4.com/wireguard/main_windows.go">golang.zx2c4.com/wireguard/main_windows.go</a>, which exhibits the exact same behavior as my program, ending with an error like <span style="font-family:courier new,monospace">ERROR: (MyTunTest) 2019/05/21 18:14:17 Failed to read packet from TUN device: open \\.\Global\WINTUN32769: Access is denied</span>.</div><div><br></div><div>At this point I was convinced that it might be some factor about my system which was preventing this from working, but much to my surprise when I downloaded and ran the current v0.0.8 release version of the WireGuard client, it worked just fine, and I was able to connect to and route traffic through a WireGuard server.<br></div><div><br></div><div>I then considered that there was something special about opening the tun device from a service specifically, as opposed to an elevated user space process (although I cannot figure out a reason why this should be so). I whipped up a very quick windows service in C# to only tries to open the already created WinTUN device (literally, just var <span style="font-family:courier new,monospace">tunRead = File.Open(TUN_NAME, FileMode.Open, FileAccess.Read);</span>, plus all the usual service boiler plate). I installed this service with the LocalSystem permission and when starting, it similarly gets an access denied error.</div><div><br></div><div>Clearly, the WireGuard windows client is executing some command which puts the tun into an ready to open state or changes the privileges in some key way, but I have been unable to find this key command or function. Any help on a minimum viable program to successfully call Read on a WinTUN object is most appreciated.</div><div><br></div><div>All the best,</div><div><br></div><div>~ Christopher<br></div></div>