Giter Club home page Giter Club logo

wgctrl-go's Introduction

WireGuard โ€” fast, modern, secure kernel VPN tunnel

WireGuard is a novel VPN that runs inside the Linux Kernel and utilizes state-of-the-art cryptography. It aims to be faster, simpler, leaner, and more useful than IPsec, while avoiding the massive headache. It intends to be considerably more performant than OpenVPN. WireGuard is designed as a general purpose VPN for running on embedded interfaces and super computers alike, fit for many different circumstances. It runs over UDP.

More information may be found at WireGuard.com.

License

This project is released under the GPLv2.

wgctrl-go's People

Contributors

adphi avatar aleksi avatar apognu avatar geowiwi avatar jameshartig avatar mdlayher avatar muhlemmer avatar samczsun avatar sergeymakinen avatar stenya avatar tklauser avatar zx2c4 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

wgctrl-go's Issues

internal/wgnl: consider using rtnetlink to filter and fetch only WireGuard devices

Right now, we try to probe every network interface on the system to determine if it's a WireGuard device, but this is a bit inefficient.

We could consider using rtnetlink and using the ifinfomsg structure directly to determine which devices are WireGuard devices:

https://lists.zx2c4.com/pipermail/wireguard/2018-July/003148.html

The thing you're dumping from a single device is all the peers. If you
want a list of all interfaces, then the place to NLM_F_DUMP is
RTM_GETLINK, where you can then inspect
ifinfomsg->IFLA_LINKINFO->IFLA_INFO_KIND and make sure that it's
"wireguard". WireGuard itself doesn't [necessarily need to] know all
of the instances of itself, since it's instantiated by the rtnl
subsystem. Check out kernel_get_wireguard_interfaces here:

https://git.zx2c4.com/WireGuard/tree/src/tools/ipc.c#n458

Peer to PeerConfig method

I'm writing a getter/ setter kind of config app for which I need to convert wgtypes.Peer to wgtypes.PeerConfig. I'm planning to write a helper function for that. If you guys are interested, I can make it a method of wgtypes.Peer and send a pull request instead.

I'm thinking of the following design:

// PeerConfig converts Peer into a config.
// Empty fields become nil in output, so those properties will not be reconfigured.
// Remove field in output is always false.
// ReplaceAllowedIPs configures the likewise named field in output.
func(p *Peer)PeerConfig(ReplaceAllowedIPs bool) PeerConfig

Removes allowed ips of all existing peers when new peer is added

Hello,
Thank you very much for the library. I am trying to change wireguard configuration on the server side to dynamically add peers. To accomplish this, I do this when a client gets connected:

conf:=wgtypes.Config{
			ReplacePeers: false,
			Peers: []wgtypes.PeerConfig{{
				PublicKey: CLIENT_PUBLIC_KEY,
				Remove:     false,
				UpdateOnly: false,
				Endpoint:nil,
				PersistentKeepaliveInterval: 20*time.Second,
				ReplaceAllowedIPs:           false,
				AllowedIPs: []net.IPNet{{
					IP:   net.ParseIP("0.0.0.0"),
					Mask: net.ParseIP("0.0.0.0"+"/24").DefaultMask(),
				}},
			}},
		}
Client.ConfigureDevice("wg0", conf)

I am relaxing AllowedIPs to allow any for now. Later I will be specific to the given client. This works fine for one client and I see communication fine but when second client connects, first client looses connection. When I looked at wg showconf wg0, I see old peer lost AllowedIPs settings. It shows like this:

wg showconf wg0
[Peer]
PublicKey = 6ssntOAN/Fr6at6ZH0sdjVssvYmVpaX60idhu8HBJXo=
PersistentKeepalive = 20

[Peer]
PublicKey = 63aWx7RpOlxMnXFt0unfBGUryafooPlsMn8d2rQeH2o=
AllowedIPs = 0.0.0.0/0
PersistentKeepalive = 20

When I again add another peer, the Peer with public key 63aWx7RpOlxMnXFt0unfBGUryafooPlsMn8d2rQeH2o= also looses AllowedIPs section. Is there any work around/ config parameter to retain old Allowed IPs?? I did play around with ReplaceAllowedIPs and other parameters but didn't help :(

