The Go linker isn't smart enough to prevent gvisor from being pulled
into modules that use other parts of tun/, due to the types exposed. So,
we put this into its own standalone module.
We use this as an opportunity to introduce some example code as well.
I'm still not happy that this not only clutters this repo's go.sum, but
all the other projects that consume it, but it seems like making a new
module inside of this repo will lead to even greater confusion.
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
Type tcpip.Error is not an error.
I've filed https://github.com/google/gvisor/issues/5314
to fix this upstream.
Until that is fixed, use %v instead of %w,
to keep vet happy.
Signed-off-by: Josh Bleecher Snyder <josh@tailscale.com>
This allows people to initiate connections over WireGuard without any
underlying operating system support.
I'm not crazy about the trash it adds to go.sum, but the code this
actually adds to the binaries seems contained to the gvisor repo.
For the TCP/IP implementation, it uses gvisor. And it borrows some
internals from the Go standard library's resolver in order to bring Dial
and DialContext to tun_net, along with the LookupHost helper function.
This allows for things like HTTP2-over-TLS to work quite well:
package main
import (
"io"
"log"
"net"
"net/http"
"golang.zx2c4.com/wireguard/device"
"golang.zx2c4.com/wireguard/tun"
)
func main() {
tun, tnet, err := tun.CreateNetTUN([]net.IP{net.ParseIP("192.168.4.29")}, []net.IP{net.ParseIP("8.8.8.8"), net.ParseIP("8.8.4.4")}, 1420)
if err != nil {
log.Panic(err)
}
dev := device.NewDevice(tun, &device.Logger{log.Default(), log.Default(), log.Default()})
dev.IpcSet(`private_key=a8dac1d8a70a751f0f699fb14ba1cff7b79cf4fbd8f09f44c6e6a90d0369604f
public_key=25123c5dcd3328ff645e4f2a3fce0d754400d3887a0cb7c56f0267e20fbf3c5b
endpoint=163.172.161.0:12912
allowed_ip=0.0.0.0/0
`)
dev.Up()
client := http.Client{
Transport: &http.Transport{
DialContext: tnet.DialContext,
},
}
resp, err := client.Get("https://www.zx2c4.com/ip")
if err != nil {
log.Panic(err)
}
body, err := io.ReadAll(resp.Body)
if err != nil {
log.Panic(err)
}
log.Println(string(body))
}
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
Since _32 and _64 aren't valid goarchs, they don't match _GOOS_GOARCH,
and so the existing tags wind up not being restricted to windows-only.
This fixes the problem by adding windows to the tags explicitly. We
could also fix it by calling the files _32_windows or _64_windows, but
that changes the convention with the other single-arch files.
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
It doesn't really matter, because it is only used in tests,
but it does remove some noise from pprof profiles.
Signed-off-by: Josh Bleecher Snyder <josh@tailscale.com>
Rather than having every application using Wintun driver reinvent the
wheel, the Wintun device/adapter/interface management has been moved
from wireguard-go to wintun.dll deployed with Wintun itself.
Signed-off-by: Simon Rozman <simon@rozman.si>
Direct syscalls using unix.Syscall(unix.SYS_*, ...) are discouraged on
macOS and might not be supported in future versions. Switch to use
unix.Connect with unix.SockaddrCtl instead.
Signed-off-by: Tobias Klauser <tklauser@distanz.ch>
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
Direct syscalls using unix.Syscall(unix.SYS_*, ...) are discouraged on
macOS and might not be supported in future versions. Switch to use
unix.Ioctl{Get,Set}IfreqMTU to get and set an interface's MTU.
Signed-off-by: Tobias Klauser <tklauser@distanz.ch>
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
Direct syscalls using unix.Syscall(unix.SYS_*, ...) are discouraged on
macOS and might not be supported in future versions. Switch to use
unix.IoctlCtlInfo to get the kernel control info.
Signed-off-by: Tobias Klauser <tklauser@distanz.ch>
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
Direct syscalls using unix.Syscall(unix.SYS_*, ...) are discouraged on
macOS and might not be supported in future versions. Instead, use the
existing unix.GetsockoptString wrapper to get the interface name.
Signed-off-by: Tobias Klauser <tklauser@distanz.ch>
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
c85e4a410f introduced preliminary HWID
checking to speed up Wintun adapter enumeration. However, all HWID are
case insensitive by Windows convention.
Furthermore, a device might have multiple HWIDs. When DevInfo's
DeviceRegistryProperty(SPDRP_HARDWAREID) method returns []string, all
strings returned should be checked against given hardware ID.
This issue was discovered when researching Wintun and wireguard-go on
Windows 10 ARM64. The Wintun adapter was created using devcon.exe
utility with "wintun" hardware ID, causing wireguard-go fail to
enumerate the adapter properly.
Signed-off-by: Simon Rozman <simon@rozman.si>
It was just returning "no such file or directory" (the String of the
syscall.Errno returned by CreateTUN).
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
This works around a startup race condition when competing with
HackListener, which is trying to do the same job. If HackListener
detects that the tundev is running while there is still an event in the
netlink queue that says it isn't running, then the device receives a
string of events like
EventUp (HackListener)
EventDown (NetlinkListener)
EventUp (NetlinkListener)
Unfortunately, after the first EventDown, the device stops itself,
thinking incorrectly that the administrator has downed its tundev.
The device is ignoring the initial EventDown anyway, so just don't emit
it.
Signed-off-by: Avery Pennarun <apenwarr@tailscale.com>
Update the golang.org/x/sys/unix dependency and use the newly introduced
RTMGRP_* consts instead of using the corresponding RTNLGRP_* const to
create a mask.
Signed-off-by: Tobias Klauser <tklauser@distanz.ch>
Some devices take ~2 seconds to enumerate on Windows if we try to get
their instance name. The hardware id property, on the other hand,
is available right away.
Signed-off-by: Avery Pennarun <apenwarr@gmail.com>
[zx2c4: inlined this to where it makes sense, reused setupapi const]
In some cases, we operate on an already-up interface, or the user brings
up the interface before we start monitoring. For those situations, we
should first check if the interface is already up.
This still technically races between the initial check and the start of
the route loop, but fixing that is a bit ugly and probably not worth it
at the moment.
Reported-by: Theo Buehler <tb@theobuehler.org>