wireguard.lists.zx2c4.com archive mirror
 help / color / mirror / Atom feed
* wireguardnl: Go package for interacting with WireGuard via generic netlink
@ 2018-07-21 19:19 Matt Layher
  2018-07-23 11:59 ` Jason A. Donenfeld
  0 siblings, 1 reply; 8+ messages in thread
From: Matt Layher @ 2018-07-21 19:19 UTC (permalink / raw)
  To: wireguard

Hi all!

I've heard quite a few good things about WireGuard and decided to try it 
out at home today.  On top of that, I've done a lot of work with netlink 
and generic netlink in Go, and decided to implement a Go package that 
can use wireguard's generic netlink interface in the same way as the 
"wg" tool.  To avoid confusion with "wireguard" or "wireguard-go", I've 
chosen "wireguardnl" as the name:

https://github.com/mdlayher/wireguardnl

This was just a fun experiment for me (it works, but no tests yet), but 
perhaps it'll be useful for someone who wants to inspect the kernel 
module from a Go program (no support for changing settings as of now, 
but that'd be fun!).

While I'm here, I did have one inquiry about "WG_CMD_GET_DEVICE": after 
working with a handful of generic netlink families, I was slightly 
surprised to see that a request paired with "NLM_F_DUMP" doesn't return 
a list of all WireGuard devices from the kernel.

Per the documentation, sending an interface index or name attribute 
works just fine to retrieve a single device, but perhaps it'd be nice to 
be able to just dump a list of all WireGuard devices when "NLM_F_DUMP" 
and no attributes are specified.  For the time being, I can easily work 
around this with my "Devices" method by attempting to query the kernel 
for WireGuard device information about each of my network interfaces, 
and then filter out the ones that return "ENOTSUP".

Thanks for WireGuard, it seems extremely promising so far!

- Matt Layher

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

* Re: wireguardnl: Go package for interacting with WireGuard via generic netlink
  2018-07-21 19:19 wireguardnl: Go package for interacting with WireGuard via generic netlink Matt Layher
@ 2018-07-23 11:59 ` Jason A. Donenfeld
  2018-07-23 13:43   ` Matt Layher
  0 siblings, 1 reply; 8+ messages in thread
From: Jason A. Donenfeld @ 2018-07-23 11:59 UTC (permalink / raw)
  To: mdlayher; +Cc: WireGuard mailing list

Hey Matt,

That's terrific! Thanks for making that. I look forward to seeing
utilities develop around your library.

Something to consider with this is the chunking. Since a device has
many peers and a peer has many allowedips, it's possible that these
might span multiple messages, larger than the maximum netlink packet
size. For that reason, wg(8) will properly split things into several
calls. Here's the set call:

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

It accounts for toobig_allowedips and toobig_peers with some goto
jumps that are sure to make your eyes bleed (read: you can do better
than that :-). Similar in the get call, we coalesce peers that span
multiple messages:

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

The other thing that might be sort of neat to try to implement is
falling back to the userspace API:

https://www.wireguard.com/xplatform/

This is a simple unix socket-based approach that mimics the same
semantics as the netlink API, but is portable to different platforms.
This is what wireguard-go and wireguard-rs and friends use for
configuration. wg(8) implements both and provides an identical
frontend for the two. However, I imagine you starting with netlink
will be much more useful and is a good decision, since serious
wireguard users are expected to continue using the serious kernel
implementation.

> While I'm here, I did have one inquiry about "WG_CMD_GET_DEVICE": after
> working with a handful of generic netlink families, I was slightly
> surprised to see that a request paired with "NLM_F_DUMP" doesn't return
> a list of all WireGuard devices from the kernel.

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

If you're on IRC, come on into #wireguard on Freenode and poke me, and
we can chat about it further; I'm zx2c4.

Talk soon,
Jason

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

* Re: wireguardnl: Go package for interacting with WireGuard via generic netlink
  2018-07-23 11:59 ` Jason A. Donenfeld
