Development discussion of WireGuard
 help / color / mirror / Atom feed
* Minimal WinTUN Program Access Denied Opening Tun
@ 2019-05-21 15:17 Christopher O'Connell
  2019-05-21 15:59 ` Christopher O'Connell
  0 siblings, 1 reply; 3+ messages in thread
From: Christopher O'Connell @ 2019-05-21 15:17 UTC (permalink / raw)
  To: wireguard


[-- Attachment #1.1: Type: text/plain, Size: 3958 bytes --]

Hello,

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.

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 open \\.\Global\WINTUN32768: Access is denied.

In a nutshell, my code does the following (error checking and some other
ancillary code is omitted, please see this gist
<https://gist.github.com/jwriteclub/4f0fa081cb4eb39620702d7f7e212afd> for
the complete code):

func main() {
    // These two functions are taken from wireguard windows, added just to
make sure that
    // this code is running from the same privilege level as the WireGuard
windows code
    checkForAdminGroup()
    checkForWow64()
    // Create a tun. This works, with the small patch to tun_windows.go
which I submitted earlier
    t, err := tun.CreateTun("My Test Tun")
    nt := t.(*tun.NativeTun)
    // Get the interface and set IPs, etc
    iface, err := winipccfg.InterfaceFromLUID(nt.LUID())
    iface.SetAddresses("172.16.16.1/24")// Omitting all the mangly code to
create an IPNet
    // Listen for Reads
    wg := &sync.WaitGroup{}
    wg.Add(1)
    go func() {
        defer wg.Done()
        for {
            bt := make([]byte, 15000) // Lots of packets
            read, err := nt.Read(bt, 0) // Offset of 0 for now, just trying
to read
            if err != nil {
                fmt.Printf("%#v\n", err)
                return
            }
            fmt.Printf("Read %d bytes\n", read)
        }
    }()
    wg.Wait()
}

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, CreateTun and interface calls work, and I'm able to
see the network adapter added to Windows. However, in both cases, the call
to Read fails. Ultimately, after drilling down, the failing call is in
tun_windows.go in func (tun *NativeTun) openTUN, and the offending
line is tun.tunFileRead,
err = os.OpenFile(name, os.O_RDONLY, 0).

To test out my code, and see if I am missing some key component, I compiled
and ran golang.zx2c4.com/wireguard/main_windows.go, which exhibits the
exact same behavior as my program, ending with an error like ERROR:
(MyTunTest) 2019/05/21 18:14:17 Failed to read packet from TUN device: open
\\.\Global\WINTUN32769: Access is denied.

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.

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 tunRead =
File.Open(TUN_NAME, FileMode.Open, FileAccess.Read);, 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.

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.

All the best,

~ Christopher

[-- Attachment #1.2: Type: text/html, Size: 6828 bytes --]

[-- Attachment #2: Type: text/plain, Size: 148 bytes --]

_______________________________________________
WireGuard mailing list
WireGuard@lists.zx2c4.com
https://lists.zx2c4.com/mailman/listinfo/wireguard

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: Minimal WinTUN Program Access Denied Opening Tun
  2019-05-21 15:17 Minimal WinTUN Program Access Denied Opening Tun Christopher O'Connell
@ 2019-05-21 15:59 ` Christopher O'Connell
  2019-06-06 10:13   ` Jason A. Donenfeld
  0 siblings, 1 reply; 3+ messages in thread
From: Christopher O'Connell @ 2019-05-21 15:59 UTC (permalink / raw)
  To: wireguard


[-- Attachment #1.1: Type: text/plain, Size: 4831 bytes --]

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.

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).

I'm also interested in the rationale for requiring the system user to open
the device?

All the best,

~ Christopher

On Tue, May 21, 2019 at 6:17 PM Christopher O'Connell <jwriteclub@gmail.com>
wrote:

> Hello,
>
> 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.
>
> 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 open \\.\Global\WINTUN32768: Access is denied.
>
> In a nutshell, my code does the following (error checking and some other
> ancillary code is omitted, please see this gist
> <https://gist.github.com/jwriteclub/4f0fa081cb4eb39620702d7f7e212afd> for
> the complete code):
>
> func main() {
>     // These two functions are taken from wireguard windows, added just to
> make sure that
>     // this code is running from the same privilege level as the WireGuard
> windows code
>     checkForAdminGroup()
>     checkForWow64()
>     // Create a tun. This works, with the small patch to tun_windows.go
> which I submitted earlier
>     t, err := tun.CreateTun("My Test Tun")
>     nt := t.(*tun.NativeTun)
>     // Get the interface and set IPs, etc
>     iface, err := winipccfg.InterfaceFromLUID(nt.LUID())
>     iface.SetAddresses("172.16.16.1/24")// Omitting all the mangly code
> to create an IPNet
>     // Listen for Reads
>     wg := &sync.WaitGroup{}
>     wg.Add(1)
>     go func() {
>         defer wg.Done()
>         for {
>             bt := make([]byte, 15000) // Lots of packets
>             read, err := nt.Read(bt, 0) // Offset of 0 for now, just
> trying to read
>             if err != nil {
>                 fmt.Printf("%#v\n", err)
>                 return
>             }
>             fmt.Printf("Read %d bytes\n", read)
>         }
>     }()
>     wg.Wait()
> }
>
> 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, CreateTun and interface calls work, and I'm able
> to see the network adapter added to Windows. However, in both cases, the
> call to Read fails. Ultimately, after drilling down, the failing call is
> in tun_windows.go in func (tun *NativeTun) openTUN, and the offending
> line is tun.tunFileRead, err = os.OpenFile(name, os.O_RDONLY, 0).
>
> To test out my code, and see if I am missing some key component, I
> compiled and ran golang.zx2c4.com/wireguard/main_windows.go, which
> exhibits the exact same behavior as my program, ending with an error like ERROR:
> (MyTunTest) 2019/05/21 18:14:17 Failed to read packet from TUN device: open
> \\.\Global\WINTUN32769: Access is denied.
>
> 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.
>
> 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 tunRead =
> File.Open(TUN_NAME, FileMode.Open, FileAccess.Read);, 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.
>
> 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.
>
> All the best,
>
> ~ Christopher
>

[-- Attachment #1.2: Type: text/html, Size: 7985 bytes --]

[-- Attachment #2: Type: text/plain, Size: 148 bytes --]

_______________________________________________
WireGuard mailing list
WireGuard@lists.zx2c4.com
https://lists.zx2c4.com/mailman/listinfo/wireguard

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: Minimal WinTUN Program Access Denied Opening Tun
  2019-05-21 15:59 ` Christopher O'Connell
