<div dir="ltr"><div>So I must have messed up my service installer and wasn't really running as the LocalSystem, because with some tweaking it does open now. I further confirmed this using the PSExec64 utility and calling the basic code to run as the system user and it runs correctly.</div><div><br></div><div>So it seems that the WinTUN device does restrict itself to being opened as the system user. It might be good to add such a note to the documentation for WinTUN (I'm happy to make an edit and push a patch if others would like that).</div><div><br></div><div>I'm also interested in the rationale for requiring the system user to open the device?</div><div><br></div><div>All the best,</div><div><br></div><div>~ Christopher<br></div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Tue, May 21, 2019 at 6:17 PM Christopher O'Connell <<a href="mailto:jwriteclub@gmail.com">jwriteclub@gmail.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><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" target="_blank">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" target="_blank">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" target="_blank">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>
</blockquote></div>