@ 2018-07-23 13:43   ` Matt Layher
  2018-07-23 15:12     ` Jason A. Donenfeld
  0 siblings, 1 reply; 8+ messages in thread
From: Matt Layher @ 2018-07-23 13:43 UTC (permalink / raw)
  To: Jason A. Donenfeld; +Cc: WireGuard mailing list

Hey Jason,

Thanks very much for WireGuard and for the information.

 > Something to consider with this is the chunking.

Certainly! This was a first pass but these changes should be reasonable 
to port to Go as well.  I suppose I'll have to introduce some more 
complicated test devices to this logic.  I've filed a couple issues to 
track this and hope that I can at least implement the chunking get logic 
this week.

 > The other thing that might be sort of neat to try to implement is
falling back to the userspace API:

This is super interesting and I actually did not discover it until after 
I pushed the first few commits to my package.  I could see it making 
sense to refactor my current package layout to something like three 
packages:

- wireguardnl: netlink-based communication
- wireguardcfg: text-based userspace configuration protocol communication
- wireguard: wrapper for both that detects the module in use and 
seamlessly presents a unified interface

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

Ahhh, that makes more sense to me.  Perhaps I glossed over the 
uapi/wireguard.h documentation.  For the time being, I'm doing a call to 
Go's "net.Interfaces" which is a bit easier (though less efficient) than 
doing rtnetlink calls directly.  Perhaps this is something I can iterate 
on in the future as well.

 > If you're on IRC, come on into #wireguard on Freenode and poke me, and
we can chat about it further; I'm zx2c4.

Certainly!  I don't have any further inquiries at this time, but I'll 
join up!

Thank you again for WireGuard, and thank you very much for your time, 
feedback, and answers to my questions.

- Matt Layher


On 07/23/2018 07:59 AM, Jason A. Donenfeld wrote:
> Hey Matt,
>
> That's terrific! Thanks for making that. I look forward to seeing
> utilities develop around your library.
>
> Something to consider with this is the chunking. Since a device has
> many peers and a peer has many allowedips, it's possible that these
> might span multiple messages, larger than the maximum netlink packet
> size. For that reason, wg(8) will properly split things into several
> calls. Here's the set call:
>
> https://git.zx2c4.com/WireGuard/tree/src/tools/ipc.c#n558
>
> It accounts for toobig_allowedips and toobig_peers with some goto
> jumps that are sure to make your eyes bleed (read: you can do better
> than that :-). Similar in the get call, we coalesce peers that span
> multiple messages:
>
> https://git.zx2c4.com/WireGuard/tree/src/tools/ipc.c#n899
> https://git.zx2c4.com/WireGuard/tree/src/tools/ipc.c#n877
>
> The other thing that might be sort of neat to try to implement is
> falling back to the userspace API:
>
> https://www.wireguard.com/xplatform/
>
> This is a simple unix socket-based approach that mimics the same
> semantics as the netlink API, but is portable to different platforms.
> This is what wireguard-go and wireguard-rs and friends use for
> configuration. wg(8) implements both and provides an identical
> frontend for the two. However, I imagine you starting with netlink
> will be much more useful and is a good decision, since serious
> wireguard users are expected to continue using the serious kernel
> implementation.
>
>> While I'm here, I did have one inquiry about "WG_CMD_GET_DEVICE": after
>> working with a handful of generic netlink families, I was slightly
>> surprised to see that a request paired with "NLM_F_DUMP" doesn't return
>> a list of all WireGuard devices from the kernel.
> 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
>
> If you're on IRC, come on into #wireguard on Freenode and poke me, and
> we can chat about it further; I'm zx2c4.
>
> Talk soon,
> Jason

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

