* [RESEND PATCH v1 wireguard-tools] ipc: linux: Support incremental allowed ips updates @ 2025-05-17 19:29 Jordan Rife 2025-05-17 19:29 ` [RESEND PATCH v3 net-next] wireguard: allowedips: Add WGALLOWEDIP_F_REMOVE_ME flag Jordan Rife 2025-05-20 20:14 ` [RESEND PATCH v1 wireguard-tools] ipc: linux: Support incremental allowed ips updates Jason A. Donenfeld 0 siblings, 2 replies; 15+ messages in thread From: Jordan Rife @ 2025-05-17 19:29 UTC (permalink / raw) To: wireguard, Jason A. Donenfeld Cc: Jordan Rife, netdev, Jakub Kicinski, Daniel Borkmann Extend the interface of `wg set` to leverage the WGALLOWEDIP_F_REMOVE_ME flag, a direct way of removing a single allowed ip from a peer, allowing for incremental updates to a peer's configuration. By default, allowed-ips fully replaces a peer's allowed ips using WGPEER_REPLACE_ALLOWEDIPS under the hood. When '+' or '-' is prepended to any ip in the list, wg clears WGPEER_F_REPLACE_ALLOWEDIPS and sets the WGALLOWEDIP_F_REMOVE_ME flag on any ip prefixed with '-'. $ wg set wg0 peer <PUBKEY> allowed-ips +192.168.88.0/24,-192.168.0.1/32 This command means "add 192.168.88.0/24 to this peer's allowed ips if not present, and remove 192.168.0.1/32 if present". Use -isystem so that headers in uapi/ take precedence over system headers; otherwise, the build will fail on systems running kernels without the WGALLOWEDIP_F_REMOVE_ME flag. Note that this patch is meant to be merged alongside the kernel patch that introduces the flag. Signed-off-by: Jordan Rife <jordan@jrife.io> --- src/Makefile | 2 +- src/config.c | 27 +++++++++++++++++++++++++++ src/containers.h | 5 +++++ src/ipc-linux.h | 2 ++ src/man/wg.8 | 8 ++++++-- src/set.c | 2 +- src/uapi/linux/linux/wireguard.h | 9 +++++++++ 7 files changed, 51 insertions(+), 4 deletions(-) diff --git a/src/Makefile b/src/Makefile index 0533910..1c4b3f6 100644 --- a/src/Makefile +++ b/src/Makefile @@ -39,7 +39,7 @@ PLATFORM ?= $(shell uname -s | tr '[:upper:]' '[:lower:]') CFLAGS ?= -O3 ifneq ($(wildcard uapi/$(PLATFORM)/.),) -CFLAGS += -idirafter uapi/$(PLATFORM) +CFLAGS += -isystem uapi/$(PLATFORM) endif CFLAGS += -std=gnu99 -D_GNU_SOURCE CFLAGS += -Wall -Wextra diff --git a/src/config.c b/src/config.c index 81ccb47..b740f73 100644 --- a/src/config.c +++ b/src/config.c @@ -337,6 +337,29 @@ static bool validate_netmask(struct wgallowedip *allowedip) return true; } +#if defined(__linux__) +static inline void parse_ip_prefix(struct wgpeer *peer, uint32_t *flags, char **mask) +{ + /* If the IP is prefixed with either '+' or '-' consider + * this an incremental change. Disable WGPEER_REPLACE_ALLOWEDIPS. + */ + switch ((*mask)[0]) { + case '-': + *flags |= WGALLOWEDIP_REMOVE_ME; + /* fall through */ + case '+': + peer->flags &= ~WGPEER_REPLACE_ALLOWEDIPS; + (*mask)++; + } +} +#else +static inline void parse_ip_prefix(struct wgpeer *peer __attribute__ ((unused)), + uint32_t *flags __attribute__ ((unused)), + char **mask __attribute__ ((unused))) +{ +} +#endif + static inline bool parse_allowedips(struct wgpeer *peer, struct wgallowedip **last_allowedip, const char *value) { struct wgallowedip *allowedip = *last_allowedip, *new_allowedip; @@ -353,9 +376,12 @@ static inline bool parse_allowedips(struct wgpeer *peer, struct wgallowedip **la } sep = mutable; while ((mask = strsep(&sep, ","))) { + uint32_t flags = 0; unsigned long cidr; char *end, *ip; + parse_ip_prefix(peer, &flags, &mask); + saved_entry = strdup(mask); ip = strsep(&mask, "/"); @@ -387,6 +413,7 @@ static inline bool parse_allowedips(struct wgpeer *peer, struct wgallowedip **la else goto err; new_allowedip->cidr = cidr; + new_allowedip->flags = flags; if (!validate_netmask(new_allowedip)) fprintf(stderr, "Warning: AllowedIP has nonzero host part: %s/%s\n", ip, mask); diff --git a/src/containers.h b/src/containers.h index a82e8dd..8fd813a 100644 --- a/src/containers.h +++ b/src/containers.h @@ -28,6 +28,10 @@ struct timespec64 { int64_t tv_nsec; }; +enum { + WGALLOWEDIP_REMOVE_ME = 1U << 0, +}; + struct wgallowedip { uint16_t family; union { @@ -35,6 +39,7 @@ struct wgallowedip { struct in6_addr ip6; }; uint8_t cidr; + uint32_t flags; struct wgallowedip *next_allowedip; }; diff --git a/src/ipc-linux.h b/src/ipc-linux.h index d29c0c5..01247f1 100644 --- a/src/ipc-linux.h +++ b/src/ipc-linux.h @@ -228,6 +228,8 @@ again: } if (!mnl_attr_put_u8_check(nlh, SOCKET_BUFFER_SIZE, WGALLOWEDIP_A_CIDR_MASK, allowedip->cidr)) goto toobig_allowedips; + if (allowedip->flags && !mnl_attr_put_u32_check(nlh, SOCKET_BUFFER_SIZE, WGALLOWEDIP_A_FLAGS, allowedip->flags)) + goto toobig_allowedips; mnl_attr_nest_end(nlh, allowedip_nest); allowedip_nest = NULL; } diff --git a/src/man/wg.8 b/src/man/wg.8 index 7984539..1ec68df 100644 --- a/src/man/wg.8 +++ b/src/man/wg.8 @@ -55,7 +55,7 @@ transfer-rx, transfer-tx, persistent-keepalive. Shows the current configuration of \fI<interface>\fP in the format described by \fICONFIGURATION FILE FORMAT\fP below. .TP -\fBset\fP \fI<interface>\fP [\fIlisten-port\fP \fI<port>\fP] [\fIfwmark\fP \fI<fwmark>\fP] [\fIprivate-key\fP \fI<file-path>\fP] [\fIpeer\fP \fI<base64-public-key>\fP [\fIremove\fP] [\fIpreshared-key\fP \fI<file-path>\fP] [\fIendpoint\fP \fI<ip>:<port>\fP] [\fIpersistent-keepalive\fP \fI<interval seconds>\fP] [\fIallowed-ips\fP \fI<ip1>/<cidr1>\fP[,\fI<ip2>/<cidr2>\fP]...] ]... +\fBset\fP \fI<interface>\fP [\fIlisten-port\fP \fI<port>\fP] [\fIfwmark\fP \fI<fwmark>\fP] [\fIprivate-key\fP \fI<file-path>\fP] [\fIpeer\fP \fI<base64-public-key>\fP [\fIremove\fP] [\fIpreshared-key\fP \fI<file-path>\fP] [\fIendpoint\fP \fI<ip>:<port>\fP] [\fIpersistent-keepalive\fP \fI<interval seconds>\fP] [\fIallowed-ips\fP \fI[+|-]<ip1>/<cidr1>\fP[,\fI[+|-]<ip2>/<cidr2>\fP]...] ]... Sets configuration values for the specified \fI<interface>\fP. Multiple \fIpeer\fPs may be specified, and if the \fIremove\fP argument is given for a peer, that peer is removed, not configured. If \fIlisten-port\fP @@ -72,7 +72,11 @@ the device. The use of \fIpreshared-key\fP is optional, and may be omitted; it adds an additional layer of symmetric-key cryptography to be mixed into the already existing public-key cryptography, for post-quantum resistance. If \fIallowed-ips\fP is specified, but the value is the empty string, all -allowed ips are removed from the peer. The use of \fIpersistent-keepalive\fP +allowed ips are removed from the peer. By default, \fIallowed-ips\fP replaces +a peer's allowed ips. (Linux only) If + or - is prepended to any of the ips then +the update is incremental; ips prefixed with '+' or '' are added to the peer's +allowed ips if not present while ips prefixed with '-' are removed if present. +The use of \fIpersistent-keepalive\fP is optional and is by default off; setting it to 0 or "off" disables it. Otherwise it represents, in seconds, between 1 and 65535 inclusive, how often to send an authenticated empty packet to the peer, for the purpose of keeping diff --git a/src/set.c b/src/set.c index 75560fd..992ffa2 100644 --- a/src/set.c +++ b/src/set.c @@ -18,7 +18,7 @@ int set_main(int argc, const char *argv[]) int ret = 1; if (argc < 3) { - fprintf(stderr, "Usage: %s %s <interface> [listen-port <port>] [fwmark <mark>] [private-key <file path>] [peer <base64 public key> [remove] [preshared-key <file path>] [endpoint <ip>:<port>] [persistent-keepalive <interval seconds>] [allowed-ips <ip1>/<cidr1>[,<ip2>/<cidr2>]...] ]...\n", PROG_NAME, argv[0]); + fprintf(stderr, "Usage: %s %s <interface> [listen-port <port>] [fwmark <mark>] [private-key <file path>] [peer <base64 public key> [remove] [preshared-key <file path>] [endpoint <ip>:<port>] [persistent-keepalive <interval seconds>] [allowed-ips [+|-]<ip1>/<cidr1>[,[+|-]<ip2>/<cidr2>]...] ]...\n", PROG_NAME, argv[0]); return 1; } diff --git a/src/uapi/linux/linux/wireguard.h b/src/uapi/linux/linux/wireguard.h index 0efd52c..6ca266a 100644 --- a/src/uapi/linux/linux/wireguard.h +++ b/src/uapi/linux/linux/wireguard.h @@ -101,6 +101,10 @@ * WGALLOWEDIP_A_FAMILY: NLA_U16 * WGALLOWEDIP_A_IPADDR: struct in_addr or struct in6_addr * WGALLOWEDIP_A_CIDR_MASK: NLA_U8 + * WGALLOWEDIP_A_FLAGS: NLA_U32, WGALLOWEDIP_F_REMOVE_ME if + * the specified IP should be removed; + * otherwise, this IP will be added if + * it is not already present. * 0: NLA_NESTED * ... * 0: NLA_NESTED @@ -184,11 +188,16 @@ enum wgpeer_attribute { }; #define WGPEER_A_MAX (__WGPEER_A_LAST - 1) +enum wgallowedip_flag { + WGALLOWEDIP_F_REMOVE_ME = 1U << 0, + __WGALLOWEDIP_F_ALL = WGALLOWEDIP_F_REMOVE_ME +}; enum wgallowedip_attribute { WGALLOWEDIP_A_UNSPEC, WGALLOWEDIP_A_FAMILY, WGALLOWEDIP_A_IPADDR, WGALLOWEDIP_A_CIDR_MASK, + WGALLOWEDIP_A_FLAGS, __WGALLOWEDIP_A_LAST }; #define WGALLOWEDIP_A_MAX (__WGALLOWEDIP_A_LAST - 1) -- 2.43.0 ^ permalink raw reply related [flat|nested] 15+ messages in thread
* [RESEND PATCH v3 net-next] wireguard: allowedips: Add WGALLOWEDIP_F_REMOVE_ME flag 2025-05-17 19:29 [RESEND PATCH v1 wireguard-tools] ipc: linux: Support incremental allowed ips updates Jordan Rife @ 2025-05-17 19:29 ` Jordan Rife 2025-05-20 21:47 ` Jason A. Donenfeld ` (2 more replies) 2025-05-20 20:14 ` [RESEND PATCH v1 wireguard-tools] ipc: linux: Support incremental allowed ips updates Jason A. Donenfeld 1 sibling, 3 replies; 15+ messages in thread From: Jordan Rife @ 2025-05-17 19:29 UTC (permalink / raw) To: wireguard, Jason A. Donenfeld Cc: Jordan Rife, netdev, Jakub Kicinski, Daniel Borkmann The current netlink API for WireGuard does not directly support removal of allowed ips from a peer. A user can remove an allowed ip from a peer in one of two ways: 1. By using the WGPEER_F_REPLACE_ALLOWEDIPS flag and providing a new list of allowed ips which omits the allowed ip that is to be removed. 2. By reassigning an allowed ip to a "dummy" peer then removing that peer with WGPEER_F_REMOVE_ME. With the first approach, the driver completely rebuilds the allowed ip list for a peer. If my current configuration is such that a peer has allowed ips 192.168.0.2 and 192.168.0.3 and I want to remove 192.168.0.2 the actual transition looks like this. [192.168.0.2, 192.168.0.3] <-- Initial state [] <-- Step 1: Allowed ips removed for peer [192.168.0.3] <-- Step 2: Allowed ips added back for peer This is true even if the allowed ip list is small and the update does not need to be batched into multiple WG_CMD_SET_DEVICE requests, as the removal and subsequent addition of ips is non-atomic within a single request. Consequently, wg_allowedips_lookup_dst and wg_allowedips_lookup_src may return NULL while reconfiguring a peer even for packets bound for ips a user did not intend to remove leading to unintended interruptions in connectivity. This presents in userspace as failed calls to sendto and sendmsg for UDP sockets. In my case, I ran netperf while repeatedly reconfiguring the allowed ips for a peer with wg. /usr/local/bin/netperf -H 10.102.73.72 -l 10m -t UDP_STREAM -- -R 1 -m 1024 send_data: data send error: No route to host (errno 113) netperf: send_omni: send_data failed: No route to host While this may not be of particular concern for environments where peers and allowed ips are mostly static, systems like Cilium manage peers and allowed ips in a dynamic environment where peers (i.e. Kubernetes nodes) and allowed ips (i.e. pods running on those nodes) can frequently change making WGPEER_F_REPLACE_ALLOWEDIPS problematic. The second approach avoids any possible connectivity interruptions but is hacky and less direct, requiring the creation of a temporary peer just to dispose of an allowed ip. Introduce a new flag called WGALLOWEDIP_F_REMOVE_ME which in the same way that WGPEER_F_REMOVE_ME allows a user to remove a single peer from a WireGuard device's configuration allows a user to remove an ip from a peer's set of allowed ips. This enables incremental updates to a device's configuration without any connectivity blips or messy workarounds. A corresponding patch for wg extends the existing `wg set` interface to leverage this feature. $ wg set wg0 peer <PUBKEY> allowed-ips +192.168.88.0/24,-192.168.0.1/32 When '+' or '-' is prepended to any ip in the list, wg clears WGPEER_F_REPLACE_ALLOWEDIPS and sets the WGALLOWEDIP_F_REMOVE_ME flag on any ip prefixed with '-'. v2->v3 ------ * Revert WG_GENL_VERSION back to 1 (Jason). * Rename _remove() to remove_node() (Jason). * Remove unnecessary !peer guard from remove() (Jason). * Adjust line length for calls to wg_allowedips_(remove|insert)_v(4|6) (Jason). * Fix punctuation inside uapi docs for WGALLOWEDIP_A_FLAGS (Jason). * Get rid of remove-ip program and use wg instead in selftests (Jason). * Use NLA_POLICY_MASK for WGALLOWEDIP_A_FLAGS validation (Jakub). v1->v2 ------ * Fixed some Sparse warnings. Link: https://lore.kernel.org/netdev/20240905200551.4099064-1-jrife@google.com/ Signed-off-by: Jordan Rife <jordan@jrife.io> --- drivers/net/wireguard/allowedips.c | 106 ++++++++++++++------ drivers/net/wireguard/allowedips.h | 4 + drivers/net/wireguard/netlink.c | 37 ++++--- drivers/net/wireguard/selftest/allowedips.c | 48 +++++++++ include/uapi/linux/wireguard.h | 9 ++ tools/testing/selftests/wireguard/netns.sh | 32 ++++++ 6 files changed, 193 insertions(+), 43 deletions(-) diff --git a/drivers/net/wireguard/allowedips.c b/drivers/net/wireguard/allowedips.c index 4b8528206cc8..dcf068ba2881 100644 --- a/drivers/net/wireguard/allowedips.c +++ b/drivers/net/wireguard/allowedips.c @@ -249,6 +249,56 @@ static int add(struct allowedips_node __rcu **trie, u8 bits, const u8 *key, return 0; } +static void remove_node(struct allowedips_node *node, struct mutex *lock) +{ + struct allowedips_node *child, **parent_bit, *parent; + bool free_parent; + + list_del_init(&node->peer_list); + RCU_INIT_POINTER(node->peer, NULL); + if (node->bit[0] && node->bit[1]) + return; + child = rcu_dereference_protected(node->bit[!rcu_access_pointer(node->bit[0])], + lockdep_is_held(lock)); + if (child) + child->parent_bit_packed = node->parent_bit_packed; + parent_bit = (struct allowedips_node **)(node->parent_bit_packed & ~3UL); + *parent_bit = child; + parent = (void *)parent_bit - + offsetof(struct allowedips_node, bit[node->parent_bit_packed & 1]); + free_parent = !rcu_access_pointer(node->bit[0]) && + !rcu_access_pointer(node->bit[1]) && + (node->parent_bit_packed & 3) <= 1 && + !rcu_access_pointer(parent->peer); + if (free_parent) + child = rcu_dereference_protected(parent->bit[!(node->parent_bit_packed & 1)], + lockdep_is_held(lock)); + call_rcu(&node->rcu, node_free_rcu); + if (!free_parent) + return; + if (child) + child->parent_bit_packed = parent->parent_bit_packed; + *(struct allowedips_node **)(parent->parent_bit_packed & ~3UL) = child; + call_rcu(&parent->rcu, node_free_rcu); +} + +static int remove(struct allowedips_node __rcu **trie, u8 bits, const u8 *key, + u8 cidr, struct wg_peer *peer, struct mutex *lock) +{ + struct allowedips_node *node; + + if (unlikely(cidr > bits)) + return -EINVAL; + if (!rcu_access_pointer(*trie) || + !node_placement(*trie, key, cidr, bits, &node, lock) || + peer != rcu_access_pointer(node->peer)) + return 0; + + remove_node(node, lock); + + return 0; +} + void wg_allowedips_init(struct allowedips *table) { table->root4 = table->root6 = NULL; @@ -300,44 +350,38 @@ int wg_allowedips_insert_v6(struct allowedips *table, const struct in6_addr *ip, return add(&table->root6, 128, key, cidr, peer, lock); } +int wg_allowedips_remove_v4(struct allowedips *table, const struct in_addr *ip, + u8 cidr, struct wg_peer *peer, struct mutex *lock) +{ + /* Aligned so it can be passed to fls */ + u8 key[4] __aligned(__alignof(u32)); + + ++table->seq; + swap_endian(key, (const u8 *)ip, 32); + return remove(&table->root4, 32, key, cidr, peer, lock); +} + +int wg_allowedips_remove_v6(struct allowedips *table, const struct in6_addr *ip, + u8 cidr, struct wg_peer *peer, struct mutex *lock) +{ + /* Aligned so it can be passed to fls64 */ + u8 key[16] __aligned(__alignof(u64)); + + ++table->seq; + swap_endian(key, (const u8 *)ip, 128); + return remove(&table->root6, 128, key, cidr, peer, lock); +} + void wg_allowedips_remove_by_peer(struct allowedips *table, struct wg_peer *peer, struct mutex *lock) { - struct allowedips_node *node, *child, **parent_bit, *parent, *tmp; - bool free_parent; + struct allowedips_node *node, *tmp; if (list_empty(&peer->allowedips_list)) return; ++table->seq; - list_for_each_entry_safe(node, tmp, &peer->allowedips_list, peer_list) { - list_del_init(&node->peer_list); - RCU_INIT_POINTER(node->peer, NULL); - if (node->bit[0] && node->bit[1]) - continue; - child = rcu_dereference_protected(node->bit[!rcu_access_pointer(node->bit[0])], - lockdep_is_held(lock)); - if (child) - child->parent_bit_packed = node->parent_bit_packed; - parent_bit = (struct allowedips_node **)(node->parent_bit_packed & ~3UL); - *parent_bit = child; - parent = (void *)parent_bit - - offsetof(struct allowedips_node, bit[node->parent_bit_packed & 1]); - free_parent = !rcu_access_pointer(node->bit[0]) && - !rcu_access_pointer(node->bit[1]) && - (node->parent_bit_packed & 3) <= 1 && - !rcu_access_pointer(parent->peer); - if (free_parent) - child = rcu_dereference_protected( - parent->bit[!(node->parent_bit_packed & 1)], - lockdep_is_held(lock)); - call_rcu(&node->rcu, node_free_rcu); - if (!free_parent) - continue; - if (child) - child->parent_bit_packed = parent->parent_bit_packed; - *(struct allowedips_node **)(parent->parent_bit_packed & ~3UL) = child; - call_rcu(&parent->rcu, node_free_rcu); - } + list_for_each_entry_safe(node, tmp, &peer->allowedips_list, peer_list) + remove_node(node, lock); } int wg_allowedips_read_node(struct allowedips_node *node, u8 ip[16], u8 *cidr) diff --git a/drivers/net/wireguard/allowedips.h b/drivers/net/wireguard/allowedips.h index 2346c797eb4d..931958cb6e10 100644 --- a/drivers/net/wireguard/allowedips.h +++ b/drivers/net/wireguard/allowedips.h @@ -38,6 +38,10 @@ int wg_allowedips_insert_v4(struct allowedips *table, const struct in_addr *ip, u8 cidr, struct wg_peer *peer, struct mutex *lock); int wg_allowedips_insert_v6(struct allowedips *table, const struct in6_addr *ip, u8 cidr, struct wg_peer *peer, struct mutex *lock); +int wg_allowedips_remove_v4(struct allowedips *table, const struct in_addr *ip, + u8 cidr, struct wg_peer *peer, struct mutex *lock); +int wg_allowedips_remove_v6(struct allowedips *table, const struct in6_addr *ip, + u8 cidr, struct wg_peer *peer, struct mutex *lock); void wg_allowedips_remove_by_peer(struct allowedips *table, struct wg_peer *peer, struct mutex *lock); /* The ip input pointer should be __aligned(__alignof(u64))) */ diff --git a/drivers/net/wireguard/netlink.c b/drivers/net/wireguard/netlink.c index f7055180ba4a..386f65042072 100644 --- a/drivers/net/wireguard/netlink.c +++ b/drivers/net/wireguard/netlink.c @@ -46,7 +46,8 @@ static const struct nla_policy peer_policy[WGPEER_A_MAX + 1] = { static const struct nla_policy allowedip_policy[WGALLOWEDIP_A_MAX + 1] = { [WGALLOWEDIP_A_FAMILY] = { .type = NLA_U16 }, [WGALLOWEDIP_A_IPADDR] = NLA_POLICY_MIN_LEN(sizeof(struct in_addr)), - [WGALLOWEDIP_A_CIDR_MASK] = { .type = NLA_U8 } + [WGALLOWEDIP_A_CIDR_MASK] = { .type = NLA_U8 }, + [WGALLOWEDIP_A_FLAGS] = NLA_POLICY_MASK(NLA_U32, __WGALLOWEDIP_F_ALL), }; static struct wg_device *lookup_interface(struct nlattr **attrs, @@ -329,6 +330,7 @@ static int set_port(struct wg_device *wg, u16 port) static int set_allowedip(struct wg_peer *peer, struct nlattr **attrs) { int ret = -EINVAL; + u32 flags = 0; u16 family; u8 cidr; @@ -337,19 +339,30 @@ static int set_allowedip(struct wg_peer *peer, struct nlattr **attrs) return ret; family = nla_get_u16(attrs[WGALLOWEDIP_A_FAMILY]); cidr = nla_get_u8(attrs[WGALLOWEDIP_A_CIDR_MASK]); + if (attrs[WGALLOWEDIP_A_FLAGS]) + flags = nla_get_u32(attrs[WGALLOWEDIP_A_FLAGS]); if (family == AF_INET && cidr <= 32 && - nla_len(attrs[WGALLOWEDIP_A_IPADDR]) == sizeof(struct in_addr)) - ret = wg_allowedips_insert_v4( - &peer->device->peer_allowedips, - nla_data(attrs[WGALLOWEDIP_A_IPADDR]), cidr, peer, - &peer->device->device_update_lock); - else if (family == AF_INET6 && cidr <= 128 && - nla_len(attrs[WGALLOWEDIP_A_IPADDR]) == sizeof(struct in6_addr)) - ret = wg_allowedips_insert_v6( - &peer->device->peer_allowedips, - nla_data(attrs[WGALLOWEDIP_A_IPADDR]), cidr, peer, - &peer->device->device_update_lock); + nla_len(attrs[WGALLOWEDIP_A_IPADDR]) == sizeof(struct in_addr)) { + if (flags & WGALLOWEDIP_F_REMOVE_ME) + ret = wg_allowedips_remove_v4(&peer->device->peer_allowedips, + nla_data(attrs[WGALLOWEDIP_A_IPADDR]), cidr, + peer, &peer->device->device_update_lock); + else + ret = wg_allowedips_insert_v4(&peer->device->peer_allowedips, + nla_data(attrs[WGALLOWEDIP_A_IPADDR]), cidr, + peer, &peer->device->device_update_lock); + } else if (family == AF_INET6 && cidr <= 128 && + nla_len(attrs[WGALLOWEDIP_A_IPADDR]) == sizeof(struct in6_addr)) { + if (flags & WGALLOWEDIP_F_REMOVE_ME) + ret = wg_allowedips_remove_v6(&peer->device->peer_allowedips, + nla_data(attrs[WGALLOWEDIP_A_IPADDR]), cidr, + peer, &peer->device->device_update_lock); + else + ret = wg_allowedips_insert_v6(&peer->device->peer_allowedips, + nla_data(attrs[WGALLOWEDIP_A_IPADDR]), cidr, + peer, &peer->device->device_update_lock); + } return ret; } diff --git a/drivers/net/wireguard/selftest/allowedips.c b/drivers/net/wireguard/selftest/allowedips.c index 25de7058701a..41837efa70cb 100644 --- a/drivers/net/wireguard/selftest/allowedips.c +++ b/drivers/net/wireguard/selftest/allowedips.c @@ -460,6 +460,10 @@ static __init struct wg_peer *init_peer(void) wg_allowedips_insert_v##version(&t, ip##version(ipa, ipb, ipc, ipd), \ cidr, mem, &mutex) +#define remove(version, mem, ipa, ipb, ipc, ipd, cidr) \ + wg_allowedips_remove_v##version(&t, ip##version(ipa, ipb, ipc, ipd), \ + cidr, mem, &mutex) + #define maybe_fail() do { \ ++i; \ if (!_s) { \ @@ -585,6 +589,50 @@ bool __init wg_allowedips_selftest(void) test_negative(4, a, 192, 0, 0, 0); test_negative(4, a, 255, 0, 0, 0); + insert(4, a, 1, 0, 0, 0, 32); + insert(4, a, 192, 0, 0, 0, 24); + insert(6, a, 0x24446801, 0x40e40800, 0xdeaebeef, 0xdefbeef, 128); + insert(6, a, 0x24446800, 0xf0e40800, 0xeeaebeef, 0, 98); + test(4, a, 1, 0, 0, 0); + test(4, a, 192, 0, 0, 1); + test(6, a, 0x24446801, 0x40e40800, 0xdeaebeef, 0xdefbeef); + test(6, a, 0x24446800, 0xf0e40800, 0xeeaebeef, 0x10101010); + /* Must be an exact match to remove */ + remove(4, a, 192, 0, 0, 0, 32); + test(4, a, 192, 0, 0, 1); + /* NULL peer should have no effect and return 0 */ + test_boolean(!remove(4, NULL, 192, 0, 0, 0, 24)); + test(4, a, 192, 0, 0, 1); + /* different peer should have no effect and return 0 */ + test_boolean(!remove(4, b, 192, 0, 0, 0, 24)); + test(4, a, 192, 0, 0, 1); + /* invalid CIDR should have no effect and return -EINVAL */ + test_boolean(remove(4, b, 192, 0, 0, 0, 33) == -EINVAL); + test(4, a, 192, 0, 0, 1); + remove(4, a, 192, 0, 0, 0, 24); + test_negative(4, a, 192, 0, 0, 1); + remove(4, a, 1, 0, 0, 0, 32); + test_negative(4, a, 1, 0, 0, 0); + /* Must be an exact match to remove */ + remove(6, a, 0x24446801, 0x40e40800, 0xdeaebeef, 0xdefbeef, 96); + test(6, a, 0x24446801, 0x40e40800, 0xdeaebeef, 0xdefbeef); + /* NULL peer should have no effect and return 0 */ + test_boolean(!remove(6, NULL, 0x24446801, 0x40e40800, 0xdeaebeef, 0xdefbeef, 128)); + test(6, a, 0x24446801, 0x40e40800, 0xdeaebeef, 0xdefbeef); + /* different peer should have no effect and return 0 */ + test_boolean(!remove(6, b, 0x24446801, 0x40e40800, 0xdeaebeef, 0xdefbeef, 128)); + test(6, a, 0x24446801, 0x40e40800, 0xdeaebeef, 0xdefbeef); + /* invalid CIDR should have no effect and return -EINVAL */ + test_boolean(remove(6, a, 0x24446801, 0x40e40800, 0xdeaebeef, 0xdefbeef, 129) == -EINVAL); + test(6, a, 0x24446801, 0x40e40800, 0xdeaebeef, 0xdefbeef); + remove(6, a, 0x24446801, 0x40e40800, 0xdeaebeef, 0xdefbeef, 128); + test_negative(6, a, 0x24446801, 0x40e40800, 0xdeaebeef, 0xdefbeef); + /* Must match the peer to remove */ + remove(6, b, 0x24446800, 0xf0e40800, 0xeeaebeef, 0, 98); + test(6, a, 0x24446800, 0xf0e40800, 0xeeaebeef, 0x10101010); + remove(6, a, 0x24446800, 0xf0e40800, 0xeeaebeef, 0, 98); + test_negative(6, a, 0x24446800, 0xf0e40800, 0xeeaebeef, 0x10101010); + wg_allowedips_free(&t, &mutex); wg_allowedips_init(&t); insert(4, a, 192, 168, 0, 0, 16); diff --git a/include/uapi/linux/wireguard.h b/include/uapi/linux/wireguard.h index ae88be14c947..8c26391196d5 100644 --- a/include/uapi/linux/wireguard.h +++ b/include/uapi/linux/wireguard.h @@ -101,6 +101,10 @@ * WGALLOWEDIP_A_FAMILY: NLA_U16 * WGALLOWEDIP_A_IPADDR: struct in_addr or struct in6_addr * WGALLOWEDIP_A_CIDR_MASK: NLA_U8 + * WGALLOWEDIP_A_FLAGS: NLA_U32, WGALLOWEDIP_F_REMOVE_ME if + * the specified IP should be removed; + * otherwise, this IP will be added if + * it is not already present. * 0: NLA_NESTED * ... * 0: NLA_NESTED @@ -184,11 +188,16 @@ enum wgpeer_attribute { }; #define WGPEER_A_MAX (__WGPEER_A_LAST - 1) +enum wgallowedip_flag { + WGALLOWEDIP_F_REMOVE_ME = 1U << 0, + __WGALLOWEDIP_F_ALL = WGALLOWEDIP_F_REMOVE_ME +}; enum wgallowedip_attribute { WGALLOWEDIP_A_UNSPEC, WGALLOWEDIP_A_FAMILY, WGALLOWEDIP_A_IPADDR, WGALLOWEDIP_A_CIDR_MASK, + WGALLOWEDIP_A_FLAGS, __WGALLOWEDIP_A_LAST }; #define WGALLOWEDIP_A_MAX (__WGALLOWEDIP_A_LAST - 1) diff --git a/tools/testing/selftests/wireguard/netns.sh b/tools/testing/selftests/wireguard/netns.sh index 55500f901fbc..70248c77ce11 100755 --- a/tools/testing/selftests/wireguard/netns.sh +++ b/tools/testing/selftests/wireguard/netns.sh @@ -611,6 +611,38 @@ n0 wg set wg0 peer "$pub2" allowed-ips "$allowedips" } < <(n0 wg show wg0 allowed-ips) ip0 link del wg0 +# Test IP removal +allowedips=( ) +for i in {1..197}; do + allowedips+=( 192.168.0.$i ) + allowedips+=( abcd::$i ) +done +saved_ifs="$IFS" +IFS=, +allowedips="${allowedips[*]}" +IFS="$saved_ifs" +ip0 link add wg0 type wireguard +n0 wg set wg0 peer "$pub1" allowed-ips "$allowedips" +pub1_hex=$(echo "$pub1" | base64 -d | xxd -p -c 50) +n0 wg set wg0 peer "$pub1" allowed-ips -192.168.0.1/32,-192.168.0.20/32,-192.168.0.100/32,-abcd::1/128,-abcd::20/128,-abcd::100/128 +n0 wg show wg0 allowed-ips +{ + read -r pub allowedips + [[ $pub == "$pub1" ]] + i=0 + for ip in $allowedips; do + [[ "$ip" != "192.168.0.1" ]] + [[ "$ip" != "192.168.0.20" ]] + [[ "$ip" != "192.168.0.100" ]] + [[ "$ip" != "abcd::1" ]] + [[ "$ip" != "abcd::20" ]] + [[ "$ip" != "abcd::100" ]] + ((++i)) + done + ((i == 388)) +} < <(n0 wg show wg0 allowed-ips) +ip0 link del wg0 + ! n0 wg show doesnotexist || false ip0 link add wg0 type wireguard -- 2.43.0 ^ permalink raw reply related [flat|nested] 15+ messages in thread
* Re: [RESEND PATCH v3 net-next] wireguard: allowedips: Add WGALLOWEDIP_F_REMOVE_ME flag 2025-05-17 19:29 ` [RESEND PATCH v3 net-next] wireguard: allowedips: Add WGALLOWEDIP_F_REMOVE_ME flag Jordan Rife @ 2025-05-20 21:47 ` Jason A. Donenfeld 2025-05-20 22:00 ` Jason A. Donenfeld 2025-05-20 21:50 ` Jason A. Donenfeld 2025-05-20 23:25 ` Jason A. Donenfeld 2 siblings, 1 reply; 15+ messages in thread From: Jason A. Donenfeld @ 2025-05-20 21:47 UTC (permalink / raw) To: Jordan Rife; +Cc: wireguard, netdev, Jakub Kicinski, Daniel Borkmann Hi Jakub, Jordan, On Sat, May 17, 2025 at 12:29:52PM -0700, Jordan Rife wrote: > * Use NLA_POLICY_MASK for WGALLOWEDIP_A_FLAGS validation (Jakub). [...] > + [WGALLOWEDIP_A_FLAGS] = NLA_POLICY_MASK(NLA_U32, __WGALLOWEDIP_F_ALL), I wonder... Can we update, in a separate patch, these to also use NLA_POLICY_MASK? ... [WGDEVICE_A_FLAGS] = { .type = NLA_U32 }, ... [WGPEER_A_FLAGS] = { .type = NLA_U32 }, ... Some consistency would be nice. Regards, Jason ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [RESEND PATCH v3 net-next] wireguard: allowedips: Add WGALLOWEDIP_F_REMOVE_ME flag 2025-05-20 21:47 ` Jason A. Donenfeld @ 2025-05-20 22:00 ` Jason A. Donenfeld 2025-05-21 23:11 ` Jordan Rife 0 siblings, 1 reply; 15+ messages in thread From: Jason A. Donenfeld @ 2025-05-20 22:00 UTC (permalink / raw) To: Jordan Rife; +Cc: wireguard, netdev, Jakub Kicinski, Daniel Borkmann On Tue, May 20, 2025 at 11:47:56PM +0200, Jason A. Donenfeld wrote: > Hi Jakub, Jordan, > > On Sat, May 17, 2025 at 12:29:52PM -0700, Jordan Rife wrote: > > * Use NLA_POLICY_MASK for WGALLOWEDIP_A_FLAGS validation (Jakub). > [...] > > + [WGALLOWEDIP_A_FLAGS] = NLA_POLICY_MASK(NLA_U32, __WGALLOWEDIP_F_ALL), > > I wonder... Can we update, in a separate patch, these to also use > NLA_POLICY_MASK? > > ... > [WGDEVICE_A_FLAGS] = { .type = NLA_U32 }, > ... > [WGPEER_A_FLAGS] = { .type = NLA_U32 }, > ... > > Some consistency would be nice. Perhaps I'll commit something like this? From 22b6d15ad2a2e38bc80ebf65694106ff554b572f Mon Sep 17 00:00:00 2001 From: "Jason A. Donenfeld" <Jason@zx2c4.com> Date: Tue, 20 May 2025 23:56:18 +0200 Subject: [PATCH] wireguard: netlink: use NLA_POLICY_MASK where possible Rather than manually validating flags against the various __ALL_* constants, put this in the netlink policy description and have the upper layer machinery check it for us. Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com> --- drivers/net/wireguard/netlink.c | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/drivers/net/wireguard/netlink.c b/drivers/net/wireguard/netlink.c index f7055180ba4a..b82266da949a 100644 --- a/drivers/net/wireguard/netlink.c +++ b/drivers/net/wireguard/netlink.c @@ -24,7 +24,7 @@ static const struct nla_policy device_policy[WGDEVICE_A_MAX + 1] = { [WGDEVICE_A_IFNAME] = { .type = NLA_NUL_STRING, .len = IFNAMSIZ - 1 }, [WGDEVICE_A_PRIVATE_KEY] = NLA_POLICY_EXACT_LEN(NOISE_PUBLIC_KEY_LEN), [WGDEVICE_A_PUBLIC_KEY] = NLA_POLICY_EXACT_LEN(NOISE_PUBLIC_KEY_LEN), - [WGDEVICE_A_FLAGS] = { .type = NLA_U32 }, + [WGDEVICE_A_FLAGS] = { .type = NLA_POLICY_MASK(NLA_U32, __WGDEVICE_F_ALL) }, [WGDEVICE_A_LISTEN_PORT] = { .type = NLA_U16 }, [WGDEVICE_A_FWMARK] = { .type = NLA_U32 }, [WGDEVICE_A_PEERS] = { .type = NLA_NESTED } @@ -33,7 +33,7 @@ static const struct nla_policy device_policy[WGDEVICE_A_MAX + 1] = { static const struct nla_policy peer_policy[WGPEER_A_MAX + 1] = { [WGPEER_A_PUBLIC_KEY] = NLA_POLICY_EXACT_LEN(NOISE_PUBLIC_KEY_LEN), [WGPEER_A_PRESHARED_KEY] = NLA_POLICY_EXACT_LEN(NOISE_SYMMETRIC_KEY_LEN), - [WGPEER_A_FLAGS] = { .type = NLA_U32 }, + [WGPEER_A_FLAGS] = { .type = NLA_POLICY_MASK(NLA_U32, __WGPEER_F_ALL) }, [WGPEER_A_ENDPOINT] = NLA_POLICY_MIN_LEN(sizeof(struct sockaddr)), [WGPEER_A_PERSISTENT_KEEPALIVE_INTERVAL] = { .type = NLA_U16 }, [WGPEER_A_LAST_HANDSHAKE_TIME] = NLA_POLICY_EXACT_LEN(sizeof(struct __kernel_timespec)), @@ -373,9 +373,6 @@ static int set_peer(struct wg_device *wg, struct nlattr **attrs) if (attrs[WGPEER_A_FLAGS]) flags = nla_get_u32(attrs[WGPEER_A_FLAGS]); - ret = -EOPNOTSUPP; - if (flags & ~__WGPEER_F_ALL) - goto out; ret = -EPFNOSUPPORT; if (attrs[WGPEER_A_PROTOCOL_VERSION]) { @@ -506,9 +503,6 @@ static int wg_set_device(struct sk_buff *skb, struct genl_info *info) if (info->attrs[WGDEVICE_A_FLAGS]) flags = nla_get_u32(info->attrs[WGDEVICE_A_FLAGS]); - ret = -EOPNOTSUPP; - if (flags & ~__WGDEVICE_F_ALL) - goto out; if (info->attrs[WGDEVICE_A_LISTEN_PORT] || info->attrs[WGDEVICE_A_FWMARK]) { struct net *net; -- 2.48.1 ^ permalink raw reply related [flat|nested] 15+ messages in thread
* Re: [RESEND PATCH v3 net-next] wireguard: allowedips: Add WGALLOWEDIP_F_REMOVE_ME flag 2025-05-20 22:00 ` Jason A. Donenfeld @ 2025-05-21 23:11 ` Jordan Rife 0 siblings, 0 replies; 15+ messages in thread From: Jordan Rife @ 2025-05-21 23:11 UTC (permalink / raw) To: Jason A. Donenfeld; +Cc: wireguard, netdev, Jakub Kicinski, Daniel Borkmann On Wed, May 21, 2025 at 12:00:00AM +0200, Jason A. Donenfeld wrote: > On Tue, May 20, 2025 at 11:47:56PM +0200, Jason A. Donenfeld wrote: > > Hi Jakub, Jordan, > > > > On Sat, May 17, 2025 at 12:29:52PM -0700, Jordan Rife wrote: > > > * Use NLA_POLICY_MASK for WGALLOWEDIP_A_FLAGS validation (Jakub). > > [...] > > > + [WGALLOWEDIP_A_FLAGS] = NLA_POLICY_MASK(NLA_U32, __WGALLOWEDIP_F_ALL), > > > > I wonder... Can we update, in a separate patch, these to also use > > NLA_POLICY_MASK? > > > > ... > > [WGDEVICE_A_FLAGS] = { .type = NLA_U32 }, > > ... > > [WGPEER_A_FLAGS] = { .type = NLA_U32 }, > > ... > > > > Some consistency would be nice. > > Perhaps I'll commit something like this? > > From 22b6d15ad2a2e38bc80ebf65694106ff554b572f Mon Sep 17 00:00:00 2001 > From: "Jason A. Donenfeld" <Jason@zx2c4.com> > Date: Tue, 20 May 2025 23:56:18 +0200 > Subject: [PATCH] wireguard: netlink: use NLA_POLICY_MASK where possible > > Rather than manually validating flags against the various __ALL_* > constants, put this in the netlink policy description and have the upper > layer machinery check it for us. > > Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com> > --- > drivers/net/wireguard/netlink.c | 10 ++-------- > 1 file changed, 2 insertions(+), 8 deletions(-) > > diff --git a/drivers/net/wireguard/netlink.c b/drivers/net/wireguard/netlink.c > index f7055180ba4a..b82266da949a 100644 > --- a/drivers/net/wireguard/netlink.c > +++ b/drivers/net/wireguard/netlink.c > @@ -24,7 +24,7 @@ static const struct nla_policy device_policy[WGDEVICE_A_MAX + 1] = { > [WGDEVICE_A_IFNAME] = { .type = NLA_NUL_STRING, .len = IFNAMSIZ - 1 }, > [WGDEVICE_A_PRIVATE_KEY] = NLA_POLICY_EXACT_LEN(NOISE_PUBLIC_KEY_LEN), > [WGDEVICE_A_PUBLIC_KEY] = NLA_POLICY_EXACT_LEN(NOISE_PUBLIC_KEY_LEN), > - [WGDEVICE_A_FLAGS] = { .type = NLA_U32 }, > + [WGDEVICE_A_FLAGS] = { .type = NLA_POLICY_MASK(NLA_U32, __WGDEVICE_F_ALL) }, > [WGDEVICE_A_LISTEN_PORT] = { .type = NLA_U16 }, > [WGDEVICE_A_FWMARK] = { .type = NLA_U32 }, > [WGDEVICE_A_PEERS] = { .type = NLA_NESTED } > @@ -33,7 +33,7 @@ static const struct nla_policy device_policy[WGDEVICE_A_MAX + 1] = { > static const struct nla_policy peer_policy[WGPEER_A_MAX + 1] = { > [WGPEER_A_PUBLIC_KEY] = NLA_POLICY_EXACT_LEN(NOISE_PUBLIC_KEY_LEN), > [WGPEER_A_PRESHARED_KEY] = NLA_POLICY_EXACT_LEN(NOISE_SYMMETRIC_KEY_LEN), > - [WGPEER_A_FLAGS] = { .type = NLA_U32 }, > + [WGPEER_A_FLAGS] = { .type = NLA_POLICY_MASK(NLA_U32, __WGPEER_F_ALL) }, > [WGPEER_A_ENDPOINT] = NLA_POLICY_MIN_LEN(sizeof(struct sockaddr)), > [WGPEER_A_PERSISTENT_KEEPALIVE_INTERVAL] = { .type = NLA_U16 }, > [WGPEER_A_LAST_HANDSHAKE_TIME] = NLA_POLICY_EXACT_LEN(sizeof(struct __kernel_timespec)), > @@ -373,9 +373,6 @@ static int set_peer(struct wg_device *wg, struct nlattr **attrs) > > if (attrs[WGPEER_A_FLAGS]) > flags = nla_get_u32(attrs[WGPEER_A_FLAGS]); > - ret = -EOPNOTSUPP; > - if (flags & ~__WGPEER_F_ALL) > - goto out; > > ret = -EPFNOSUPPORT; > if (attrs[WGPEER_A_PROTOCOL_VERSION]) { > @@ -506,9 +503,6 @@ static int wg_set_device(struct sk_buff *skb, struct genl_info *info) > > if (info->attrs[WGDEVICE_A_FLAGS]) > flags = nla_get_u32(info->attrs[WGDEVICE_A_FLAGS]); > - ret = -EOPNOTSUPP; > - if (flags & ~__WGDEVICE_F_ALL) > - goto out; > > if (info->attrs[WGDEVICE_A_LISTEN_PORT] || info->attrs[WGDEVICE_A_FWMARK]) { > struct net *net; > -- > 2.48.1 This changes the error code returned in userspace in these cases from EOPNOTSUPP to EINVAL I think, but if there's nothing relying on that behavior then it seems like a nice cleanup to me. Jordan ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [RESEND PATCH v3 net-next] wireguard: allowedips: Add WGALLOWEDIP_F_REMOVE_ME flag 2025-05-17 19:29 ` [RESEND PATCH v3 net-next] wireguard: allowedips: Add WGALLOWEDIP_F_REMOVE_ME flag Jordan Rife 2025-05-20 21:47 ` Jason A. Donenfeld @ 2025-05-20 21:50 ` Jason A. Donenfeld 2025-05-20 23:25 ` Jason A. Donenfeld 2 siblings, 0 replies; 15+ messages in thread From: Jason A. Donenfeld @ 2025-05-20 21:50 UTC (permalink / raw) To: Jordan Rife; +Cc: wireguard, netdev, Jakub Kicinski, Daniel Borkmann On Sat, May 17, 2025 at 12:29:52PM -0700, Jordan Rife wrote: > +pub1_hex=$(echo "$pub1" | base64 -d | xxd -p -c 50) There's no xxd or base64 commands on the test harness vm, but also this line isn't used, so I'll just nix it on commit. ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [RESEND PATCH v3 net-next] wireguard: allowedips: Add WGALLOWEDIP_F_REMOVE_ME flag 2025-05-17 19:29 ` [RESEND PATCH v3 net-next] wireguard: allowedips: Add WGALLOWEDIP_F_REMOVE_ME flag Jordan Rife 2025-05-20 21:47 ` Jason A. Donenfeld 2025-05-20 21:50 ` Jason A. Donenfeld @ 2025-05-20 23:25 ` Jason A. Donenfeld 2025-05-21 23:13 ` Jordan Rife 2 siblings, 1 reply; 15+ messages in thread From: Jason A. Donenfeld @ 2025-05-20 23:25 UTC (permalink / raw) To: Jordan Rife; +Cc: wireguard, netdev, Jakub Kicinski, Daniel Borkmann On Sat, May 17, 2025 at 12:29:52PM -0700, Jordan Rife wrote: > Introduce a new flag called WGALLOWEDIP_F_REMOVE_ME which in the same > way that WGPEER_F_REMOVE_ME allows a user to remove a single peer from > a WireGuard device's configuration allows a user to remove an ip from a > peer's set of allowed ips. This enables incremental updates to a > device's configuration without any connectivity blips or messy > workarounds. Applied as: https://git.zx2c4.com/wireguard-linux/commit/?h=devel&id=8f697b71a615c5dfff98fe93554036a2643d1976 And the userspace changes have been released already: https://lists.zx2c4.com/pipermail/wireguard/2025-May/008789.html Thanks for this! And sorry it took so long to get it applied. I'll send this up via net-next in a few days after a bunch of testing. Jason ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [RESEND PATCH v3 net-next] wireguard: allowedips: Add WGALLOWEDIP_F_REMOVE_ME flag 2025-05-20 23:25 ` Jason A. Donenfeld @ 2025-05-21 23:13 ` Jordan Rife 0 siblings, 0 replies; 15+ messages in thread From: Jordan Rife @ 2025-05-21 23:13 UTC (permalink / raw) To: Jason A. Donenfeld; +Cc: wireguard, netdev, Jakub Kicinski, Daniel Borkmann On Wed, May 21, 2025 at 01:25:04AM +0200, Jason A. Donenfeld wrote: > On Sat, May 17, 2025 at 12:29:52PM -0700, Jordan Rife wrote: > > Introduce a new flag called WGALLOWEDIP_F_REMOVE_ME which in the same > > way that WGPEER_F_REMOVE_ME allows a user to remove a single peer from > > a WireGuard device's configuration allows a user to remove an ip from a > > peer's set of allowed ips. This enables incremental updates to a > > device's configuration without any connectivity blips or messy > > workarounds. > > Applied as: > https://git.zx2c4.com/wireguard-linux/commit/?h=devel&id=8f697b71a615c5dfff98fe93554036a2643d1976 > > And the userspace changes have been released already: > https://lists.zx2c4.com/pipermail/wireguard/2025-May/008789.html > > Thanks for this! And sorry it took so long to get it applied. I'll send > this up via net-next in a few days after a bunch of testing. > > Jason No problem, we all get busy :). Thanks for applying. Jordan ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [RESEND PATCH v1 wireguard-tools] ipc: linux: Support incremental allowed ips updates 2025-05-17 19:29 [RESEND PATCH v1 wireguard-tools] ipc: linux: Support incremental allowed ips updates Jordan Rife 2025-05-17 19:29 ` [RESEND PATCH v3 net-next] wireguard: allowedips: Add WGALLOWEDIP_F_REMOVE_ME flag Jordan Rife @ 2025-05-20 20:14 ` Jason A. Donenfeld 2025-05-20 21:10 ` Jason A. Donenfeld 1 sibling, 1 reply; 15+ messages in thread From: Jason A. Donenfeld @ 2025-05-20 20:14 UTC (permalink / raw) To: Jordan Rife; +Cc: wireguard, netdev, Jakub Kicinski, Daniel Borkmann On Sat, May 17, 2025 at 12:29:51PM -0700, Jordan Rife wrote: > Extend the interface of `wg set` to leverage the WGALLOWEDIP_F_REMOVE_ME > flag, a direct way of removing a single allowed ip from a peer, > allowing for incremental updates to a peer's configuration. By default, > allowed-ips fully replaces a peer's allowed ips using > WGPEER_REPLACE_ALLOWEDIPS under the hood. When '+' or '-' is prepended > to any ip in the list, wg clears WGPEER_F_REPLACE_ALLOWEDIPS and sets > the WGALLOWEDIP_F_REMOVE_ME flag on any ip prefixed with '-'. > > $ wg set wg0 peer <PUBKEY> allowed-ips +192.168.88.0/24,-192.168.0.1/32 > > This command means "add 192.168.88.0/24 to this peer's allowed ips if > not present, and remove 192.168.0.1/32 if present". > > Use -isystem so that headers in uapi/ take precedence over system > headers; otherwise, the build will fail on systems running kernels > without the WGALLOWEDIP_F_REMOVE_ME flag. > > Note that this patch is meant to be merged alongside the kernel patch > that introduces the flag. Merged here: https://git.zx2c4.com/wireguard-tools/commit/?id=0788f90810efde88cfa07ed96e7eca77c7f2eedd With a followup here: https://git.zx2c4.com/wireguard-tools/commit/?id=dce8ac6e2fa30f8b07e84859f244f81b3c6b2353 Sorry for the delay. Next, the kernel changes. Regards, Jason ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [RESEND PATCH v1 wireguard-tools] ipc: linux: Support incremental allowed ips updates 2025-05-20 20:14 ` [RESEND PATCH v1 wireguard-tools] ipc: linux: Support incremental allowed ips updates Jason A. Donenfeld @ 2025-05-20 21:10 ` Jason A. Donenfeld 2025-05-21 23:02 ` Jordan Rife 0 siblings, 1 reply; 15+ messages in thread From: Jason A. Donenfeld @ 2025-05-20 21:10 UTC (permalink / raw) To: Jordan Rife; +Cc: wireguard, netdev, Jakub Kicinski, Daniel Borkmann On Tue, May 20, 2025 at 10:14:38PM +0200, Jason A. Donenfeld wrote: > On Sat, May 17, 2025 at 12:29:51PM -0700, Jordan Rife wrote: > > Extend the interface of `wg set` to leverage the WGALLOWEDIP_F_REMOVE_ME > > flag, a direct way of removing a single allowed ip from a peer, > > allowing for incremental updates to a peer's configuration. By default, > > allowed-ips fully replaces a peer's allowed ips using > > WGPEER_REPLACE_ALLOWEDIPS under the hood. When '+' or '-' is prepended > > to any ip in the list, wg clears WGPEER_F_REPLACE_ALLOWEDIPS and sets > > the WGALLOWEDIP_F_REMOVE_ME flag on any ip prefixed with '-'. > > > > $ wg set wg0 peer <PUBKEY> allowed-ips +192.168.88.0/24,-192.168.0.1/32 > > > > This command means "add 192.168.88.0/24 to this peer's allowed ips if > > not present, and remove 192.168.0.1/32 if present". > > > > Use -isystem so that headers in uapi/ take precedence over system > > headers; otherwise, the build will fail on systems running kernels > > without the WGALLOWEDIP_F_REMOVE_ME flag. > > > > Note that this patch is meant to be merged alongside the kernel patch > > that introduces the flag. > > Merged here: > https://git.zx2c4.com/wireguard-tools/commit/?id=0788f90810efde88cfa07ed96e7eca77c7f2eedd > > With a followup here: > https://git.zx2c4.com/wireguard-tools/commit/?id=dce8ac6e2fa30f8b07e84859f244f81b3c6b2353 Also, https://git.zx2c4.com/wireguard-go/commit/?id=256bcbd70d5b4eaae2a9f21a9889498c0f89041c ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [RESEND PATCH v1 wireguard-tools] ipc: linux: Support incremental allowed ips updates 2025-05-20 21:10 ` Jason A. Donenfeld @ 2025-05-21 23:02 ` Jordan Rife 2025-05-21 23:51 ` Jason A. Donenfeld 0 siblings, 1 reply; 15+ messages in thread From: Jordan Rife @ 2025-05-21 23:02 UTC (permalink / raw) To: Jason A. Donenfeld; +Cc: wireguard, netdev, Jakub Kicinski, Daniel Borkmann > > Merged here: > > https://git.zx2c4.com/wireguard-tools/commit/?id=0788f90810efde88cfa07ed96e7eca77c7f2eedd > > > > With a followup here: > > https://git.zx2c4.com/wireguard-tools/commit/?id=dce8ac6e2fa30f8b07e84859f244f81b3c6b2353 > > Also, > https://git.zx2c4.com/wireguard-go/commit/?id=256bcbd70d5b4eaae2a9f21a9889498c0f89041c Nice, cool to see this extended to wireguard-go as well. As a follow up, I was planning to also create a patch for golang.zx2c4.com/wireguard/wgctrl so the feature can be used from there too. Jordan ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [RESEND PATCH v1 wireguard-tools] ipc: linux: Support incremental allowed ips updates 2025-05-21 23:02 ` Jordan Rife @ 2025-05-21 23:51 ` Jason A. Donenfeld 2025-06-26 3:37 ` Kyle Evans 0 siblings, 1 reply; 15+ messages in thread From: Jason A. Donenfeld @ 2025-05-21 23:51 UTC (permalink / raw) To: Jordan Rife; +Cc: wireguard, netdev, Jakub Kicinski, Daniel Borkmann On Thu, May 22, 2025 at 1:02 AM Jordan Rife <jordan@jrife.io> wrote: > > > Merged here: > > > https://git.zx2c4.com/wireguard-tools/commit/?id=0788f90810efde88cfa07ed96e7eca77c7f2eedd > > > > > > With a followup here: > > > https://git.zx2c4.com/wireguard-tools/commit/?id=dce8ac6e2fa30f8b07e84859f244f81b3c6b2353 > > > > Also, > > https://git.zx2c4.com/wireguard-go/commit/?id=256bcbd70d5b4eaae2a9f21a9889498c0f89041c > > Nice, cool to see this extended to wireguard-go as well. As a follow up, > I was planning to also create a patch for golang.zx2c4.com/wireguard/wgctrl > so the feature can be used from there too. Wonderful, please do! Looking forward to merging that. There's already an open PR in FreeBSD too. ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [RESEND PATCH v1 wireguard-tools] ipc: linux: Support incremental allowed ips updates 2025-05-21 23:51 ` Jason A. Donenfeld @ 2025-06-26 3:37 ` Kyle Evans 2025-06-28 16:05 ` Jordan Rife 0 siblings, 1 reply; 15+ messages in thread From: Kyle Evans @ 2025-06-26 3:37 UTC (permalink / raw) To: Jason A. Donenfeld, Jordan Rife Cc: wireguard, netdev, Jakub Kicinski, Daniel Borkmann On 5/21/25 18:51, Jason A. Donenfeld wrote: > On Thu, May 22, 2025 at 1:02 AM Jordan Rife <jordan@jrife.io> wrote: >>>> Merged here: >>>> https://git.zx2c4.com/wireguard-tools/commit/?id=0788f90810efde88cfa07ed96e7eca77c7f2eedd >>>> >>>> With a followup here: >>>> https://git.zx2c4.com/wireguard-tools/commit/?id=dce8ac6e2fa30f8b07e84859f244f81b3c6b2353 >>> >>> Also, >>> https://git.zx2c4.com/wireguard-go/commit/?id=256bcbd70d5b4eaae2a9f21a9889498c0f89041c >> >> Nice, cool to see this extended to wireguard-go as well. As a follow up, >> I was planning to also create a patch for golang.zx2c4.com/wireguard/wgctrl >> so the feature can be used from there too. > > Wonderful, please do! Looking forward to merging that. > > There's already an open PR in FreeBSD too. FreeBSD support landed as of: https://cgit.freebsd.org/src/commit/?id=f6d9e22982a It will be available in FreeBSD 15.0 and probably 14.4 (to be released next year) as well. I have pushed a branch, ke/fbsd_aip, to the wireguard-tools repository for your consideration. Aside: this is a really neat feature. Thanks! Kyle Evans ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [RESEND PATCH v1 wireguard-tools] ipc: linux: Support incremental allowed ips updates 2025-06-26 3:37 ` Kyle Evans @ 2025-06-28 16:05 ` Jordan Rife 2025-06-30 1:44 ` Kyle Evans 0 siblings, 1 reply; 15+ messages in thread From: Jordan Rife @ 2025-06-28 16:05 UTC (permalink / raw) To: Kyle Evans Cc: Jason A. Donenfeld, wireguard, netdev, Jakub Kicinski, Daniel Borkmann On Wed, Jun 25, 2025 at 10:37:55PM -0500, Kyle Evans wrote: > On 5/21/25 18:51, Jason A. Donenfeld wrote: > > On Thu, May 22, 2025 at 1:02 AM Jordan Rife <jordan@jrife.io> wrote: > > > > > Merged here: > > > > > https://git.zx2c4.com/wireguard-tools/commit/?id=0788f90810efde88cfa07ed96e7eca77c7f2eedd > > > > > > > > > > With a followup here: > > > > > https://git.zx2c4.com/wireguard-tools/commit/?id=dce8ac6e2fa30f8b07e84859f244f81b3c6b2353 > > > > > > > > Also, > > > > https://git.zx2c4.com/wireguard-go/commit/?id=256bcbd70d5b4eaae2a9f21a9889498c0f89041c > > > > > > Nice, cool to see this extended to wireguard-go as well. As a follow up, > > > I was planning to also create a patch for golang.zx2c4.com/wireguard/wgctrl > > > so the feature can be used from there too. > > > > Wonderful, please do! Looking forward to merging that. > > > > There's already an open PR in FreeBSD too. > > FreeBSD support landed as of: > > https://cgit.freebsd.org/src/commit/?id=f6d9e22982a > > It will be available in FreeBSD 15.0 and probably 14.4 (to be released next > year) as well. I have pushed a branch, ke/fbsd_aip, to the wireguard-tools > repository for your consideration. > > Aside: this is a really neat feature. > > Thanks! > > Kyle Evans That's great news. It's nice to see this feature percolating through the WireGuard ecosystem. I was working on adding support for direct IP removal to wgctrl-go too, a Go library for controlling WireGuard devices: https://github.com/WireGuard/wgctrl-go/pull/156 While I'm at it, I'll try to add native support for IP removal on FreeBSD if I can get a dev build working with the latest and greatest ( I am a FreeBSD noob :) ). Jordan ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [RESEND PATCH v1 wireguard-tools] ipc: linux: Support incremental allowed ips updates 2025-06-28 16:05 ` Jordan Rife @ 2025-06-30 1:44 ` Kyle Evans 0 siblings, 0 replies; 15+ messages in thread From: Kyle Evans @ 2025-06-30 1:44 UTC (permalink / raw) To: Jordan Rife Cc: Jason A. Donenfeld, wireguard, netdev, Jakub Kicinski, Daniel Borkmann On 6/28/25 11:05, Jordan Rife wrote: > On Wed, Jun 25, 2025 at 10:37:55PM -0500, Kyle Evans wrote: >> On 5/21/25 18:51, Jason A. Donenfeld wrote: >>> On Thu, May 22, 2025 at 1:02 AM Jordan Rife <jordan@jrife.io> wrote: >>>>>> Merged here: >>>>>> https://git.zx2c4.com/wireguard-tools/commit/?id=0788f90810efde88cfa07ed96e7eca77c7f2eedd >>>>>> >>>>>> With a followup here: >>>>>> https://git.zx2c4.com/wireguard-tools/commit/?id=dce8ac6e2fa30f8b07e84859f244f81b3c6b2353 >>>>> >>>>> Also, >>>>> https://git.zx2c4.com/wireguard-go/commit/?id=256bcbd70d5b4eaae2a9f21a9889498c0f89041c >>>> >>>> Nice, cool to see this extended to wireguard-go as well. As a follow up, >>>> I was planning to also create a patch for golang.zx2c4.com/wireguard/wgctrl >>>> so the feature can be used from there too. >>> >>> Wonderful, please do! Looking forward to merging that. >>> >>> There's already an open PR in FreeBSD too. >> >> FreeBSD support landed as of: >> >> https://cgit.freebsd.org/src/commit/?id=f6d9e22982a >> >> It will be available in FreeBSD 15.0 and probably 14.4 (to be released next >> year) as well. I have pushed a branch, ke/fbsd_aip, to the wireguard-tools >> repository for your consideration. >> >> Aside: this is a really neat feature. >> >> Thanks! >> >> Kyle Evans > > That's great news. It's nice to see this feature percolating through > the WireGuard ecosystem. > > I was working on adding support for direct IP removal to wgctrl-go too, > a Go library for controlling WireGuard devices: > > https://github.com/WireGuard/wgctrl-go/pull/156 > Ah, neat! > While I'm at it, I'll try to add native support for IP removal on > FreeBSD if I can get a dev build working with the latest and greatest > ( I am a FreeBSD noob :) ). > Feel free to shoot me an e-mail off-list if you need any assistance there, more than happy to lend a hand for the cause. Thanks, Kyle Evans ^ permalink raw reply [flat|nested] 15+ messages in thread
end of thread, other threads:[~2025-06-30 1:44 UTC | newest] Thread overview: 15+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2025-05-17 19:29 [RESEND PATCH v1 wireguard-tools] ipc: linux: Support incremental allowed ips updates Jordan Rife 2025-05-17 19:29 ` [RESEND PATCH v3 net-next] wireguard: allowedips: Add WGALLOWEDIP_F_REMOVE_ME flag Jordan Rife 2025-05-20 21:47 ` Jason A. Donenfeld 2025-05-20 22:00 ` Jason A. Donenfeld 2025-05-21 23:11 ` Jordan Rife 2025-05-20 21:50 ` Jason A. Donenfeld 2025-05-20 23:25 ` Jason A. Donenfeld 2025-05-21 23:13 ` Jordan Rife 2025-05-20 20:14 ` [RESEND PATCH v1 wireguard-tools] ipc: linux: Support incremental allowed ips updates Jason A. Donenfeld 2025-05-20 21:10 ` Jason A. Donenfeld 2025-05-21 23:02 ` Jordan Rife 2025-05-21 23:51 ` Jason A. Donenfeld 2025-06-26 3:37 ` Kyle Evans 2025-06-28 16:05 ` Jordan Rife 2025-06-30 1:44 ` Kyle Evans
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.