Unable to open peer after adding it via wgctl on MacOS

I am unable to access added peer with address using below code on MacOS.
This code works well on both Windows and Linux but on MacOS Added peers dont open.
Is there something else i have to do ?

`

	conf := wgtypes.Config{
		ReplacePeers: true,
		Peers:        peers,
	}

	x,_ := client.Devices()


	a	:= client.ConfigureDevice(x[0].Name, conf)

Using wg-quick route for peer similar to stated below is added automatically
101.0.0.8/32 utun1 USc 1 0 utun1
But using wgctl-go route is not added .
Any work around or solution for this on MacOs ??

Bug in `func (k Key) PublicKey() Key`?

I'm trying to use wctrl-go in a go program, but i am getting weird results.

the only usage for wgctrl-go i have currently is to generate keys, which i then put in the /etc/wireguard/wg0.conf. it's done with the following code:

	var privKey wgtypes.Key
	if privKey, err := wgtypes.GeneratePrivateKey(); err == nil {
		bouncerConfig.BouncerPrivKey = privKey.String()
		log.Printf("Bouncer private key: %v\n", bouncerConfig.BouncerPrivKey)
	} else {
		log.Println("ERROR: error generating private key", err)
		return nil, err
	}
	bouncerConfig.BouncerPubKey = privKey.PublicKey().String()
	log.Printf("Bouncer public key: %v\n", bouncerConfig.BouncerPubKey)

when i run it, this is what's logged:

2020-02-04 22:57:56.832801500  2020/02/04 22:57:56 Bouncer private key: +LRL+OLjKPNkdoqohPuIib6uYpIdl0GhR4PYS2oIGFs=
2020-02-04 22:57:56.832810500  2020/02/04 22:57:56 Bouncer public key: L+V9o0fNYkMVKNqsX7spBzD/9oSvxM/C7ZCZX1jLO3Q=

here's the weird part: if I copy the private key and generate a public key from it using wg, i get a totally different key:

bouncer2:/# echo "+LRL+OLjKPNkdoqohPuIib6uYpIdl0GhR4PYS2oIGFs=" | wg pubkey
a549Q66azW/EDHnrg1PmL7d4ruTO0/M2ti3Yo+dn8SI=
bouncer2:/#

And if I use it, the key generated by the go code does not work. this is on the the other node:

[Interface]
Address = 10.20.30.11
PrivateKey = eDSeLcnjtIZvBG0bkdnL4VF2KhkZ0jwIPHdGScv+fnw=
DNS = 1.1.1.1
MTU = 1500
SaveConfig = true

[Peer]
PublicKey = L+V9o0fNYkMVKNqsX7spBzD/9oSvxM/C7ZCZX1jLO3Q=
AllowedIPs = 10.20.30.10/32
Endpoint = 172.17.0.4:27182

/ # ip l del wg0; wg-quick up wg0
[#] ip link add wg0 type wireguard
[#] wg setconf wg0 /dev/fd/63
[#] ip -4 address add 10.20.30.11 dev wg0
[#] ip link set mtu 1500 up dev wg0
[#] resolvconf -a wg0 -m 0 -x
[#] ip -4 route add 10.20.30.10/32 dev wg0
/ # ping 10.20.30.10
PING 10.20.30.10 (10.20.30.10): 56 data bytes
^C
--- 10.20.30.10 ping statistics ---
2 packets transmitted, 0 packets received, 100% packet loss

and if i use the public key generated with wg on the command line, it works:

/ # cat /etc/wireguard/wg0.conf
[Interface]
Address = 10.20.30.11
PrivateKey = eDSeLcnjtIZvBG0bkdnL4VF2KhkZ0jwIPHdGScv+fnw=
DNS = 1.1.1.1
MTU = 1500
SaveConfig = true

[Peer]
PublicKey = a549Q66azW/EDHnrg1PmL7d4ruTO0/M2ti3Yo+dn8SI=
AllowedIPs = 10.20.30.10/32
Endpoint = 172.17.0.4:27182

/ # ip l del wg0; wg-quick up wg0
[#] ip link add wg0 type wireguard
[#] wg setconf wg0 /dev/fd/63
[#] ip -4 address add 10.20.30.11 dev wg0
[#] ip link set mtu 1500 up dev wg0
[#] resolvconf -a wg0 -m 0 -x
[#] ip -4 route add 10.20.30.10/32 dev wg0
/ # ping 10.20.30.10
PING 10.20.30.10 (10.20.30.10): 56 data bytes
64 bytes from 10.20.30.10: seq=0 ttl=64 time=2.854 ms
64 bytes from 10.20.30.10: seq=1 ttl=64 time=0.992 ms
64 bytes from 10.20.30.10: seq=2 ttl=64 time=0.484 ms
^C
--- 10.20.30.10 ping statistics ---
3 packets transmitted, 3 packets received, 0% packet loss
round-trip min/avg/max = 0.484/1.443/2.854 ms

am i doing something wrong?

Add support for creating an interface

It would be really cool to have support to create and initialize a new wireguard interface. In theory, it should only be neccessary to have a client.CreateWG(name string) error method, which creates a blank interface (basically the equivalent of running ip link add dev wg0 type wireguard)

wireguardctrl: consider eliminating Client.DeviceByIndex

This function is arguably less friendly than Client.DeviceByName. On top of this, there is no concept of an interface index in the userspace interface, so in wguser, it is implemented by calling net.InterfaceByIndex and then Client.DeviceByName immediately after.

Removing this function also means that the method Client.DeviceByName could be shortened to just Client.Device.

Expired last handshake

How to know if a peer connexion is expired, when the last handshake time is too old ?

Testing: staticcheck fails

As noted in PR #85: On current master branch staticcheck fails:

$ staticcheck ./...
internal/wglinux/configure_linux_test.go:126:14: netlink.Nested | 0 always equals netlink.Nested (SA4016)
internal/wglinux/configure_linux_test.go:355:12: netlink.Nested | 0 always equals netlink.Nested (SA4016)
internal/wglinux/configure_linux_test.go:379:12: netlink.Nested | 0 always equals netlink.Nested (SA4016)
internal/wglinux/configure_linux_test.go:405:12: netlink.Nested | 0 always equals netlink.Nested (SA4016)
internal/wglinux/configure_linux_test.go:430:12: netlink.Nested | 0 always equals netlink.Nested (SA4016)
internal/wglinux/configure_linux_test.go:454:12: netlink.Nested | 0 always equals netlink.Nested (SA4016)
internal/wglinux/configure_linux_test.go:479:12: netlink.Nested | 0 always equals netlink.Nested (SA4016)
internal/wglinux/configure_linux_test.go:504:12: netlink.Nested | 0 always equals netlink.Nested (SA4016)
$ staticcheck -version
staticcheck 2020.1.3

The solution seems simple, remove the bit-wise OR 0. I will work on a PR today fixing this.

Peer endpoint port is not packed correctly

Hi,

The port of a peer endpoint seems to be transmitted incorrectly to netlink, here are the values set in the PeerConfig (left) struct and the resulting value as reported by wg (right) after calling ConfigureDevice:

  • 10000 -> 4135
  • 51820 -> 27850

go mods

any chance you can version control the dependencies ?

wgctrl: replace "not found" sentinels with errors.Is check

In Go 1.13, we can use errors.Is(err, os.ErrNotExist) and similar to look for certain classes of errors. The code in this package should comply with that pattern, while also attempting to retain some compatibility with older versions of Go.

wgctrl: specify network namespace

There already is support within netlink for creating getting a socket to a specific netns, however when dialing, the client passes nil instead of a new netlink.Config. This would still lead to unix.Setns in the end, and you still need to find the fd first, but it provides better leverage over network namespaces. I think this could be used to allow a new wgctrl.NewClientWithNSfunction (with a better name than I just thought of).

I think there would also be an even better approach. Instead of using unix.Setns, there are already examples from other projects where unix.Bind got used. From what I see, unix.Bind is already used but only after the new thread gets created with newLockedNetNSGoroutine. I think it is possible to go straight away for a socket to another network namespace, without forcing an OS thread with runtime.LockOSThread().

If you think I am on a good path here, please let me know and I will try to dig deeper, fork the projects and try this out.

Peer list is empty

I have a wg0 up and wg command shows

interface: wg0
  public key: Y3Rl1Sz+kqmPYdbhpPDt5hNi55RUoWdbZQ9gjgxo8Vs=
  private key: (hidden)
  listening port: 44884
  fwmark: 0xca6c

peer: vSVK3Lri4HFW0ztVCy181M81+nO24+sY1xIVYAwcYwk=
  endpoint: 94.237.85.150:51820
  allowed ips: 0.0.0.0/0, ::/0
  transfer: 0 B received, 148 B sent

I can query the wg0 device though wgctrl-go as seen below

&{wg0 Linux kernel aOpy+HOCNz8mXqXAluECXnMfPKOWAKFOjfgxYS0zZk0= Y3Rl1Sz+kqmPYdbhpPDt5hNi55RUoWdbZQ9gjgxo8Vs= 44884 51820 []}

However, as seen above, the peer slice is empty. Any ideas why?

Thanks

Add support for ARM

I am trying to cross-compile wireguardctrl for my NAS device. It has very old kernel so I cannot use kernel based wireguard. The wireguard-go implementation doesn't include configuration command. So I decided that wireguardctrl could be a good option since as it seems to support userspace implementations. However I have a problem to compile it with go1.11.4. Here is the list of commands I use:

(master)$ go version
go version go1.11.4 linux/amd64

(master)$ GOARM=7 GOOS=linux GOARCH=arm go get -ldflags "-R 65536" -u github.com/mdlayher/wireguardctrl
# github.com/mdlayher/wireguardctrl/internal/wgnl
tools/go/go1.11.4/lib/src/github.com/mdlayher/wireguardctrl/internal/wgnl/parse_linux.go:265:20: cannot use ts.Sec (type int32) as type int64 in argument to time.Unix
tools/go/go1.11.4/lib/src/github.com/mdlayher/wireguardctrl/internal/wgnl/parse_linux.go:265:28: cannot use ts.Nsec (type int32) as type int64 in argument to time.Unix

Force to use specific implementation

Right now kernel and userspace implementation are behind the /internal subpackage and inaccessible to foreign packages. I'd like to force my code to use only kernel implementation and fail if that's not possible.

The simplest way to do it is making those implementations reachable by other packages, e.g. renaming internal to pkg or something like that

internal/wglinux: dealing with network namespaces

A situation came up in IRC this morning where a user (@bitkeks) would like to enter a network namespace in their own code using setns(2) and then manipulate WireGuard devices using wgctrl.

The goroutine with a modified namespace called into wgctrl and ultimately netlink, but because of the way my netlink package spins up an internal goroutine for dealing with system calls, that internal goroutine was not part of the same network namespace as its calling goroutine. To remedy this, I've added mdlayher/netlink#141 which enables the caller to explicitly opt-in to setting the namespace of the calling thread on the internal goroutine/syscall thread.

On IRC, we had also discussed that EPERM from setns(2) (due to lack of CAP_SYS_ADMIN/root) could be non-fatal, but then we can end up in a state where the caller attempted to configure a namespace but the namespace was not actually applied. Yet, no error would be returned in this case.

In order to integrate these ideas into wgctrl, we have a few options. At this point, I'm leaning toward option 2, but I'd be happy to hear from others as well.

/cc @bitkeks @zx2c4


  1. set netlink.CallingThreadNetNS in genetlink.Dial config and do nothing else

This means that the calling and netlink socket goroutines will share the same network namespace, but either root or CAP_SYS_ADMIN is now required at all times to set the network namespace. root or CAP_NET_ADMIN are already required to manipulate WireGuard devices.

I consider this the least favorable option, although it is the simplest.


  1. expose a config struct for wgctrl.New and add an option to use the calling thread's namespace

This option is explicit and requires the caller to actually opt-in to calling setns(2) under the hood, so root/CAP_SYS_ADMIN is only required if the user explicitly says so.

This pattern is pretty common in Go applications, and could look something like:

package wgctrl

type Config struct {
    // Make Client retrieve the network namespace of the calling thread and use it
    // internally, so WireGuard devices in that namespace can be manipulated.
    LinuxCallingThreadNetNS bool

    // Alternative: actually specify a namespace FD for the netlink socket to enter,
    // with a constant for "calling thread". If set to zero, nothing happens.
    // LinuxNetNS int

    // Room for future options and extensibility...
    // OpenBSDFoo int
}

Then the caller can either use an explicit config, or nil for none:

// Use all defaults.
c, err := wgctrl.New(nil)

// Configure only what is needed. Empty fields are defaults.
c, err := wgctrl.New(&wgctrl.Config{
    LinuxCallingThreadNetNS: true,
})

I'm currently in favor of doing this because it is simple to implement and explicit. It is slightly unfortunate that:

  • it would break existing callers, but it won't be hard for them to replace wgctrl.New() with wgctrl.New(nil) (however, we make zero API stability guarantees at this time anyway)
  • the user has to explicitly opt-in to this to get the behavior they might assume would already work, if they're already using setns(2) (as @bitkeks is)

  1. set netlink.CallingThreadNetNS and add additional logic in package netlink to figure out if we're already in the right namespace in both the calling thread and internal syscall thread

If we create the internal sycall goroutine and lock OS thread, then determine it has an identical network namespace to the calling thread, there's no need to ever invoke setns(2). This could mean that the code could continue to work without privileges, unless a network namespace was explicitly set in either the calling thread or configuration. If the calling thread was able to set a namespace, package netlink will already have permission to do so as well.

There is the potential to use something like kcmp(2) to see if the namespaces match, but it appears to have some caveats according to the manpage:

       Note the kcmp() is not protected against false positives which may occur if the processes are currently running.   One  should  stop  the
       processes by sending SIGSTOP (see signal(7)) prior to inspection with this system call to obtain meaningful results.
       This system call is available only if the kernel was configured with CONFIG_CHECKPOINT_RESTORE.  The main use of the system call  is  for
       the  checkpoint/restore  in  user  space  (CRIU) feature.  The alternative to this system call would have been to expose suitable process
       information via the proc(5) filesystem; this was deemed to be unsuitable for security reasons.

I did a couple of quick experiments with this and didn't seem to come up with a meaningful result, although perhaps I'm doing it wrong.

func kcmp(pid1, pid2, typ, idx1, idx2 int) (int, error) {
	r0, r1, errno := unix.Syscall6(
		unix.SYS_KCMP,
		uintptr(pid1),
		uintptr(pid2),
		uintptr(typ),
		uintptr(idx1),
		uintptr(idx2),
		0,
	)
	log.Println("kcmp", r0, r1, errno)

	if errno != 0 {
		return 0, os.NewSyscallError("kcmp", errno)
	}

	return int(r0), nil
}
			pid := os.Getpid()
			const kcmpFile = 0
			res, err := kcmp(pid, pid, kcmpFile, netNS, origNetNS)
			if err != nil {
				errC <- err
				return
			}
			log.Println("KCMP:", res)
$ go run main.go
2019/06/04 13:26:40 CALLER NETNS FD: 3
2019/06/04 13:26:40 SYSCALL NETNS FD: 5
2019/06/04 13:26:40 kcmp 2 0 errno 0
2019/06/04 13:26:40 KCMP: 2
2019/06/04 13:26:40 &os.SyscallError{Syscall:"setns", Err:0x1}
2019/06/04 13:26:40 failed to open wgctrl: setns: operation not permitted
exit status 1

Perhaps this merits more investigation, but due to the caveats listed on the manpage and potential complexity, I'm still leaning toward option 2.

wgtypes: Add ParseKey(string) function

Right now its easy to get from a key to a string, but its non-trivial to get from a string to a key. Given that this is a common transform if coming from something like JSON, or protobuf, it would be much more convenient if there was a builtin to get a key out of a string.

problems with ip-forwarding

Hi there,

i seem to have a strange behavior which I narrowed down to this library even if it makes no sense in the first place.

I wrote an application where clients can add themselves to the wireguard vpn via gprc calls.I want to have ipforwarding within the private network using the "wireguard -server" where the application is running as a "router". It's a machine running Arch linux, IP-forwarding is activated via sysctl and iptables, routes for the network (lets say 172.15.0.0/16) get set when firing up the device with wg-quick up wg0.

When server is up the clients can connect the server via gprc, give their public key, get their associated IP and the public key of server and are added to the server wireguard configuration using this library (adding a new peer like shown in the examples). So far everything works fine, i get a connection, I can ping or ssh from server to client and backwards, just like a dream. BUT: i can not ping from Client A to Client B. I use the same configuration for allowedIPs as I do when configuring manually via wg0.conf. Configuring the wireguard device on server 100% via wg0.conf, IP-forwarding works 100% (I tested by using wg showconf wg, stored configuration into wg0.conf and started again without using this library.) Is there any flag I have to set when adding a peer with this library i may have overlooked? Any Ideas what might be wrong?

Just to clearify: i am using wireguard as a kernel module

Deleting 400 keys takes 10 seconds

Here is the code I use to delete keys:

	peers := []wgtypes.PeerConfig{}
	peers = append(peers, wgtypes.PeerConfig{
		PublicKey: p.PublicKey,
		Remove:    true,
	})
	newConfig := wgtypes.Config{
		ReplacePeers: false,
		Peers:        peers,
	}
	err := c.ConfigureDevice(wgI.Name(), newConfig)

I've been running some unit tests and I saw that deletion takes more time than expected. I can add 1000 keys in 1 second, however deleting 400 keys takes 10 seconds and deleting 1000 keys takes 30 seconds.

Is this behavior normal? Can the deletion time be reduced?

internal/wglinux: nil wg0 device returned on example cross-compiled to arm7

I use the example programm from this repository, together with boringtun. On my dekstop linux pc and on windows this program works without problems. On an arm7 device getting all created wireguard devices per c.Devices() works without problems:

interface: wg0 (userspace)
  public key: L+V9o0fNYkMVKNqsX7spBzD/9oSvxM/C7ZCZX1jLO3Q=
  private key: (hidden)
  listening port: 58097

but calling it with a named device per c.Device("wg0") i get only

interface:  (unknown)
  public key: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=
  private key: (hidden)
  listening port: 0

sadly the same with configuration. I can configure my device on my desktop pc with Arch Linux (using Kernel and boringtun) and on Windows (using wireguard-go), but it doesn't work on my Arm7.

Any ideas?

Expose the Client interface

I'm working on an app that uses this library, and for writing my tests it would be very nice to generate a mock for the Client. However, what's exposed/exported from this library is only a concrete wrapper type which implements that interface, but not the interface itself.

Obviously I can copy-paste that interface definition, but being able to directly use the upstream interface avoids some risks down the road.

Unable to download via go get (Windows)

Running "go get -v golang.zx2c4.com/wireguard/wgctrl" gives the following output:

get "golang.zx2c4.com/wireguard/wgctrl": found meta tag get.metaImport{Prefix:"golang.zx2c4.com/wireguard/wgctrl", VCS:"git", RepoRoot:"https://github.com/WireGuard/wgctrl-go"} at //golang.zx2c4.com/wireguard/wgctrl?go-get=1
golang.zx2c4.com/wireguard/wgctrl (download)
get "golang.org/x/crypto/curve25519": found meta tag get.metaImport{Prefix:"golang.org/x/crypto", VCS:"git", RepoRoot:"https://go.googlesource.com/crypto"} at //golang.org/x/crypto/curve25519?go-get=1
get "golang.org/x/crypto/curve25519": verifying non-authoritative meta tag
golang.org/x/crypto (download)
get "golang.org/x/sys/windows": found meta tag get.metaImport{Prefix:"golang.org/x/sys", VCS:"git", RepoRoot:"https://go.googlesource.com/sys"} at //golang.org/x/sys/windows?go-get=1
get "golang.org/x/sys/windows": verifying non-authoritative meta tag
golang.org/x/sys (download)
get "golang.zx2c4.com/wireguard/ipc/winpipe": found meta tag get.metaImport{Prefix:"golang.zx2c4.com/wireguard", VCS:"git", RepoRoot:"https://git.zx2c4.com/wireguard-go"} at //golang.zx2c4.com/wireguard/ipc/winpipe?go-get=1
get "golang.zx2c4.com/wireguard/ipc/winpipe": verifying non-authoritative meta tag
golang.zx2c4.com/wireguard (download)
package golang.zx2c4.com/wireguard/ipc/winpipe: C:\Users\nicka\go\src\golang.zx2c4.com\wireguard exists but C:\Users\nicka\go\src\golang.zx2c4.com\wireguard.git does not - stale checkout?

Running from a linux machine (or WSL), the go get completes ok, so this issue seems to be windows specific

wgtypes: add Error type

At the moment I'm doing some kind of nasty fmt.Errorf in internal/wguser, and internal/wgnl is propagating raw unix.Errno errors I believe. We should wrap these in a nicer error type and consider implementing our own version of IsNotExist and similar that provides more detail than the stdlib one we are using now.

Add config support for wg-quick types

I'd love if wireguardctrl supported wg-quick configuration options in wgtypes.Config.

I'm mostly interested in:

  • Address field
  • MTU
  • Table
  • PreUp, PostUp, PreDown, PostDown

I can open rudimentary PR for this

"invalid argument" on Linux 5.2.1

Ever since I upgraded to Linux 5.1.2 (Arch Linux 5.1.2-arch1-1-ARCH), my tool that uses this library fails to set up Wireguard with a invalid argument error returned by the ConfigureDevice function. By my testing around, the peers configuration is what makes this error show up (if I remove all my code about peers, no issue appears, but of course, no peers are added to the Wireguard setup).

I checked by using the same version of my tool on another box running 5.0.5 and the issue does not appear. And as far as I can tell, my previous kernel version (5.1.4) did not have this issue either.

Using wg-quick instead of this library works properly on my current kernel.

I'm a bit at a loss as to how to debug this on my end and provide you with more information.

wgctrl: expand documentation and add examples

This projects looks like it will have a good future in the FOSS community, however for people to jump in, extended documentation would be good, preferably in-the-face (starting with README.md) and noob-friendly. There already is a good code sample here, however, people new to wireguardctl have to read through the project to find this sample code.

I think it would be useful to have something like this.

github.com/WireGuard/wgctrl-go expects import "golang.zx2c4.com/wireguard/wgctrl"

github.com/WireGuard/wgctrl-go expects import "golang.zx2c4.com/wireguard/wgctrl"

Seem to continue to get this error while trying to "go build" on another project. I made sure that library is installed, not sure what the issue is or if this is a bug or not.

$GOPATH is defined and working because other libraries are being found.

Any help would be great.

Thanks

wgctrl: add a high-level configuration interface

The current interface only implements the raw configuration parameters expected by WireGuard devices, but it could be nice to implement some kind of higher level interface to ease configuration for end users.

Perhaps a transactional interface would be nice (named and exact operations TBD):

m, err := wgctrl.NewManager()

err := m.Apply("wg0", func(tx *wgctrl.Transaction) error {
    tx.SetPrivateKey(wgtypes.GeneratePrivateKey()),
    tx.ClearPeers()
    tx.AddPeer(peer)
    
    return tx.Commit()
})

wgtypes: comments on Key

Key is a bit weird now:

type Key [keyLen]byte

You expose its representation only halfway: you say it's a byte array (is that important?), but don't say its length.

If it's going to be opaque-ish, just go all the way and make it a struct with only hidden fields.

Also, the package isn't sure whether it's a pointer type or value type:

func ClearKey() *Key
func GenerateKey() (Key, error)

At least in PeerConfig.PublicKey Key vs PeerConfig.PresharedKey *Key the difference is whether it's required or not. But I would fix still make those consistent, and have the concept of a zero Key value, rather than having to use a pointer.

Or always use a pointer. Just be consistent?

Missing files in Windows imports

I'm trying to compile code on Windows that works on Linux and I'm missing files after importing.

I tried cross-compiling from linux without luck. Now I've copied the code to a Windows box.

Using: go version go1.15.7 windows/amd64

vscode shows no missing dependencies. But when you execute, you get:

C:\Users\peter\go\src\golang.zx2c4.com\wireguard\wgctrl\internal\wguser\conn_windows.go:14:2: cannot find package "golang.zx2c4.com/wireguard/ipc/winpipe" in any of:
c:\go\src\golang.zx2c4.com\wireguard\ipc\winpipe (from $GOROOT)
C:\Users\peter\go\src\golang.zx2c4.com\wireguard\ipc\winpipe (from $GOPATH)
exit status 1
Process exiting with code: 1

If I try to reimport wgctrl, I get the following:
go get golang.zx2c4.com/wireguard/wgctrl
package golang.zx2c4.com/wireguard/ipc/winpipe: C:\Users\peter\go\src\golang.zx2c4.com\wireguard exists but C:\Users\peter\go\src\golang.zx2c4.com\wireguard.git does not - stale checkout?

Any ideas?

AllowedIPs not applied properly

Hi, thanks for this package! I've been playing around with it, and it seems like AllowedIPs as part of wgtypes.PeerConfig when passed to wgctrl.ConfigureDevice() isn't applied properly:

# PeerConfig A 
backend_1   | 2020/05/21 17:01:37 {ihFgmvJFsG8gLpyWHAp/y9W0mtnWqXtZnEdVXptnQzY= false false qs91slZ5udbFNOdp6WZnxlw89ZtwZLiCjZZ2qkn7Peo= <nil> <nil> false [{10.100.0.80 ffffff00}]}
# PeerConfig B
backend_1   | 2020/05/21 17:01:37 {NEfzWNvt/KleuQPYm3S1kKjs2tbiuvTYrcNYpVPrk38= false false bwzBUg3nDYr2TzAaBYWUYAnLvUGw5+/XDqx1fhLybIs= <nil> <nil> false [{10.100.0.116 ffffff00}]}
# Peers []PeerConfig
backend_1   | 2020/05/21 17:01:37 [{ihFgmvJFsG8gLpyWHAp/y9W0mtnWqXtZnEdVXptnQzY= false false qs91slZ5udbFNOdp6WZnxlw89ZtwZLiCjZZ2qkn7Peo= <nil> <nil> false [{10.100.0.80 ffffff00}]} {NEfzWNvt/KleuQPYm3S1kKjs2tbiuvTYrcNYpVPrk38= false false bwzBUg3nDYr2TzAaBYWUYAnLvUGw5+/XDqx1fhLybIs= <nil> <nil> false [{10.100.0.116 ffffff00}]}]
# Output of wgctrl.Devices()
backend_1   | 2020/05/21 17:01:37 [0xc0002a8380]
backend_1   | 2020/05/21 17:01:37 wg0
backend_1   | 2020/05/21 17:01:37 Linux kernel
backend_1   | 2020/05/21 17:01:37 IPOxbEgVcT0UDdT57XgCqap4KaxcbnJN5ov+zE8vWXM=
backend_1   | 2020/05/21 17:01:37 G4KXIoG4zm/I119wu1F6C7XLOmSEWAk2hNZ6hzmSp38=
backend_1   | 2020/05/21 17:01:37 51820
backend_1   | 2020/05/21 17:01:37 0
backend_1   | 2020/05/21 17:01:37 [{NEfzWNvt/KleuQPYm3S1kKjs2tbiuvTYrcNYpVPrk38= bwzBUg3nDYr2TzAaBYWUYAnLvUGw5+/XDqx1fhLybIs= <nil> 0s 0001-01-01 00:00:00 +0000 UTC 0 0 [{10.100.0.0 ffffff00}] 1} {ihFgmvJFsG8gLpyWHAp/y9W0mtnWqXtZnEdVXptnQzY= qs91slZ5udbFNOdp6WZnxlw89ZtwZLiCjZZ2qkn7Peo= <nil> 0s 0001-01-01 00:00:00 +0000 UTC 0 0 [] 1}]

AllowedIPs for Peer A end up as [], and Peer B gets [{10.100.0.0 ffffff00}]. I'd expect [{10.100.0.80 ffffff00}] and [{10.100.0.116 ffffff00}] respectively. Inspecting with wg:

interface: wg0
  public key: G4KXIoG4zm/I119wu1F6C7XLOmSEWAk2hNZ6hzmSp38=
  private key: (hidden)
  listening port: 51820

peer: NEfzWNvt/KleuQPYm3S1kKjs2tbiuvTYrcNYpVPrk38=
  preshared key: (hidden)
  allowed ips: 10.100.0.0/24

peer: ihFgmvJFsG8gLpyWHAp/y9W0mtnWqXtZnEdVXptnQzY=
  preshared key: (hidden)
  allowed ips: (none)

Not sure if I'm holding it wrong of if there's a bug somewhere. Any help would be appreciated. Thanks :)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.