This patch depends on da5095d052860baa7fe2932fb1209628dd3e3813 from udp_tunnel module, and allows to bind the transport socket to a specific interface.
With this patch, it is possible to use wireguard with VRFs: The transport uses a separate "WAN" VRF, cleanly isolating Local/VPN and WAN Routing. The userspace API is designed to transmit the device index of the device to listen on. Listening on a device does only work if the socketdev_index is set/changed before the socket is brought up. Signed-off-by: Marvin Gaube <d...@marvingaube.de> --- drivers/net/wireguard/device.h | 1 + drivers/net/wireguard/netlink.c | 8 +++++++- drivers/net/wireguard/socket.c | 10 ++++++++++ include/uapi/linux/wireguard.h | 3 +++ 4 files changed, 21 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireguard/device.h b/drivers/net/wireguard/device.h index 854bc3d97150..a08f0893f687 100644 --- a/drivers/net/wireguard/device.h +++ b/drivers/net/wireguard/device.h @@ -56,6 +56,7 @@ struct wg_device { struct list_head device_list, peer_list; unsigned int num_peers, device_update_gen; u32 fwmark; + u32 socketdev_index; u16 incoming_port; }; diff --git a/drivers/net/wireguard/netlink.c b/drivers/net/wireguard/netlink.c index d0f3b6d7f408..c594a7063038 100644 --- a/drivers/net/wireguard/netlink.c +++ b/drivers/net/wireguard/netlink.c @@ -27,7 +27,8 @@ static const struct nla_policy device_policy[WGDEVICE_A_MAX + 1] = { [WGDEVICE_A_FLAGS] = { .type = NLA_U32 }, [WGDEVICE_A_LISTEN_PORT] = { .type = NLA_U16 }, [WGDEVICE_A_FWMARK] = { .type = NLA_U32 }, - [WGDEVICE_A_PEERS] = { .type = NLA_NESTED } + [WGDEVICE_A_PEERS] = { .type = NLA_NESTED }, + [WGDEVICE_A_SOCKETDEV_INDEX] = { .type = NLA_U32 } }; static const struct nla_policy peer_policy[WGPEER_A_MAX + 1] = { @@ -232,6 +233,7 @@ static int wg_get_device_dump(struct sk_buff *skb, struct netlink_callback *cb) if (nla_put_u16(skb, WGDEVICE_A_LISTEN_PORT, wg->incoming_port) || nla_put_u32(skb, WGDEVICE_A_FWMARK, wg->fwmark) || + nla_put_u32(skb, WGDEVICE_A_SOCKETDEV_INDEX, wg->socketdev_index) || nla_put_u32(skb, WGDEVICE_A_IFINDEX, wg->dev->ifindex) || nla_put_string(skb, WGDEVICE_A_IFNAME, wg->dev->name)) goto out; @@ -538,6 +540,10 @@ static int wg_set_device(struct sk_buff *skb, struct genl_info *info) goto out; } + if (info->attrs[WGDEVICE_A_SOCKETDEV_INDEX]) { + wg->socketdev_index = nla_get_u32(info->attrs[WGDEVICE_A_SOCKETDEV_INDEX]); + } + if (flags & WGDEVICE_F_REPLACE_PEERS) wg_peer_remove_all(wg); diff --git a/drivers/net/wireguard/socket.c b/drivers/net/wireguard/socket.c index d9ad850daa79..885d8a890079 100644 --- a/drivers/net/wireguard/socket.c +++ b/drivers/net/wireguard/socket.c @@ -370,8 +370,18 @@ int wg_socket_init(struct wg_device *wg, u16 port) .use_udp6_rx_checksums = true, .ipv6_v6only = true }; + if (wg->socketdev_index > 0) { + port6.bind_ifindex = wg->socketdev_index; + } else { + port6.bind_ifindex = 0; + } #endif + if (wg->socketdev_index > 0) { + port4.bind_ifindex = wg->socketdev_index; + } else { + port4.bind_ifindex = 0; + } rcu_read_lock(); net = rcu_dereference(wg->creating_net); net = net ? maybe_get_net(net) : NULL; diff --git a/include/uapi/linux/wireguard.h b/include/uapi/linux/wireguard.h index ae88be14c947..52b1bd422f50 100644 --- a/include/uapi/linux/wireguard.h +++ b/include/uapi/linux/wireguard.h @@ -29,6 +29,7 @@ * WGDEVICE_A_PUBLIC_KEY: NLA_EXACT_LEN, len WG_KEY_LEN * WGDEVICE_A_LISTEN_PORT: NLA_U16 * WGDEVICE_A_FWMARK: NLA_U32 + * WGDEVICE_A_SOCKETDEV_INDEX: NLA_U32 * WGDEVICE_A_PEERS: NLA_NESTED * 0: NLA_NESTED * WGPEER_A_PUBLIC_KEY: NLA_EXACT_LEN, len WG_KEY_LEN @@ -83,6 +84,7 @@ * WGDEVICE_A_PRIVATE_KEY: len WG_KEY_LEN, all zeros to remove * WGDEVICE_A_LISTEN_PORT: NLA_U16, 0 to choose randomly * WGDEVICE_A_FWMARK: NLA_U32, 0 to disable + * WGDEVICE_A_SOCKETDEV_INDEX: NLA_U32, 0 to disable * WGDEVICE_A_PEERS: NLA_NESTED * 0: NLA_NESTED * WGPEER_A_PUBLIC_KEY: len WG_KEY_LEN @@ -157,6 +159,7 @@ enum wgdevice_attribute { WGDEVICE_A_LISTEN_PORT, WGDEVICE_A_FWMARK, WGDEVICE_A_PEERS, + WGDEVICE_A_SOCKETDEV_INDEX, __WGDEVICE_A_LAST }; #define WGDEVICE_A_MAX (__WGDEVICE_A_LAST - 1) -- 2.25.1