* Re: wireguardnl: Go package for interacting with WireGuard via generic netlink
  2018-07-23 13:43   ` Matt Layher
@ 2018-07-23 15:12     ` Jason A. Donenfeld
  2018-07-23 15:29       ` Matt Layher
  0 siblings, 1 reply; 8+ messages in thread
From: Jason A. Donenfeld @ 2018-07-23 15:12 UTC (permalink / raw)
  To: mdlayher; +Cc: WireGuard mailing list

Hi Matt,

> This is super interesting and I actually did not discover it until after
> I pushed the first few commits to my package.  I could see it making
> sense to refactor my current package layout to something like three
> packages:
>
> - wireguardnl: netlink-based communication
> - wireguardcfg: text-based userspace configuration protocol communication
> - wireguard: wrapper for both that detects the module in use and
> seamlessly presents a unified interface

No, that's really not a good approach at all. First of all, do not
take the raw name "wireguard". That's going to cause a lot of
confusion. It's really not appropriate.

But more importantly, you shouldn't expose either the netlink or the
xplatform API distinction to users ever. They should be given one
interface, not three, and that one interface should be able to select
the right thing in 100% of cases.

Jason

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

* Re: wireguardnl: Go package for interacting with WireGuard via generic netlink
  2018-07-23 15:12     ` Jason A. Donenfeld
@ 2018-07-23 15:29       ` Matt Layher
  2018-07-23 15:59         ` Matt Layher
  2018-07-23 16:22         ` Jason A. Donenfeld
  0 siblings, 2 replies; 8+ messages in thread
From: Matt Layher @ 2018-07-23 15:29 UTC (permalink / raw)
  To: Jason A. Donenfeld; +Cc: WireGuard mailing list

Understood and renamed to "wireguardctrl" to avoid confusion.

 > But more importantly, you shouldn't expose either the netlink or the 
xplatform API distinction to users ever. They should be given one 
interface, not three, and that one interface should be able to select 
the right thing in 100% of cases.

I can't say I agree with this under all circumstances.

While I will encourage the use of the unified interface, I read that 
there could be future work to allow the netlink interface to support 
something like multicast group notifications.  Would you plan on 
implementing the same functionality for the userspace interface?

I think there are potential use cases for selecting one or the other, 
but if this ends up being untrue, I can always push these packages 
behind a Go "internal/" directory at a later time to prevent outside 
imports.

- Matt


On 07/23/2018 11:12 AM, Jason A. Donenfeld wrote:
> Hi Matt,
>
>> This is super interesting and I actually did not discover it until after
>> I pushed the first few commits to my package.  I could see it making
>> sense to refactor my current package layout to something like three
>> packages:
>>
>> - wireguardnl: netlink-based communication
>> - wireguardcfg: text-based userspace configuration protocol communication
>> - wireguard: wrapper for both that detects the module in use and
>> seamlessly presents a unified interface
> No, that's really not a good approach at all. First of all, do not
> take the raw name "wireguard". That's going to cause a lot of
> confusion. It's really not appropriate.
>
> But more importantly, you shouldn't expose either the netlink or the
> xplatform API distinction to users ever. They should be given one
> interface, not three, and that one interface should be able to select
> the right thing in 100% of cases.
>
> Jason

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

* Re: wireguardnl: Go package for interacting with WireGuard via generic netlink
  2018-07-23 15:29       ` Matt Layher
