WireGuard / wgctrl-go

Package wgctrl enables control of WireGuard interfaces on multiple platforms.
https://godoc.org/golang.zx2c4.com/wireguard/wgctrl
MIT License
730 stars 85 forks source link

Force to use specific implementation #28

Closed nmiculinic closed 5 years ago

nmiculinic commented 5 years ago

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

mdlayher commented 5 years ago

What's the use case for doing so? Both implementations should have feature parity.

There's nothing stopping you from filtering on Device.Type in your own code, but I wouldn't recommend it. I'd really prefer not to export any more code though.

nmiculinic commented 5 years ago

For my specific use case, I need the kernel module implementation.

And what happens is this:

mdlayher commented 5 years ago

For my specific use case, I need the kernel module implementation.

Again, please share what your actual use case is, and why only operating on the kernel module implementation is appropriate.

What is lacking in the userspace implementation? Why would you not want full parity for users who run different WireGuard implementations, if the interface for configuring each of these implementations can be identical and transparent in your code?

The wg tool operates on this same principle. It makes no differentiation between kernel and userspace devices.

matt@nerr-2:~$ sudo wg show
interface: wg0
  public key: TM7UyJLMf7nPvWC4fb5xoEQedgQ9RwyyEaWGk1Zrow4=
  private key: (hidden)
  listening port: 45490

peer: 2RTeXgsWP9siIqULJukjlfA3SRYA3R6YsVnJ5GUzu3o=
  endpoint: 192.168.1.99:51820
  allowed ips: 192.168.20.0/24

interface: wggo0
✔ ~/src/github.com/mdlayher/wireguardctrl/cmd/wgctrl [master|✔] 
07:00 $ sudo ./wgctrl 
interface: wg0
  public key: TM7UyJLMf7nPvWC4fb5xoEQedgQ9RwyyEaWGk1Zrow4=
  private key: (hidden)
  listening port: 45490

peer: 2RTeXgsWP9siIqULJukjlfA3SRYA3R6YsVnJ5GUzu3o=
  endpoint: 192.168.1.99:51820
  allowed ips: 192.168.20.0/24
  latest handshake: 0001-01-01 00:00:00 +0000 UTC
  transfer: 0 B received, 0 B sent

interface: wggo0
  public key: L+V9o0fNYkMVKNqsX7spBzD/9oSvxM/C7ZCZX1jLO3Q=
  private key: (hidden)
  listening port: 0

This sounds like "XY Problem" (http://xyproblem.info/) territory to me.

I try to apply config I get error, file not found I have to strace the binary to see which file isn't found

The documentation for ConfigureDevice (https://godoc.org/github.com/mdlayher/wireguardctrl#Client.ConfigureDevice) mentions:

If the device specified by name does not exist or is not a WireGuard device, an error is returned which can be checked using os.IsNotExist.

You can inspect the result of the call to determine this in your own code.

Then I find out /var/run/wireguard is missing since I'm not using software emulation

The package searches for all available implementations for the platform you're using, and will not report an error for this reason alone.

And I have no idea why kernel module hasn't worked. This automagic is fine, but I want to see proper log/error why the kernel module failed. Otherwise, I get magic error and yeah, now I'm strace ing the binary again, though Netlink is much less legible than human-readable errors.

This type of logging belongs in your application code, not in this library. I recommend enumerating all valid WireGuard devices with https://godoc.org/github.com/mdlayher/wireguardctrl#Client.Devices, and then configuring known good devices from that list. That is, unless you already know the correct name of the device ahead of time.

Edit: it could be worth exposing more information via an Error type (see: https://github.com/mdlayher/wireguardctrl/issues/13) but that hasn't been implemented yet. At the moment though, you'll only see "doesn't exist" in your own code if all of the registered implementations do not recognize a device: https://github.com/mdlayher/wireguardctrl/blob/master/client.go#L122.

nmiculinic commented 5 years ago

Thank you for taking the time to explain. I misunderstood who is creating the wireguard interface; naively I assume that is the responsibility of this library, not me doing ip link add dev wg1 type wireguard or something similar.

my end use case:

Have go process managing wireguard networking lifecycle. Like wg-quick, but in Go and getting configuration from the external system. Since it needs to be cross arch (( arm7 & amd64 in my case )) I'm trying to avoid having external dependencies (iproute2, mostly since this is going to run in a container and building complex arm containers require arm build machine and other complexities I'd rather avoid)

Right now I've managed to create basic initial implementation in the wg-operator. Now I'm seeing how to replace calles to iproute2 with netlink:

Most of my problems stem from unfamiliarity with Netlink, and using wg-quick mostly, not wg tool. I'll try using github.com/vishvananda/netlink you mentioned to replace ip our of the dependency tree. (( Though wished they had more examples in their source ))

mdlayher commented 5 years ago

Thanks for clarifying! I just wanted to make sure that I wasn't missing some feature or critical piece of information.

This package should still be useful for you once you've done the prerequisite link configuration via route netlink like you've mentioned above. Please feel free to reach out if you run into any trouble.

I also should have mentioned this sooner, but there are quite a few folks in the #networking channel in Gophers Slack that ought to be able to provide some guidance on these sorts of things as well. Please do join us if that interests you!

Thanks for your time and for the report.

afeiszli commented 2 years ago

Hi, I am also interested in this. I am running freebsd which is not a supported device type, and thinking if I can force a different device type, it might work for my needs (just need to parse the interface for peers).