@ 2019-06-06 10:13   ` Jason A. Donenfeld
  0 siblings, 0 replies; 3+ messages in thread
From: Jason A. Donenfeld @ 2019-06-06 10:13 UTC (permalink / raw)
  To: Christopher O'Connell; +Cc: WireGuard mailing list

Hey Chris,

Glad to hear you're playing with Wintun. Indeed we're keeping it
locked down to SYSTEM for the time being. As we gain a better
understanding of the attack surface, maybe we'll reduce that to
built-in administrators. But you can pretty easily impersonate SYSTEM
if you have enough admin privs. Here's some code I wrote to do it from
Go: https://github.com/WireGuard/wgctrl-go/issues/36#issuecomment-491912143
Just replace the "DialPipe" invocation with "os.Open(path/to/wintun)".
Or if you want to do it from C, here's something similar:
https://git.zx2c4.com/WireGuard/tree/src/tools/wincompat/ipc.c

Jason
_______________________________________________
WireGuard mailing list
WireGuard@lists.zx2c4.com
https://lists.zx2c4.com/mailman/listinfo/wireguard

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2019-06-06 10:14 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-05-21 15:17 Minimal WinTUN Program Access Denied Opening Tun Christopher O'Connell
2019-05-21 15:59 ` Christopher O'Connell
2019-06-06 10:13   ` Jason A. Donenfeld

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).