@ 2018-07-23 15:59         ` Matt Layher
  2018-07-23 16:22           ` Jason A. Donenfeld
  2018-07-23 16:22         ` Jason A. Donenfeld
  1 sibling, 1 reply; 8+ messages in thread
From: Matt Layher @ 2018-07-23 15:59 UTC (permalink / raw)
  To: Jason A. Donenfeld; +Cc: WireGuard mailing list

An update for those on the list, I've implemented Jason's requested name 
change and the API is now set up to allow seamless kernel and userspace 
implementations via https://godoc.org/github.com/mdlayher/wireguardctrl.

I will explicitly encourage callers to use this interface rather than 
the "wireguardnl" package, unless we do end up with useful 
netlink-specific functionality like the situation I described previously.

I'll keep working on this for now and report back when I have a working 
userspace implementation.  Should be quite straightforward compared to 
dealing with netlink! :)

- Matt


On 07/23/2018 11:29 AM, Matt Layher wrote:
> Understood and renamed to "wireguardctrl" to avoid confusion.
>
> > But more importantly, you shouldn't expose either the netlink or the 
> xplatform API distinction to users ever. They should be given one 
> interface, not three, and that one interface should be able to select 
> the right thing in 100% of cases.
>
> I can't say I agree with this under all circumstances.
>
> While I will encourage the use of the unified interface, I read that 
> there could be future work to allow the netlink interface to support 
> something like multicast group notifications.  Would you plan on 
> implementing the same functionality for the userspace interface?
>
> I think there are potential use cases for selecting one or the other, 
> but if this ends up being untrue, I can always push these packages 
> behind a Go "internal/" directory at a later time to prevent outside 
> imports.
>
> - Matt
>
>
> On 07/23/2018 11:12 AM, Jason A. Donenfeld wrote:
>> Hi Matt,
>>
>>> This is super interesting and I actually did not discover it until 
>>> after
>>> I pushed the first few commits to my package.  I could see it making
>>> sense to refactor my current package layout to something like three
>>> packages:
>>>
>>> - wireguardnl: netlink-based communication
>>> - wireguardcfg: text-based userspace configuration protocol 
>>> communication
>>> - wireguard: wrapper for both that detects the module in use and
>>> seamlessly presents a unified interface
>> No, that's really not a good approach at all. First of all, do not
>> take the raw name "wireguard". That's going to cause a lot of
>> confusion. It's really not appropriate.
>>
>> But more importantly, you shouldn't expose either the netlink or the
>> xplatform API distinction to users ever. They should be given one
>> interface, not three, and that one interface should be able to select
>> the right thing in 100% of cases.
>>
>> Jason
>

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

* Re: wireguardnl: Go package for interacting with WireGuard via generic netlink
  2018-07-23 15:29       ` Matt Layher
  2018-07-23 15:59         ` Matt Layher
@ 2018-07-23 16:22         ` Jason A. Donenfeld
  1 sibling, 0 replies; 8+ messages in thread
From: Jason A. Donenfeld @ 2018-07-23 16:22 UTC (permalink / raw)
  To: mdlayher; +Cc: WireGuard mailing list

Hey Matt,

On Mon, Jul 23, 2018 at 5:29 PM Matt Layher <mdlayher@gmail.com> wrote:
> While I will encourage the use of the unified interface, I read that
> there could be future work to allow the netlink interface to support
> something like multicast group notifications.  Would you plan on
> implementing the same functionality for the userspace interface?

Yes, absolutely. We're aiming for full parity with the API.

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

* Re: wireguardnl: Go package for interacting with WireGuard via generic netlink
  2018-07-23 15:59         ` Matt Layher
@ 2018-07-23 16:22           ` Jason A. Donenfeld
  0 siblings, 0 replies; 8+ messages in thread
From: Jason A. Donenfeld @ 2018-07-23 16:22 UTC (permalink / raw)
  To: mdlayher; +Cc: WireGuard mailing list

On Mon, Jul 23, 2018 at 5:59 PM Matt Layher <mdlayher@gmail.com> wrote:
>
> An update for those on the list, I've implemented Jason's requested name
> change and the API is now set up to allow seamless kernel and userspace
> implementations via https://godoc.org/github.com/mdlayher/wireguardctrl.
>
> I will explicitly encourage callers to use this interface rather than
> the "wireguardnl" package, unless we do end up with useful
> netlink-specific functionality like the situation I described previously.
>
> I'll keep working on this for now and report back when I have a working
> userspace implementation.  Should be quite straightforward compared to
> dealing with netlink! :)

Wonderful! Thanks Matt!

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

end of thread, other threads:[~2018-07-23 16:14 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-07-21 19:19 wireguardnl: Go package for interacting with WireGuard via generic netlink Matt Layher
2018-07-23 11:59 ` Jason A. Donenfeld
2018-07-23 13:43   ` Matt Layher
2018-07-23 15:12     ` Jason A. Donenfeld
2018-07-23 15:29       ` Matt Layher
2018-07-23 15:59         ` Matt Layher
2018-07-23 16:22           ` Jason A. Donenfeld
2018-07-23 16:22         ` 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).